Excel-常用宏技巧(3)

Name 语句示例

本示例使用 Name 语句来更改文件的名称。示例中假设所有使用到的目录或文件夹都已存在。 在 Macintosh 中,默认驱动器名称是 “HD” 并且路径部分由冒号取代反斜线隔开。

Dim OldName, NewName

OldName = "OLDFILE": NewName = "NEWFILE" ' 定义文件名。

Name OldName As NewName ' 更改文件名。

OldName = "C:/MYDIR/OLDFILE": NewName = "C:/YOURDIR/NEWFILE"

Name OldName As NewName ' 更改文件名,并移动文件。


本示例显示当前默认文件路径。

MsgBox "The current default file path is " & _

Application.DefaultFilePath


本示例设置替换启动文件夹。

Application.AltStartupPath = "C:/EXCEL/MACROS"


FolderExists 方法

如果指定的文件夹存在返回 True,不存在返回 False。

语法

object.FolderExists(folderspec)


本示例在单元格中启用编辑。

Application.EditDirectlyInCell = True


VBA 入门课程 http://www.cpearson.com/excel/topic.htm

Advanced Office 2000 Password Recovery 破解VBA的程序

我学VBA时的两本书!《excle2000vba开发实例指南》晶辰工作室

《excle2002函数应用秘笈》中国铁路出版社


程序说明:

几种用VBA在单元格输入数据的方法:

Public Sub Writes()

1-- 2 方法,最简单在 "[ ]" 中输入单元格名称。

1 [A1] = 100 '在 A1 单元格输入100。

2 [A2:A4] = 10 '在 A2:A4 单元格输入10。

3-- 4 方法,采用 Range(" "), " " 中输入单元格名称。

3 Range("B1") = 200 '在 B1 单元格输入200。

4 Range("C1:C3") = 300 '在 C1:C3 单元格输入300。

5-- 6 方法,采用 Cells(Row,Column),Row是单元格行数,Column是单元格栏数。

5 Cells(1, 4) = 400 '在 D1 单元格输入400。

6 Range(Cells(1, 5), Cells(5, 5)) = 50 '在 E1:E 5单元格输入50。

End Sub


你点选任何单元格,按 Selection 按钮,則则所点选的单元格均会被输入文字 "Test"。

Public Sub Selection1()

Selection.Value = "Test" '在任何你点选的单元格输入文字 "Test"。

End Sub


VBALesson2 程序说明:

几种如何把别的工作表 Sheet4 数据,读到这个工作表的方法:在被读取的单元格前加上工作表名称 Sheet4。

Public Sub Writes()

1-- 2 方法,最简单在被读取的 "[ ]" 前加上被读取的工作表名称 Sheet4。

1 [A1] = Sheet4.[A1] '把Sheet4 A1 单元格的数据,读到 A1单元格。

2 [A2:A4] = Sheet4.[B1] ''把 Shee4 工作表单元格 B1 数据,读到 A2:A4 单元格。

3-- 4 方法,在被读取的工作表 Range(" ")的 Range 前加上被读取的工作表名称Sheet4。

3 Range("B1") = Sheet4.Range("B1") ''把 Shee4工作表单元格 B1 数据,读到 B1 单元格。

4 Range("C1:C3") = Sheet4.Range("C1") '把 Shee4 工作表单元格 C1 数据,读到 C1:C3 单元格。

5-- 6 方法,在被读取的工作表 Cells(Row,Column),Cells 前加上被读取工作表名称 Sheet4。

5 Cells(1, 4) = Sheet4.Cells(1, 4) '把 Shee4 工作表单元格 D1 数据,读到 D1 单元格。

6 Range(Cells(1, 5), Cells(5, 5)) = Sheet4.Cells(1, 5) '把 Shee4 工作表单元格 E1 数据,读到 E1:E 5单元格。

End Sub


你点选任何单元格,按 Selection 按钮,则所点选的单元格均会被输入 Shee4 工作表单元格 F1 数据。

Public Sub Selection1()

Selection.Value = Sheet4.[F1] '把 Shee4 工作表单元格 F1 数据,读到任何你点选的单元格。

End Sub


VBALesson3 程序说明:

如何利用 Worksheet_SelectionChange 输入数据的方法。

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

Target = 100

End Sub


Target 指的是你鼠标所选的单元格,Worksheet_SelectionChange() 事件的参数。

可以是一个也可以是好几个单元格。

Range 是 Excel 特有的变量形态,叫范围。

Target As Rang 是把 Target 这个参数设定为 Range 变量形态。

Target = 100 是把你点选的单元格输入数字100。


VBALesson4 程序说明:

