VBA常用技巧
目录
VBA常用技巧 ................................................................................................................................... 1
第8章 控件与用户窗体 ................................................................................................... 4
技巧1 文本框的输入 ........................................................................................... 4 技巧2 文本框添加右键快捷菜单 ............................................................................... 6 技巧3 文本框回车自动输入 ..................................................................................... 10 技巧4 自动选择文本框内容 ..................................................................................... 11 技巧5 设置文本框数据格式 ..................................................................................... 12 技巧6 文本框的输入长度 ................................................................................. 14 技巧7 将光标返回文本框中 ..................................................................................... 15 技巧8 文本框的自动换行 ......................................................................................... 17 技巧9 多个文本框数据相加 ..................................................................................... 19 技巧10 控件跟随活动单元格 ................................................................................... 20 技巧11 高亮显示按钮 ............................................................................................... 21 技巧12 组合框和列表框添加列表项的方法 ........................................................... 23
12-1 使用RowSource属性添加列表项 ............................................................ 23 12-2 使用List属性添加列表项 ........................................................................ 24 12-3 使用AddItem方法添加列表项 ................................................................ 25 技巧13 去除列表框数据源的重复值和空格 ........................................................... 27 技巧14 移动列表框条目 ........................................................................................... 29 技巧15 允许多项选择的列表框 ............................................................................... 32 技巧16 多列组合框和列表框的设置 ....................................................................... 35
16-1 多列组合框和列表框添加列表项 ............................................................. 35 16-2 多列列表框写入工作表 ............................................................................. 37 技巧17 输入时逐步提示信息 ................................................................................... 39 技巧18 二级组合框 ................................................................................................... 46 技巧19 使用DTP控件输入日期 ............................................................................. 48 技巧20 使用RefEdit控件选择区域 ........................................................................ 51 技巧21 如何注册控件 ............................................................................................... 52 技巧22 遍历控件的方法 ........................................................................................... 55
22-1 使用名称中的变量遍历控件 ..................................................................... 55 22-2 使用对象类型遍历控件 ............................................................................. 57 22-3 使用程序标识符遍历控件 ......................................................................... 58 22-4 使用名称中的变量遍历图形 ..................................................................... 59 22-5 使用FormControlType属性遍历图形 ...................................................... 60 技巧23 使微调框最小变动量小于1 ........................................................................ 61 技巧24 不打印工作表中的控件 ............................................................................... 63
24-1 设置控件格式 ............................................................................................ 63 24-2 设置控件的printobjcet属性 ..................................................................... 65
1
VBA常用技巧代码解析
技巧25 技巧26 技巧27 技巧28 技巧29 技巧30 技巧31
31-1 31-2 技巧32
32-1 32-2 技巧33 技巧34
34-1 34-2 34-3 34-4 34-5 技巧35 技巧36
36-1 36-2 技巧37 技巧38 技巧39 技巧40 技巧41 技巧42 技巧43 技巧44 技巧45 技巧46 技巧47 技巧48 技巧49
49-1 49-2 技巧50 技巧51 技巧52 技巧53 技巧54
54-1
在框架中使用滚动条 ................................................................................... 65 使用多页控件 ............................................................................................... 67 标签文字垂直居中对齐 ............................................................................... 69 使用TabStrip控件 ....................................................................................... 71 显示GIF动画图片 ...................................................................................... 73 播放Flash文件 ............................................................................................ 76 在工作表中添加窗体控件 ........................................................................... 78 使用AddFormControl方法 ....................................................................... 79 使用Add方法 ............................................................................................ 81 在工作表中添加ActiveX控件 ................................................................... 83 使用Add方法 ............................................................................................ 84 使用AddOLEObject方法 ......................................................................... 86 使用spreadsheet控件 .................................................................................. 87 使用Listview控件 ....................................................................................... 90 使用Listview控件显示数据列表 ............................................................. 90 在Listview控件中使用复选框 ................................................................. 93 调整Listview控件的行距 ......................................................................... 95 在Listview控件中排序 ............................................................................. 98 Listview控件的图标设置 ........................................................................... 99 调用非模式窗体 ......................................................................................... 102 进度条的制作 ............................................................................................. 104 使用进度条控件 ...................................................................................... 104 使用标签控件 .......................................................................................... 106 使用TreeView控件显示层次 ................................................................... 109 用户窗体添加图标 ..................................................................................... 113 用户窗体添加最大最小化按纽 ................................................................. 115 禁用窗体标题栏的关闭按钮 ..................................................................... 116 屏蔽窗体标题栏的关闭按钮 ..................................................................... 117 无标题栏和边框的窗体 ............................................................................. 119 制作年月选择窗体 ..................................................................................... 120 自定义窗体中的鼠标指针类型 ................................................................. 123 调整窗体的显示位置 ................................................................................. 124 由鼠标确定窗体显示位置 ......................................................................... 126 用户窗体的打印 ......................................................................................... 127 使用自定义颜色设置窗体颜色 ................................................................. 129 在窗体中显示图表 ..................................................................................... 130 使用Export方法 ...................................................................................... 130 使用API函数 .......................................................................................... 132 窗体运行时调整控件大小 ......................................................................... 133 在用户窗体上添加菜单 ............................................................................. 136 在用户窗体上添加工具栏 ......................................................................... 140 使用代码添加窗体及控件 ......................................................................... 145 用户窗体的全屏显示 ................................................................................. 151 设置用户窗体为应用程序的大小 ........................................................... 151
2
VBA常用技巧代码解析
54-2 根据屏幕分辨率进行设置 ....................................................................... 152 技巧55 在用户窗体上添加状态栏 ......................................................................... 153
3
VBA常用技巧代码解析
第8章 控件与用户窗体
技巧1 文本框的输入
用户在使用文本框输入数据时,往往希望能输入数据的类型,比如只能输入数字。但是没有内置的属性能在文本框中只能输入数字,只能在文本框的事件过程中使用代码来测试输入的是哪类字符,然后只允许输入数字字符和一个“-”号、一个“.”号,如下面的代码所示。
#001 Private Sub TextBox1_KeyPress(ByVal KeyANSI As MSForms.ReturnInteger) #002 Select Case KeyANSI
#003 Case Asc(\"0\") To Asc(\"9\") #004 Case Asc(\"-\")
#005 If InStr(1, Me.TextBox1.Text, \"-\") > 0 Or _ #006 Me.TextBox1.SelStart > 0 Then #007 KeyANSI = 0 #008 End If #009 Case Asc(\".\")
#010 If InStr(1, Me.TextBox1.Text, \".\") > 0 Then #011 KeyANSI = 0 #012 End If #013 Case Else #014 KeyANSI = 0 #015 End Select #016 End Sub
代码解析:
文本框的KeyPress事件过程,测试键盘输入的是哪类字符,只允许输入数字字符和一个“-”号、一个“.”号。
4
VBA常用技巧代码解析
KeyPress事件的语法如下:
Private Sub object_KeyPress( ByVal KeyANSI As MSForms.ReturnInteger)
参数Object是必需的,一个有效的对象。
参数KeyANSI是可选的,整数值,代表标准的数字ANSI 键代码。
第2行代码使用Case Else语句测试文本框KeyPress事件的KeyANSI参数值。 第3行代码,如果键盘输入的是0到9之间的数字字符,则允许输入。如果想在文本框中允许其它类型的字符输入,在此句代码中列出允许输入的字符即可。
第4行到第8行代码,如果键盘输入的是“-”号,先使用InStr函数测试文本框中是否已有“-”号,如果InStr函数返回值大于0,说明文本框中已有“-”号。接下来使用文本框的SelStart 属性来测试插入点,如果文本框的SelStart 属性值大于0,说明“-”号的插入点不是第一个。如果以上两个条件中有任何一个成立,将KeyAscii参数值设置为0,使文本框只能在第一位输入一个“-”号。
第9行到第12行代码,如果键盘输入的是“.”号的话,使用InStr函数测试文本框中是否已有“.”号,如果已有“.”号,将KeyAscii参数值设置为0,使文本框只能输入一个“.”号。
第13、14行代码,如果键盘输入的是其他字符则将KeyAscii参数值设置为0,使文本框不能输入其他字符。
经过以上设置文本框只允许输入数字字符和一个“-”号、一个“.”号,但是能输入中文字符。如果希望中文字符的输入,可以在文本框的Change事件中进行设置,如下面的代码所示。
#001 Private Sub TextBox1_Change() #002 Dim i As Integer #003 Dim s As String #004 With TextBox1
#005 For i = 1 To Len(.Text) #006 s = Mid(.Text, i, 1) #007 Select Case s
#008 Case \".\#009 Case Else
#010 .Text = Replace(.Text, s, \"\") #011 End Select #012 Next #013 End With
5
VBA常用技巧代码解析
#014 End Sub
代码解析:
文本框的Change事件,判断输入的字符是否为数字字符和“-”号、“.”号,如果不是则使用Replace函数将文本框中输入的其他字符替换成空白。
第5、6行代码在文本框输入的所有字符中循环。
第8行代码列出允许输入的字符。如果想在文本框中允许其它字符输入,在此句代码中列出即可。
第9、10行代码,如果不是允许输入的字符,使用Replace函数替换成空白。 经过以上的设置,文本框中只能在第一位输入一个“-”号、一个“.”号和“0”到“9”的数字。
技巧2 文本框添加右键快捷菜单
VBA中的控件没有提供右键快捷菜单,用户可以使用Excel 中的命令栏自已添加右键快捷菜单。
步骤1:按 #001 Private ActiveTB As MSForms.TextBox #002 Public Sub CreateShortCutMenu() #003 Dim ShortCutMenu As CommandBar #004 Dim ShortCutMenuItem As CommandBarButton #005 Dim sCaption As Variant #006 Dim iFaceId As Variant #007 Dim sAction As Variant #008 Dim i As Integer #009 sCaption = Array(\"剪切(&C)\复制(&T)\贴粘(&P)\删除(&D)\") #010 iFaceId = Array(21, 19, 22, 1786) #011 sAction = Array(\"Action_Cut\\"Action_Copy\\"Action_Paste\\"Action_Delete\") 6 VBA常用技巧代码解析 #012 On Error Resume Next #013 Application.CommandBars(\"ShortCut\").Delete #014 Set ShortCutMenu = Application.CommandBars.Add(\"ShortCut\msoBarPopup) #015 With ShortCutMenu #016 For i = 0 To 3 #017 Set ShortCutMenuItem = .Controls.Add(msoControlButton) #018 With ShortCutMenuItem #019 .Caption = sCaption(i) #020 .faceID = Val(iFaceId(i)) #021 .OnAction = sAction(i) #022 End With #023 Next #024 End With #025 End Sub 代码解析: 第1行代码,在模块级别中声明变量ActiveTB是用来对应窗体中的文本框所触发的所有事件的变量。 CreateShortCutMenu过程用来创建标题为“ShortCut”的右键快捷菜单,并添加4个菜单项。关于自定义右键快捷菜单请参阅错误!未找到引用源。。 #001 Public Sub ShowPopupMenu(txtCtr As MSForms.TextBox) #002 Dim Action As Variant #003 Set ActiveTB = txtCtr #004 With Application.CommandBars(\"ShortCut\") #005 .Controls(1).Enabled = txtCtr.SelLength > 0 #006 .Controls(2).Enabled = .Controls(1).Enabled #007 .Controls(3).Enabled = txtCtr.CanPaste #008 .Controls(4).Enabled = .Controls(1).Enabled #009 .ShowPopup #010 End With #011 End Sub 代码解析: 7 VBA常用技巧代码解析 ShowPopupMenu过程根据文本框中字符的选中状态设置右键快捷菜单菜单项的Enabled属性后使用ShowPopup方法显示右键快捷菜单。 第5行代码,如果当前文本框中已有选中的字符则“剪切”按钮有效。 第6行代码,如果当前文本框中已有选中的字符则“复制”按钮有效。 第7行代码,如果剪贴板中包含对象支持的数据。则“贴粘”按钮有效。 第8行代码,如果当前文本框中已有选中的字符则“删除”按钮有效。 第9行代码,显示快捷菜单。 #001 Public Sub Action_Cut() #002 ActiveTB.Cut #003 End Sub #004 Public Sub Action_Copy() #005 ActiveTB.Copy #006 End Sub #007 Public Sub Action_Paste() #008 ActiveTB.Paste #009 End Sub #010 Public Sub Action_Delete() #011 Dim s As String #012 With ActiveTB #013 s = .SelText #014 .Value = Replace(.Value, s, \"\") #015 End With #016 End Sub 代码解析: Action_Cut过程是快捷菜单中单击“剪切”菜单项所运行的过程。使用Cut 方法将当前选中的文本框中的文本删除并移至剪贴板。 Action_Copy过程是快捷菜单中单击“复制”菜单项所运行的过程。使用Copy方法将文本框选中的文本复制到剪贴板上。 Action_Paste过程是快捷菜单中单击“贴粘”菜单项所运行的过程。使用Paste方法把剪贴板上的内容传送到一个文本框中。 Action_Delete过程是快捷菜单中单击“贴粘”菜单项所运行的过程。使用Replace函数将文本框中选中的文本的文本替换成空字符。 #001 Public Sub DeleteShortCutMenu() 8 VBA常用技巧代码解析 #002 On Error Resume Next #003 Application.CommandBars(\"ShortCut\").Delete #004 End Sub 代码解析: DeleteShortCutMenu过程删除创建的右键快捷菜单。 步骤2:在VBE窗口中,单击菜单“插入”→“用户窗体”,在窗体上添加两个文本框控件。双击窗体,在其代码窗口中输入下面的代码。 #001 Private Sub UserForm_Initialize() #002 Call CreateShortCutMenu #003 End Sub #004 Private Sub TextBox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) #005 If Button = 2 Then ShowPopupMenu ActiveControl #006 End Sub #007 Private Sub TextBox2_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) #008 If Button = 2 Then ShowPopupMenu ActiveControl #009 End Sub #010 Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) #011 Call DeleteShortCutMenu #012 End Sub 代码解析: 第1行到第3行代码,窗体的Initialize事件,在窗体初始化时运行CreateShortCutMenu过程创建右键快捷菜单。 第4行到第9行代码,文本框的MouseUp事件,当用户右健单击文本框时运行ShowPopupMenu过程在选中的菜单项上显示右键快捷菜单。 第10行到第12行代码,窗体的QueryClose事件,在关闭窗体时运行DeleteShortCutMenu过程删除右键快捷菜单。 窗体运行后,右键单击文本框显示右键快捷菜单,如图 2-1所示。 9 VBA常用技巧代码解析 图 2-1 文本框快捷菜单 技巧3 文本框回车自动输入 在使用文本框向工作表输入数据时,为了加快输入速度,可以利用文本框的KeyDown事件,回车后自动输入并清空文本框,如下面的代码所示。 #001 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) #002 With TextBox1 #003 If Len(Trim(.Value)) > 0 Then #004 If KeyCode = vbKeyReturn Then #005 Sheet1.Range(\"A65536\").End(xlUp).Offset(1, 0) = .Value #006 .Text = \"\" #007 End If #008 End If #009 End With #010 End Sub 代码解析: 文本框的KeyDown事件,在输入数据并按 KeyDown事件在按下键盘按键时发生,语法如下: Private Sub object_KeyDown( ByVal KeyCode As MSForms.ReturnInteger, ByVal 10 VBA常用技巧代码解析 Shift As fmShiftState) 参数object是必需的,一个有效的对象。 参数KeyCode是必需的,代表被按下的键的键代码。 参数Shift是可选的,Shift、Ctrl 和Alt的状态。 第3行代码,为了防止误输入空白数据,使用Len 函数和Trim 函数检查文本框内是否为有效数据。 第4行代码,根据KeyCode参数值判断是否按下了回车键。如果用户按下了回车键,KeyCode参数返回常数vbKeyReturn。 第5、6行代码,将文本框数据输入到工作表A列的最后一个单元格内,同时清空文本框内容准备下一次输入。 技巧4 自动选择文本框内容 如果希望光标进入文本框时能自动选择文本框内容,可以在文本框的MouseUp事件中来完成,如下面的代码所示。 #001 Private Sub TextBox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) #002 With TextBox1 #003 If Button = 2 Then #004 .SelStart = 0 #005 .SelLength = Len(.Text) #006 End If #007 End With #008 End Sub 代码解析: 文本框的MouseUp事件,在光标进入文本框释放鼠标右键时自动选择文本框内容。 MouseUp事件在用户释放鼠标按键时发生,语法如下: Private Sub object_MouseUp( ByVal Button As fmButton, ByVal Shift As fmShiftState, ByVal X As Single, ByVal Y As Single) 11 VBA常用技巧代码解析 参数object是必需的,一个有效的对象。 参数Button是可选的,设置引起该事件的鼠标按键的整数值,如表格 4-1所示。 常数 fmButtonLeft fmButtonRight fmButtonMiddle 值 1 2 3 说明 按下左键。 按下右键。 按下中键。 表格 4-1 Button参数值 参数Shift是可选的,Shift、Ctrl 和Alt的状态。 参数X和参数Y是可选的,窗体、框架或页的位置的横坐标与纵坐标。 第3行到第6行代码,如果用户进入文本框释放鼠标右键,设置文本框的SelStart 属性为0,SelLength属性为文本框的全部字符数。 SelStart 属性指定选中文本的起点,语法如下: object.SelStart [= Long] 参数object是必需的,一个有效的对象。 参数Long是可选的,指定选中文本的起点。 SelLength 属性指定文本框或组合框的文本部分中选中的字符数,语法如下: object.SelLength [= Long] 参数object是必需的,一个有效的对象。 参数Long是可选的,指定选中的字符数。 运行窗体,当光标进入文本框释放鼠标右键时自动选择文本框内容,如图 4-1所示。 图 4-1 自动选择文本框内容 技巧5 设置文本框数据格式 12 VBA常用技巧代码解析 文本框在用来输入数据时,除了输入的数据类型外,还可以设置文本框的数据格式,如下面的代码所示。 #001 Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean) #002 TextBox1 = Format(TextBox1, \"0.00\") #003 End Sub #004 Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean) #005 TextBox2 = Format(TextBox2, \"0.00\") #006 End Sub 代码解析: 文本框的Exit事件过程,在文本框输入数据时使用Format函数格式化为两位小数格式。 控件的Exit事件在同一窗体中的一个控件即将把焦点转移到另一个控件之前发生,语法如下: Private Sub object_Exit( ByVal Cancel As MSForms.ReturnBoolean) 参数Object是必需的,一个有效的对象。 参数Cancel是必需的,事件状态。如果设置为False表示由该控件处理这个事件(默认方式)。设置为True表示由应用程序处理这个事件,并且焦点留在当前控件上。 当文本框在输入完数据失去焦点时使用Format函数格式化自定义数值格式。Format函数语法如下: Format(expression[, format[, firstdayofweek[, firstweekofyear]]]) 参数expression是必需的,任何有效的表达式。 参数format是可选的,有效的命名表达式或用户自定义格式表达式。 参数firstdayofweek是可选的,常数,表示一星期的第一天。 参数firstweekofyear是可选的,常数,表示一年的第一周。 在本例中,将文本框的数据格式化成自定义的两位小数的数值格式,关于Format函数格式化日期和时间等其他数据请参阅VBA中Format函数的帮助。 #001 Private Sub TextBox1_Change() #002 TextBox3 = Format(Val(TextBox1) * Val(TextBox2), \"0.00\") #003 End Sub #004 Private Sub TextBox2_Change() #005 TextBox3 = Format(Val(TextBox1) * Val(TextBox2), \"0.00\") #006 End Sub 代码解析: 文本框的Change事件过程,在两个文本框输入完数据后,使用文本框的Change事件 13 VBA常用技巧代码解析 使TextBox3显示其相乘的金额并格式化为两位小数的数据格式。 Change事件在控件的 Value 属性改变时发生,语法如下: Private Sub object_Change( ) 参数object是必需的,一个有效的对象。 Change事件过程可以使显示在控件上的数据同步或一致。在本例中,当TextBox1或TextBox2的数据发生改变时,两者相乘的金额的金额也随之改变并在TextBox3中显示。 因为文本框的数据类型是文本字符串,不能直接进行计算的,所以计算前先使用Val函数转换为数字,才能进行计算。 运行窗体,输入数据后格式化为两位小数的数据格式,如图 5-1所示。 图 5-1 设置文本框的数据格式 技巧6 文本框的输入长度 在使用文本框输入数据时,可能希望能输入的字符长度,即只能输入一定长度的字符,超过设置数值就不能输入,这时可以通过设置文本框的MaxLength属性来实现,如下面的代码所示。 #001 Private Sub Worksheet_Activate() #002 Me.TextBox1.MaxLength = 6 #003 End Sub 代码解析: 工作表的激活事件过程,将文本框的MaxLength属性设置为6,使文本框只能输入6个字符,超过6个字符即不能输入。 应用于文本框控件的MaxLength属性规定用户可以在文本框中输入的最多字符数,语 14 VBA常用技巧代码解析 法如下: object.MaxLength [= Long] 参数object是必需的,一个有效的对象。 参数Long是可选的,整数,表示所允许的字符数。 如果将MaxLength属性设置为0,表示只要内存允许则没有。 技巧7 将光标返回文本框中 在用文本框往工作表录入数据时,一般会在录入到工作表前验证输入的数据是否正确,如果错误,则清空文本框内容,提示用户重新输入。但此时光标已经不在文本框中,需要重新选择文本框才能输入。 可以在Exit事件中可以设置Cancel参数值使光标停留在当前文本框中,如下面的代码所示。 #001 Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean) #002 With TextBox1 #003 If .Text <> \"\" And Len(Trim(.Text)) <> 15 And Len(Trim(.Text)) <> 18 Then #004 .Text = \"\" #005 MsgBox \"身份证号码录入错误!\" #006 Cancel = True #007 End If #008 End With #009 End Sub 代码解析: 文本框的Exit事件,在输入身份证号码后即将把焦点转移到录入按钮控件之前检查输入的身份证号码是否正确。 Exit事件在一个控件从同一窗体的另一个控件实际接收到焦点之前发生,语法如下: Private Sub object_Exit( ByVal Cancel As MSForms.ReturnBoolean) Cancel参数为事件状态。False表示由该控件处理这个事件(这是默认方式)。True表 15 VBA常用技巧代码解析 示由应用程序处理这个事件,并且焦点应当留在当前控件上。 第3行代码,使用Len函数和Trim函数检查输入的身份证号码是否为15位或18位。 第4行到第6行代码,如果输入的身份证号码不正确,清空文本框以便重新输入并提示用户,设置Cancel参数为True使光标停留在文本框中。 在Exit事件中之所以把文本框为空也做为通过验证的条件之一,因为如果不加上“TextBox1.Text <> \"\"”这一条件,那么在窗体显示后,如果用户取消输入或关闭输入窗体,也会提示输入错误。所以在录入到工作表之前再验证文本框是否为空,如下面的代码所示。 #001 Private Sub CommandButton1_Click() #002 With TextBox1 #003 If .Text <> \"\" Then #004 Sheet1.Range(\"a65536\").End(xlUp).Offset(1, 0) = .Text #005 .Text = \"\" #006 Else #007 MsgBox \"请输入身份证号码!\" #008 End If #009 .SetFocus #010 End With #011 End Sub 代码解析: 输入按钮的Click事件,把文本框数据录入到工作表A列最后一个单元格中并重新选择文本框准备下一次输入。 第3行代码,在输入到工作表前检查文本框是否为空。 第4、5行代码,如果文本框不为空,录入数据到工作表并清空文本框内容。 第7行代码,如果文本框为空,提示用户输入数据。 第8行代码,使用SetFocus方法将光标返回到文本框中以便重新输入。 SetFocus方法将焦点移动到对象的实例中,语法如下 : object.SetFocus 参数object.是必需的,一个有效的对象。 运行窗体,在输入框中输入身份证号码后自动验证输入的数据,如果输入数据错误,清空文本框并提示用户重新输入,如图 7-1所示。 16 VBA常用技巧代码解析 图 7-1 提示用户重新输入 技巧8 文本框的自动换行 在使用使用文本框显示或录入一段很长的文本时,需要将文本框设置成多行显示,否则文本内容只能在一行中显示,示例代码如下: #001 Private Sub UserForm_Initialize() #002 With TextBox1 #003 .WordWrap = True #004 .MultiLine = True #005 .Text = Space(4) & \"VBA(Visual Basic for Application)是\" _ #006 & \"微软公司为了加强Office软件的二次开发能力而附加\" _ #007 & \"于其中的编程语言。VBA的确非常强大,其与VB完全一\" _ #008 & \"致的语法结构,高效控制Office对象模型的能力,令无\" _ #009 & \"数人为之折腰。利用VBA,几乎可以在Office里面做任何\" _ #010 & \"其他程序能做的事情。但是,应该清楚的认识到VBA是依\" _ #011 & \"托其宿主─—Excel(或其他Office组件)而存在的,对\" _ #012 & \"于Excel用户来讲,VBA只不过是锦上添花的东西,切不可\" _ #013 & \"本末倒置,捡了芝麻丢了西瓜,把明明能够利用Excel内置\" _ #014 & \"功能完成的任务,硬是搬到VBA里面去做,以为用代码实现\" _ #015 & \"就是高人一头的表现。其实,真正的高手,会尽量发挥\" _ #016 & \"Excel自身的威力,不到万不得已的时候是不会去 17 VBA常用技巧代码解析 #017 End With #018 End Sub 代码解析: 窗体的Initialize事件过程,在窗体显示时将文本框设置成多行显示文本。 第3行代码设置文本框的WordWrap属性。WordWrap属性指定一个控件的内容在行末是否自动换行,语法如下: object.WordWrap [= Boolean] 参数object是必需的,一个有效的对象。 参数Boolean是可选的,控件是否扩展以适应文本的大小,设置为True,文本换行,设置为False,文本不换行。 第4行代码设置文本框的MultiLine属性。MultiLine属性规定控件能否接受和显示多行文本,语法如下: object.MultiLine [= Boolean] 参数object是必需的,一个有效的对象。 参数Boolean是可选的,控件是否支持多行文本,设置为True,以多行显示文本,设置为False,不多行显示文本。如果将多行文本框的MultiLine属性设置为False,则文本框的所有字符都将合并为一行,包括非打印字符(如,回车和换行)。 对于既支持WordWrap属性又支持MultiLine属性的控件,当MultiLine属性为False时,WordWrap属性被忽略。 运行窗体,文本框显示如图 8-1所示。 图 8-1 文本框自动换行 18 VBA常用技巧代码解析 技巧9 多个文本框数据相加 在技巧5 中,我们在TextBox1、TextBox2中输入完数据后,利用文本框的Change事件使TextBox3显示其两者相乘的金额,但是如果窗体中有多个文本框,需要在每一个文本框的Change事件中写上相同的重复代码,因此使用类模块可以简化代码。 在附件的窗体有七个文本框,其中六个用来输入数据,一个用来显示其他六个文本框相加后的合计数,首先打开VBE,插入一个类模块建立一个类,类模块的名字就是类的名字修改为“cmds”,在类模块中输入下面的代码: Public WithEvents cmd As MSForms.TextBox 代码解析: 使用Public语句声明变量cmd是用来响应由TextBox对象触发的事件的对象变量。 在窗体的Initialize事件中写入下面的代码: #001 Dim col As New Collection #002 Private Sub UserForm_Initialize() #003 Dim i As Integer #004 Dim myc As cmds #005 For i = 1 To 6 #006 Set myc = New cmds #007 Set myc.cmd = Me.Controls(\"TextBox\" & i) #008 col.Add myc #009 Next #010 Set myc = Nothing #011 End Sub 代码解析: 第1行代码在模块顶部声明变量col的类型为集合。 第5行到第9行代码,将窗体中的六个文本框赋给col集合。 (关于类模块请参阅论坛中有关的资料。) 在类模块中写入下面的代码: #001 Private Sub cmd_Change() #002 Dim i As Integer #003 Dim Dval As Double #004 For i = 1 To 6 19 VBA常用技巧代码解析 #005 Dval = Dval + Val(UserForm1.Controls(\"TextBox\" & i)) #006 UserForm1.TextBox7.Value = Dval #007 Next #008 End Sub 代码解析: 窗体中的六个文本框统一的Change事件,当任何一个文本框中的数据发生变化时,所有文本框相加的合计数显示在最后一个文本框中。 运行窗体在文本框中输入数据结果如图 9-1所示。 图 9-1 多个文本框数据相加 技巧10 控件跟随活动单元格 在工作表中使用控件时一般都把控件放在工作表的上部,如果工作表中数据较多,当页 20 VBA常用技巧代码解析 面滚动到工作表下面的区域时,控件会离开当前可视区域,这时操作起来很不方便。解决方法除了冻结工作表的第一行放置控件的外,还可以使控件出现在选定的单元格位置,如下面的代码所示。 #001 Private Sub Worksheet_SelectionChange(ByVal Target As Range) #002 With Me.CommandButton1 #003 .Top = Target.Top #004 .Left = Target.Left + Target.Width #005 End With #006 End Sub 代码解析: 工作表的SelectionChange事件,使工作表中的按钮控件出现在选定单元格的右边。 第3行代码,设置按钮的Top属性等于选定单元格的Top属性。Top属性设置对象顶端到第一行顶端的距离。 第4行代码,设置按钮的Left属性等于选定单元格的Left属性加上选定单元格的宽度,即按钮出现在选定单元格的右边。Left属性设置对象左边界至 A 列左边界的距离。 当单击工作表区域的任一单元格,按钮出现在单元格的右边,如图 10-1所示。 图 10-1 控件跟随活动单元格 技巧11 高亮显示按钮 21 VBA常用技巧代码解析 为了达到当鼠标掠过按钮时以高亮和凸起显示按钮的效果,可以在窗体和按钮的MouseMove事件中进行模拟,如下面的代码所示。 #001 Private Sub CommandButton1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) #002 With Me.CommandButton1 #003 .BackColor = &HFFFF00 #004 .Width = 62 #005 .Height = 62 #006 .Top = 69 #007 .Left = 31 #008 End With #009 End Sub #010 Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) #011 With Me.CommandButton1 #012 .BackColor = Me.BackColor #013 .Width = 60 #014 .Height = 60 #015 .Top = 70 #016 .Left = 32 #017 End With #018 End Sub 代码解析: 窗体和按钮的MouseMove事件过程,以高亮和凸起显示按钮。 当用户在窗体中移动鼠标时,分别在窗体和按钮的MouseMove事件设置按钮的BackColor属性值,指定按钮的背景色,当鼠标移动到按钮时以高亮显示,当鼠标移动到窗体时恢复原来的设置。接下来分别设置按钮不同的Width属性、Height属性、Top属性和Left属性值,以模拟按钮凸起的效果。 运行窗体,当鼠标掠过按钮时效果如图 11-1所示。 22 VBA常用技巧代码解析 图 11-1 高亮和凸起显示按钮 技巧12 组合框和列表框添加列表项的方法 组合框和列表框是Excel中最常用的控件,可以用来显示工作表中的数据。为组合框和列表框添加列表项的方法有多种,下面以列表框为例演示添加列表项的方法。 12-1 使用RowSource属性添加列表项 使用RowSource属性将列表框直接与工作表上的一个单元格区域相链接,如下面的代码所示。 #001 Private Sub UserForm_Initialize() #002 Dim iRow As Integer #003 iRow = Sheet1.Range(\"A65536\").End(xlUp).Row #004 Me.ListBox1.RowSource = \"sheet1!a1:a\" & iRow #005 End Sub 代码解析: 在窗体初始化时使用RowSource属性为列表框添加列表项。 RowSource属性的语法如下: object.RowSource [= String] 23 VBA常用技巧代码解析 参数object是必需的,一个有效的对象。 参数String是可选的,组合框或列表框列表的来源。 RowSource属性也可以使用单元格地址,第4行代码可以改成下面的代码: Me.ListBox1.RowSource = Sheet1.Range(\"A1:A\" & iRow).Address(External:=True) 需要注意的是,如果RowSource属性指定的工作表区域不是活动工作表的话,Address属性的External参数是不可缺的,设置为True表示是外部引用,如果缺省此参数或为False,将不能为列表框添加列表项。 RowSource属性还可以使用命名的单元格区域,如果已把工作表区域命名为“城市”,第4行代码可以改成下面的代码: Me.ListBox1.RowSource = \"城市\" 对于工作表中的列表框控件或使用窗体添加的列表框控件不能使用RowSource属性,需要使用ListFillRange属性指定填充列表框的工作表区域,如下面的代码所示。 #001 Sub ListFillRange() #002 Dim iRow As Integer #003 iRow = Sheet1.Range(\"A65536\").End(xlUp).Row #004 Sheet2.ListBox1.ListFillRange = \"Sheet1!a1:a\" & iRow #005 Sheet2.Shapes(\"列表框\").ControlFormat.ListFillRange = \"Sheet1!a1:a\" & iRow #006 End Sub 代码解析: ListFillRange过程为工作表中的列表框的填充区域,ListFillRange属性用于指定填充列表框的工作表区域。 第4行代码对于使用窗体添加的列表框控件需要使用ControlFormat属性来返回窗体控件以后才能设置其ListFillRange属性。 12-2 使用List属性添加列表项 使用List属性为列表框添加列表项,如下面的代码所示。 #001 Private Sub UserForm_Initialize() #002 Dim Arr As Variant #003 Dim iRow As Integer #004 iRow = Sheet1.Range(\"A65536\").End(xlUp).Row #005 Arr = Sheet1.Range(\"A1:A\" & iRow) #006 Me.ListBox1.List = Arr 24 VBA常用技巧代码解析 #007 End Sub 代码解析: 在窗体初始化时使用List属性为列表框添加列表项。 List属性的语法如下: object.List( row, column ) [= Variant] 参数object是必需的,一个有效对象。 参数row是必需的,取值范围为 0 到列表条目数减 1 之间的数值。 参数column是必需的,取值范围为 0 到总列数减 1 之间的数值。 参数Variant是可选的,列表框中指定条目的内容。 第6行代码,使用List属性把数组复制到列表框控件上。 除了使用数组外,List属性还可以使用命名的单元格区域,如果已把工作表区域命名为“城市”,可以改成下面的代码: #001 Private Sub UserForm_Initialize() #002 Me.ComboBox1.List = Range(\"城市\").Value #003 End Sub 对于工作表中使用窗体添加的列表框控件使用List属性添加列表项,如下面的代码所示。 #001 Sub List() #002 Dim Arr As Variant #003 Dim iRow As Integer #004 Dim myObj As Object #005 iRow = Sheet1.Range(\"A65536\").End(xlUp).Row #006 Arr = Sheet1.Range(\"A1:A\" & iRow) #007 Set myObj = Sheet2.Shapes(\"列表框\").ControlFormat #008 myObj.List = Arr #009 End Sub 代码解析: List过程设置列表框的List性,用于指定填充列表框的工作表区域。 12-3 使用AddItem方法添加列表项 使用AddItem方法添加列表项,对于单列的列表框,在列表中添加一项。对于多列的列表框,在列表中添加一行,如下面的代码所示。 25 VBA常用技巧代码解析 #001 Private Sub UserForm_Initialize() #002 Dim iRow As Integer #003 Dim i As Integer #004 iRow = Sheet1.Range(\"A65536\").End(xlUp).Row #005 For i = 1 To iRow #006 Me.ListBox1.AddItem (Sheet1.Cells(i, 1)) #007 Next #008 End Sub 代码解析: 在窗体初始化时使用AddItem方法为列表框添加列表项。 AddItem方法的语法如下: object.AddItem [ item [, varIndex]] 参数object是必需的,一个有效的对象。 参数item是可选的,指定要添加的项或行。第一个项或行的编号为 0;第二个项或行的编号为 1,依此类推。 参数varIndex是可选的,指定新的项或行在对象中的位置。 如果提供一个有效的varIndex的值,AddItem方法就把项或行放在列表中的那个位置。如果忽略 varIndex,此方法就把项或行添加在列表的末尾。对于多列列表框或者组合框,AddItem 方法插入一个完整的行,为控件的每一列都插入一项。为了给第一列后面的项赋值,可用List或Column属性来规定项的行和列。 对于工作表中使用窗体添加的列表框控件使用AddItem方法添加列表项,如下面的代码所示。 #001 Sub AddItem() #002 Dim iRow As Integer #003 Dim i As Integer #004 iRow = Sheet1.Range(\"A65536\").End(xlUp).Row #005 With Sheet2.Shapes(\"列表框\").ControlFormat #006 .RemoveAllItems #007 For i = 1 To iRow #008 .AddItem Sheet1.Cells(i, 1) #009 Next #010 End With #011 End Sub 26 VBA常用技巧代码解析 代码解析: AddItem过程设置使用AddItem方法添加为工作表中使用窗体控件添加的列表框添加列表项。 其中第5行代码使用ControlFormat属性来返回窗体控件,第6行代码使用RemoveAllItems方法删除窗体控件中的列表框的所有数据项,如果控件是ActiveX 列表框则需要使用Clear方法。 技巧13 去除列表框数据源的重复值和空格 列表框的数据源引用工作表的数据时,如果工作表数据有重复值和空格,列表框也会出现重复值和空格,如图 13-1所示。 图 13-1 列表框中的重复值和空格 为了在窗体显示时去除列表框的重复值和空格,可以使用Add方法,如下面的代码所示。 #001 Private Sub UserForm_Initialize() #002 On Error Resume Next #003 Dim Col As New Collection #004 Dim rng As Range, arr 27 VBA常用技巧代码解析 #005 Dim i As Integer #006 For Each rng In Range(\"A1:A\" & [a65536].End(xlUp).Row) #007 If Trim(rng) <> \"\" Then #008 Col.Add rng, key:=CStr(rng) #009 End If #010 Next #011 ReDim arr(1 To Col.Count) #012 For i = 1 To Col.Count #013 arr(i) = Col(i) #014 Next #015 Me.ListBox1.List = arr #016 End Sub 代码解析: 窗体的初始化事件,去除列表框引用工作表数据中的重复值和空格。 第2行代码,错误处理语句,忽略错误。 第3行到第5行代码,声明变量类型。 第6行到第9行代码代码,在列表框引用的工作表数据中循环,把工作表数据源中的空格去除后使用Add方法添加到变量Col中。Add方法添加一个成员到Collection 对象,语法如下: object.Add item, key, before, after 参数object是必需的,一个有效的对象。 参数Item是必需的,任意类型的表达式,指定要添加到集合中的成员。 参数Key是可选的,唯一字符串表达式,指定可以使用的键字符串,代替位置索引来访问集合中的成员。 如果指定的key和集合中现有成员的key发生重复,则会导致错误发生。所以在第2行代码中使用错误处理语句,忽略错误,继续执行下一句代码,这样就将数据源中的重复值去除。 参数before是可选的,指定集合中的相对位置。在集合中将添加的成员放置在before参数识别的成员之前。如果参数是数值表达式,则before必须是介于 1 和集合Count属性值之间的值。如果参数是字符串表达式,则当添加一个被引用的成员到集合时,before 必须对应于指定的key值。可以指定before位置或after位置,但不能同时指定这两个位置。 参数after是可选的,指定集合中的相对位置。在集合中将添加的成员放置在After参数识别的成员之后。如果参数是数值表达式,则after必须是介于 1 和集合Count属性值 28 VBA常用技巧代码解析 之间的值;如果参数是字符串表达式,则当添加一个被引用的成员到集合时,after 必须对应于指定的key值。可以指定before位置或after位置,但不能同时指定这两个位置。 第10行到第14行代码,重新定义数组arr大小,把Col中数据赋给数组。 第15行代码,把数组arr复制到列表框中。 运行窗体,窗体中的列表框引用去除重复值和空格后的工作表数据,如图 13-2所示。 图 13-2 去除重复值和空格的列表框 技巧14 移动列表框条目 将列表框中的条目进行上下移动,如下面的代码所示。 #001 Dim Intlist As Integer #002 Dim Strlist As String #003 Private Sub CommandButton1_Click() #004 With Me.ListBox1 #005 Intlist = .ListIndex #006 Select Case Intlist #007 Case -1 #008 MsgBox \"请选择一行后再移动!\" 29 VBA常用技巧代码解析 #009 Case 0 #010 MsgBox \"已经是最上一行了!\" #011 Case Is > 0 #012 Strlist = .List(Intlist) #013 .List(Intlist) = .List(Intlist - 1) #014 .List(Intlist - 1) = Strlist #015 .ListIndex = Intlist - 1 #016 End Select #017 End With #018 End Sub #019 Private Sub CommandButton2_Click() #020 With ListBox1 #021 Intlist = .ListIndex #022 Select Case Intlist #023 Case -1 #024 MsgBox \"请选择一行后再移动!\" #025 Case .ListCount - 1 #026 MsgBox \"已经是最下一行了!\" #027 Case Is < .ListCount - 1 #028 Strlist = .List(Intlist) #029 .List(Intlist) = .List(Intlist + 1) #030 .List(Intlist + 1) = Strlist #031 .ListIndex = Intlist + 1 #032 End Select #033 End With #034 End Sub 代码解析: 第1、2行代码在模块顶部声明两个变量分别用于保存列表框当前选中行的索引和内容。 第3行到第18行代码,将列表框当前选中行的内容上移一行的代码。其中第5行代码使用变量Intlist保存列表框当前选中行的索引号,第6行代码判断索引号,,第7、8行代码如果变量Intlist值为-1 ,说明当前没有选中的行,显示一个消息框进行提示。第9、10行代码变量Intlist值为0 ,说明当前选中的行已是第一行了。 30 VBA常用技巧代码解析 列表框的ListIndex属性指定当前选中的列表框或组合框条目,语法如下: object.ListIndex [= Variant] 参数object是必需的,一个有效的对象。 参数Variant是可选的,控件中当前被选的条目。 第11行到第15行代码将当前选中的行向下移动一行,其中第12行代码将当前选中的行的内容赋给变量Strlist,第13行代码将当前选中行的内容更改为下面一行的内容,第14行代码将当前选中行的下面一行的内容更改为变量Strlist保存的内容,第15行代码将选中行向下移动一行,这样就将当前选中的行向下移动了一行。 第19行到第34行代码将当前选中的行向上移动一行。 将移动后的列表框条目保存到工作表中的代码如下: #001 Private Sub CommandButton3_Click() #002 Dim i As Integer #003 For i = 1 To ListBox1.ListCount #004 Sheet1.Cells(i + 1, 1) = ListBox1.List(i - 1) #005 Next #006 End Sub 代码解析: 窗体中“保存”按钮的单击过程,将移动后的列表框条目保存到工作表。 第3行到第5行代码使用For...Next 语句循环遍历列表框所有条目,将List属性返回的列表框的列表条目写入到工作表中。List属性返回或设置列表框或组合框的列表条目数,语法请参阅技巧12-2。 运行窗体效果如所示。 图 14-1 移动列表框条目 31 VBA常用技巧代码解析 技巧15 允许多项选择的列表框 一般情况下在显示的列表框中用户只能选择一个列表项,而经过简单的设置,列表框条目前可以显示选项按钮,允许进行多项选择,如下面的代码所示。 #001 Private Sub UserForm_Initialize() #002 Dim arr As Variant #003 arr = Array(\"经理室\办公室\生技科\财务科\营业部\制水车间\污水厂\安装公司\其他\") #004 With Me.ListBox1 #005 .List = arr #006 .ListStyle = 1 #007 .MultiSelect = 1 #008 End With #009 End Sub 代码解析: 窗体的Initialize事件过程,在窗体初始化时对列表框进行设置。 其中第5行代码使用List属性为列表框添加列表项,请参阅技巧12-2。 第6行代码将列表框的ListStyle属性设置为1(fmListStyleOption),显示用于多重选择列表的复选框,ListStyle属性规定列表框或组合框中的列表的外观,语法如下: object.ListStyle [= fmListStyle] 参数object是必需的,一个有效的对象。 参数fmListStyle是可选的,列表的可视风格,设置值如表格 15-1所示。 常量 fmListStylePlain fmListStyleOption 值 0 1 说明 外观与常规的列表框相似,条目的背景为高亮 显示选项按钮,或显示用于多重选择列表的复选框(默认)。当用户选定组中的条目时,与该条目相关的选项按钮即被选中,而该组其他条目的选项按钮则被取消选择 表格 15-1 fmListStyle设置值 ListStyle 属性可用来改变列表框或组合框的可视外观。通过一种不同于 fmListStylePlain 的设置,可以将任意控件的内容作为一组单独项目演示,每个项目都包含一个可视记号用以表示它是否被选中。 如果控件支持单一选择(MultiSelect属性被设置为mMultiSelectSingle),则可按下组中的一个按钮。如果控件支持多重选择,则可以按下组中两个或更多的按钮。 32 VBA常用技巧代码解析 第7行代码将MultiSelect属性设置为1(fmMultiSelectMulti),允许列表框进行多项选择,MultiSelect属性表示对象是否允许多项选择,语法如下: object.MultiSelect [= fmMultiSelect] 参数object是必需的,一个有效的对象。 参数fmMultiSelect是可选的,控件所用的选择方式,设置值如表格 15-2所示。 常量 fmMultiSelectSingle fmMultiSelectMulti fmMultiSelectExtended 值 0 1 2 说明 只可选择一个条目(默认) 按空格键或单击鼠标以选定列表中一个条目或取消选定 按 Shift 并单击鼠标,或按 Shift 的同时按一个方向键,将所选条目由前一项扩展到当前项。按 Ctrl 的同时单击鼠标可选定或取消选定 表格 15-2 fmMultiSelect设置值 经过以上设置,列表框显示时可以进行多项选择并且条目前都有一个选项按钮用以表示它是否被选中,如图 15-1所示。 图 15-1 允许多项选择的列表框 如果将列表框的ListStyle属性设置为0则与常规的列表框相似。 如果将列表框的MultiSelect属性设置0则列表框只能进行单项选择,如图 15-2所示。 33 VBA常用技巧代码解析 图 15-2 允许单项选择的列表框 通过列表框的Selected属性值可以判断列表框中条目的选定状态,如下面的代码所示。 #001 Private Sub CommandButton1_Click() #002 Dim i As Integer #003 Dim s As String #004 For i = 0 To ListBox1.ListCount - 1 #005 If ListBox1.Selected(i) = True Then #006 s = s & ListBox1.List(i) & Chr(13) #007 End If #008 Next #009 If s <> \"\" Then #010 MsgBox \"你选择了:\" & Chr(13) & s #011 Else #012 MsgBox \"请最少选择一个部门!\" #013 End If #014 End Sub 代码解析: 按钮的单击过程,将列表框中选中的条目使用消息框显示出来。 第4行到第8行代码使用For...Next 语句循环遍历列表框所有条目,通过返回的Selected属性值判断列表框中条目的选定状态,如果处于选中状态,第6行代码将列表框选中条目的值赋给字符串变量s。 Selected属性判断列表框中条目的选定状态,语法如下: object.Selected( index ) [= Boolean] 34 VBA常用技巧代码解析 参数object是必需的,一个有效的对象。 参数index是必需的,整数,取值范围是0到列表中的条目数减1之间的数值。 参数Boolean是必需的,判断一个条目是否被选中。 第9行到第13行代码使用消息框显示列表框中选中的条目。 运行窗体结果如图 15-3所示。 图 15-3 允许多项选择的列表框 技巧16 多列组合框和列表框的设置 16-1 多列组合框和列表框添加列表项 如果组合框和列表框是多列的话,除了使用技巧12 的方法外,还需要设置控件的其他属性,如下面的代码所示。 #001 Private Sub UserForm_Initialize() #002 Dim iRow As Integer #003 Dim Arr As Variant #004 iRow = Sheet1.Range(\"A65536\").End(xlUp).Row #005 Arr = Sheet1.Range(\"A1:G\" & iRow) #006 With Me.ListBox1 #007 .ColumnCount = 7 35 VBA常用技巧代码解析 #008 .ColumnWidths = \"45,45,45,45,45,30,45\" #009 .BoundColumn = 1 #010 .Column = Application.WorksheetFunction.Transpose(Arr) #011 End With #012 End Sub 代码解析: 在窗体初始化时为多列列表框添加列表项。 第4行代码,设置列表框显示的列数。ColumnCount 属性指定列表框或组合框的显示列数,语法如下: object.ColumnCount [= Long] 参数object是必需的,一个有效的对象。 参数Long是可选的,指定需显示的列数。 如果将ColumnCount设为 -1,将显示所有列。 第8行代码,设置列表框各列的宽度。ColumnWidths 属性指定多列的组合框或列表框中的各列的宽度,语法如下: object.ColumnWidths [= String] 参数object是必需的,一个有效的对象。 参数String是可选的,以磅为单位设置列的宽度。 如将ColumnWidths 属性设为 -1 或空,则将控件宽度等分,给予列表中的各列。设为 0 则隐藏该列,大于 0 的数值则是该列的精确宽度值。若要指定另一种不同的度量单位,设置时必须包括该度量单位。 第9行代码,设置多列列表框中的第一列为数据的来源。BoundColumn 属性标识多列组合框或列表框中的数据的来源,语法如下: object.BoundColumn [= Variant] 参数object是必需的,一个有效的对象。 参数Variant是可选的,标识选择 BoundColumn 属性值的方法,设置值如表格 16-1所示: 值 0 1 或者大于 1 说明 将 ListIndex 属性的值赋予控件。 将指定列中的值赋予控件。当采用此属性时,列从 1 开始计数(默认值)。 表格 16-1 Variant 的设置值 当选择了多列列表框的一行时,BoundColumn 属性标识出将该行的哪一条目作为控件的值存储。BoundColumn属性设为 0,将所选行的行号赋予控件,作为控件的值。如果 36 VBA常用技巧代码解析 BoundColumn属性设为1 或者大于 1,则将指定列中的值赋予控件。 第10行代码,设置多列列表框中列表的来源。在设置列表来源时除了可以使用技巧12 所介绍的方法外,还可以使用Column属性指定列表框中的一个或多个条目,Column属性语法如下: object.Column( column, row ) [= Variant] 参数object是必需的,一个有效对象。 参数column是可选的,取值范围为0到总列数减1之间的数值。 参数row是可选的,取值范围为0到总行数减1之间的数值。 参数Variant是可选的,指定欲加载到列表框的一个值、一列值或一个二维数组。 注意 当从一个二维数组中复制数据时,使用Column属性将转置控件中数组的内容,所以在加载时需使用Transpose函数对数组进行转置。 多列列表框设置完成后效果如图 16-1所示。 图 16-1 多列列表框 16-2 多列列表框写入工作表 在把多列列表框的写入工作表中时,只能把BoundColumn属性所指定列中的值写入工作表中,不能把选中的整行内容写入到工作表中。如果需要把多列列表框中选中行的整行内容写入工作表中,可以使用循环语句将列表框各列的写入工作表,如下面的代码所示。 #001 Private Sub UserForm_Initialize() #002 Dim iRow As Integer #003 iRow = Sheet2.Range(\"A65536\").End(xlUp).Row #004 With Me.ListBox1 #005 .ColumnCount = 7 #006 .ColumnWidths = \"45,45,45,45,45,30,45\" 37 VBA常用技巧代码解析 #007 .BoundColumn = 1 #008 .ColumnHeads = True #009 .RowSource = Sheet2.Range(\"A2:G\" & iRow).Address(External:=True) #010 End With #011 End Sub #012 Private Sub ListBox1_Click() #013 Dim iRow As Integer #014 Dim i As Byte #015 iRow = Sheet1.Range(\"A65536\").End(xlUp).Row + 1 #016 For i = 1 To ListBox1.ColumnCount #017 Sheet1.Cells(iRow, i) = ListBox1.Column(i - 1) #018 Next #019 End Sub 代码解析: 第1行到第11行代码窗体的Initialize事件过程,在窗体初始化时为多列列表框添加列表项,请参阅技巧16-1。 第8行代码,设置多列列表框中的第一行为列标题行。ColumnHeads 属性显示列表框、组合框及接受列题注的对象中的列标题行,语法如下: object.ColumnHeads [= Boolean] 参数object是必需的,一个有效的对象。 参数Boolean是可选的,指定是否显示列标题。 将ColumnHeads 属性设置为True,多列列表框的第一行显示为列标题,默认值为False,不显示列标题。 需要注意的是,当数据项中的第一行作为列标题时,则不可选中该行。 第9行代码,使用RowSource属性设置多列列表框中列表的来源。关于RowSource属性请参阅技巧12-1。 注意 如果已将多列列表框中列表项来源的第一行设置为列标题,在设置RowSource属性时应从列表项来源的第二行开始设置。 第12行到第19行代码列表框的Click事件,单击多列列表框时把选中行的整行内容写入工作表中。其中第17行代码,使用循环语句将多列列表框选中行的各列的值写入工作表对应的单元格中。关于Column属性请参阅技巧16-1,在本例中没有指定row参数,所以是把当前选中行的内容写入工作表。 38 VBA常用技巧代码解析 运行窗体后,单击列表框将选中的整行内容写入工作表中,如图 16-2所示。 图 16-2 多列列表框选中的整行内容写入工作表 技巧17 输入时逐步提示信息 用户在录入数据时,比如在工作表中输入产品名称,除了希望有所有产品名称的下拉列表供选择外,更希望能逐步给出提示信息。比如在输入一两个字符后把符合条件的数据筛选出来供选择,最好是中英文、拼音首字母、大小写能混合查询,如输入“LJ”或“六角”后所有以“六角”开头的产品名称都筛选到列表中供选择,这将大大提高录入速度和正确率。 为了达到这一目的,首先在工作簿需要有如图 17-1所示的基础数据表。 39 VBA常用技巧代码解析 图 17-1 基础数据表 基础数据表中A列保存不重复的产品名称,为了能用中英文、拼音首字母、大小写混合查询,要把产品名称转换成小写的拼音首字母保存在B列。 步骤1:在VBE窗口单击菜单“插入”→“模块”,在代码窗口写入下面的代码。 #001 Public Function LChin(Str As String) As Variant #002 On Error Resume Next #003 Str = StrConv(Str, vbNarrow) #004 If Asc(Str) > 0 Or Err.Number = 1004 Then LChin = \"\" #005 LChin = WorksheetFunction.VLookup(Str, [{\"吖\八\嚓\咑\鵽\发\猤\铪\夻\咔\垃\嘸\旀\噢\妑\七\囕\仨\他\屲\夕\丫\帀\ #006 End Function 代码解析: 自定义LChin函数,该函数把中文字符转换为拼音首字母。 步骤2:在VBE窗口双击Sheet2表,在代码窗口写入下面的代码。 40 VBA常用技巧代码解析 #001 Private Sub Worksheet_Change(ByVal Target As Range) #002 Dim i As Integer #003 Dim myStr As String #004 With Target #005 If .Column <> 1 Or .Count > 1 Then Exit Sub #006 If WorksheetFunction.CountIf(Sheet2.Range(\"A:A\"), .Value) > 1 Then #007 .Value = \"\" #008 MsgBox \"不能输入重复的产品名称!\#009 Exit Sub #010 End If #011 For i = 1 To Len(.Value) #012 If Asc(Mid$(.Value, i, 1)) > 255 Or Asc(Mid$(.Value, i, 1)) < 0 Then #013 myStr = myStr & LChin(Mid$(.Value, i, 1)) #014 Else #015 myStr = myStr & LCase(Mid$(.Value, i, 1)) #016 End If #017 Next #018 .Offset(, 1).Value = myStr #019 End With #020 End Sub 代码解析: 工作表的Change事件,当A列输入不重复的产品名称后,转换成小写的字母保存在B列的单元格中,便于以后的查询。 第11行代码,设置事件触发的条件,只有在A列输入产品名称后才触发Change事件。 第12行到第16行代码,使用工作表CountIf函数检查输入的产品名称是否重复。 第17行到第23行代码,字符的转换过程。首先检查是否是中文字符,如果是使用自定义函数LChin转换成小写拼音首字母。如果是大写的英文字母使用LCase函数转换成小写字母。 第24行代码,将转换后的字符保存到B列。 步骤3:基础数据表完成后,在工作表“录入表”中添加一个文本框控件和一个列表框控件。在VBE窗口中双击Sheet1表,写入下面的代码。 41 VBA常用技巧代码解析 #001 Private Sub Worksheet_SelectionChange(ByVal Target As Range) #002 Dim i As Integer #003 If Target.Count = 1 Then #004 If Target.Column = 1 And Target.Row > 1 Then #005 With Me.TextBox1 #006 .Visible = True #007 .Top = Target.Top #008 .Left = Target.Left #009 .Width = Target.Width #010 .Height = Target.Height #011 .Activate #012 End With #013 With Me.ListBox1 #014 .Visible = True #015 .Top = Target.Top #016 .Left = Target.Left + Target.Width #017 .Width = Target.Width #018 .Height = Target.Height * 5 #019 For i = 2 To Sheet2.Range(\"A65536\").End(xlUp).Row #020 .AddItem Sheet2.Cells(i, 1).Value #021 Next #022 End With #023 Else #024 Me.ListBox1.Clear #025 Me.TextBox1 = \"\" #026 Me.ListBox1.Visible = False #027 Me.TextBox1.Visible = False #028 End If #029 End If #030 End Sub 代码解析: 工作表的SelectionChange事件,当用户选定工作表A列第2行以下的单个单元格时, 42 VBA常用技巧代码解析 设置文本框和列表框的Visible为True,使它们成为可见的,并设置其外观,同时给列表框加载列表项。当用户选定其他列的单元格时隐藏文本框和列表框控件。 步骤4:在设计模式下双击文本框,在代码窗口写入下面的代码。 #001 Private Sub TextBox1_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) #002 Dim i As Integer #003 Dim Language As Boolean #004 Dim myStr As String #005 Me.ListBox1.Clear #006 With Me.TextBox1 #007 For i = 1 To Len(.Value) #008 If Asc(Mid$(.Value, i, 1)) > 255 Or Asc(Mid$(.Value, i, 1)) < 0 Then #009 Language = True #010 myStr = myStr & Mid$(.Value, i, 1) #011 Else #012 myStr = myStr & LCase(Mid$(.Value, i, 1)) #013 End If #014 Next #015 End With #016 With Sheet2 #017 For i = 2 To .Range(\"A65536\").End(xlUp).Row #018 If Language = True Then #019 If Left(.Cells(i, 1).Value, Len(myStr)) = myStr Then #020 Me.ListBox1.AddItem .Cells(i, 1).Value #021 End If #022 Else #023 If Left(.Cells(i, 2).Value, Len(myStr)) = myStr Then #024 Me.ListBox1.AddItem .Cells(i, 1).Value #025 End If #026 End If #027 Next 43 VBA常用技巧代码解析 #028 End With #029 End Sub 代码解析: 文本框的KeyUp事件,在文本框输入查询条件时筛选符合条件的数据加载到列表框。 第3行代码,声明变量Language为Boolean数据类型,在下面的代码中使用Language的值判断输入的是否为中文。 第5行代码,使用Clear方法删除列表框所有的列表项,语法如下: object.Clear 参数object是必需的,一个有效的对象。 注意 如果列表框绑定了数据,Clear方法将会失败。 第6行到第15行代码,判断文本框输入的是否为中文字符。如果是中文字符,将变量Language赋值为True,并把文本框中的字符赋给变量myStr。如果是英文字符则转换成小写字母后赋变量myStr。 第16行到第29行代码,如果变量Language的值为True,在基础数据表的A列中使用Left函数查找与文本框字符相符的单元格并加载到列表框,否则就在B列查找。 步骤5:在设计模式下双击文本框,在代码窗口写入下面的代码。 #001 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) #002 If KeyCode = vbKeyReturn Then #003 Sheet1.ListBox1.Activate #004 End If #005 End Sub 代码解析: 文本框的KeyDown事件,当用户在文本框中输入完成,列表框中已显示所需的内容后按回车键后选择列表框。 步骤6:在设计模式下双击列表框,在代码窗口写入下面的代码 #001 Private Sub ListBox1_GotFocus() #002 On Error Resume Next #003 ListBox1.ListIndex = 0 #004 End Sub 代码解析: 列表框的GotFocus事件,当用户在文本框中输入完成按回车键后,选定列表框中第1个条目,方便用户进行下一步操作。 44 VBA常用技巧代码解析 #001 Private Sub ListBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) #002 If KeyCode = vbKeyReturn Then #003 ActiveCell.Value = ListBox1.Value #004 Me.ListBox1.Clear #005 Me.TextBox1 = \"\" #006 Me.ListBox1.Visible = False #007 Me.TextBox1.Visible = False #008 End If #009 End Sub 代码解析: 列表框的KeyDown事件,当用户在列表框中按下回车后将列表框选中的条目写入到活动工作表的单元格中,同时清空文本框和列表框内容后隐藏,准备下一次录入。 #001 Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean) #002 ActiveCell.Value = ListBox1.Value #003 Me.ListBox1.Clear #004 Me.TextBox1 = \"\" #005 Me.ListBox1.Visible = False #006 Me.TextBox1.Visible = False #007 End Sub 代码解析: 列表框的DblClick事件,当用户双击列表框的列表项时,把列表框数据赋给活动单元格,同时清空文本框和列表框内容后隐藏,准备下一次录入。 以上设置完成后,在“录入”工作表的A列选定单元格后,显示一个文本框和一个列表框,在文本框中输入查询条件后列表框显示符合查询条件的所有内容供用户选择,如图 17-2所示。 45 VBA常用技巧代码解析 图 17-2 输入时逐步提示信息 技巧18 二级组合框 在使用多个组合框输入数据时,往往希望后一个组合框中的条目能根据前一个组合框的内容有所不同,如示例中第二个选择城市的组合框根据第一个选择省份的组合框所选择的不同省份加载不同的县市名称,示例代码如下: #001 Private Sub UserForm_Initialize() #002 Dim col As New Collection #003 Dim arr As Variant #004 Dim rng As Range #005 Dim i As Integer #006 On Error Resume Next #007 For Each rng In Range(\"A2:A\" & Sheet1.Range(\"A65536\").End(xlUp).Row) #008 If rng <> \"\" Then col.Add rng, CStr(rng) #009 Next #010 ReDim arr(1 To col.Count) 46 VBA常用技巧代码解析 #011 For i = 1 To col.Count #012 arr(i) = col(i) #013 Next #014 ComboBox1.List = arr #015 ComboBox1.ListIndex = 0 #016 CommandButton1.Accelerator = \"D\" #017 End Sub #018 Private Sub ComboBox1_Change() #019 Dim myAddress As String #020 Dim rng As Range #021 Dim mymsg As Integer #022 ComboBox2.Clear #023 With Sheet1.Range(\"A:A\") #024 Set rng = .Find(What:=ComboBox1.Text) #025 If Not rng Is Nothing Then #026 myAddress = rng.Address #027 Do #028 ComboBox2.AddItem rng.Offset(, 1) #029 Set rng = .FindNext(rng) #030 Loop While Not rng Is Nothing And rng.Address <> myAddress #031 End If #032 End With #033 ComboBox2.ListIndex = 0 #034 End Sub 代码解析: 第1行到第17行代码窗体的Initialize事件过程,在窗体显示时将工作表A列中的省份名称去除重复后加载到组合框中。 其中第7行到第13行代码把工作表A列中的省份名称使用Add方法去除重复后加载到组合框中,应用于Collection 对象的Add方法添加一个成员对象,请参阅技巧13 。 第15行代码设置组合框的ListIndex属性为0,选中组合框的第一行条目。ListIndex属性指定当前选中的列表框或组合框条目,语法如下: object.ListIndex [= Variant] 47 VBA常用技巧代码解析 参数Variant是可选的,控件中当前被选的条目。 ListIndex 属性包含列表中被选行的索引,取值范围为 -1 到列表总行数减 1(即ListCount - 1)之间的数值。当用户没有选中行时,ListIndex 返回 -1。列表中第一行的 ListIndex值是0,第二行的ListIndex 值是1,依此类推。 第16行代码设置窗体中按钮的Accelerator属性值。Accelerator属性设置或检索控件的加速键,语法如下: object.Accelerator [= String] 参数String是可选的,用作加速键的字符。 先按住 Alt 再紧接着按加速键,会将焦点定位到该对象上,并初始化与该对象关联的一个或多个事件,也就是说窗体显示后按Alt+D组合键将会执行“关闭”按钮中的代码关闭窗体。 第18行到第34行代码ComboBox1的Change事件过程,使用Find方法将所有属于ComboBox1所选择的省份的县市加载到ComboBox2中。关于Find方法请参阅技巧错误!未找到引用源。。 窗体运行后效果如图 18-1所示。 图 18-1 二级组合框 技巧19 使用DTP控件输入日期 在工作表中输入日期可以使用日期时间控件(Microsoft Date and Time Picker Control 6.0,简称DTP控件)。 在工作表中单击菜单“视图”→“工具栏”→“控件工具箱”,选择“其他控件”中的DTP控件如图 19-1所示,在工作表中添加一个DTP控件。 48 VBA常用技巧代码解析 图 19-1 选择DTP控件 在设计模式下双击DTP控件写入下面的代码: #001 Private Sub Worksheet_SelectionChange(ByVal Target As Range) #002 With Me.DTPicker1 #003 If Target.Count = 1 And Target.Column = 2 And (Not Target.Row = 1) Or Target.MergeCells Then #004 .Visible = True #005 .Top = Selection.Top #006 .Left = Selection.Left #007 .Height = Selection.Height #008 .Width = Selection.Width #009 If Target.Cells(1, 1) <> \"\" Then #010 .Value = Target.Cells(1, 1).Value #011 Else #012 .Value = Date #013 End If #014 Else #015 .Visible = False #016 End If #017 End With #018 End Sub #019 Private Sub DTPicker1_CloseUp() #020 ActiveCell.Value = Me.DTPicker1.Value #021 Me.DTPicker1.Visible = False #022 End Sub 49 VBA常用技巧代码解析 #023 Private Sub Worksheet_Change(ByVal Target As Range) #024 If Target.Count = 1 And Target.Column = 2 Or Target.MergeCells Then #025 If Target.Cells(1, 1).Value = \"\" Then #026 DTPicker1.Visible = False #027 End If #028 End If #029 End Sub 代码解析: 第1行到第18行代码工作表的SelectionChange事件,当选择工作表的B列第2行以下的单个单元格时显示日期控件供用户选择日期。 其中第3行代码设置显示日期控件的触发条件。只有当用户选择B列第2行以下单元格且只能选择单个单元格时才显示日期控件,因为本例B列中存在合并单元格,所以需要加上Or Target.MergeCells这个条件,否则单击合并单元格不显示日期控件。 第4行到第8行代码显示日期控件并设置日期控件的大小等于所选单元格的大小。 第9行到第13行代码,如果单元格已经输入了日期,将单元格中的日期赋给日期控件,否则将当前日期赋给日期控件。因为本例B列中存在合并单元格,而合并区域的值在该区域左上角的单元格中指定,所以用Target.Cells(1, 1) 指定合并单元格的值,否则代码会出错。 第15行代码如果选择的是其他列则隐藏日期控件。 第19行到第22行代码日期控件的CloseUp事件,将日期控件的值赋给活动单元格后隐藏日期控件。 第23行到第29行代码工作表的Change事件,如果删除了B列单元格的日期则隐藏日期控件。 当用户选择B列单元格时效果如图 19-2所示。 图 19-2 使用DTP控件输入日期 50 VBA常用技巧代码解析 技巧20 使用RefEdit控件选择区域 在技巧错误!未找到引用源。中介绍了如何使用InputBox方法获得所选单元格区域的地址,而使用RefEdit控件获得单元格区域的地址比使用InputBox方法更加方便,可以单击RefEdit控件中的按钮以折叠用户窗体,选定区域后再单击按钮展开用户窗体,示例代码如下: #001 Private Sub CommandButton1_Click() #002 Dim Rng As Range #003 On Error GoTo line #004 Set Rng = Range(RefEdit1.Value) #005 Rng.Interior.ColorIndex = 15 #006 Unload UserForm1 #007 Exit Sub #008 line: #009 MsgBox \"你选择的是非单元格区域!\" #010 End Sub 代码解析: 用户窗体中按钮的单击事件过程,改变用户使用RefEdit控件所选择的单元格区域内部的颜色。 第3行代码,错误处理语句。因为如果用户输入或选定了错误的单元格区域地址,将显示一错误信息,如图 20-1所示,所以必需使用On Error GoTo语句来绕过错误。 图 20-1 提示运行错误 第4行代码,使用Set语句将用户选择的单元格区域赋给变量rng。 第5行代码,改变用户所选单元格区域内部的颜色。 51 VBA常用技巧代码解析 注意 不能在无模式用户窗体中使用RefEdit控件。 窗体运行后,当用户在工作表中选择一个单元格区域后改变所选单元格区域内部的颜色,如图 20-2所示。 图 20-2 使用RefEdit控件获得区域地址 技巧21 如何注册控件 Excel文件中如果有ActiveX控件如日期时间控件(Microsoft Date and Time Picker Control 6.0,简称DTP控件),在有些电脑上运行时会出现“无法装载这个对象,因为它不适于这台计算机”的提示,如图 21-1所示。文件中的控件丢失,无法正常使用。 图 21-1 无法装载对象提示 这是因为DTP控件没有注册引起的,解决办法是在能运行该控件的电脑中复制DTP控件的文件到目标电脑中进行注册。在VBE窗口中右键单击“工具箱”,选择“附加控件”,在“附加控件”对话框中选择DTP控件,对话框底部会显示控件的名称和文件所在的路径,如图 21-2所示。 52 VBA常用技巧代码解析 图 21-2 OCX文件名称和路径 DTP控件的文件名为MSCOMCT2.OCX,在C盘的Windows\\system32文件夹中,把该文件复制到目标电脑C盘的Windows\\system32文件夹中,单击“开始”→“运行”,在“运行”对话框中键入“regsvr32 C:\\Windows\\system32\\MSCOMCT2.OCX”,注册成功后会出现如图 21-3所示的对话框,DTP控件即能正常使用。 图 21-3 注册成功提示 在Excel中可以使用程序代码进行自动注册,代码如下: #001 Sub regsvrs() #002 Dim SouFile As String #003 Dim DesFile As String #004 On Error Resume Next #005 SouFile = ThisWorkbook.Path & \"\\MSCOMCT2.OCX\" #006 DesFile = \"c:\\Windows\\system32\\MSCOMCT2.OCX\" #007 FileCopy SouFile, DesFile #008 Shell \"regsvr32 /s\" & DesFile #009 MsgBox \"DTP控件已成功注册,现在可以使用了!\" 53 VBA常用技巧代码解析 #010 End Sub 代码解析: Regsvrs过程将保存在同一目录中的MSCOMCT2.OCX文件复制到电脑的文件夹中,使用Shell函数注册DTP控件。 第4行代码,错误处理语句,用于忽略复制文件时可能出现的错误。因为如果电脑文件夹中已存在MSCOMCT2.OCX文件,使用FileCopy方法复制时会发生错误,如图 21-4所示。 图 21-4 复制文件错误提示 第7行代码,使用FileCopy方法复制MSCOMCT2.OCX文件到电脑中。 FileCopy方法的语法如下: FileCopy source, destination 参数Source是必需的,字符串表达式,用来表示要被复制的文件名。 参数destination是必需的,字符串表达式,用来指定要复制的目的文件名。 第8行代码,使用Shell函数注册DTP控件。 Shell函数执行一个可执行文件,语法如下: Shell(pathname[,windowstyle]) 参数pathname是必需的,要执行的程序名,以及任何必需的参数或命令行变量,可能还包括目录或文件夹,以及驱动器。 参数windowstyle是可选的,表示在程序运行时窗口的样式。windowstyle参数值如表格 21-1所示。 常量 vbHide 值 描述 0 窗口被隐藏,且焦点会移到隐式窗口。常数vbHide在Macintosh平台不可用。 VbNormalFocus VbMinimizedFocus 1 2 窗口具有焦点,且会还原到它原来的大小和位置。 窗口会以一个具有焦点的图标来显示。 54 VBA常用技巧代码解析 VbMaximizedFocus VbNormalNoFocus VbMinimizedNoFocus 3 4 6 窗口是一个具有焦点的最大化窗口。 窗口会被还原到最近使用的大小和位置,而当前活动的窗口仍然保持活动。 窗口会以一个图标来显示。而当前活动的的窗口仍然保持活动。 表格 21-1 windowstyle参数值 运行程序前应确保在工作簿同一目录中存在MSCOMCT2.OCX文件。此代码相当于在“运行”对话框中键入“regsvr32 C:\\ Windows\\system32\\MSCOMCT2.OCX”后进行注册,只是在“REGSVR32”后加上了s参数,使注册成功后不会出现如图 21-3所示的对话框。 可以使用程序代码卸载该控件,代码如下: #001 Sub regsvru() #002 Shell \"REGSVR32 /u \" & ThisWorkbook.Path & \"\\MSCOMCT2.OCX\" #003 End Sub 代码解析: Regsvru过程使用Shell函数注册DTP控件,在pathname参数“REGSVR32”后加上u参数,对DTP控件进行反注册。 技巧22 遍历控件的方法 如果窗体或工作表中的控件很多,在写代码时,如果是相同的代码,可以使用循环语句遍历控件,无需每个控件都写相同的代码,以减少代码量。 22-1 使用名称中的变量遍历控件 如果控件使用系统缺省名称,如“TextBox1”、“TextBox2”,前面是固定的字符串,后面是序号的,可以使用For...Next 语句循环遍历控件。 对于窗体中的控件,如下面的代码所示。 #001 Private Sub CommandButton1_Click() #002 Dim i As Integer #003 For i = 1 To 3 #004 Me.Controls(\"TextBox\" & i) = \"\" 55 VBA常用技巧代码解析 #005 Next #006 End Sub 代码解析: 窗体按钮的单击事件,一次性清空窗体中三个文本框的内容。 第4行代码,将窗体中三个文本框名称中的最后一个序号设成变量,在文本框中循环并清空其内容。 对于工作表中的控件,如下面的代码所示。 #001 Private Sub CommandButton1_Click() #002 Dim i As Integer #003 For i = 1 To 4 #004 Me.OLEObjects(\"TextBox\" & i).Object.Text = \"\" #005 Next #006 End Sub 代码解析: 工作表中按钮的单击事件,在工作表中的三个文本框中循环,清空文本框的内容。 第4行代码,将工作表中四个文本框名称中的最后一个序号设成变量,使用OLEObjects方法在工作表中的文本框中循环。 OLEObjects方法返回图表或工作表上单个OLE对象(OLEObject)或所有OLE对象的集合(OLEObjects集合)的对象,语法如下: expression.OLEObjects(Index) 参数expression是必需的,返回一个Chart 对象或Worksheet 对象。 参数Index 是可选的,OLE对象的名称或编号。 注意 控件的名称是指控件在属性窗口中的名称,如图 22-1所示。如果控件的名称没有规律不适用此方法。 56 VBA常用技巧代码解析 图 22-1 控件属性窗口中的名称 22-2 使用对象类型遍历控件 如果控件的名称没有规律,可以使用For Each...Next 语句循环遍历所有控件,使用TypeName函数返回控件的对象类型,根据控件的对象类型进行相应的操作。 对于窗体中的控件,如下面的代码所示。 #001 Private Sub CommandButton1_Click() #002 Dim Ctr As Control #003 For Each Ctr In Me.Controls #004 If TypeName(Ctr) = \"TextBox\" Then #005 Ctr = \"\" #006 End If #007 Next #008 End Sub 57 VBA常用技巧代码解析 代码解析: 按钮的单击事件,遍历所有控件并把所有文本框的内容清空。 第2行代码,声明变量类型。 第3行代码,使用For Each...Next 语句遍历窗体所有控件。 第4行代码,使用TypeName 函数返回变量的对象类型。 TypeName 函数返回一个字符串,提供有关变量的信息,语法如下: TypeName(varname) 参数varname是必需的,它包含用户定义类型变量之外的任何变量。 如果变量Ctr是文本框控件,无论该文本框的名称是否已经被修改,TypeName(Ctr)都会返回“TextBox”字符串。 对于工作表中的控件,则使用下面的代码。 #001 Private Sub CommandButton1_Click() #002 Dim Obj As OLEObject #003 For Each Obj In Me.OLEObjects #004 If TypeName(Obj.Object) = \"TextBox\" Then #005 Obj.Object.Text = \"\" #006 End If #007 Next #008 End Sub 22-3 使用程序标识符遍历控件 工作表中的ActiveX控件还可以根据控件的程序标识符找到相应的控件,如下面的代码所示。 #001 Private Sub CommandButton1_Click() #002 Dim Obj As OLEObject #003 For Each Obj In Me.OLEObjects #004 If Obj.progID = \"Forms.TextBox.1\" Then #005 Obj.Object.Text = \"\" #006 End If #007 Next #008 End Sub 代码解析: 58 VBA常用技巧代码解析 工作表中按钮的单击事件,遍历工作表中的所有控件并把工作表中所有文本框的内容清空。 第2行代码,声明变量类型。 第3行代码,使用For Each...Next 语句遍历工作表中的所有控件。 第4行代码,使用控件的ProgId 属性返回控件的程序标识符。 ProgId 属性返回控件的程序标识符,语法如下: expression.ProgId 参数expression是必需的,一个有效的对象。 ActiveX 控件的程序标识符如表格 22-1所示。 控件名称 复选框 组合框 命令按钮 框架 图像 标签 列表框 多页 选项按钮 滚动条 旋转按钮 TabStrip 文字框 切换按钮 标识符 Forms.CheckBox.1 Forms.ComboBox.1 Forms.CommandButton.1 Forms.Frame.1 Forms.Image.1 Forms.Label.1 Forms.ListBox.1 Forms.ListBox.1 Forms.OptionButton.1 Forms.ScrollBar.1 Forms.SpinButton.1 Forms.TabStrip.1 Forms.TextBox.1 Forms.ToggleButton.1 表格 22-1 ActiveX 控件的程序标识符 文本框控件返回的程序标识符是“Forms.TextBox.1”,此返回值并不受文本框控件名称的影响,所以根据工作表中控件的程序标识符可以找出全部文本框控件。 22-4 使用名称中的变量遍历图形 如果工作表中有多个图形,可以根据名称的序号使用For...Next 语句遍历图形,如下面的代码所示。 #001 Private Sub CommandButton1_Click() #002 Dim i As Integer 59 VBA常用技巧代码解析 #003 For i = 1 To 3 #004 Me.Shapes(\"文本框 \" & i).TextFrame.Characters.Text = \"TextBox\" & i #005 Next #006 End Sub 代码解析: 工作表中按钮的单击事件,在工作表中的三个图形文本框中依次写入“TextBox1”、“TextBox2”和“TextBox3”字符串。 第3行到第5行代码,使用Shapes属性在工作表上的三个图形文本框中循环。 Shapes属性返回Shapes对象,代表工作表或图形工作表上的所有图形,可以使用Shapes(index)(其中index是图形的名称或索引号)返回单个的Shape对象。 返回单个的Shape对象后使用Characters 方法向图形文本框中添加字符。Characters 方法的语法如下: expression.Characters(Start, Length) 参数expression是必需的,返回一个指定文本框内Characters对象的表达式。 参数Start是可选的,表示将要返回的第一个字符。如果此参数设置为 1 或被忽略,则Characters方法会返回以第一个字符为起始字符的字符区域。 参数Length是可选的,表示要返回的字符个数。如果此参数被忽略,则Characters 方法会返回该字符串的剩余部分。 22-5 使用FormControlType属性遍历图形 如果工作表中的是窗体控件,可以使用For Each...Next语句遍历工作表中图形并根据其FormControlType属性返回特定的窗体控件,如下面的代码所示。 #001 Private Sub CommandButton2_Click() #002 Dim myShape As Shape #003 For Each myShape In Sheet4.Shapes #004 If myShape.Type = msoFormControl Then #005 If myShape.FormControlType = xlCheckBox Then #006 myShape.ControlFormat.Value = 1 #007 End If #008 End If #009 Next #010 End Sub 60 VBA常用技巧代码解析 代码解析: 工作表中按钮的单击事件,清除工作表中所有的复选框。 第2行代码声明变量myShape为图形对象。 第3行代码使用For Each...Next语句遍历工作表中的图形。 第4行代码根据图形的Type属性判断图形是否为窗体控件。应用于Shape对象的Type属性返回或设置图形类型,窗体控件返回常量msoFormControl。 第5行代码根据控件的FormControlType属性判断窗体控件是否为复选框控件。FormControlType属性返回窗体控件的类型,可以为表格 22-2所示的XlFormControl常量之一。 常量 xlButtonControl xlCheckBox xlDropDown xlGroupBox xlLabel xlListBox xlOptionButton xlScrollBar xlSpinner 值 0 1 2 4 5 6 7 8 9 控件类型 按钮 复选框 组合框 分组框 标签 列表框 选项按钮 滚动条 微调项 表格 22-2 XlFormControl常量 第6行代码使用ControlFormat属性返回工作表中的复选框,并将其他Value属性设置为1选中复选框,如果需要取消复选框只需将Value属性设置为-4146。 技巧23 使微调框最小变动量小于1 在用微调框调节数值时,默认的变动量只能设置成整数。为了使微调框的变动量小于1,如每次的变动量为0.01,需要在代码中做必要的设置,如下面的代码所示。 #001 Private Sub UserForm_Initialize() #002 With Me.SpinButton1 61 VBA常用技巧代码解析 #003 .Max = 10000 #004 .Min = -10000 #005 .SmallChange = 1 #006 .Value = 0 #007 Me.TextBox1 = Format(.Value, \"0.00\") #008 End With #009 End Sub #010 Private Sub SpinButton1_Change() #011 Me.TextBox1 = Format(Me.SpinButton1 * 0.01, \"0.00\") #012 End Sub 代码解析: 使用微调框调节文本框的数值,每次的变动量为0.01。 第1行代码到第9行代码,窗体的初始化事件,在窗体显示时对微调框控件进行必要的设置。 第3、4行代码,设置微调框控件的Max、Min 属性。Max、Min 属性规定滚动条或数值调节钮的 Value 属性可接收的最大值和最小值,语法如下: object.Max [= Long] object.Min [= Long] 参数object是必需的,一个有效的对象。 参数Long是可选的,指定Value属性的最大设置值或最小设置值。 第5行代码,设置微调框控件的SmallChange属性为1。SmallChange属性设定当用户单击滚动条或数值调节钮中的滚动箭头时发生的变动量,语法如下: object.SmallChange [= Long] 参数object是必需的,一个有效的对象。 参数Long是可选的,设定Value属性的变动量。 SmallChange属性只能设置为整数。 第6行代码,设置窗体显示时微调框控件的Value属性为0。 第7行代码,使用Format函数将将文本框的初始值格式化为“0.00”。关于Format函数请参阅技巧5 。 第11行代码,微调框控件的Change事件,在微调框控件的Value属性发生变动时,将变动量乘0.01后赋给文本框,使文本框的变动量每次为0.01。 窗体运行后效果如图 23-1所示。 62 VBA常用技巧代码解析 图 23-1 微调框变动量小于1 技巧24 不打印工作表中的控件 在打印工作表时,如果工作表中有控件,会把控件也一起打印出来,从而影响打印出来的工作表的美观。经过简单的设置能使工作表中的控件不被打印出来。 24-1 设置控件格式 如果工作表中的是窗体控件,设置时右键单击控件,在显示的右键快捷菜单中选择“设置控件格式”,在“设置控件格式”选项卡中选择“属性”页面,使“打印对象”前的复选框为空白状态,如图 24-1所示。 63 VBA常用技巧代码解析 图 24-1 窗体控件 如果工作表中的控件是ActiveX控件,那么需要在设计模式下右键单击控件,在显示的右键快捷菜单中选择“设置控件格式”,在“设置控件格式”选项卡中选择“属性”页面,使“打印对象”前的复选框为空白状态,如图 24-2所示。 VBA常用技巧代码解析 图 24-2 ActiveX控件 24-2 设置控件的printobjcet属性 如果工作表中的控件是ActiveX控件,使用除了使用技巧24-1的方法外,还可以在设计模式下右键单击控件,选择“属性”,设置控件的printobjcet属性为False。如图 24-3所示。 图 24-3 设置控件printobjcet属性 技巧25 在框架中使用滚动条 如果需要在窗体中显示较多的内容,比如使用标签显示一段很长的文本内容,而又不希望窗体很大的话,可以在窗体中使用框架放置标签,设置框架可滚动区域的高度,使标签可 65 VBA常用技巧代码解析 以进行上下移动以查看全部区域。 在VBE窗口中单击菜单“插入”→“用户窗体”,在窗体中添加一个框架控件,在框架中添加一个标签控件。根据需要显示的内容调整好标签的大小,再将框架和窗体调整为合适的大小。 在VBE中双击窗体,写入下面的代码。 #001 Private Sub UserForm_Initialize() #002 Dim sLab As String #003 sLab = Space(4) & \"欢迎来到ExcelHome技术论坛,全球最领先的Excel技术论坛之一。\" & vbLf _ #004 & Space(4) & \"在这里,我们讨论Microsoft Office系列产品的应用技术,重点讨论Microsoft Excel。本论坛从属于Excel Home这一全球最大的华语Excel技术门户,目前是个人、非营利性质的网站学习平台。各行各业的Excel使用者都活跃在此,各种形式的学习资源也汇聚于在此,所以,只要您愿意花时间,并使用正确的方法,我们有理由相信您的绝大部分应用问题和学习愿望都在这里被满足。无数已经取得了非凡进步的人,也可以证明这一点。\" & vbLf _ #005 & Space(4) & \"Let’s do it better!这是Excel Home的口号,我们的宗旨是帮助大家解决在使用Office软件中的问题,提升自己的应用技能。\" & vbLf _ #006 & Space(4) & \"鉴于许多人在此之前没有正确使用网络学习资源的经验,或者对Excel Home的行为规则缺乏了解,我们特别准备了这样一篇文章,送给每一位有志与我们一起成长的朋友。本文将重点叙述学习方法和论坛的规则,对于如何使用论坛的各项功能,请阅读论坛的帮助系统(http://club.excelhome.net/boardhelp.asp )\" #007 Label1.Caption = sLab #008 With Frame1 #009 .ScrollBars = 2 #010 .ScrollHeight = Label1.Height #011 End With #012 End Sub 代码解析: 窗体的初始化事件,在窗体加载时使用标签显示文本内容。 第3行到第6行代码,变量sLab为要显示的文本,使用Space函数在每段的首字前插入4个空格,使首字缩进。在需要换行的地方插入常数vbLf进行换行。 第9行代码,设置框架的ScrollBars属性为显示垂直滚动条。ScrollBars属性指定一个控件、窗体或页面是否有垂直或水平滚动条,或两者都有,语法如下: object.ScrollBars [= fmScrollBars] 参数object是必需的,一个有效的对象。 66 VBA常用技巧代码解析 参数fmScrollBars是可选的,滚动条的显示位置,设置值如表格 25-1所示。 常量 fmScrollBarsNone fmScrollBarsHorizontal fmScrollBarsVertical fmScrollBarsBoth 值 0 1 2 3 说明 不显示滚动条(默认)。 显示水平滚动条。 显示垂直滚动条。 垂直和水平滚动条都显示。 表格 25-1 ScrollBars属性设置值 第10行代码,设置框架的ScrollHeight属性为标签的高度。ScrollHeight属性指定通过移动控件、窗体或页面中的滚动条,可以查看的全部区域的高度,语法如下: object.ScrollHeight [= Single] 参数object是必需的,一个有效的对象。 参数Single是可选的,可滚动区域的高度。 如果框架具有水平滚动条,可以设置框架的ScrollWidth属性来设置可以查看的全部区域的宽度。 运行窗体,使用标签显示文本内容,可通过框架的滚动条查看全部内容,如图 25-1所示。 图 25-1 在框架中使用滚动条 技巧26 使用多页控件 67 VBA常用技巧代码解析 在处理可以划分为不同类别的大量信息时可以使用多页控件。例如,在示例中,多页控件的第一页用于显示欢迎信息,另三页显示其他信息。利用多页控件能够将相关信息组织在一起显示出来,同时又能够随时访问整条记录。 多页控件中的每个页面都是一个窗体,含有自己的控件,并且可以有唯一的布局。一般情况下,多页控件中的页面都有标签,以便让用户选择单个页面。 在窗体中使用多页控件时,往往希望窗体显示时能显示特定的页面,比如每次打开窗体时先显示第一页的欢迎信息,除了在VBE中选择多页控件的第一页后保存外,还可以通过设置多页控件的Value属性来实现,如下面的代码所示。 #001 Private Sub UserForm_Initialize() #002 MultiPage1.Value = 0 #003 End Sub 代码解析: 窗体的Initialize事件,在窗体显示时选择多页控件的第一页。 控件的Value属性定义某给定的控件的状态或内容,对于多页控件标识当前激活页。 Value属性是多页控件的默认属性,该属性返回当前活动页面的索引编号(位于多页控件的Pages集合中),零 ( 0 ) 表示是第一页,最大值比总页数少一。 多页控件的默认事件是Change事件,示例中使用消息框显示当前活动页面的Caption属性,代码如下: #001 Private Sub MultiPage1_Change() #002 If MultiPage1.SelectedItem.Index > 0 Then #003 MsgBox \"欢迎来到\" & MultiPage1.SelectedItem.Caption & \"版块!\" #004 End If #005 End Sub 代码解析: MultiPage1_Change过程根据当前活动页面是否是第一页,如果不是则使用消息框显示当前活动页面的Caption属性。 应用于Page对象的Index属性指Pages集合中Page对象的位置,语法如下: object.Index [= Integer] 参数object是必需的,一个有效对象。 参数Integer是可选的,当前选定的Page对象的索引。 Index 属性指定了标签出现的顺序,改变Index属性的值将改变多页控件中页面的顺序,第一页的索引值是0,第二页的索引值是 1,依此类推。 应用于多页控件的SelectedItem属性返回当前选中的Page对象,SelectedItem属性 68 VBA常用技巧代码解析 是只读的,用SelectedItem属性可对当前选中的Page对象进行可编程控制。 运行窗体,多页控件显示第一页的欢迎信息,当选择其他页面时显示提示信息,如图 26-1所示。 图 26-1 使用多页控件 技巧27 标签文字垂直居中对齐 在使用标签控件为其他控件作题注时,只能设置题注文字在水平方向的对齐方式,不能设置为垂直居中。要达到题注文字垂直居中的效果,可以使用两个标签控件组合来完成。 步骤1,在窗体中添加一个标签控件Label1,将Caption属性设置为空,再设置需要的背景颜色及边框颜色。 步骤2,添加一个标签控件Label2,将Caption属性设置为需要的标题;AutoSize属性设置为True,BackStyle属性设置为0,TextAligh属性设置为fmTextAlignCenter,其它属性不改变。 AutoSize属性规定对象是否自动调整大小以显示其完整的内容,语法如下: object.AutoSize [= Boolean] 参数object是必需的,一个有效对象。 69 VBA常用技巧代码解析 参数Boolean是可选的,是否自动调整大小。设置值为True控件可自动调整大小以显示其完整的内容,设置为False控件尺寸保持不变。如果内容超出了控件的区域,内容将被剪裁(默认)。 BorderStyle属性指定控件或窗体的边框类型,语法如下: object.BorderStyle [= fmBorderStyle] 参数object是必需的,一个有效对象。 参数fmBorderStyle是可选的,指定边框类型,设置值如表格 27-1所示。 常量 fmBackStyleTransparent fmBackStyleOpaque 值 0 1 描述 背景为透明 背景为不透明(默认值) 表格 27-1 fmBorderStyle设置值 TextAligh属性定义控件中文本的对齐方式,语法如下: object.TextAlign [= fmTextAlign] 参数object是必需的,一个有效对象。 参数fmTextAlign是可选的,控件中文本的对齐方式,设置值如表格 27-2所示。 常量 fmTextAlignLeft fmTextAlignCenter fmTextAlignRight 值 1 2 3 描述 将所显示文本的第一个字符与控件显示或编辑区的左边界对齐(默认值)。 在控件的显示或编辑区中,使文本对齐 将所显示文本的最后一个字符与控件显示或编辑区的右边界对齐。 表格 27-2 fmTextAlign设置值 步骤3,同时选中两个标签控件,在右键弹出菜单中选择“统一尺寸”→“宽度相同”,再右击选择“对齐”→“左对齐”,重新右键“对齐”→“中间对齐”。 步骤4,最后同时选中两个标签控件,在右键弹出菜单中选择“生成组”,就达到标题为垂直居中的效果了,如图 27-1窗体中左边的标签所示。 70 VBA常用技巧代码解析 图 27-1 标签控件标题垂直居中 技巧28 使用TabStrip控件 使用TabStrip控件,可以在用户窗体中的同一区域定义多个数据页面,也就是说使用TabStrip控件可以使用户窗体中的同一组控件根据TabStrip控件所选择的页面具有不同的功能,而不必像多页控件那样需要在每个页面中放置相同的控件。 在示例的窗体中使用一个图像控件和一个标签控件,根据TabStrip控件所选择的页面来显示相应城市的图片和标签控件的题注。 步骤1,在窗体中添加一个TabStrip控件,默认情况下,一个TabStrip控件包含两个页面,所以需要在TabStrip控件上右键单击,在显示的右键菜单中选择“新建页”继续添加三个页面。因为TabStrip控件不像多页控件具有分页的属性窗口,所以需要在显示的右键菜单中选择“重命名”将页面分别重命名为各城市的名称。 步骤2,在TabStrip控件上添加一个Image控件和一个Label控件,调整为合适的大小。 步骤3,双击窗体写入下面的代码: #001 Private Sub TabStrip1_Change() #002 Dim FilPath As String #003 FilPath = ThisWorkbook.Path & \"\\\" & TabStrip1.SelectedItem.Caption & \".jpg\" #004 Image1.Picture = LoadPicture(FilPath) 71 VBA常用技巧代码解析 #005 Label1.Caption = TabStrip1.SelectedItem.Caption & \"欢迎您!\" #006 End Sub #007 Private Sub UserForm_Initialize() #008 TabStrip1.Value = 0 #009 End Sub 代码解析: 第1行到第6行代码,TabStrip控件的Change事件过程,根据TabStrip控件所选择的页面来显示相应城市的图片和标签控件的题注。 第3行代码设置Image控件需加载图片的完整路径,使用SelectedItem属性返回TabStrip控件当前选中页面的Caption属性,即窗体中所选城市的名称,将图片的完整路径设置为保存在同一目录中已命名为所选城市的图片。 第4行代码为Image控件加载图片。Picture 属性指定显示在对象上的位图,语法如下: object.Picture = LoadPicture( pathname ) 参数expression是必需的,一个有效的对象。 参数pathname是必需的,一个图片文件的完整路径。 第5行代码设置标签控件的题注为窗体中所选城市的名称和“欢迎您!”。 第7行到第9行代码窗体的Initialize事件过程,为了使窗体显示时TabStrip控件显示第一页,将其Value设置为零 ( 0 )。 运行窗体,选择不同的标签将显示不同城市的图片,如图 28-1所示。 图 28-1 使用TabStrip控件(一) 如果将TabStrip控件的Style属性设置为1则在标签条中显示的是按钮而不是标签,如图 28-2所示。 72 VBA常用技巧代码解析 图 28-2 使用TabStrip控件(二) 技巧29 显示GIF动画图片 如果希望在Excel中显示GIF格式的动画图片,可以使用AniGif控件。 步骤1,在工作表中单击菜单“视图”→“工具栏”→“控件工具箱”→“其他控件”,选择“VBAniGIF. AniGif”后在工作表中拖动添加AniGif控件,如图 29-1所示。 图 29-1 添加AniGif控件 如果“其他控件”中没有该控件,那么需要对该控件进行注册。注册控件请参阅技巧21 。AniGif控件的文件名为VBAniGIF.OCX,也可以在工作表中单击菜单“视图”→“工具栏”→“控件工具箱”→“其他控件”,选择“注册自定义控件”,在显示的对话框中选择VBAniGIF.OCX文件进行注册,如图 29-2所示。 73 VBA常用技巧代码解析 图 29-2 注册AniGif控件 步骤2,在设计模式下右键单击AniGif控件,选择“属性”,设置AniGif控件的Filename属性为CIF图片所在的路径,如图 29-3所示。 图 29-3 设置Filename属性 可以使用代码设置AniGif控件的Filename属性,如下面的代码所示。 #001 Private Sub Workbook_Open() #002 Sheet1.AniGif1.Filename = ThisWorkbook.Path & \"\\001.gif\" 74 VBA常用技巧代码解析 #003 End Sub 代码解析: 工作簿打开时将AniGif控件的Filename属性设置为同一目录中的“001.gif”文件。 工作簿打开时可能出现如图 29-4所示的对话框,这是因为当打开包含ActiveX控件的文件时,如果该控件被标识为初始化不安全时,Office程序不加载或激活未被标志为初始化安全的ActiveX控件。 图 29-4 初始化不安全ActiveX控件提示 解决此问题的方法是更改Office程序处理ActiveX组件的方式,需要对注册表进行修改。也可以使用以下代码修改注册表: #001 Sub RegWriteProc() #002 Dim WshShell #003 Set WshShell = CreateObject(\"Wscript.Shell\") #004 WshShell.RegWrite \"HKCU\\Software\\Microsoft\\Office\\Common\\Security\\UFIControls\ #005 WshShell.RegWrite \"HKCU\\Software\\Microsoft\\VBA\\Security\\LoadControlsInForms\ #006 Set WshShell = Nothing #007 End Sub 代码解析: RegWriteProc过程修改注册表设置。第4行代码将UFIControls子项设置为1(最不安全)。第5行代码将LoadControlsInForms子项设置为1(最不安全)。关于为ActiveX控件授予权限请参阅微软的技术文章:http://support.microsoft.com/kb/827742/zh-cn 退出设计模式后,将在工作表中显示GIF动画图片,如图 29-5所示。 75 VBA常用技巧代码解析 图 29-5 显示GIF动画图片 技巧30 播放Flash文件 如果需要在工作表中播放Flash文件,那么可以使用ShockwaveFlash控件。 步骤1,在工作表中单击菜单“视图”→“工具栏”→“控件工具箱”→“其他控件”,选择“ShocKwave Flash Object”后在工作表中拖动添加ShockwaveFlash控件,如图 30-1所示。 76 VBA常用技巧代码解析 图 30-1 添加ShockwaveFlash控件 如果“其他控件”中没有该控件,请参阅技巧29 对其进行注册,ShockwaveFlash控件的文件名为Flash9d.OCX。 步骤2,在设计模式下右键单击ShockwaveFlash控件,选择“属性”,设置ShockwaveFlash控件的Base属性和Movie属性为Flash文件所在的路径,设置Embedmovie属性为True,使Flash文件嵌入到Excel中,如图 30-2所示。 图 30-2 设置ShockwaveFlash控件属性 可以使用代码设置ShockwaveFlash控件的各项属性,如下面的代码所示。 #001 Private Sub Workbook_Open() 77 VBA常用技巧代码解析 #002 With Sheet1.ShockwaveFlash1 #003 .Base = ThisWorkbook.Path & \"\\face.swf\" #004 .Movie = ThisWorkbook.Path & \"\\face.swf\" #005 .EmbedMovie = True #006 End With #007 End Sub 代码解析: 工作簿打开时将ShockwaveFlash控件的Base属性和Movie属性设置为同一目录中的“face.swf”文件,设置Embedmovie属性为True。 退出设计模式后,将在工作表中显示Flash动画,如图 30-3所示。 图 30-3 显示Flash动画 技巧31 在工作表中添加窗体控件 78 VBA常用技巧代码解析 在工作表中添加窗体控件,除了使用手工添加外,还可以使用代码添加,方法如下: 31-1 使用AddFormControl方法 使用AddFormControl方法在工作表中添加窗体控件,如下面的代码所示。 #001 Sub AddFormControls() #002 Dim myShape As Shape #003 On Error Resume Next #004 Sheet1.Shapes(\"myButton\").Delete #005 Set myShape = Sheet1.Shapes.AddFormControl(0, 108, 72, 108, 27) #006 With myShape #007 .Name = \"myButton\" #008 With .TextFrame.Characters #009 .Font.ColorIndex = 3 #010 .Font.Size = 12 #011 .Text = \"新建的按钮\" #012 End With #013 .OnAction = \"myButton\" #014 End With #015 End Sub #016 Sub myButton() #017 MsgBox \"这是使用AddFormControl方法新建的按钮!\" #018 End Sub 代码解析: AddFormControls过程使用AddFormControl方法在工作表中添加窗体控件。 第3、4行代码为了避免在工作表中重复添加按钮控件,先删除工作表中的“myButton”按钮。 第5行代码,使用AddFormControl方法在工作表中添加命令按钮控件并设置控件的坐标和大小。应用于Shapes对象的AddFormContl方法创建一个Microsoft Excel控件,返回一个Shape对象,该对象代表新建的控件,语法如下: expression.AddFormControl(Type, Left, Top, Width, Height) 参数expression是必需的,一个有效的对象。 参数Type是必需的,Microsoft Excel控件类型,可以为表格 31-1所列XlFormControl 79 VBA常用技巧代码解析 常量之一。 常量 xlButtonControl xlCheckBox xlDropDown xlEditBox xlGroupBox xlLabel xlListBox xlOptionButton xlScrollBar xlSpinner 值 0 1 2 3 4 5 6 7 8 9 说明 命令按钮 复选框 组合框 编辑框 分组框 标签 列表框 选项按钮 滚动条 微调项 表格 31-1 XlFormControl 常量 参数Left是必需的,新对象的初始坐标(以磅为单位)相对于工作表 A1 单元格的左上角或图表的左上角。 参数Top是必需的,新对象的初始坐标(以磅为单位)相对于工作表 A1 单元格的左上角或图表的左上角。 参数Width是必需的,以磅为单位的新对象的初始大小。 参数Height是必需的,以磅为单位的新对象的初始大小。 第7行代码将新添加的按钮名称设置为“myButton”。 第8行到第12行代码设置新添加的按钮文字设置为“新建的按钮”,并设置文字的大小和颜色。 第13行代码,指定新添加按钮所执行的宏名称。 myButton过程是单击新添加按钮所执行的过程,显示一个消息框。 运行AddFormControls过程将在工作表中添加一个命令按钮,单击按钮显示一个消息框,如图 31-1所示。 80 VBA常用技巧代码解析 图 31-1 使用AddFormControl方法添加窗体控件 31-2 使用Add方法 在工作表中添加窗体控件还可以使用Add方法,如下面的代码所示。 #001 Sub AddChartObjects() #002 Dim myButton As Button #003 On Error Resume Next #004 Sheet1.Shapes(\"myButton\").Delete #005 Set myButton = Sheet1.Buttons.Add(108, 72, 108, 27) #006 With myButton #007 .Name = \"myButton\" #008 .Font.Size = 12 #009 .Font.ColorIndex = 5 #010 .Characters.Text = \"新建的按钮\" #011 .OnAction = \"myButton\" #012 End With #013 End Sub #014 Sub myButton() #015 MsgBox \"这是使用Add方法新建的按钮!\" #016 End Sub 代码解析: 81 VBA常用技巧代码解析 AddChartObjects过程使用Add方法在工作表中添加窗体控件。 第3、4行代码为了避免在工作表中重复添加按钮控件,先删除工作表中的“myButton”按钮。 第5行代码,使用Add方法在工作表中添加命令按钮控件,Add方法适用于ChartObjects对象的语法如下: expression.Add(Left, Top, Width, Height) 参数expression是必需的,该表达式返回一个ChartObjects对象。 如果需要在工作表中添加其他窗体控件,可以将参数expression设置为表格 31-2所示的ChartObjects对象之一。 类型 复选框 组合框 标签 列表框 选项按钮 滚动条 微调项 ChartObjects对象 CheckBoxes DropDowns Labels ListBoxes OptionButtons ScrollBars Spinners 表格 31-2 ChartObjects对象 参数Left和Top是必需的,以磅为单位给出新对象的初始坐标,该坐标是相对于工作表上单元格 A1 的左上角或图表的左上角的坐标。 参数Width和参数Height是必需的,以磅为单位给出新对象的初始大小。 第7行代码将新添加的按钮的名称设置为“myButton”。 第8行到第10代码新添加的按钮的文字设置为“新建的按钮”并设置文字的大小和颜色。 第11行代码,指定新添加命令按钮所执行的宏名称。 myButton过程是单击新添加按钮所执行的过程,显示一个消息框。 运行AddChartObjects过程将在工作表中添加一个命令按钮,单击按钮显示一个消息框,如图 31-2所示。 82 VBA常用技巧代码解析 图 31-2 使用Add方法添加窗体控件 技巧32 在工作表中添加ActiveX控件 技巧31 中使用代码在工作表中添加的是窗体控件,而本例中使用代码在工作表中添加的是ActiveX控件,两者是有区别的,在工作表中前者是使用窗体对话框添加,而后者是使用控件工具箱添加,如图 32-1所示。 83 VBA常用技巧代码解析 图 32-1 窗体控件和ActiveX控件的区别 32-1 使用Add方法 使用Add方法在工作表中添加ActiveX控件,如下面的代码所示。 #001 Sub AddObj() #002 Dim Obj As New OLEObject #003 On Error Resume Next #004 Sheet1.OLEObjects(\"MyButton\").Delete #005 Set Obj = Sheet1.OLEObjects.Add(ClassType:=\"Forms.CommandButton.1\_ #006 Left:=108, Top:=72, Width:=108, Height:=27) #007 With Obj #008 .Name = \"MyButton\" #009 .Object.Caption = \"新建的按钮\" #010 .Object.Font.Size = 16 #011 .Object.ForeColor = &HFF& #012 End With #013 With ActiveWorkbook.VBProject.VBComponents(Sheet1.CodeName).CodeModule #014 If .Lines(1, 1) <> \"Option Explicit\" Then #015 .InsertLines 1, \"Option Explicit\" #016 End If #017 If .Lines(2, 1) = \"Private Sub MyButton_Click()\" Then Exit Sub #018 .InsertLines 2, \"Private Sub MyButton_Click()\" #019 .InsertLines 3, vbTab & \"MsgBox \"\"这是使用Add方法新建的按钮!\"\"\" #020 .InsertLines 4, \"End Sub\" #021 End With #022 End Sub 代码解析: AddOLEObject过程使用Add方法在向工作表中添加ActiveX控件中的命令按钮和相应的代码。 第3、4行代码为了避免在工作表中重复添加按钮控件,先删除工作表中的名称为 84 VBA常用技巧代码解析 “myButton”的按钮。 第5、6行代码,使用Add方法在向工作表中添加ActiveX控件中的命令按钮,Add方法应用于OLEObjects 对象的语法如下: expression.Add(ClassType, FileName, Link, DisplayAsIcon, IconFileName, IconIndex, IconLabel, Left, Top, Width, Height) 其中参数expression是必需的,返回一个 OLEObjects 对象。 参数ClassType是可选的,创建的对象的程序标识符。如果指定了 ClassType参数,则忽略FileName参数和Link参数。 在本例中指定添加控件的程序标识符为“Forms.CommandButton.1”,即命令按钮控件,关于对象的程序标识符请参阅技巧22-3。 参数Left和参数Top是必需的,以磅为单位给出新对象的初始坐标,该坐标是相对于工作表上单元格 A1 的左上角或图表的左上角的坐标。 参数Width和参数Height是可选的,以磅为单位给出OLE对象的初始大小。 第8行代码,设置命令按钮的名称为“MyButton”。 第9行代码,设置命令按钮的文字为“新建的按钮” 第10行代码,设置命令按钮的文字的大小。 第11行代码,设置命令按钮的文字的颜色。 第13行到第21行代码,在工作表中写入新添加的命令按钮的单击事件代码。 ActiveX控件不能像窗体控件用OnAction属性来指定宏,需要使用CodeModule对象的InsertLines方法在工作表中插入代码。 应用于CodeModule对象的InsertLines方法的语法如下: object.InsertLines(line, code) 参数object是必需的,一个有效的对象。 参数line是必需的,用来指定要插入代码的位置。 参数code是必需的,要插入的代码。 第14行到第16行代码判断首行内容是否为要求变量声明,如不是则添加要求变量声明语句。 第17行到第20行代码判断是否已存在相同名称的过程,如不存在则使用InsertLines方法在工作表中插入代码。 运行AddOLEObject过程,将在工作表中添加一个命令按钮和相应的代码,单击按钮显示一个消息框,如图 32-2所示。 85 VBA常用技巧代码解析 图 32-2 使用Add方法添加ActiveX控件 32-2 使用AddOLEObject方法 在工作表中添加ActiveX控件,还可以使用AddOLEObject方法,如下面的代码所示。 #001 Sub AddShapes() #002 Dim ShpBut As Shape #003 On Error Resume Next #004 Sheet1.OLEObjects(\"MyButton\").Delete #005 Set ShpBut = Sheet1.Shapes.AddOLEObject(ClassType:=\"Forms.CommandButton.1\ #006 Left:=108, Top:=72, Width:=108, Height:=27) #007 ShpBut.Name = \"MyButton\" #008 With ActiveWorkbook.VBProject.VBComponents(Sheet1.CodeName).CodeModule #009 If .Lines(1, 1) <> \"Option Explicit\" Then #010 .InsertLines 1, \"Option Explicit\" #011 End If #012 If .Lines(2, 1) = \"Private Sub MyButton_Click()\" Then Exit Sub #013 .InsertLines 2, \"Private Sub MyButton_Click()\" #014 .InsertLines 3, vbTab & \"MsgBox \"\"这是使用AddOLEObject方法新建的 86 VBA常用技巧代码解析 按钮!\"\"\" #015 .InsertLines 4, \"End Sub\" #016 End With #017 End Sub 代码解析: AddShapes过程使用AddOLEObject方法在向工作表中添加ActiveX控件中的命令按钮和相应的代码。 第5、6行代码,使用AddOLEObject方法在向工作表中添加ActiveX控件中的命令按钮,AddOLEObject方法创建OLE对象,语法如下: expression.AddOLEObject(ClassType, FileName, Link, DisplayAsIcon, IconFileName, IconIndex, IconLabel, Left, Top, Width, Height) AddOLEObject方法参数与Add方法类似,请参阅技巧32-1。 运行AddShapes过程,将在工作表中添加一个命令按钮和相应的代码,单击按钮显示一个消息框,如图 32-3所示。 图 32-3 使用AddOLEObject方法添加ActiveX控件 技巧33 使用spreadsheet控件 87 VBA常用技巧代码解析 如果希望在窗体中显示类似工作表的表格,并且可以像工作表一样进行操作,那么可以在窗体中使用表格控件(Spreadsheet控件)。 步骤1,在VBE窗口中单击菜单“插入”→“用户窗体”,在窗体上添加一个Spreadsheet控件,双击窗体,在其代码窗口中输入下面的代码: #001 Private Sub UserForm_Initialize() #002 Dim iRow As Integer #003 Dim arr As Variant #004 With Me.Spreadsheet1 #005 .DisplayToolbar = False #006 .DisplayHorizontalScrollBar = False #007 .DisplayVerticalScrollBar = False #008 .DisplayWorkbookTabs = False #009 iRow = Sheet1.Range(\"B65536\").End(xlUp).Row #010 arr = Sheet1.Range(\"B2:H\" & iRow) #011 With .Range(\"B2:H\" & iRow) #012 .Value = arr #013 .Borders.LineStyle = xlContinuous #014 .Borders.Weight = xlMedium #015 .Borders.ColorIndex = 10 #016 End With #017 With .Range(\"B2:H2\") #018 .HorizontalAlignment = -4108 #019 .VerticalAlignment = -4108 #020 .Interior.ColorIndex = 44 #021 End With #022 .Range(\"B3:B\" & iRow).HorizontalAlignment = -4108 #023 .Range(\"C3:H\" & iRow).NumberFormat = \"0.00\" #024 .Rows(2).RowHeight = 23.25 #025 .Columns(\"A\").ColumnWidth = 2.75 #026 .Columns(\"B:H\").ColumnWidth = 8 #027 End With #028 End Sub 88 VBA常用技巧代码解析 代码解析: 用户窗体的初始化事件过程,使用窗体显示工作表中的表格。 第5行代码,设置Spreadsheet控件不显示工具栏。 DisplayToolbar 属性设置工具栏是否隐藏,语法如下: expression.DisplayToolbar 参数expression是必需的,一个有效的对象。 如果指定电子表格、图表区或“数据透视表”列表显示了工具栏,则返回True。 第6、7行代码,设置Spreadsheet控件不显示水平和垂直滚动条。 第8行代码,设置Spreadsheet控件不显示工作表标签。 第9行代码,取得工作表B列有数据的最后一行的行号。 第10行代码,把工作表数据赋值给数组。 第11行到16行代码,把数组赋给Spreadsheet控件的单元格,使Spreadsheet控件显示工作表内容,并且添加加框线。 第17行到第21行代码,设置Spreadsheet控件中表格第一行的字体对齐方式为居中并添加单元格的底纹颜色。 第22行代码,设置Spreadsheet控件中表格第一列的字体对齐方式为居中。 第23行代码,设置Spreadsheet控件中表格数据的格式。 第24行到26行代码,设置Spreadsheet控件的行高与列宽。 步骤2,在窗体上添加一个按钮控件,将其Caption属性设置为“保存”,双击按钮控件,在其代码窗口中输入下面的代码: #001 Private Sub CommandButton1_Click() #002 Dim iRow As Integer #003 Dim arr As Variant #004 If MsgBox(\"是否保存对表格所作的修改?\#005 With Me.Spreadsheet1 #006 iRow = .Range(\"B65536\").End(xlUp).Row #007 arr = .Range(\"B2:H\" & iRow).Value #008 Sheet1.Range(\"B2:H\" & iRow).Value = arr #009 End With #010 End If #011 Unload Me #012 End Sub VBA常用技巧代码解析 代码解析: 用户窗体中“保存”按钮的单击过程,把在窗体中对数据的修改重新保存到工作表。 第4行代码,询问用户是否保存修改。 第5行到第10行代码,如果用户选择保存,把Spreadsheet控件中的数据保存到工作表。 运行窗体,显示效果如图 33-1所示。 图 33-1 使用Spreadsheet控件 技巧34 使用Listview控件 ListView控件是VBA程序开发中的常用控件,可以用来显示各项带图标的列表,也可以用来显示带有子项的列表。 34-1 使用Listview控件显示数据列表 使用Listview控件在用户窗体中显示数据列表,代码如下: #001 Private Sub UserForm_Initialize() #002 Dim Itm As ListItem #003 Dim r As Integer 90 VBA常用技巧代码解析 #004 Dim c As Integer #005 With ListView1 #006 .ColumnHeaders.Add , , \"人员编号 \#007 .ColumnHeaders.Add , , \"技能工资 \#008 .ColumnHeaders.Add , , \"岗位工资 \#009 .ColumnHeaders.Add , , \"工龄工资 \#010 .ColumnHeaders.Add , , \"浮动工资 \#011 .ColumnHeaders.Add , , \"其他 \#012 .ColumnHeaders.Add , , \"应发合计\#013 .View = lvwReport #014 .Gridlines = True #015 For r = 2 To Sheet1.[A65536].End(xlUp).Row #016 Set Itm = .ListItems.Add() #017 Itm.Text = Space(2) & Sheet1.Cells(r, 1) #018 For c = 1 To 6 #019 Itm.SubItems(c) = Format(Sheet1.Cells(r, c + 1), \"##,#,0.00\") #020 Next #021 Next #022 End With #023 Set Itm = Nothing #024 End Sub 代码解析: 窗体的初始化事件,在窗体显示时将工作表中数据显示在Listview控件中。 第6行到第12行代码,使用ColumnHeader对象的Add方法在Listview控件中添加标题列,并设置列标题、列宽和文本对齐方式。 ColumnHeader对象是ListView控件中包含标题文字的项目,应用于ColumnHeader对象的Add方法语法如下: object.ColumnHeader.Add(index,key,text,width,alignment) 其中参数text代表标题文字,参数width代表标题的列宽,参数alignment代表列标题中文本对齐方式。Listview控件中文本的对齐方法有三种,如表格 34-1所示。 常数 值 说明 91 VBA常用技巧代码解析 lvwColumnLeft lvwColumnRight lvwColumnCenter 0 1 2 文本向左对齐。(缺省值) 文本向右对齐。 文本居中对齐。 表格 34-1 Listview控件中文本的对齐方法 在Listview控件中第一列的文本对齐方式只能设置为左对齐。 第13行代码,设置Listview控件的View属性为lvwReport,使Listview控件显示为报表型。View属性决定在列表中控件使用何种视图显示项目,语法如下: object.view [= value] 参数object是必需的,对象表达式,listview控件。 参数value是必需的,指定控件外观的整数或常数,如表格 34-2所示。 常数 lvwicon lvwsmallicon lvwlist lvwreport 值 0 1 2 3 说明 图标 小图标 列表 报表 表格 34-2 View属性的设置值 第14行代码,设置Listview控件的Gridlines属性为True,显示网格线。只有在将View属性设置为lvwReport时才能显示网格线,否则Gridlines属性无效。 第16行代码,使用ListItem对象的Add方法在Listview控件中添加项目。应用于ListItem对象的Add方法语法如下: ListItems.Add(index,key,text,icon,smallIcon) 其中参数text代表添加的项目内容。 第17行代码,添加行标题。ListItem对象的text属性代表Listview控件的第一列内容,因为Listview控件的第一列的文本对齐方式只能设置为左对齐,所以在添加时使用Space函数插入两个空格,使行标题达到居中显示的效果。 第18行到20行代码,继续添加其他列的内容。Listview控件其他列的项目需要使用SubItems属性来添加。 运行窗体,Listview控件显示工作表中的内容,如图 34-1所示。 92 VBA常用技巧代码解析 图 34-1 使用Listview控件显示数据 34-2 在Listview控件中使用复选框 在Listview控件中使用复选框,可以进行多重选择,示例代码如下: #001 Private Sub UserForm_Initialize() #002 Dim Itm As ListItem #003 Dim r As Integer #004 Dim c As Integer #005 With ListView1 #006 .ColumnHeaders.Add , , \"人员编号 \#007 .ColumnHeaders.Add , , \"技能工资 \#008 .ColumnHeaders.Add , , \"岗位工资 \#009 .ColumnHeaders.Add , , \"工龄工资 \#010 .ColumnHeaders.Add , , \"浮动工资 \#011 .ColumnHeaders.Add , , \"其他 \#012 .ColumnHeaders.Add , , \"应发合计\#013 .View = lvwReport #014 .Gridlines = True #015 .FullRowSelect = True #016 .CheckBoxes = True #017 For r = 2 To Sheet2.[A65536].End(xlUp).Row - 1 #018 Set Itm = .ListItems.Add() 93 VBA常用技巧代码解析 #019 Itm.Text = Sheet2.Cells(r, 1) #020 For c = 1 To 6 #021 Itm.SubItems(c) = Format(Sheet2.Cells(r, c + 1), \"##,#,0.00\") #022 Next #023 Next #024 End With #025 Set Itm = Nothing #026 End Sub #027 Private Sub CommandButton1_Click() #028 Dim r As Integer #029 Dim i As Integer #030 Dim c As Integer #031 r = Sheet1.[A65536].End(xlUp).Row #032 If r > 1 Then Sheet1.Range(\"A2:G\" & r) = \"\" #033 With ListView1 #034 For i = 1 To .ListItems.Count #035 If .ListItems(i).Checked = True Then #036 Sheet1.Range(\"A65536\").End(xlUp).Offset(1, 0) = .ListItems(i) #037 For c = 1 To 6 #038 Sheet1.Cells(65536, c + 1).End(xlUp).Offset(1, 0) = .ListItems(i).SubItems(c) #039 Next #040 End If #041 Next #042 End With #043 End Sub 代码解析: 第1行到第26行代码,用户窗体的Initialize事件过程,在窗体显示时将工作表中数据显示在Listview控件中,请参阅技巧0。 其中第15行代码设置Listview控件的FullRowSelect属性为True,使用户可以选择整行。 94 VBA常用技巧代码解析 第16行代码设置Listview控件的CheckBoxes属性为True,使Listview控件在列表的每个项的旁边显示复选框。 第27行到第43行代码,用户窗体中“保存”按钮的单击过程,将Listview控件中选中的项目写入到工作表中。 第31、32行代码,删除工作表中原有的数据, 第34、35行代码遍历Listview控件中所有的ListItem对象,判定其Checked值,如果为True,即说明其处于选中状态。 第36行到第40行代码将Listview控件中选中的内容依次写入到工作表中。 运行窗体,Listview控件显示工作表中的内容,单击“保存”按钮将如Listview控件中选中的内容依次写入到工作表中,如图 34-2所示。 图 34-2 Listview控件使用复选框 34-3 调整Listview控件的行距 在使用Listview控件显示数据列表时,行距是由Listview控件所设置的字体大小决定的,无法自定义行距,即使调整了字体大小,行距还是很近。 如果需要自定义Listview控件的行距,可以在窗体中添加一个ImageList控件,在ImageList控件中导入一张大小合适的空白图片,然后指定Listview控件的SmallIcons属性为ImageList控件中的图片,代码如下: #001 Private Sub UserForm_Initialize() #002 Dim Itm As ListItem #003 Dim r As Integer #004 Dim c As Integer 95 VBA常用技巧代码解析 #005 Dim Img As ListImage #006 With ListView1 #007 .ColumnHeaders.Add , , \"人员编号 \#008 .ColumnHeaders.Add , , \"技能工资 \#009 .ColumnHeaders.Add , , \"岗位工资 \#010 .ColumnHeaders.Add , , \"工龄工资 \#011 .ColumnHeaders.Add , , \"浮动工资 \#012 .ColumnHeaders.Add , , \"其他 \#013 .ColumnHeaders.Add , , \"应发合计\#014 .View = lvwReport #015 .Gridlines = True #016 .FullRowSelect = True #017 Set Img = ImageList1.ListImages.Add(, , LoadPicture(ThisWorkbook.Path & \"\\\" & \"1×25.bmp\")) #018 .SmallIcons = ImageList1 #019 For r = 2 To Sheet1.[A65536].End(xlUp).Row - 1 #020 Set Itm = .ListItems.Add() #021 Itm.Text = Space(2) & Sheet1.Cells(r, 1) #022 For c = 1 To 6 #023 Itm.SubItems(c) = Format(Sheet1.Cells(r, c + 1), \"##,#,0.00\") #024 Next #025 Next #026 End With #027 Set Itm = Nothing #028 Set Img = Nothing #029 End Sub 代码解析: 用户窗体的Initialize事件过程,在窗体显示时将工作表中数据显示在Listview控件中并调整Listview控件的行距。 第17行代码使用Add方法在ImageList控件中添加图片。ImageList控件是一个向其他控件提供图像的资料中心,它包含了一组ListImage对象即一组图像的集合,该集合中的每个对象都可以通过其索引或关键字被其他控件所引用,但控件本身并不能单独使用。 96 VBA常用技巧代码解析 在运行时给ImageList控件添加图片需要使用Add方法,语法如下: Add(index,key,picture) 参数index是可选的,整数,指定要插入的ListImage对象的位置。如果没有指定index,ListImage对象将被添加到ListImages集合的末尾。 参数key是可选的,用来标识ListImage对象的唯一字符串。 参数picture是必需的,指定欲添加到集合中的图片。 也可以在设计时在ImageList控件中添加图片,这样就无需在文件夹中保留图片文件。在VBE中选择ImageList控件属性页中的“自定义”,在显示的“属性页”对话框中插入图片,如图 34-3所示。 图 34-3 在ImageList控件中添加图片 第18行代码,指定Listview控件的SmallIcons属性为ImageList控件中的图片,使用图片来调整行距。 运行窗体,Listview控件显示工作表中的内容,调整Listview控件的行距,如图 34-4所示。 97 VBA常用技巧代码解析 图 34-4 调整Listview控件的行距 34-4 在Listview控件中排序 在使用Listview控件显示报表型的数据时,可能通过单击Listview控件的列标题对列表数据进行排序,代码如下: #001 Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader) #002 With ListView1 #003 .Sorted = True #004 .SortOrder = (.SortOrder + 1) Mod 2 #005 .SortKey = ColumnHeader.Index - 1 #006 End With #007 End Sub 代码解析: Listview控件的ColumnClick事件过程,单击列标题时触发,对列表数据进行升序或降序排序。 第3行代码将Listview控件的Sorted属性设置为True。Sorted属性返回或设置确定ListView控件中的ListItem对象是否排序,设置为False则不进行排序。 第4行代码设置Listview控件的排序方式。SortOrder属性返回或设置一个值,决定ListView控件中的ListItem对象以升序或降序排序,设置为0以升序排序,设置为1则以降序排序。在设置SortOrder属性值时使用Mod运算符以达到第一次排序以降序排序,再次排序时以升序排序,交替进行的效果。 98 VBA常用技巧代码解析 第5行代码设置Listview控件排序关键字的整数,即指定Listview控件以当前选定的列数据进排序。SortKey属性返回或设置一个值,此值决定ListView控件中的ListItem对象如何排序,语法如下: object.SortKey [=integer] 参数object是必需的,对象表达式,其值为ListView控件。 参数integer是必需的,指定排序关键字的整数,设置为0使用ListItem对象的Text属性排序,即第一列的数据进行排序。设置为大于0的整数则使用子项目的集合索引排序。 运行窗体,Listview控件显示工作表中的内容,单击列标题对列表数据进行升序或降序排序,如图 34-5所示。 图 34-5 在Listview控件中排序 34-5 Listview控件的图标设置 ListView 控件作为一个可以显示图标或者子项的列表控件,可以在控件中显示自定义的图标,它最重要的属性就是View 属性,该属性决定了以哪种视图模式显示控件的项,请参阅技巧34-1。 在ListView 控件中显示图标,需要在用户窗体中添加一个ImageList控件用于保存图像文件。关于ImageList控件的使用请参阅技巧34-3。 以大图标模式显示ListView控件的代码如下: #001 Private Sub UserForm_Initialize() #002 Dim ITM As ListItem #003 Dim r As Integer #004 With ListView1 99 VBA常用技巧代码解析 #005 .View = lvwIcon #006 .Icons = ImageList1 #007 For r = 2 To 6 #008 Set ITM = .ListItems.Add() #009 ITM.Text = Cells(r, 1) #010 ITM.Icon = r - 1 #011 Next #012 End With #013 Set ITM = Nothing #014 End Sub 代码解析: 在用户窗体中以大图标模式显示ListView控件,可使用鼠标拖放图标,并重新排列。 第5行代码将ListView控件的View属性设置为lvwIcon,大图标视图模式。 第6行代码使用ListView控件的Icons 属性建立与ImageList控件的关联。 第7行到第11行代码在ListView控件中添加ListItem对象,其中第10行代码设置使用ListItem对象的Icon属性指定其图像文件在ImageList控件中的编号。 ListView控件以大图标视图模式显示时如图 34-6所示。 图 34-6 大图标视图模式 以小图标模式显示ListView控件的代码如下: #001 Private Sub UserForm_Initialize() #002 Dim ITM As ListItem #003 Dim r As Integer #004 With ListView1 100 VBA常用技巧代码解析 #005 .View = lvwSmallIcon #006 .SmallIcons = ImageList1 #007 For r = 2 To 6 #008 Set ITM = .ListItems.Add() #009 ITM.Text = Sheet1.Cells(r, 1) #010 ITM.SmallIcon = r - 1 #011 Next #012 End With #013 Set ITM = Nothing #014 End Sub 代码解析: 在用户窗体中以小图标模式显示ListView控件,可使用鼠标拖放图标,并重新排列。 第5行代码将ListView控件的View属性设置为lvwSmallIcon,小图标视图模式。 与大图标视图模式有所不同的是,当使用小图标视图模式时需要使用ListView控件的SmallIcons属性建立与ImageList控件的关联,使用ListItem对象的SmallIcon属性指定其图像文件在ImageList控件中的编号。 ListView控件以小图标视图模式显示时如图 34-7所示。 图 34-7 小图标视图模式 将ListView控件的View属性设置为lvwList,以列表视图模式显示,如图 34-8所示。 101 VBA常用技巧代码解析 图 34-8 列表视图模式 将ListView控件的View属性设置为lvwReport,以报表视图模式显示,如图 34-9所示。 图 34-9 报表视图模式 技巧35 调用非模式窗体 在VBA中显示用户窗体需要使用Show方法,Show方法显示窗体对象,语法如下: [object.]Show modal 参数object是可选的,对象表达式。如果省略掉object,则将与活动的窗体模块相关联的窗体当作object。 102 VBA常用技巧代码解析 参数modal是可选的,决定窗体是模态的还是非模式的。Modal参数的设置值如表格 35-1所示。 常数 vbModal vbModeless 值 1 0 描述 UserForm是模态的,缺省值。 UserForm是非模式的。 表格 35-1 modal参数的设置值 当窗体显示时是模态时,用户在使用应用程序的其它部分之前,必须先对其作出响应。在隐藏或卸载窗体之前,后续代码不会被执行。 比如下面的代码,希望在显示窗体的同时给单元格赋值,但因为窗体显示为模态的,在窗体没有关闭之前,给单元格赋值的代码是不会执行的,所以达不到显示窗体的同时给单元格赋值的目的。 #001 Private Sub CommandButton1_Click() #002 Dim i As Integer #003 Columns(1).ClearContents #004 UserForm1.Show 0 #005 For i = 1 To 1000 #006 Cells(i, 1) = i #007 Next #008 End Sub 只有在窗体显示为非模式时,后续代码才一出现即被执行。模态下是无法操作工作表的,所以应将第4行代码改成如下的代码,才能在显示窗体的同时给单元格赋值,如图 35-1所示。 UserForm1.Show 0 103 VBA常用技巧代码解析 图 35-1 调用非模式窗体 技巧36 进度条的制作 如果程序执行时间较长,使用进度条能让用户知道程序执行到何种程度,大约需等待多长时间,可以使界面显得友好。 36-1 使用进度条控件 使用窗体加进度条控件(ProgressBar)制作进度条是最常用的方法。 在VBE窗口中单击菜单“插入”→“用户窗体”,在窗体上添加一个进度条控件,调整为合适的大小,如图 36-1所示。 104 VBA常用技巧代码解析 图 36-1 使用ProgressBar控件 在工作表中添加一个命令按钮,双击后写入下面的代码。 #001 Private Sub CommandButton1_Click() #002 Dim i As Integer #003 UserForm1.Show 0 #004 With UserForm1.ProgressBar1 #005 .Min = 1 #006 .Max = 10000 #007 .Scrolling = 0 #008 For i = 1 To 10000 #009 Cells(i, 1) = i #010 .Value = i #011 UserForm1.Caption = \"正在运行,已完成\" & i / 100 & \"%,请稍候!\" #012 Next #013 End With #014 Unload UserForm1 #015 Columns(1).ClearContents #016 End Sub 代码解析: 工作表中命令按钮的单击事件,在给工作表A1到A10000单元格赋值的同时使用进度 105 VBA常用技巧代码解析 条显示其运行速度。 第3行代码,使用Show方法显示进度条控件所在的窗体,并且设置为无模式显示,请参阅技巧35 。 第5、6行代码,设置进度条控件的最小值和最大值,应与第8行代码中的循环计数器的start参数和End参数相一致。 第7行代码,设置进度条控件显示为有间隔的。如果将Scrolling属性设置为1则显示为无间隔的。 第9行代码,在单元格中进行无意义的填充数据以演示进度条。在实际应用中可以将进度条嵌入到程序的循环中。 第11行代码,在窗体的标题栏中显示已完成的百分比。 第14行代码,使用Unload 语句卸载窗体。 Unload 语句从内存中删除一个对象,语法如下: Unload object 参数object参数是必需的,一个有效的对象。 第19行代码,清空A列填充的数据。 单击工作表中的命令按钮,填充单元格并显示进度条,如图 36-2所示。 图 36-2 ProgressBar进度条 36-2 使用标签控件 在窗体中使用标签可以制作双色的进度条。 步骤1,在VBE窗口中单击菜单“插入”→“用户窗体”,在窗体上添加一个框架控件,在框架控件中添加两个标签控件。 步骤2,在控件的属性窗口中将框架的BackColor 属性设为&H000000FF&,使框架的背景色为红色。将标签1的BackColor属性设为&H0000C000&,使标签1的背景色为绿色。将标签2的BackStyle属性设为fmBackStyleTransparent,使标签2的背景为透明,并把它们的Caption属性全部设置为空白。 步骤3,将窗体和控件调整为合适的大小,如图 36-3所示。 106 VBA常用技巧代码解析 图 36-3 制作标签进度条 步骤4,在VBE中双击窗体,写入下面的代码。 #001 Private Declare Function DrawMenuBar Lib \"user32\" (ByVal Hwnd As Long) As Long #002 Private Declare Function GetWindowLong Lib \"user32\" Alias \"GetWindowLongA\" (ByVal Hwnd As Long, ByVal nIndex As Long) As Long #003 Private Declare Function SetWindowLong Lib \"user32\" Alias \"SetWindowLongA\" (ByVal Hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long #004 Private Declare Function FindWindow Lib \"user32\" Alias \"FindWindowA\" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long #005 Private Const GWL_STYLE As Long = (-16) #006 Private Const GWL_EXSTYLE = (-20) #007 Private Const WS_CAPTION As Long = &HC00000 #008 Private Sub UserForm_Initialize() #009 Dim IStyle As Long #010 Dim Hwnd As Long #011 If Val(Application.Version) < 9 Then #012 Hwnd = FindWindow(\"ThunderXFrame\#013 Else #014 Hwnd = FindWindow(\"ThunderDFrame\ 107 VBA常用技巧代码解析 #015 End If #016 IStyle = GetWindowLong(Hwnd, GWL_STYLE) #017 IStyle = IStyle And Not WS_CAPTION #018 SetWindowLong Hwnd, GWL_STYLE, IStyle #019 DrawMenuBar Hwnd #020 UserForm1.Height = 28 #021 End Sub 代码解析: 窗体的初始化事件,在窗体加载时使用API函数去除其标题栏。 第1行到第7行代码,API函数的声明。 第11行到第15行代码,获取窗口句柄。 第16行到第19行代码,去除窗体标题栏。 第20行代码,设置窗体的高度。 步骤5,在工作表中添加一个命令按钮,双击后写入下面的代码。 #001 Private Sub CommandButton1_Click() #002 Dim n As Integer #003 Dim i As Integer #004 n = 10000 #005 With UserForm1 #006 .Show 0 #007 For i = 1 To n #008 Cells(i, 1) = i #009 .Label1.Width = i / n * .Frame1.Width #010 .Label2.Caption = \"已完成\" & Round(i / n * 100, 0) & \"%\" #011 .Label2.Left = .Label1.Width - 50 #012 DoEvents #013 Next #014 End With #015 Unload UserForm1 #016 Range(\"A1:A\" & n).ClearContents #017 End Sub 代码解析: 108 VBA常用技巧代码解析 工作表中命令按钮的单击事件,在给工作表A1到A10000单元格赋值的同时使用进度条显示其运行速度。 第4行代码,设置循环最大值,可根据实际需要设置。 第6行代码,使用Show方法显示窗体,并且设置为无模式的。 第8行代码,在单元格中进行无意义的填充数据以演示进度条。 第9行代码,根据程序运行程度动态设置标签1的宽度,使之达到进度条的效果。 第10行代码,标签2显示已完成百分比。 第11行代码,根据标签1的宽度动态设置标签2的Left属性,使已完成百分比跟随标签1移动。 第12行代码,使用DoEvents函数转让控制权。DoEvents函数将控制权传给操作系统。当操作系统处理完队列中的事件,并且在 SendKeys队列中的所有键也都已送出之后,返回控制权。如果不使用DoEvents函数转让控制权,进度条不能正常显示。 第15行代码,使用Unload 语句卸载窗体。 单击工作表中的命令按钮,填充单元格并显示进度条,如图 36-4所示。 图 36-4 标签进度条 技巧37 使用TreeView控件显示层次 TreeView控件是一个树形结构的控件,该控件用于显示分层数据,如目录或文件目录,使程序的表现更为灵活,用户的操作更加方便,示例代码如下: #001 Private Sub UserForm_Initialize() #002 Dim c As Integer #003 Dim r As Integer #004 Dim rng As Variant #005 rng = Sheet1.UsedRange #006 With Me.TreeView1 #007 .Style = tvwTreelinesPlusMinusPictureText #008 .LineStyle = tvwRootLines 109 VBA常用技巧代码解析 #009 .CheckBoxes = False #010 With .Nodes #011 .Clear #012 .Add Key:=\"科目\科目名称\" #013 For c = 1 To Sheet1.UsedRange.Columns.Count #014 For r = 2 To Sheet1.UsedRange.Rows.Count #015 If Not IsEmpty(rng(r, c)) Then #016 If c = 1 Then #017 .Add relative:=\"科目\relationship:=tvwChild, Key:=rng(r, c), Text:=rng(r, c) #018 ElseIf Not IsEmpty(rng(r, c - 1)) Then #019 .Add relative:=rng(r, c - 1), relationship:=tvwChild, Key:=rng(r, c), Text:=rng(r, c) #020 Else #021 .Add relative:=CStr(Sheet1.Cells(r, c - 1).End(xlUp)), relationship:=tvwChild, Key:=rng(r, c), Text:=rng(r, c) #022 End If #023 End If #024 Next #025 Next #026 End With #027 End With #028 End Sub 代码解析: 在窗体初始化时将工作表中的科目名称填充TreeView控件。 第7行代码,设置TreeView控件每个列表的组成方式。Style属性设置值如表格 34-2所示。 常量 tvwTextOnly tvwPictureText tvwPlusMinusText tvwTreelinesText tvwTreelinesPlusMinusPictureText 110 值 0 1 2 4 7 描述 文本 图像文本 符号文本 直线文本 正常显示 VBA常用技巧代码解析 表格 37-1 Style属性设置值 第8行代码,设置TreeView控件显示根节点连线。TreeView控件的LineStyle属性设置为tvwRootLines显示根节点连线,设置为tvwTreeLines则隐藏根节点连线。 第9行代码,设置TreeView控件不显示复选框。 第10行代码使用Nodes属性返回对TreeView控件的Node对象的集合的引用。 第11行代码,清除TreeView控件所有的节点。 第12行代码,使用Add方法在Treeview控件的Nodes集合中添加一个Node对象。,Add方法语法如下: object.Add(relative, relationship, key, text, image, selectedimage) 参数Object是必需的,一个有效的对象。 参数Relative是可选的,代表已存在的Node对象的索引号或键值。 参数relationship是可选的,代表新节点与已存在的节点间的关系,指定的Node对象的相对位置。relationship的设置值如表格 37-2所示。 常量 tvwFirst tvwLast 值 说明 0 1 首节点,该Node和在relative中被命名的节点位于同一层,并位于所有同层节点之前。 最后的节点,该Node和在relative中被命名的节点位于同一层,并位于所有同层节点之后。任何连续地添加的节点可能位于最后添加的节点之后。 tvwNext 2 下一个节点,该Node位于在relative中被命名的节点之后。 前一个节点,该Node位于在relative中被命名的节点之前。 子节点。该Node 为在relative中被命名的节点的子节点。 tvwPrevious 3 tvwChild 4 表格 37-2 relationship的设置值 参数key是可选的,唯一的字符串,可用于用Item方法检索Node。 参数text 是必需的,在Node中出现的字符串。 参数image是可选的,代表一个图像或在ImageList控件中图象的索引。 参数selectedimage是可选的,代表一个图像或在ImageList控件中图象的索引,在 Node被选中时显示。 第13行到第25行代码代,在根节点下添加子节点。添加子节点仍然使用Add方法,需要一个唯一的Key值,必须提供根节点的Key值(参数relative)和参数relationship值(tvwChild)。要将子节点链接到根节点的下面,参数relative必须与根节点的Key值一致,参数relationship必须设置为tvwchild。要使子节点有效,子节点必须也有自已唯一的Key值。 获得双击TreeView控件后的返回值的代码如下: #001 Private Sub TreeView1_DblClick() 111 VBA常用技巧代码解析 #002 If TreeView1.SelectedItem.Children = 0 Then #003 Sheet1.Range(\"A65536\").End(xlUp).Offset(1) = TreeView1.SelectedItem.Text #004 Else #005 MsgBox \"所选择的不是末级科目,请重新选择科目!\" #006 End If #007 End Sub 代码解析: TreeView1_ DblClick过程是TreeView控件的双击事件,将所选的科目名称写入到工作表中。 第2行代码判断所选节点是否是末级科目。TreeView控件的SelectedItem属性返回当前所选择的节点,而Children属性检查所选节点是否还有子节点,如没有子节点则返回0。 运行窗体效果如图 37-1所示。 图 37-1 使用TreeView控件显示层次 112 VBA常用技巧代码解析 技巧38 用户窗体添加图标 窗体在显示时标题栏上是没有图标的,如果希望在窗体上添加图标,可以借助API函数在窗体显示时添加自定义的图标。 在VBE窗口中单击菜单“插入”→“用户窗体”,插入一个窗体,在窗体中添加一个Image控件,设置Image控件Picture属性为自定义图标的位图,并将Image控件的Visible属性设置为False,使窗体运行时隐藏Image控件,如图 38-1所示。 图 38-1 窗体中添加Image控件 在VBE中双击窗体,写入下面的代码。 #001 Private Declare Function SendMessage Lib \"user32\" Alias \"SendMessageA\" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long #002 Private Declare Function DrawMenuBar Lib \"user32\" (ByVal hWnd As Long) As Long #003 Private Declare Function FindWindow Lib \"user32\" Alias \"FindWindowA\" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long #004 Private Const WM_SETICON = &H80 #005 Private Const ICON_SMALL = 0& 113 VBA常用技巧代码解析 #006 Private Const ICON_BIG = 1& #007 Sub ChangeIcon(ByVal hWnd As Long, Optional ByVal hicon As Long = 0&) #008 SendMessage hWnd, WM_SETICON, ICON_SMALL, ByVal hicon #009 SendMessage hWnd, WM_SETICON, ICON_BIG, ByVal hicon #010 DrawMenuBar hWnd #011 End Sub #012 Private Sub UserForm_Initialize() #013 Dim hWnd As Long #014 hWnd = FindWindow(vbNullString, Me.Caption) #015 Call ChangeIcon(hWnd, Image1.Picture.Handle) #016 End Sub 代码解析: 窗体的初始化事件,窗体在显示时运行ChangeIcon函数,在标题栏中添加图标。 第1行到第6行代码, API函数声明。 第7行到第11行代码,ChangeIcon过程,用于转换图标。 第14行代码,获得窗口句柄。 第15行代码,运行ChangeIcon过程,将Image控件中的位图显示在窗体的标题栏上。 运行窗体后,在窗体标题栏上添加图标,如图 38-2所示。 图 38-2 在窗体标题栏中添加图标 114 VBA常用技巧代码解析 技巧39 用户窗体添加最大最小化按纽 VBA中的窗体标题栏上只有关闭按纽,没有最大最小化按纽的,可以使用API函数在窗体的标题栏上添加最大最小化按纽,如下面的代码所示。 #001 Private Declare Function FindWindow Lib \"user32\" Alias \"FindWindowA\" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long #002 Private Declare Function GetWindowLong Lib \"user32\" Alias \"GetWindowLongA\" (ByVal hWnd As Long, ByVal nIndex As Long) As Long #003 Private Declare Function SetWindowLong Lib \"user32\" Alias \"SetWindowLongA\" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long #004 Private Const WS_MAXIMIZEBOX = &H10000 #005 Private Const WS_MINIMIZEBOX = &H20000 #006 Private Const GWL_STYLE = (-16) #007 Private Sub UserForm_Initialize() #008 Dim hWndForm As Long #009 Dim iStyle As Long #010 hWndForm = FindWindow(\"ThunderDFrame\#011 iStyle = GetWindowLong(hWndForm, GWL_STYLE) #012 iStyle = iStyle Or WS_MINIMIZEBOX #013 iStyle = iStyle Or WS_MAXIMIZEBOX #014 SetWindowLong hWndForm, GWL_STYLE, iStyle #015 End Sub 代码解析: 窗体初始化时使用API函数在标题栏上添加最大最小化按纽。 第1行到第6行代码,API函数声明。 第10行代码,获取窗口句柄。 第11行到第14行代码,在标题栏上添加最大最小化按纽。 运行窗体后效果如图 39-1所示。 115 VBA常用技巧代码解析 图 39-1 标题栏上添加最大最小化按纽 技巧40 禁用窗体标题栏的关闭按钮 如果不希望用户通过窗体标题栏的关闭命令来关闭窗体,可以禁用窗体标题栏上的关闭按钮,如下面的代码所示。 #001 Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) #002 If CloseMode <> 1 Then #003 Cancel = True #004 MsgBox \"请点击按钮关闭窗体!\" #005 End If #006 End Sub 代码解析: 窗体的QueryClose事件,禁用窗体标题栏上的关闭按钮。 窗体的QueryClose事件发生在窗体关闭之前,语法如下: Private Sub UserForm_QueryClose(cancel As Integer, closemode As Integer) 参数Cance是可选的,整数。将此参数设置成 0 以外的任意值,在所有加载的用户窗体中停止QueryClose事件,并防止关闭窗体与应用程序。 参数closemode是可选的,一个值或常数,用来指示引起QueryClose事件的原因。 closemode参数的设置值如表格 40-1所示。 116 VBA常用技巧代码解析 常数 vbFormControlMenu VbFormCode vbAppWindows vbAppTaskManager 值 描述 0 1 2 3 用户在 UserForm上选择“控制”菜单中的“关闭”命令 由代码调用 Unload 语句 正在结束当前 Windows 操作环境的过程。(仅用于Visual Basic 5.0 ) Windows 的“任务管理器”正在关闭这个应用。(仅用于Visual Basic 5.0 ) 表格 40-1 closemode 参数 第2、3行代码,如果窗体不是由代码调用Unload语句关闭,则停止关闭过程,从而禁用窗体标题栏的关闭按钮。 需要注意的是,一定要在窗体上设置关闭窗体的途径,否则会使窗体无法关闭。 窗体运行后,禁用窗体上的关闭按钮关闭窗体,只能使用按钮关闭窗体,如图 40-1所示。 图 40-1 禁用窗体标题栏的关闭命令 技巧41 屏蔽窗体标题栏的关闭按钮 使用API函数可以屏蔽窗体标题栏的关闭按钮,如下面的代码所示。 #001 Private Declare Function FindWindow Lib \"user32\" Alias \"FindWindowA\" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long #002 Private Declare Function GetWindowLong Lib \"user32\" Alias \"GetWindowLongA\" (ByVal Hwnd As Long, ByVal nIndex As Long) As Long 117 VBA常用技巧代码解析 #003 Private Declare Function SetWindowLong Lib \"user32\" Alias \"SetWindowLongA\" (ByVal Hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long #004 Private Declare Function DrawMenuBar Lib \"user32\" (ByVal Hwnd As Long) As Long #005 Private Const GWL_STYLE = (-16) #006 Private Const WS_SYSMENU = &H80000 #007 Private Hwnd As Long #008 Private Sub UserForm_Initialize() #009 Dim Istype As Long #010 Hwnd = FindWindow(\"ThunderDFrame\#011 Istype = GetWindowLong(Hwnd, GWL_STYLE) #012 Istype = Istype And Not WS_SYSMENU #013 SetWindowLong Hwnd, GWL_STYLE, Istype #014 DrawMenuBar Hwnd #015 End Sub 代码解析: 第1行到第7行代码是API函数声明。 第8行到第15行代码是窗体的Initialize事件,当窗体显示时屏蔽窗体标题栏的关闭按钮。 窗体运行后,屏蔽窗体上的关闭按钮,只能使用按钮关闭窗体,如图 41-1所示。 图 41-1 屏蔽窗体标题栏的关闭按钮 118 VBA常用技巧代码解析 技巧42 无标题栏和边框的窗体 如果希望制作无标题栏和边框的窗体,那么可以使用API函数。 在VBE窗口中单击菜单“插入”→“用户窗体”,双击窗体,在其代码窗口中输入下面的代码: #001 Private Declare Function DrawMenuBar Lib \"user32\" (ByVal Hwnd As Long) As Long #002 Private Declare Function GetWindowLong Lib \"user32\" Alias \"GetWindowLongA\" (ByVal Hwnd As Long, ByVal nIndex As Long) As Long #003 Private Declare Function SetWindowLong Lib \"user32\" Alias \"SetWindowLongA\" (ByVal Hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long #004 Private Declare Function FindWindow Lib \"user32\" Alias \"FindWindowA\" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long #005 Private Const GWL_STYLE As Long = (-16) #006 Private Const GWL_EXSTYLE = (-20) #007 Private Const WS_CAPTION As Long = &HC00000 #008 Private Const WS_EX_DLGMODALFRAME = &H1& #009 Private Sub UserForm_Initialize() #010 Dim IStyle As Long #011 Dim Hwnd As Long #012 If Val(Application.Version) < 9 Then #013 Hwnd = FindWindow(\"ThunderXFrame\#014 Else #015 Hwnd = FindWindow(\"ThunderDFrame\#016 End If #017 IStyle = GetWindowLong(Hwnd, GWL_STYLE) #018 IStyle = IStyle And Not WS_CAPTION #019 SetWindowLong Hwnd, GWL_STYLE, IStyle #020 DrawMenuBar Hwnd #021 IStyle = GetWindowLong(Hwnd, GWL_EXSTYLE) And Not WS_EX_DLGMODALFRAME #022 SetWindowLong Hwnd, GWL_EXSTYLE, IStyle 119 VBA常用技巧代码解析 #023 End Sub #024 Private Sub UserForm_Click() #025 Unload Me #026 End Sub 代码解析: 窗体初始化时使用API函数去除其标题栏和边框。 第1行到第8行代码,API函数的声明。 第12行到第16行代码,获取窗口句柄。 第17行到第20行代码,去除窗体标题栏。 第21、22行代码,去除窗体边框。 第24行到第26行代码,窗体的单击事件,单击窗体后关闭该窗体。 窗体运行后如图 42-1所示,单击后关闭该窗体。 图 42-1 无标题栏和边框的窗体 技巧43 制作年月选择窗体 在工作表中需要输入日期时,可以使用日期时间控件(Microsoft Date and Time Picker Control 6.0,简称DTP控件),请参阅技巧19 。但有时只需要输入年份和月份,使用DTP 120 VBA常用技巧代码解析 控件选择月份并不方便,此时可以使用文本框结合微调框做一个年月选择窗体供用户输入年份和月份。 步骤1,在VBE窗口中单击菜单“插入”→“用户窗体”,将窗体的Caption属性设置为“请选择年月”。 步骤2,在窗体上添加一个框架控件和两个命令按纽控件。在框架控件中添加两个文本框控件和两个SpinButton控件,并把命令按纽的Caption属性分别设置为“确定”和“取消”。 步骤3,调整好控件位置,双击窗体写入下面的代码。 #001 Private Sub UserForm_Initialize() #002 SpinButton1.Value = Year(Date) #003 SpinButton2.Value = Month(Date) #004 TextBox1.Text = Year(Date) & \"年\" #005 TextBox2.Text = Month(Date) & \"月份\" #006 End Sub #007 Private Sub SpinButton1_Change() #008 TextBox1.Text = SpinButton1.Value & \"年\" #009 End Sub #010 Private Sub SpinButton2_Change() #011 With SpinButton2 #012 Select Case .Value #013 Case 1 To 12 #014 TextBox2.Text = .Value & \"月份\" #015 Case Is > 12 #016 TextBox1.Text = Left(TextBox1.Text, 4) + 1 & \"年\" #017 .Value = 1 #018 Case Is < 1 #019 TextBox1.Text = Left(TextBox1.Text, 4) - 1 & \"年\" #020 .Value = 12 #021 End Select #022 End With #023 End Sub #024 Private Sub CommandButton1_Click() 121 VBA常用技巧代码解析 #025 Sheet1.Range(\"A65536\").End(xlUp).Offset(1) = TextBox1.Text & TextBox2.Text #026 End Sub #027 Private Sub CommandButton2_Click() #028 Unload Me #029 End Sub 代码解析: 第1行到第6行代码,窗体的初始化事件,在窗体加载时设置文本框和微调框的初始值。 第2行代码,设置微调框1的初始值为当前年份。Year函数返回年份的整数,语法如下: Year(date) 参数date是必需的,可以是任何能够表示日期的Variant、数值表达式、字符串表达式或它们的组合。 第3行代码,设置微调框2的初始值为当前月份。Mont函数返回值为1到12之间的整数,表示一年中的某月,语法如下: Month(date) 参数date与Year函数的参数date相同。 第4行代码,设置文本框1显示的文本为当前年份。 第5行代码,设置文本框2显示的文本为当前月份。 第7行到第9行代码,微调框1的Change事件过程。当单击微调框1数值调节钮的向上键或向下键调节年份时,文本框1显示的年份等于调节后的年份。 第10行到第23行代码,微调框2的Change事件过程。当单击微调框2数值调节钮的向上键或向下键调节月份时,文本框2显示的月份等于调节后的月份。如果是一年以内的调节,只调节文本框2显示的月份,否则还需要调节文本框1显示的年份。 第25行代码,“确定”按钮的单击过程,将选择好的年月写入工作表中。 第28行代码,使用Unload 语句卸载窗体。 运行窗体后效果如图 43-1所示。 122 VBA常用技巧代码解析 图 43-1 年月选择窗体 技巧44 自定义窗体中的鼠标指针类型 使用对象的MousePointer属性可以自定义鼠标掠过窗体控件时的指针类型,如下面的代码所示。 #001 Private Sub UserForm_Initialize() #002 With Me.TextBox1 #003 .MousePointer = 99 #004 .MouseIcon = LoadPicture(ThisWorkbook.Path & \"\\myMouse.ico\") #005 End With #006 End Sub 代码解析: 当用户把鼠标放到窗体的文本框上时,所显示的鼠标指针的类型为自定义图标。 第3行代码设置文本框的MousePointer属性。MousePointer属性指定当用户把鼠标放到特定对象上时,所显示鼠标指针的类型,语法如下: object.MousePointer [= fmMousePointer] 参数object是必需的,一个有效对象。 参数fmMousePointer是可选的,所需鼠标指针的形状。fmMousePointer的设置值如表格 44-1所示。 常量 fmMousePointerDefault fmMousePointerArrow fmMousePointerCross fmMousePointerIBeam fmMousePointerSizeNESW fmMousePointerSizeNS mMousePointerSizeNWSE fmMousePointerSizeWE 值 0 1 2 3 6 7 8 9 说明 标准指针。根据对象来决定指针的图像(默认) 箭头 十字线指针 I 形标 斜下的双箭头 南北向的双箭头 斜上的双箭头 东西向的双箭头 123 VBA常用技巧代码解析 fmMousePointerUpArrow fmMousePointerHourglass fmMousePointerNoDrop 10 11 12 向上键 沙漏 在被拖动的对象上有 “Not”符号(有一条斜线的圆)。表示是无效的放置目标。 fmMousePointerAppStarting fmMousePointerHelp fmMousePointerSizeAll fmMousePointerCustom 13 14 15 99 带沙漏的箭头 带问号的箭头 调整所有尺寸的光标(四向箭头) 使用由MouseIcon属性指定的图标 表格 44-1 fmMousePointer的设置值 第3行代码将文本框的MousePointer属性设置为99,使用由MouseIcon属性指定的自定义图标。MouseIcon属性为对象指定一个自定义的图标,语法如下: object.MouseIcon = LoadPicture( pathname ) 参数object是必需的,一个有效的对象。 参数pathname是必需的,指定包含自定义图标的文件的路径和文件名。 设置后的鼠标指针的形状如图 44-1所示。 图 44-1 自定义鼠标指针类型 技巧45 调整窗体的显示位置 用户窗体显示时,默认的位置是窗体所在Excel文件的。如果需要调整,可以在窗体加载时对其进行设置,如下面的代码所示。 #001 Private Sub UserForm_Initialize() 124 VBA常用技巧代码解析 #002 With Me #003 .StartUpPosition = 0 #004 .Left = 500 #005 .Top = 300 #006 End With #007 End Sub 代码解析: 窗体的初始化事件,在窗体加载时设置其显示位置。 第3行代码,将窗体的StartUpPosition属性设置成手动。 StartUpPosition属性返回或设置一个值,用来指定窗体第一次出现时的位置,设置值如表格 45-1所示。 设置 手动 所有者中心 屏幕中心 窗口缺省 值 0 1 2 3 描述 没有初始设置指定 在 UserForm 所属项目的 在整个屏幕的 在屏幕的左上角 表格 45-1 StartUpPosition属性设置值 StartUpPosition属性可以在程序中设置,也可以在窗体的属性窗口中设置。 第4、5行代码,设置窗体的Left属性和Top属性,使其加载时显示在屏幕的右下角。 经过设置后的窗体加载时显示位置如图 45-1所示。 125 VBA常用技巧代码解析 图 45-1 调整窗体的显示位置 技巧46 由鼠标确定窗体显示位置 窗体加载时其显示位置还可以由鼠标的坐标来确定,如下面的代码所示。 #001 Private Sub CommandButton1_Click() #002 Dim ActiveCellX As Integer #003 Dim ActiveCellY As Integer #004 ActiveCellX = ExecuteExcel4Macro(\"GET.CELL(44)\") #005 ActiveCellY = ExecuteExcel4Macro(\"GET.CELL(43)\") #006 With UserForm1 #007 .Show 0 #008 .Top = ActiveCellY #009 .Left = ActiveCellX #010 End With #011 End Sub 代码解析: 使用ExecuteExcel4Macro方法执行Microsoft Excel 4.0 宏函数取得鼠标的坐标,ExecuteExcel4Macro方法的语法如下: expression.ExecuteExcel4Macro(String) expression参数是可选的,返回一个Application对象。 String参数是必需的,一个不带等号的Microsoft Excel 4.0宏语言函数。 第4行代码使用GET.CELL(44) 宏函数取得鼠标的X坐标,第5行代码使用GET.CELL(43) 宏函数取得鼠标的Y坐标。 第6行到第10行代码显示窗体并设置其Top属性和Left属性,调整其显示的位置。 还可以利用工作表SelectionChange事件的Target参数取得鼠标的坐标,如下面的代码所示。 #001 Private Sub Worksheet_SelectionChange(ByVal Target As Range) #002 With UserForm1 126 VBA常用技巧代码解析 #003 .Show 0 #004 .Top = Target.Top #005 .Left = Target.Left #006 End With #007 End Sub 代码解析: 工作表的SelectionChange事件过程,Target参数代表新选定的区域,返回一个Range对象,在显示窗体时取得其Top和Left属性后设置窗体显示的Top和Left属性。 技巧47 用户窗体的打印 在使用如图 47-1所示的窗体录入数据时,如果需要把窗体打印出来,可以使用PrintForm方法,如下面的代码所示。 图 47-1 录入窗体 #001 Private Sub CommandButton7_Click() #002 Dim myHeight As Integer 127 VBA常用技巧代码解析 #003 Application.ScreenUpdating = False #004 With UserForm1 #005 myHeight = .Height #006 .DTPicker1.Visible = False #007 .Frame1.Visible = False #008 .Height = myHeight - 30 #009 .PrintForm #010 .Height = myHeight #011 .DTPicker1.Visible = True #012 .Frame1.Visible = True #013 End With #014 Application.ScreenUpdating = True #015 End Sub 代码解析: 录入窗体中的“打印”按钮的单击代码,使用PrintForm方法打印窗体。 第5行代码使用变量myHeight记录窗体的Height属性值,以便在第10行代码中恢复窗体原有的高度。 第6、7行代码将窗体中的DTP日历控件和功能按钮的Visible属性设置为False,使之隐藏,这样在打印时就不会被打印出来。 第9行代码使用PrintForm方法打印窗体,PrintForm方法将UserForm对象的图象逐位发送到打印机,语法如下: object.PrintForm 参数object代表对象表达式,其值为“应用于”列表中的对象。如果省略该参数,则把焦点所在的窗体当做object。 第11、12行代码重新显示窗体中的DTP日历控件和功能按钮。 窗体打印后的效果如图 47-2所示。 128 VBA常用技巧代码解析 图 47-2 窗体打印效果 技巧48 使用自定义颜色设置窗体颜色 在用VBA进行设计时,会发现控件与颜色相关的属性中系统提供可选择的颜色太少。比如窗体的BackColor属性,如果需要把窗体的背景颜色设置为淡蓝色RGB(52,150,203),可以在窗体初始化过程中对之进行设置,可以实现想要的效果,但是在设计时却不能看到最终效果。 其实窗体的BackColor属性(包括ForeColor以及BorderColor等等这些设置颜色的属性)允许输入一个以十六进制表示的长整型数值,这样在设计时就看到效果。 首先获取所需要的颜色值并以十六进制表示。还以上面的颜色为例,在立即窗口输入“? Hex(RGB(52,150,203))”可得到一个十六进制数据CB9634,然后把光标定位在窗体属性窗口的BackColor属性值中,删除原来的数值后,输入“&HCB9634&”后按 129 VBA常用技巧代码解析 图 48-1 在窗体设计时显示自定义颜色 技巧49 在窗体中显示图表 工作表中的图表是不能直接显示在窗体中的,如果需要在窗体上显示图表,除了使用错误!未找到引用源。介绍的使用ShowWindow属性将工作表中嵌入的图表显示在的窗口中,还可以使用以下的方法。 49-1 使用Export方法 可以把图表以图形格式从工作表中导出,再用窗体上的Image控件把图表显示出来,如下面的代码所示。 #001 Private Sub UserForm_Initialize() #002 Dim Charts As Chart #003 Dim cName As String 130 VBA常用技巧代码解析 #004 Set Charts = Sheets(\"Sheet2\").ChartObjects(1).Chart #005 cName = ThisWorkbook.Path & \"\\Temp.gif\" #006 Charts.Export Filename:=cName, FilterName:=\"GIF\" #007 Image1.Picture = LoadPicture(cName) #008 End Sub 代码解析: 窗体的初始化事件过程,窗体加载时将工作表中的图表显示在窗体中。 第4行到第6行代码,使用Export方法把Sheet2表中的第一个图表导出到工作簿的同一目录下。 Export方法以图形格式导出图表,语法如下: expression.Export(Filename, FilterName, Interactive) 参数expression是必需的,一个有效的对象。 参数Filename是必需的,导出的文件的名称。 本例中设置Filename参数时加上了导出路径,将图形导出到同一文件夹下。 参数FilterName是可选的,导出文件的格式。 第7行代码,设置窗体中Image控件的Picture属性为导出文件的完整路径。 Picture 属性指定显示在对象上的位图,语法如下: object.Picture = LoadPicture( pathname ) 参数expression是必需的,一个有效的对象。 参数pathname是必需的,一个图片文件的完整路径。 为了使窗体关闭时删除导出的图片文件,在窗体的QueryClose事件中写入下面的代码。 #001 Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) #002 Kill ThisWorkbook.Path & \"\\Temp.gif\" #003 End Sub 代码解析: 窗体关闭时使用Kill方法删除导出的图片文件。Kill方法的语法如下: Kill pathname 参数Pathname是必需的,用来指定一个文件名的字符串表达式。Pathname参数可以包含目录或文件夹、以及驱动器。 运行窗体,将工作表的图表显示在窗体中,如图 49-2所示。 131 VBA常用技巧代码解析 图 49-1 在窗体上显示图表 49-2 使用API函数 可以使用API函数把图表从工作表中导出,再用窗体上的Image控件把图表显示出来,如下面的代码所示。 #001 Private Declare Function CreateStreamOnHGlobal Lib \"ole32\" (ByVal hGlobal As Long, ByVal fDeleteOnRelease As Long, ppstm As Any) As Long #002 Private Declare Function OleLoadPicture Lib \"olepro32\" (pStream As Any, ByVal lSize As Long, ByVal fRunmode As Long, riid As Any, ppvObj As Any) As Long ………代码略详见附件 #012 Private Declare Function GetClipboardFormatName Lib \"user32\" Alias \"GetClipboardFormatNameA\" (ByVal wFormat As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long #013 Public Function LoadShapePicture(shp As Object) As IPictureDisp #014 Dim nClipsize As Long #015 Dim hMem As Long #016 Dim lpData As Long #017 Dim sdata() As Byte #018 Dim fmt As Long #019 Dim fmtName As String #020 Dim iClipBoardFormatNumber As Long #021 Dim IID_IPicture(15) 132 VBA常用技巧代码解析 ……代码略详见附件 #058 EmptyClipboard #059 CloseClipboard #060 End Function #061 Private Sub UserForm_Initialize() #062 Image1.Picture = LoadShapePicture(Sheet1.ChartObjects(1)) #063 End Sub 代码解析: 第1行到第12行代码API函数声明。 第13行到第60行代码LoadShapePicture函数,导出工作表中的图表。 第61行到第63行代码窗体的初始化事件过程,窗体加载时将工作表中的图表显示在窗体中,如图 49-2所示。关于Image 控件的Picture属性请参阅技巧49-1。 图 49-2 在窗体上显示图表 技巧50 窗体运行时调整控件大小 用户窗体中的控件在运行时是不能调整大小的,而在某些情况下需要在窗体运行时调整控件的大小,此时可以利用控件的MouseMove事件。 133 VBA常用技巧代码解析 步骤1,在VBE窗口中单击菜单“插入”→“用户窗体”,在窗体中添加两个框架控件,在框架控件中间添加一个Image控件,如图 50-1所示。 图 50-1 添加控件 步骤2,Image控件是用来在窗体运行时拖动调整框架控件大小的,所以需要在Image控件的属性窗口将BackStyle属性设置为fmBackStyleTransparent,使控件的背景为透明;将BorderStyle属性设置为fmBorderStyleNone,使控件无可见的边框线;MousePointer属性设置为fmMousePointerSizeWE,当用户把鼠标放到Image控件上时,鼠标指针的类型为东西向的双箭头。关于控件的MousePointer属性请参阅技巧44 中的表格 44-1。 步骤3,在窗体中调整好控件的位置后双击Image控件写入下面的代码: #001 Dim Abscissa As Single #002 Private Sub Image1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single) #003 Abscissa = x #004 End Sub #005 Private Sub Image1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single) #006 If Button = 1 Then #007 If Abscissa - x > Frame1.Width Or x > Frame2.Width Then Exit Sub #008 Frame1.Width = Frame1.Width - Abscissa + x #009 Image1.Left = Image1.Left - Abscissa + x #010 Frame2.Left = Frame2.Left - Abscissa + x #011 Frame2.Width = Frame2.Width + Abscissa - x #012 End If 134 VBA常用技巧代码解析 #013 End Sub 代码解析: 第2行到第4行代码,Image控件的MouseDown事件过程,用户按下鼠标按键时发生,语法如下: Private Sub object_MouseDown( ByVal Button As fmButton, ByVal Shift As fmShiftState, ByVal X As Single, ByVal Y As Single) 其中参数x是可选的,控件位置的横坐标,以磅为单位,从左边开始测量。 第3行代码将控件的横坐标赋给变量Abscissa。 第5行到第12行代码,Image控件的MouseMove事件过程,用户移动鼠标时该事件发生,语法如下: Private Sub object_MouseMove( ByVal Button As fmButton, ByVal Shift As fmShiftState, ByVal X As Single, ByVal Y As Single) 其中参数Button是必需的,标识鼠标按键状态的整数值,其设置值如表格 50-1所示。 值 0 1 2 3 说明 按键未被按下 按下左键 按下右键 同时按下左键和右键 值 4 5 6 7 说明 按下中键 同时按下左键和中键 同时按下中键和右键 三个按键全都按下 表格 50-1 Button参数的设置值 参数x是可选的,控件位置的水平坐标,以磅为单位,从左边开始测量。 在MouseMove事件过程中,当用户在窗体上按下左键移动鼠标时,调整两个框架控件的Width属性和框架2的Left属性,使其达到窗体运行时可以进行拖动调整大小的效果。 当鼠标指针在对象上移动时,MouseMove事件是连续发生的,只要鼠标位于对象的边界之内,对象就会不断的识别MouseMove事件,所以框架控件可以连续的进行拖动调整大小。 运行窗体的,选择两个框架控件的中间位置,当鼠标指针变成东西向的双箭头时按下鼠标左键拖动可以进行拖动调整框架控件的大小,如图 50-2所示。 135 VBA常用技巧代码解析 图 50-2 窗体运行时调整控件大小 技巧51 在用户窗体上添加菜单 在VBA中,用户窗体上是没有菜单的,为了使用方便,我们可以使用API函数在用户窗体上添加菜单,示例代码如下: #001 Private Declare Function FindWindow Lib \"user32\" Alias \"FindWindowA\" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long #002 Private Declare Function SetMenu Lib \"user32\" (ByVal hwnd As Long, ByVal hMenu As Long) As Long #003 Private Declare Function CreateMenu Lib \"user32\" () As Long #004 Private Declare Function AppendMenu Lib \"user32\" Alias \"AppendMenuA\" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As Any) As Long #005 Private Declare Function DestroyMenu Lib \"user32\" (ByVal hMenu As Long) As Long #006 Private Declare Function CreatePopupMenu Lib \"user32\" () As Long #007 Private Declare Function SetWindowLong Lib \"user32\" Alias \"SetWindowLongA\" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long 136 VBA常用技巧代码解析 #008 Private Declare Function GetWindowLong Lib \"user32\" Alias \"GetWindowLongA\" (ByVal hwnd As Long, ByVal nIndex As Long) As Long #009 Private Const GWL_WNDPROC = (-4) #010 Private Const MF_STRING = &H0& #011 Private Const MF_POPUP = &H10& #012 Private Const MF_SEPARATOR = &H800& #013 Dim MenuWnd As Long, Dump As Long, PopupMenuID As Long, PopupMenuWnd As Long, MenuID As Long #014 Private Sub UserForm_Initialize() #015 If Val(Application.Version) < 9 Then #016 hwnd = FindWindow(\"ThunderXFrame\#017 Else #018 hwnd = FindWindow(\"ThunderDFrame\#019 End If #020 MenuWnd = CreateMenu() #021 PopupMenuID = CreatePopupMenu() #022 Dump = AppendMenu(MenuWnd, MF_STRING + MF_POPUP, PopupMenuID, \"系统设置(&X)\") #023 Dump = AppendMenu(PopupMenuID, MF_STRING, 100, \"保存(&S)...\") #024 Dump = AppendMenu(PopupMenuID, MF_STRING, 101, \"备份(&E)\") #025 Dump = AppendMenu(PopupMenuID, MF_STRING, 102, \"退出(&X)\") #026 PopupMenuID = CreatePopupMenu() #027 Dump = AppendMenu(MenuWnd, MF_STRING + MF_POPUP, PopupMenuID, \"会计凭证(&P)\") #028 Dump = AppendMenu(PopupMenuID, MF_STRING, 110, \"录入(&L)\") #029 Dump = AppendMenu(PopupMenuID, MF_STRING, 111, \"审核(&C)\") #030 PopupMenuID = CreatePopupMenu() #031 Dump = AppendMenu(MenuWnd, MF_STRING + MF_POPUP, PopupMenuID, \"会计账簿(&Z)\") #032 Dump = AppendMenu(PopupMenuID, MF_STRING, 112, \"记账(&T)\") #033 Dump = AppendMenu(PopupMenuID, MF_STRING, 113, \"结账(&J)\") #034 PopupMenuID = CreatePopupMenu() #035 Dump = AppendMenu(MenuWnd, MF_STRING + MF_POPUP, PopupMenuID, \"会 137 VBA常用技巧代码解析 计报表(&B)\") #036 Dump = AppendMenu(PopupMenuID, MF_STRING, 114, \"资产负债表(&F)\") #037 Dump = AppendMenu(PopupMenuID, MF_STRING, 115, \"损益表(&Y)\") #038 Dump = SetMenu(hwnd, MenuWnd) #039 PreWinProc = GetWindowLong(hwnd, GWL_WNDPROC) #040 SetWindowLong hwnd, GWL_WNDPROC, AddressOf MsgProcess #041 End Sub #042 Private Sub UserForm_Terminate() #043 DestroyMenu MenuWnd #044 DestroyMenu PopupMenuID #045 DestroyMenu PopupMenuWnd #046 SetWindowLong hwnd, GWL_WNDPROC, PreWinProc #047 End Sub 代码解析: 第1行到第13行代码,API函数声明。 第14行到第41代码,用户窗体的Initialize事件过程,在窗体显示时使用API函数在窗体上添加菜单。其中第22行代码添加第一个“系统设置”菜单,第23、24、25行代码在“系统设置”菜单中添加三个子菜单,第26行代码往下继续添加其他菜单。 第40行代码,为窗体中添加的菜单指定所执行的过程名称为“MsgProcess”函数过程。 第42行到第47行代码,用户窗体的Terminate事件过程,将所有引用对象的变量设置成Nothing,从而删除对象的所有引用。 为了能够使用窗体中添加的菜单,需要在模块中写入下面的代码: #001 Public PreWinProc As Long, hwnd As Long #002 Public Declare Function CheckMenuRadioItem Lib \"user32\" (ByVal hMenu As Long, ByVal un1 As Long, ByVal un2 As Long, ByVal un3 As Long, ByVal un4 As Long) As Long #003 Public Declare Function CheckMenuItem Lib \"user32\" (ByVal hMenu As Long, ByVal wIDCheckItem As Long, ByVal wCheck As Long) As Long #004 Public Declare Function EnableMenuItem Lib \"user32\" (ByVal hMenu As Long, ByVal wIDEnableItem As Long, ByVal wEnable As Long) As Long #005 Public Const MF_UNCHECKED = &H0& #006 Public Const MF_CHECKED = &H8& 138 VBA常用技巧代码解析 #007 Public Const MF_DISABLED = &H2& #008 Public Const MF_GRAYED = &H1& #009 Public Const MF_ENABLED = &H0& #010 Private Declare Function CallWindowProc Lib \"user32\" Alias \"CallWindowProcA\" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long #011 Private Declare Function GetMenu Lib \"user32\" (ByVal hwnd As Long) As Long #012 Private Declare Function GetSubMenu Lib \"user32\" (ByVal hMenu As Long, ByVal nPos As Long) As Long #013 Private Const MF_BYCOMMAND = &H0& #014 Public Function MsgProcess(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long #015 Dim SubMenu_hWnd As Long #016 Select Case wParam #017 Case 100 #018 MsgBox \"你选择的是\"\"保存\"\"按钮!\" #019 Case 101 #020 MsgBox \"你选择的是\"\"备份\"\"按钮!\" #021 Case 102 #022 Unload UserForm1 #023 Case 110 #024 MsgBox \"你选择的是\"\"录入\"\"按钮!\" #025 Case 111 #026 MsgBox \"你选择的是\"\"审核\"\"按钮!\" #027 Case 112 #028 MsgBox \"你选择的是\"\"记账\"\"按钮!\" #029 Case 113 #030 MsgBox \"你选择的是\"\"结账\"\"按钮!\" #031 Case 114 #032 MsgBox \"你选择的是\"\"资产负债表\"\"按钮!\" #033 Case 115 #034 MsgBox \"你选择的是\"\"损益表\"\"按钮!\" 139 VBA常用技巧代码解析 #035 Case Else #036 MsgProcess = CallWindowProc(PreWinProc, hwnd, Msg, wParam, lParam) #037 End Select #038 End Function 代码解析: 第1行到第13行代码,API函数声明。 第14行到第36行代码,MsgProcess函数过程,根据参数wParam的值为窗体中的菜单指定所执行的操作,为了演示方便只使用MsgBox函数显示一个消息框,在实际应用中可以为菜单写入代码或指定过程名称。 运行窗体后在窗体上添加菜单,如图 51-1所示。 图 51-1 用户窗体上添加菜单 技巧52 在用户窗体上添加工具栏 在技巧51 中我们在用户窗体上使用API函数添加了菜单,还可以在用户窗体上继续添加工具栏用以显示一列下拉菜单的位图按钮,单击一个工具栏按钮等于选择一个菜单命令,以提供对常用功能和命令的快速访问。 在用户窗体上添加工具栏可以使用Toolbar控件,在设计模式下右键单击“工具箱”,在显示的右键菜单中选择“附加控件”,在显示的对话框中选择“Microsoft Toolbar Control, 140 VBA常用技巧代码解析 veision 6.0”控件,在用户窗体上添加一个Toolbar控件。如图 52-1所示。 图 52-1 选择Toolbar控件 因为需要在Toolbar控件按钮中使用图标,所以还需要在用户窗体中添加一个ImageList控件保存所需要的图像文件,在ImageList控件的属性页中插入6张图片,如图 52-2所示。 图 52-2 ImageList控件插入图片 用户窗体上添加了Toolbar控件后还需要设置其属性和添加按钮控件,可以在Toolbar控件的属性页中进行设置和添加,如图 52-3所示。 141 VBA常用技巧代码解析 图 52-3 设置Toolbar控件属性 还可以在代码运行时对其进行设置和添加按钮,双击用户窗体写入下面的代码: #001 Private Sub UserForm_Initialize() #002 ……使用API函数添加菜单代码略,详见附件 #003 Dim arr As Variant #004 Dim i As Byte #005 arr = Array(\" 录入 \审核\记账 \结账 \负债表\损益表\") #006 With Toolbar1 #007 .ImageList = ImageList1 #008 .Appearance = ccFlat #009 .BorderStyle = ccNone #010 .TextAlignment = tbrTextAlignBottom #011 With .Buttons #012 .Add(1, , \"\").Style = tbrPlaceholder #013 For i = 0 To UBound(arr) #014 .Add(i + 2, , , , i + 1).Caption = arr(i) #015 Next #016 End With 142 VBA常用技巧代码解析 #017 End With #018 End Sub 代码解析: 第5行代码数组arr用来保存按钮的标题文字。 第7行代码建立Toolbar控件和ImageList控件的关联。 第8行代码设置Toolbar控件的外观效果,Appearance属性获得或设置控件的外观效果,设置值如表格 52-1所示。 设置值 ccFlat cc3D 值 0 1 说明 平面 立体 表格 52-1 Appearance属性值 第9行代码设置Toolbar控件的边界样式,BorderStyle属性获得或设置边界样式,设置值如表格 52-2所示。 设置值 ccNone ccFixedSingle 值 0 1 说明 无边界线 固定单线框 表格 52-2 BorderStyle属性值 第10行代码设置按钮文本显示在按钮图像下方,TextAlignment属性获得或设置一个值,决定按钮文本显示在按钮图像下方还是右侧,设置值如表格 52-3所示。 设置值 值 说明 下方 右侧 tbrTextAlignBottom 0 tbrTextAlignRight 1 表格 52-3 TextAlignment属性值 第11行到第15行代码在Toolbar控件中添加按钮,添加按钮需要在Buttons的集合对象中使用Add方法,语法如下: object.Buttons.Add(index, key, caption, style, image) 参数object是必需的,代表Toolbar对象。 参数index是可选的,指定新增按钮的索引值,该索引值决定了按钮在Toolbar控件中的位置。如果省略index参数新增按钮添加到Butons集合的最后。 参数key是可选的,指定新增按钮的关键字。 参数caption是可选的,指定新增按钮的标题文本。 参数style是可选的,指定新增按钮的样式,设置值如表格 52-1所示。 143 VBA常用技巧代码解析 属性值 tbrDefault tbrCheck tbrButtonGroup tbrSeparator tbrPlaceholder 值 0 1 2 3 4 说明 一般按钮 开关按钮 编组按钮 分隔按钮 占位按钮 表格 52-4 Style参数值 参数image是可选的,指定新增按钮载入的图像,图像必须是与该Toolbar控件相关联的ImageList控件图像库中的一个。image参数可以是一个整数,对应ImageList图像库中某个图片的Index值也可以是一个字符串,对应图片的关键字Key。 第12行代码代码首先在Toolbar控件中添加占位按钮,设置其style属性为tbrPlaceholder,添加的就是占位按钮,在Toolbar控件中是不显示的,仅仅起到占位的作用。 第14行代码在占位按钮后继续添加6个按钮,设置其标题文本和图像在ImageList控件中的编号。 为了响应Toolbar控件,双击Toolbar控件写入下面的代码: #001 Private Sub Toolbar1_ButtonClick(ByVal Button As MSComctlLib.Button) #002 Select Case Button.Index #003 Case 2 #004 MsgBox \"录入\" #005 Case 3 #006 MsgBox \"审核\" #007 Case 4 #008 MsgBox \"记账\" #009 Case 5 #010 MsgBox \"结账\" #011 Case 6 #012 MsgBox \"资产负债表\" #013 Case 7 #014 MsgBox \"损益表\" #015 End Select #016 End Sub 代码解析: 144 VBA常用技巧代码解析 Toolbar控件的ButtonClick事件,在单击Toolbar控件的按钮时发生,参数Button代表单击的按钮。为了演示方便,根据其Index属性值使用消息框显示按钮标题文本,在实际应用中可以为菜单写入代码或指定过程名称。 运行窗体后在窗体上添加工具栏,如图 52-4所示。 图 52-4 在用户窗体上添加工具栏 技巧53 使用代码添加窗体及控件 VBA中的用户窗体为用户提供了可视化的操作界面,在用户窗体中一般都包含控件以便与用户进行交互。我们通常是在VBE中使用菜单“插入”→“用户窗体”来创建用户窗体,然后拖动工具箱中的控件到用户窗体中,也可以使用代码来添加用户窗体及其控件,代码如下: #001 Private Sub CommandButton1_Click() #002 Dim myForm As VBComponent #003 Dim myTextBox As Control #004 Dim myButton As Control #005 Dim i As Integer #006 Set myForm = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm) 145 VBA常用技巧代码解析 #007 With myForm #008 .Properties(\"Name\") = \"Formtest\" #009 .Properties(\"Caption\") = \"演示窗体\" #010 .Properties(\"Height\") = \"180\" #011 .Properties(\"Width\") = \"240\" #012 Set myTextBox = .Designer.Controls.Add(\"Forms.CommandButton.1\") #013 With myTextBox #014 .Name = \"myTextBox\" #015 .Caption = \"新建文本框\" #016 .Top = 40 #017 .Left = 138 #018 .Height = 20 #019 .Width = 70 #020 End With #021 Set myButton = .Designer.Controls.Add(\"Forms.CommandButton.1\") #022 With myButton #023 .Name = \"myButton\" #024 .Caption = \"删除文本框\" #025 .Top = 70 #026 .Left = 138 #027 .Height = 20 #028 .Width = 70 #029 End With #030 With .CodeModule #031 i = .CreateEventProc(\"Click\ #032 .ReplaceLine i + 1, Space(4) & \"Dim myTextBox As Control\" & Chr(10) & Space(4) & \"Dim i As Integer\" & Chr(10) & Space(4) & \"Dim k As Integer\" _ #033 & Chr(10) & Space(4) & \"k = 10\" & Chr(10) & Space(4) & \"For i = 1 To 5\" & Chr(10) & Space(8) & \"Set myTextBox = Me.Controls.Add(bstrprogid:=\"\"Forms.TextBox.1\"\")\" _ #034 & Chr(10) & Space(8) & \"With myTextBox\" & Chr(10) & Space(12) & \".Name = \"\"myTextBox\"\" & i\" & Chr(10) & Space(12) & \".Left = 20\" _ 146 VBA常用技巧代码解析 #035 & Chr(10) & Space(12) & \".Top = k\" & Chr(10) & Space(12) & \".Height = 18\" & Chr(10) & Space(12) & \".Width = 80\" _ #036 & Chr(10) & Space(12) & \"k = .Top + 28\" & Chr(10) & Space(8) & \"End With\" & Chr(10) & Space(4) & \"Next\" #037 i = .CreateEventProc(\"Click\ #038 .ReplaceLine i + 1, Space(4) & \"Dim i As Integer\" & Chr(10) & Space(4) & \"On Error Resume Next\" & Chr(10) & Space(4) & \"For i = 1 To 5\" & Chr(10) & Space(8) & \"Formtest.Controls.Remove \"\"myTextBox\"\" & i\" & Chr(10) & Space(4) & \"Next\" #039 End With #040 End With #041 End Sub 代码解析: 使用代码添加一个用户窗体及其两个按钮控件,并为按钮控件添加单击事件及其相应的代码。 第2行到第5行代码声明变量类型,如果发生错误请在菜单“工具”→“引用”中引用“Microsoft Visual Basic for Applications Extensibility 5.3”,如图 53-1所示。 图 53-1 引用 第6行代码,使用Add方法添加用户窗体,应用于VBComponents集合的Add方法将一个对象添加到集合,语法如下: 147 VBA常用技巧代码解析 object.Add(component) 参数object是必需的,一个有效的对象名。 参数component是必需的,对于VBComponents集合,则为表示类模块、窗体、标准模块的列举常数,可以为表格 53-1所示的常量之一。 常量 vbext_ct_ClassModule Vbext_ct_MSForm vbext_ct_StdModule 值 2 3 1 描述 将一个类模块添加到集合 将窗体添加到集合 将标准模块添加到集合 表格 53-1 component参数值 第8行到第11行代码,使用VBComponent对象的Properties属性设置用户窗体的相关属性。 第12行代码,使用Add方法添加在用户窗体上添加一个按钮控件。VBComponent对象的Designer属性返回一个设计器对象,其Controls属性返回Controls集合,代表用户窗体中所有的控件。应用于Controls集合对象的Add方法在用户窗体中添加控件,语法如下: object.Add( ProgID [, Name [, Visible]]) 参数object是必需的,一个有效的对象名。 参数ProgID是必需的,程序设计标识符。是用于标识对象类的、没有空格的文本串。关于程序设计标识符请参阅技巧22-3中的表格 22-1。 参数Name是可选的,指定被添加的对象的名称。 参数Visible是可选的,若对象为可见的为True,若对象为隐藏的则为False。默认值为True。 第13行到第20行代码设置添加的按钮控件的相关属性。 第21行到第29行代码继续添加一个按钮控件并设置其相关属性。 第30行到第40行代码为添加的按钮控件创建单击事件过程并在其单击事件中添加代码。 其中第30、39行代码使用CreateEventProc方法为按钮控件创建单击事件过程,应用于CodeModule对象的CreateEventProc方法创建一个事件过程,语法如下: object.CreateEventProc(eventname, objectname) As Long 参数object是必需的,一个有效的对象名。 参数eventname是必需的,字符串表达式,用来指定欲添加到模块的事件名称。 参数objectname是必需的,字符串表达式,用来指定事件源的对象名称。 CreateEventProc方法可返回事件过程的开始行,所以使用变量i保存开始行。 第32行代码使用ReplaceLine方法在按钮控件的单击事件过程中添加代码,应用于 148 VBA常用技巧代码解析 CodeModule对象的ReplaceLine方法用特定的代码代替原代码,语法如下: object.ReplaceLine(line, code) 参数object是必需的,一个有效的对象名。 参数line是必需的,用来指定所要代替的行。 参数code是必需的,用来指定要插入的代码。 在使用ReplaceLine方法时将line参数设置为变量i加1,也就是在单击事件过程的第2行开始添加代码,在添加代码时使用Space函数插入空格,使用Chr函数进行换行。 运行CommandButton1_Click过程,添加一个用户窗体及两个按钮控件,并在用户窗体中添加以下的代码: #001 Private Sub myTextBox_Click() #002 Dim myTextBox As Control #003 Dim i As Integer #004 Dim k As Integer #005 k = 10 #006 For i = 1 To 5 #007 Set myTextBox = Me.Controls.Add(\"Forms.TextBox.1\") #008 With myTextBox #009 .Name = \"myTextBox\" & i #010 .Left = 20 #011 .Top = k #012 .Height = 18 #013 .Width = 80 #014 k = .Top + 28 #015 End With #016 Next #017 End Sub #018 Private Sub myButton_Click() #019 Dim i As Integer #020 On Error Resume Next #021 For i = 1 To 5 #022 Formtest.Controls.Remove \"myTextBox\" & i #023 Next 149 VBA常用技巧代码解析 #024 End Sub 代码解析: 第1行到第17行代码,用户窗体中“添加文本框”按钮的单击事件,在用户窗体运行时使用Add方法在用户窗体中添加5个文本框控件并设置其相关属性。 第18行到第24行代码,用户窗体中“删除文本框”按钮的单击事件,在用户窗体运行时使用Remove方法删除文本框控件。应用于Controls集合的Remove方法从集合中删除一个成员,或者从框架、页面或窗体中删除一个控件,语法如下: object.Remove( collectionindex) 参数object是必需的,一个有效的对象名。 参数collectionindex是必需的,成员在集合内的位置或索引。 注意 Remove方法只能删除在运行时间添加的控件,如果想删除在设计时间添加的控件则会出错。 运行CommandButton1_Click过程添加的用户窗体如图 53-2所示。 图 53-2 添加的用户窗体 单击“新建文本框”按钮在用户窗体中添加5个文本框控件,如图 53-3所示,而单击“删除文本框”按钮则删除用户窗体中添加的文本框控件。 150 VBA常用技巧代码解析 图 53-3 在用户窗体上添加文本框 技巧54 用户窗体的全屏显示 在需要用户窗体全屏显示时,可以将窗体的Height属性和Width属性设置为一定的数值,使之显示时和显示器一样大小。 使用这种方法虽然可以达到全屏显示的要求,但是如果换台显示器不一样的电脑时,此种方法便会失效。为了使用户窗体达到真正的全屏显示,可以使用以下的方法。 54-1 设置用户窗体为应用程序的大小 将用户窗体的高度和宽度设置为应用程序的高度和宽度,如下面的代码所示。 #001 Private Sub UserForm_Initialize() #002 Application.WindowState = xlMaximized #003 With Me #004 .Width = Application.Width #005 .Height = Application.Height #006 .Left = Application.Left #007 .Top = Application.Top #008 End With #009 End Sub 151 VBA常用技巧代码解析 代码解析: 用户窗体初始化时,将高度和宽度设置成与Excel应用程序窗口一样。 第2行代码,将Excel应用程序的WindowState属性设置为xlMaximized,使Excel应用程序最大化显示。 不使用对象识别符时Application属性返回一个Application对象,代表Excel应用程序。WindowState属性返回或设置窗口的状态,可以为表格 54-1所示的XlWindowState常量之一。 常量 xlMaximized xlNormal xlMinimized 值 -4137 -4143 -4140 说明 最大化 不变化 最小化 表格 54-1 XlWindowState常量 第3行到第8行代码将用户窗体的Width属性、Height属性设置为Excel应用程序的高度和宽度,Width属性、Height属性以磅为单位返回或设置对象的高度和宽度。将用户窗体的Left属性、Top属性设置为和最大化后的Excel应用程序的一样。 54-2 根据屏幕分辨率进行设置 根据屏幕分辨率的大小自动调整用户窗体的高度和宽度,如下面的代码所示。 #001 Private Declare Function GetSystemMetrics Lib \"user32\" (ByVal nIndex As Long) As Long #002 Const SM_CXSCREEN As Long = 0 #003 Const SM_CYSCREEN As Long = 1 #004 Private Sub UserForm_Initialize() #005 With Me #006 .Height = GetSystemMetrics(SM_CYSCREEN) * 0.72 #007 .Width = GetSystemMetrics(SM_CXSCREEN) * 0.75 #008 .Left = 0 #009 .Top = 0 #010 End With #011 End Sub 代码解析: 用户窗体初始化时根据屏幕分辨率的大小自动调整用户窗体的高度和宽度。 152 VBA常用技巧代码解析 第1行到第3行代码,API函数声明。 第6行代码设置用户窗体的高度,屏幕分辨率的Y坐标值乘以0.72将其换算成以磅为单位的数值。 第7行代码设置用户窗体的宽度,屏幕分辨率的X坐标值乘以0.75将其换算成以磅为单位的数值。 经过以上两种方法的设置,用户窗体显示时始终以全屏显示。 技巧55 在用户窗体上添加状态栏 在技巧51 、技巧52 中我们在用户窗体上添加了菜单和工具栏,为了使窗体更像正规的软件,还需要在用户窗体的底部添加一个状态栏,用于显示程序的各种状态信息。 在用户窗体上添加状态栏使用StatusBar控件,StatusBar控件用于设计窗体状态栏,状态栏由一组连续的窗格(最多16个)对象组合而成,用于显示应用程序当前的工作状态,其位置通常在应用程序窗体的底部。在设计模式下右键单击“工具箱”,在显示的右键菜单中选择“附加控件”,在显示的对话框中选择“Microsoft StatusBar Control, veision 6.0”控件如图 55-1所示,拖动后就可以在用户窗体上添加一个StatusBar控件。 图 55-1 选择StatusBar控件 153 VBA常用技巧代码解析 在用户窗体上添加了StatusBar控件后还需要添加窗格,可以在StatusBar控件的属性页中进行设置和添加,在StatusBar控件的属性窗口中选择“自定义”按钮,在显示的属性页中设置属性和添加窗格,如图 55-2所示。 图 55-2 添加StatusBar控件的窗格 也可以在代码运行时对其进行属性设置和添加窗格,双击用户窗体写入下面的代码: #001 Private Sub UserForm_Initialize() #002 ……使用API函数添加菜单代码略,详见附件。 #003 Dim arr As Variant #004 Dim i As Byte #005 ……使用Toolbar控件添加工具栏代码略,详见附件。 #006 arr = Array(0, 6, 5) #007 With StatusBar1 #008 .Width = Me.Width - 10 #009 For i = 1 To 3 #010 .Panels.Add(i, , \"\").Style = arr(i - 1) #011 Next #012 .Panels(1).Text = \"准备就绪!\" 154 VBA常用技巧代码解析 #013 .Panels(2).Width = 60 #014 .Panels(3).Width = 75 #015 .Panels(1).Width = Me.Width - .Panels(1).Width - .Panels(2).Width #016 .Panels(3).Picture = LoadPicture(ThisWorkbook.Path & \"\\123.BMP\") #017 For i = 0 To 2 #018 .Panels(i + 1).Alignment = i #019 Next #020 End With #021 End Sub 代码解析: 第8行代码设置StatusBar控件的宽度比用户窗体略小一点。 第9行到第11行代码在StatusBar控件中添加三个窗格并指定窗格的样式。添加窗格需要在Panels集合对象中使用Add方法,语法如下: object.Panels.Add(index, key, text, style, picture) 参数object是必需的,代表StatusBar对象。 参数index是可选的,指定新增窗格的索引值,该索引值决定了窗格在StatusBar控件中的位置。如果省略index参数新增窗格添加到Panels集合的最后。 参数key是可选的,指定新增窗格的关键字。 参数text是可选的,指定新增窗格中显示的文本。 参数style是可选的,指定新增窗格的样式,设置值如表格 55-1所示。 属性值 sbrText sbrCaps sbrNum sbrIns sbrScrl sbrtime sbrDate 值 0 1 2 3 4 5 6 说明 显示文本与图形 显示大小写状态 显示numlock键状态 显示Insert状态 显示Scroll键状态 按系统格式显示时间 按系统格式显示日期 表格 55-1 Style参数值 参数picture是可选的,指定新增窗格载入的图像。 第12行代码设置第一个窗格显示的文本。 155 VBA常用技巧代码解析 第13行到第15行代码设置三个窗格的宽度。 第16行代码为第三个窗格加载指定的图像。 第17行到第19行代码设置三个窗格中文本的对齐方式。Panels对象的Alignment属性返回或设置窗格中文本的对齐方式,设置值如表格 55-2所示。 属性值 sbrLeft sbrCenter sbrRight 值 0 1 3 说明 文本左对齐 文本居中对齐 文本右对齐 表格 55-2 Alignment属性值 在示例中使用StatusBar控件的第一个窗格在用户窗体的文本框输入时显示所输入的内容,需要在文本框中写入下面的代码。 #001 Private Sub TextBox1_Change() #002 StatusBar1.Panels(1).Text = \"正在录入:\" & TextBox1.Text #003 End Sub 代码解析: 文本框的Change事件过程,将文本框中输入的内容显示在StatusBar控件的第一个窗格中。 运行窗体后在窗体上添加状态栏,如图 55-3所示。 图 55-3 在用户窗体上添加状态栏 156
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务