学习Excel技术,关注微信公众号:
excelperfect
引子:通过前一篇文章《VBA专题05-2:一文彻底掌握用户窗体编程基础知识(上)》的学习,你已经对用户窗体有了一定的了解,本文通过4个问题的解答,进一步学习用户窗体的一些实用知识。
问题1:如何在用户窗体间传递数据?
在用户窗体间传递数据的方式主要有两种:直接从窗体到窗体传递数据(这意味着这两个窗体应同时都被装载在内存中);或者先将一个窗体中的数据存储在某个地方,然后再从另一个窗体中调用这些数据。
可以或者是从“源数据”窗体或者是从“目标”窗体中传递数据,但必须在“源数据”窗体被卸载前进行。注意,当指定另一个用户窗体中的控件时,必须加上该窗体的名字,例如:
txtName.Value =frmTheOtherForm.txtName.Value
直接从窗体到窗体传递数据会触发另一窗体的初始化事件(除非该窗体可见),因为在引用该窗体中控件的属性。如果该初始化事件过程包含有显示窗体的代码,或者调用其它的子过程,这将触发一系列的代码,导致难于调试,因此,建议仅对相当简单的窗体使用这种方式。
相比较而言,将数据存储在变量中会更灵活和便于控制。数据能被存储在公共变量中、单元格中(当关闭文件时能被保存)或工作表命名区域中。
随后的综合示例中包含有这两种方式传递数据的例子。
问题2:如何找到我的窗体中的某类控件?
能够在用户窗体中所包含的控件之间进行循环,选择那些合适类型的控件,并在这些控件中应用相应的代码。可用如下几种方式进行处理:使用TypeName函数、TypeOf运算符、或者控件名字。
TypeName()TypeName函数返回一个字符串,例如,文本框为“TextBox”,命令按钮为“CommandButton”等等。控件的类型名称一般与控件的缺省名或标题相同,但不是数字。例如,当添加一个新的文本框到用户窗体中,缺省设置命名为TextBox1。
TypeOfTypeOf是确定对象类型的很好的方式。引用了对象库之后,它能直接返回该对象的类型而不是字符串。能通过对象浏览器找到库和一个对象的类型。例如,文本框的类型是MsForms.Textbox。
TypeOf主要的优势在于使代码更易调试。当试图编译模块时能捕获类型,并且TypeOf支持智能识别——开始输入“If TypeOf ctl Is”,接着将会获得一个带有所有可用的选择的下拉列表。
“IfTypeOf…Is…Then”是If语句的一类特殊的语句,其介绍在VBA帮助文档中的If语句中。
控件名字
如果按照统一的规则命名了控件,则能使用名称(Name)属性来识别它们,并能运用一些技术或技巧。譬如运用Left函数,可以非常灵活地识别一组子文本框,例如在用户窗体中有10个文本框,其名称分别为txtTeamName、txtTeamNumber、txtMember1、txtMember2、……、txtMember8,能使用这种方法识别并清空名字中所有以”txtMember”开头的文本框。
示例
在下面的例子中有三个作用相同的If语句(假设文本框名字都是以“txt”开头):
Dim ctl As Control
For Each ctl In Me.Controls
If TypeOf ctl Is MSForms.Textbox Then '或者 If TypeName(ctl) = "TextBox" Then '或者
If Left(ctl.Name, 3) ="txt" Then'对文本框进行操作
ctl.Text = "Hello"
End If
Next ctl
随后的综合示例中也有一个例子。
问题3:如何获取数据到列表框中?
可以通过下面所介绍的三种方式为列表框获取数据。
RowSource属性
能将列表框直接与工作表上的一个单元格区域相链接,这与工作表中的列表框相同。在该区域中的任何变化将会立即使列表框相应变化,但在列表框中的数据是只读的,不能通过改变列表框中的项目来改变工作表中的内容。
注意,RowSource参数是一个字符串,而不是一个单元格区域:
lstNames.RowSource =Range("Names").Address
List属性 /Column属性
能使用List属性和Column属性来设置列表项目,这两个属性除了方向不同外,实质上是相同的。List属性的语法为:List(行,列);Column属性的语法为:Column(列,行)。可以复制整个数组到列表框中,或者只是在列表框中设置单个的项目。
lstNames.List =Range("Names").Value
AddItem方法
AddItem方法在列表框中添加一行,并且能放置一个值在新行的第一列中。在多列列表框中,必须使用List属性或Column属性放置值在剩下的列中。
With lstNames
.Additem
.List(0, 0) = "John"
.List(0, 1) = "Smith"
End With
在随后的综合示例中,有上述三个属性或方法的例子。
问题4:如何创建进度条?
创建进度条的一个简单的方法是创建带有两个标签(例如分别命名为lblBackground和lblProgressBar的两个标签)的用户窗体。使lblBackground标签与创建的进度条一样宽,设置lblProgressBar标签的宽度值(Width)从0开始,并确保lblProgressBar标签在lblBackground标签之上。接着,当运行循环时增加lblProgressBar标签的宽度。
'p为已经进行的循环所占的比例,例如0.6
Me.lblProgressBar.Width = p *Me.lblBackground.Width
在随后的综合示例中,有一个简单的进度条例子。