如何利用 Worksheet_SelectionChange 在限定的单元格输入数据的方法。

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

If Target.Row >= 2 And Target.Column = 2 Then

Target = 100

End If

End Sub


If ... Then ... End If 这是我们学的这一个逻辑判断语句。

Target.Row >= 2,指的是鼠标选定的单元格的行大于或等于 2。

Target.Column = 2 ,指的是鼠标选定的单元格的栏等于 2。

If Target.Row >= 2 And Target.Column = 2 Then 指的是只有在Target.Row >= 2及Target.Column = 2二个条件成立时。

就是 (Target.Row >= 2) 为True及(Target.Column = 2)为True时,才执行下面的程序 Target=100,

也就是 B 栏第二行及以下行用鼠标被点选时,才会被输入100,其它单元格则不被输入数据。


VBALesson5 程序说明:

比较 Worksheet_SelectionChange() 与用按钮 CommandButton1_Click() 来执行程序二者的方法与写法有何不同。

Worksheet_SelectionChange()事件

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

If Target.Row >= 2 And Target.Column = 2 Then

Target = 100

End If

End Sub


按鈕 CommandButton1_Click()

Private Sub CommandButton1_Click()

If ActiveCell.Row >= 2 And ActiveCell.Column >= 3 Then

ActiveCell = 100

End If

End Sub


二者执行方法最大的地方,在于 Worksheet_SelectionChange() 是自动的,你不用了解他是怎么完成工作的。

按钮 CommandButton1_Click() 是人工的,比 SelectionChange()多一道手续,就是要去按那接钮,程序才会执行。

SelectionChange() 有一个参数 Target 可用;CommandButton1_Click ()没有。

所以我们要用 ActiveCell 内定函数来取代Target,ActiveCell 与 Target最大的不同点他只能指定一个单元格。

就是你选取多个单元格也只有最上面的单元格会加上数据;用 Selection 取代 ActiveCell, 用法就跟 Target 一样了。


VBALesson 6 程序说明:

完整的 If...Then ┅ End 逻辑判断式。

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

If Target.Row >= 2 And Target.Column = 2 Then

Target = 200

ElseIf Target.Row >= 2 And Target.Column = 3 Then

Target = 300

ElseIf Target.Row >= 2 And Target.Column = 2 Then

Target = 400

Else

Target = 500

End If

End Sub


这是个完整的 If 逻辑判断式,意思是说,假如 If 後的判断式条件成立的话,就执行第二条程序,否则假如 ElseIf 後的判断式条件成立的话,就执行第四条程序,否则假如另一个 ElseIf 後的判断式条件成立的话,就执行第六条程序。

Else 的意思是说,假如以上条件都不成立的话,就执行第八条程序。

他的执行方式是假如 IF 的条件成立的话,就不执行其它ElseIf 及Else 的逻辑判断式,假如 If 後的条件不成立的话才会执行 ElseIf 或 Else 逻辑判断式。第二个 ElseIf後的条件因为与 IF 後的条件一样,所以这个判断式後面的 Target=400 将是永远无法执行到的程序。


VBALesson 7 程序说明∶我们为什麽要用变数。


Private Sub Worksheet_SelectionChange(ByVal Target As Range)

Dim i , j As Integer

Dim k As Range

i = Target.Row

j = Target.Column

Set k = Target

If i >= 2 And j = 2 Then

k = 200

ElseIf i >= 2 And j = 3 Then

k = 300

ElseIf i >= 2 And j = 4 Then

k = 400

Else

k = 500

End If

End Sub


跟VBALesson 6比较,程序是不是明朗多了,在前课重复的用 Target.Row,Target.Column及Target来写程序是不是有一点烦。用变量的第一个好处大家马上感觉得出来,就是可以简化程序。

使用变量前,你得先宣告变量。宣告变量的方法是在 "Dim " 后面写上变量 " i " As 后面接上变量的形态 "Integer"。

Dim i , j As Integer 就是宣告 i 与 j 为整数变量,这是同时宣告二个变量 i 与 j 所以要在二个变量间加个 " , "号。

Dim k As Range 是宣告 k 为范围资料形态,Range这是 Excel 特有的资料形态。

i = Target.Row是把当前单元格的行数,指定给变量 i。

j = Target.Column 是把当前单元格的栏数,指定给变量 j。

Set k = Target 是把当前的单元格,指定给变量 k。

用像 i 与 j 这样简单的变量,在程序的前面你可能还记得 i 或 j 代表着什厶。程序写长了,你可能忘记 i 或 j 代表着什厶。所以最好的方法是用比较有意义的代号,来为变量命名如 iRow 或 iCol 来取代 i 及 j 。


VBALesson 8 程序说明∶体会一下Worksheet_Change()事件。


Private Sub Worksheet_Change(ByVal Target As Range)

Dim iRow, iCol As Integer

iRow = Target.Row

iCol = Target.Column

If iRow >= 2 And iCol = 2 And Target <> "" Then

Application.EnableEvents = False

Cells(iRow, iCol + 1) = Cells(iRow, iCol) * 2

Application.EnableEvents = True

ElseIf iRow >= 2 And iCol = 2 And Target = "" Then

Cells(iRow, iCol + 1) = ""

Else

Cells(iRow, iCol + 1) = ""

End If

End Sub


前几个教程都是用Worksheet_SelectionChange 事件来举例子,大家应该能体会他是怎厶一回事了吧。

这个教程就是要让你来体会什厶是Worksheet_Chang()事件。因为这二个事件在VBA都是非常有用的,所以一定要了解。

简单的说,前者是你鼠标移动到那个单元格,就触发那个事件的执行。後者是要等到你点选的单元格,数 有了改变才会触发事件的执行。二者执行的时机一前一後。

Target <> "" 是代表限定当前的单元格要是有数 的,才会执行以下三行的程序。

Cells(iRow, iCol + 1) = Cells(iRow, iCol) * 2,是你在 B 栏输入数 时,C 栏将可得到 B 栏二倍的数 。

Target = "" 是限定当前的单元格要是没有数 的,才会执行以下一行的程序。

Cells(iRow, iCol + 1) = "",是把 C 栏的数 清成空格。

Application.EnableEvents = False与Application.EnableEvents = True,这是个成双的程序,当你用了前者记得在执行其他程序後要写上後面的程序。它的目的在抑制事件连锁执行。简单的说就是,在 B 字段所触发的事件,不愿在其它单元格再触发另一个Worksheet_Change()事件。


VBALesson 9 程序说明∶体会一下Worksheet_Change()事件连锁反应。


Private Sub Worksheet_Change(ByVal Target As Range)

Dim iRow As Integer

iRow = Target.Row

Application.EnableEvents = False

Cells(iRow, 3) = Cells(iRow, 3) + Cells(iRow, 2)

Application.EnableEvents = True

End Sub


Private Sub Worksheet_Change(ByVal Target As Range)

Dim iRow As Integer

iRow = Target.Row

'Application.EnableEvents = False

Cells(iRow, 3) = Cells(iRow, 3) + Cells(iRow, 2)

'Application.EnableEvents = True

End Sub


这个程序的目的是要在 B2 输入新的数 时,C2 会将 B2 输入的新数 加上 C2 原有的数 呈现在 C2 上。

照上面有加上 Application.EnableEvents = False 程序执行当然没问题。

现在你在 Application.EnableEvents = False 与 Application.EnableEvents = True 前加上「 '」看看。

程序前加上「 '」的目的是要使「 '」之后的文字变成说明文字,程序执行时是会跳过说明文字,不执行说明文字的内容。

程序前加上「 '」符号后,文字会变成绿色。

执行第二个程序时,你将发现 C2 不会按你所要求的,呈现结果。

这就是所谓的事件连锁反应。


请问这个宏该如何写!

我想运行一个宏,就能在当前工作表B3上填上一条公式;这条公式的结果是所有工作

表上的B4单元格的和.请问这个宏该如何写.谢谢!

Sub gg()

Dim sh As Worksheet, shname$

For Each sh In Worksheets

shname = sh.Name

ActiveSheet.Range("b3").value = ActiveSheet.Range("b3").value + Worksheets(shname).Range("b4")

Next

End Sub


VBA中怎样创建一个名为“table”的新工作表

通过VBA编程,很容易添加新的工作表,但是新表的名字不知怎样控制,对于新创建的工作表,由于其名字并非特定,所以就不好使用所创建的新表了。不知各位有何高见。。。。

Sheets.Add

ActiveSheet.Name = "table"


请教:如何用VBA检索表1中A列与表2,3,4,5.....中A列相同的行并把后者整行拷贝到表1检索到的行中,谢谢!!!!

To yxptwq∶用这程序试看看。

Sub Copy1()

Dim Row_dn1, Row_dnN, i, j, n As Integer

Row_dn1 = Sheet1.Range("A65536").End(xlUp).Row

k = 1: n = 1

For Each wSheet In ActiveWorkbook.Worksheets

With wSheet

If .Name <> "Sheet1" Then

Row_dnN = .Range("A65536").End(xlUp).Row

For i = 2 To Row_dn1

For j = 2 To Row_dnN

If .Cells(j, 1) = Sheet1.Cells(i, 1) Then

.Rows(j & ":" & j).Copy Destination:=Sheet1.Rows(Row_dn1 + n & ":" & Row_dn1 + n)

n = n + 1

End If

Next j

Next i

End If

End With

Next wSheet

End Sub


如果要用VBA程式输入密码使用下列程式码


Sub EnterNewPW()

'程式说明:利用SendKey输入VBAProject密码

'注意事项:执行本程式需要在Excel视窗,不能在VBE视窗

Application.SendKeys "%{F11}", True 'Alt + F11 切换到VBA视窗

Application.SendKeys "%T", True 'ALT + T 工具(繁体中文是(T))

Application.SendKeys "e", True '工具(T)-VBproject属性(E)

Application.SendKeys "^{TAB}", True 'TAB 键(切换到PAge2 保护页面)

Application.SendKeys "{+}", True '选取Checkbox方块(锁定专案以供检视)

'({+} 选取, {-} 取消选取)

Application.SendKeys "{TAB}", True 'TAB 键(跳到第一次输入密码 Textbox

myPW = "chijanzen" '假设密码 chijanzen

Application.SendKeys myPW, True '输入密码

Application.SendKeys "{TAB}", True 'TAB 键(跳到第二次输入密码 Textbox

Application.SendKeys myPW, True '输入密码

Application.SendKeys "{ENTER}", True '按确定钮(预设值)

Application.SendKeys "%{F11}", True '返回Excel视窗

End Sub


冒泡排序法:

冒泡排序法之所以成为“冒泡排序”是因为值较小的或是较轻的元素浮到作为继续排序的一组数的顶部。

Sub Macro1()

Dim i As Integer

Dim j As Integer

Dim t as integer

Static number(1 To 10) As Integer

For i = 1 To 10

number(i) = inputbox“输入要排序的数:”

Next i


For i = 10To 2 Step -1

For j = 1 To i – 1

‘下面进行位置交换

If number(j) > number(j + 1) Then

t = number(j + 1)

number(j + 1) = number(j)

number(j) = t

End If


Next j

Next i


For i = 1 To 20

Print number(i)

Next i

End sub


首先定义一个数组:通过循环录入10个整数,然后用一个二重循环测试前一个数是否大于后一个数。如果大于则交换两个数的下标,即交换两个数在数组中的位置,交换通过一个变量来进行。


我先用传统的方法解决这个问题,经过比较,选用了较为简单的和高效的排序方法

——“快速排序”,具体算法可参考数据结构等有关书籍。对所有数据排序后再合

并相同数据,合并程序较为简便,我开始时采用了这种方法,但后来发现对于这些

的数据,先合并后排序速度更快,因为有大量相同的数据。合并是采用“标记”算

法,具体如下:(设数据已存放在sData()数组中 ,结果存到Queryp()数组,

Amount是数据个数)

'把相同元素置 0

For i = 1 To Amount

If sData(i) <> 0 Then

For j = i + 1 To Amount


If sData(i) = sData(j) Then sData(j) = 0

Next j

End If

Next i

'删除相同元素

Queryp(1) = sData(1)

k = 1

For i = 2 To Amount

If Not (sData(i) = 0) Then

k = k + 1

Queryp(k) = sData(i)

End If

Next i

kMax = k

ReDim Preserve Queryp(kMax)

虽然这样使得运算速度有所高,但是仍然要进行大量的循环运算,占据了程序大部

分的运算时间。于是我一直在寻觅一种更为高效的算法。

功夫不负有心人,在仔细分析数据的特征,比较了多种方案之后,我终于找到了一

种相当成功的算法,原来要3到4秒的运算缩短到仅需0.1到0.2秒。

我遇到的数据具有以下特征:①相同数据很多,②最大、最小数之间相差不到3,

③都是带两位小数的正数。

针对数据的特征,我采用了以下算法:

针对数据的特征,我采用了以下算法:

步骤:

1. 用一个循环找出整数和小数部分的最大、最小值。小数部分的最大、最小值乘

以100转为整数。

2. 定义一个二维数组,下标范围分别是整数和小数部分的最小值到最大值。

3. 再用一个循环把所有源数据填入刚才定义的二维数组,填写规则是,源数据的

整数和小数部分分别对应二维数组的两个下标。例如,“13.51"填到“A(13,51)"

中。

4. 最后顺向或逆向读取二维数组中的非零数据即可得到从小到大或从大到小排列

的数据,而且不会含有重复数据。

用VB 编写的程序如下:

'****密集型数据处理****

Dim i As Long, j As Long, k As Long, kMax As Long

Dim Queryp() As Single

ReDim Queryp(Amount)

Dim IntegerPart As Integer, DecimalPart As Integer

Dim IPmax As Integer, IPmin As Integer

Dim DPmax As Integer, DPmin As Integer

Dim DiffDataArray()

'读取数据

ReadData

IPmax = 0: IPmin = 1000

DPmax = 0: DPmin = 99


For i = 1 To Amount

' 找整数和小数部分的最大、最小值

IntegerPart = Int(sData(i))

DecimalPart = (sData(i) - IntegerPart) * 100

If IntegerPart > IPmax Then

IPmax = IntegerPart

ElseIf IntegerPart < IPmin Then

IPmin = IntegerPart

End If

If DecimalPart > DPmax Then

DPmax = DecimalPart

ElseIf DecimalPart < DPmin Then

DPmin = DecimalPart

End If

Next i

ReDim DiffDataArray(IPmin To IPmax, DPmin To DPmax)

'填入数据

For i = 1 To Amount

IntegerPart = Int(sData(i))

DecimalPart = (sData(i) - IntegerPart) * 100

DiffDataArray(IntegerPart, DecimalPart) = sData(i)

Next i

Next i

'提取数据

k = 0

For i = IPmax To IPmin Step -1

For j = DPmax To DPmin Step -1

If DiffDataArray(i, j) <> 0 Then

k = k + 1

Queryp(k) = DiffDataArray(i, j)

End If

Next j

Next i

kMax = k

ReDim Preserve Queryp(kMax)

该方法对于本人遇到的这种“密集型”数据最为有效,但是如果遇上“稀疏型”数

据,例如最大、最小值相差几千,甚至上万的数据,就没什么优势了,而且会占用

较大的内存。

经过改进,我得到了处理稀疏型数据的高效算法。高效的前提条件同样是源数据具

有大量相同数据。思路是在前一种方法的基础上增加一个单维数组,用来保存整数

部分数据,保存过程中用插入法对其进行排序。因为有大量重复数据,要排序的数

据量相对较少。当从二维数组中读取数据时,用单维数组代入二维数组的第一个下

标,具体代码下:

'****稀疏型数据处理****

Dim i As Long, j As Long, k As Long, kMax As Long


Dim Queryp() As Single

ReDim Queryp(Amount)

Dim IntegerPart As Integer, DecimalPart As Integer

Dim IPmax As Integer, IPmin As Integer

Dim DPmax As Integer, DPmin As Integer

Dim IPArray() As Integer, IPAamount As Integer

ReDim IPArray(Amount)

Dim DiffDataArray()

'读取数据


ReadData

IPmax = 0: IPmin = 1000

DPmax = 0: DPmin = 99

IPAamount = 0

For i = 1 To Amount

'获取整数和小数部分的最大最小值

IntegerPart = Int(sData(i))

DecimalPart = (sData(i) - IntegerPart) * 100

If IntegerPart > IPmax Then

IPmax = IntegerPart

ElseIf IntegerPart < IPmin Then

IPmin = IntegerPart

IPmin = IntegerPart

End If

If DecimalPart > DPmax Then

DPmax = DecimalPart

ElseIf DecimalPart < DPmin Then

DPmin = DecimalPart

End If

'对整数部分"IPArray()"进行插入法排序 (从大到小)

For j = 1 To IPAamount

If IntegerPart > IPArray(j) Then

IPAamount = IPAamount + 1

For k = IPAamount To j + 1 Step -1

IPArray(k) = IPArray(k - 1)

Next k

IPArray(j) = IntegerPart

Exit For

ElseIf IntegerPart = IPArray(j) Then

Exit For

End If

Next j

If j > IPAamount Then

IPAamount = IPAamount + 1

IPArray(IPAamount) = IntegerPart


End If

Next i

ReDim DiffDataArray(IPmin To IPmax, DPmin To DPmax)

'填入数据

For i = 1 To Amount

IntegerPart = Int(sData(i))

DecimalPart = (sData(i) - IntegerPart) * 100

DiffDataArray(IntegerPart, DecimalPart) = sData(i)

Next i

'提取数据

k = 0

For i = 1 To IPAamount

For j = DPmax To DPmin Step -1

If DiffDataArray(IPArray(i), j) <> 0 Then

k = k + 1

Queryp(k) = DiffDataArray(IPArray

(i), j)

End If

Next j

Next i

kMax = k

ReDim Preserve Queryp(kMax)

k

ReDim Preserve Queryp(kMax)

具体采用哪种算法,要看数据的性质而定,以下是本人的一些实测数据,仅供参考

。如果你有更好的方法,可不要忘记和朋友们分享哦 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值