1、对话框和自定义窗体在第四章,你学习了如何使用Excel内置的InputBox函数在VBA过程执行期间从用户处收集单一数据。但是,万一你的程序在运行时需要多个数据怎么办呢?用户也许希望一次就提供所有数据,或者从项目清单中作出所有合适的选择。如果你定程序必须收集数据的话,那么你可以: 使用内置对话框集合 创建一个自定义窗体本章将教你如何从VBA过程里显示内置的对话框,以及从零开始设计你自己的自定义窗体。Excel对话框在开始创建自己的窗体之前,你应该花上一些时间学习如何利用Excel内置的对话框,这些内置对话框本来就是为我们准备的。我讲的不是手动选择适合的选项,而是从你自己的VBA过程里调用这些对
2、话框。Excel有一个特殊的内置对话框集合,它们用开头为xlDialog的常量表示,例如xlDialogClear,xlDialogFont,xlDialogDefineName和xlDialogOptionsView。这些内置对话框是Excel对象,属于内置Dialos集合,每个dialog对象代表一个内置对话框。表10-1 常用的内置对话框对话框名称 常量新建 xlDialogNew打开 xlDialogOpen另存为 xlDialogSaveAs页面设置 xlDialogPageSetup打印 xlDialogPrint字体 xlDialogFont按照下述格式使用Show方法来显示对话
3、框:Application.Dialogs(常量).Show 例如,下面的语句显示字体对话框:Application.Dialogs(xlDialogFont).Show如果你在对象浏览器里面选择Excel库后,再输入xlDialog搜索的话,那些代表Excel内置对话框的常量清单就会显示在对象浏览器里面了(参见图10-1)1. 打开一个新工作簿并且保存为Chap10.xls2. 切换到VB编辑器窗口3. 打开立即窗口4. 输入下述语句并查看结果:Application.Dialogs(xlDialogClear).Show Application.Dialogs(xlDialogFont).
4、Show Application.Dialogs(xlDialogFontProperties).Show Application.Dialogs(xlDialogDefineName).Show Application.Dialogs(xlDialogOptionsView).Show 最后一句指令显示“选项”对话框的“视图” 。显示内置对话框后,你可以选择合适的选项,然后Excel就会将当前被选择的单元格,区域或者整个工作表设置相应的格式。尽管你不能更改内置对话框的外观和行为,但是当你从你的VBA过程显示内置对话框的时候,你可以决定它的初始设置。如果你不更改初始设置,那么VBA将显示对话框
5、和其缺省设置。假设你要显示清除对话框,并且所有按钮都被选择上。通常Excel显示对话框的时候,内容选项按钮是被选择上的。在立即窗口里输入下列语句:Application.DialogS(xlDialogClear).Show 1 你可以在Show方法后面加上一系列的参数,在清除对话框里, “全部”选项按钮出现在四个选项按钮组的最开头。Excel通常将可用的选项进行编号,因此, “全部”=1, “格式”=2, “内容”=3,以及“批注”=4。在线帮助可以搜索到内置对话框的参数列表(参见图10-3)图10-1 前缀为“xlDialog”的常量识别Excel内置对话框在立即窗口里输入下面的语句,可以
6、显示字体对话框,并且当前选择为“Arial”字体和14字号:Application.Dialogs(xlDialogFont).Show “Arial“, 14如果只要明确字号的话,那么可以在第一个参数的位置放置一个逗号就行:Application.Dialogs(xlDialogFont).Show , 8 下面的指令显示“定义名称”对话框,并且在工作簿中的“名称”文本框中输入“John” ,“引用位置”里引用到单元格A1:Application.Dialogs(xlDialogDefineName).Show “John“, “=$A$1“ 如果你点击确定Show方法就返回True,点击取
7、消则为False。图10-2 以常量xlDialogOptionsView代表的“选项”对话框“视图”的可用设置图10-3 Excel内置对话框参数列表1.文件打开和另存为对话框OfficeXP中一个新而功能强大的对象是FileDialog。该对象允许你从你的VBA过程里显示文件打开和文件另存为对话框。因为FileDialog对象是Microsoft Office 10.0 Object Library的一部分,所以它在所有的Office XP应用程序里都是可用的。在前期的Excel版本中,程序员使用了两种特殊的方法来显示文件打开和文件另存对话框,这些方法(GetOpenFilename和Ge
8、tSaveAsFilename)将在本章后面解释。要在你的VBA过程里面使用新的FileDialog对象来显示文件打开对话框的话,你可以输入下列语句:Application.FileDialog(msoFileDialogOpen).Show 要显示文件另存对话框的话,则使用下面的语句:Application.FileDialog(msoFileDialogSaveAs).Show 现在,我们在立即窗口里输入上面的语句来看看文件打开和文件另存对话框。除了文件打开和文件另存为对话框之外,FileDialog对象也能够显示“浏览”对话框,列出文件和文件夹(参见图10-4) ,或者文件夹(图10-5
9、): browse the list of files and folders 浏览文件和文件夹清单Application.FileDialog(msoFileDialogFilePicker).Show 图10-4 文件采集对话框允许用户选择一个或多个文件,该对话框显示文件和文件夹列表,并且标题显示为“浏览” browse the list of folders 浏览文件夹清单Application.FileDialog(msoFileDialogFolderPicker).Show 图10-5 文件夹采集对话框允许用户选择一个路径,该对话框显示目录列表,并且标题显示为“浏览”文件对话框使用
10、的常量列在下面的表格里,前缀“mso”表明这些常量都是Microsoft Office 对象模型里一部分。msoFileDialog常量 值msoFileDialogOpen 1msoFileDialogSaveAs 2msoFileDialogFilePicker 3msoFileDialogFolderPicker 4可以使用FileDialog的Filters属性来控制显示文件的类型。如果你打开文件打开对话框下面的“文件类型”下拉列表框时,你将看到许多可选择的文件过滤器。那里有24种预先设置好的文件过滤器,你也可以在该清单里添加你自己的过滤器。在立即窗口里输入下述语句,我们就可以得到缺省
11、的文件过滤器数目了:set f = Application.FileDialog(msoFileDialogOpen).Filters ?f.count FileDialog对象的过滤器储存在FileDialogFilters集合里面。我们来创建一个简单的过程,将缺省的文件过滤器返回到Excel工作表:1. 在当前VBA工程里插入一个新模块,并且重命名为DialogBoxes2. 在DialogBoxes代码窗口里输入下面显示的ListFilters过程:Sub ListFilters() Dim fdfs As FileDialogFilters Dim filt As FileDialog
12、Filter Dim c As Integer Set fdfs = Application.FileDialog(msoFileDialogOpen).Filters Sheets(3).Cells(1, 1).Select Selection.Formula = “List of Default Filters“ With fdfs c = .Count For Each filt In fdfs Selection.Offset(1, 0).Formula = filt.Description & _ “: “ & filt.Extensions Selection.Offset(1,
13、0).Select Next MsgBox c & “ filters were written to Sheet3.“ End With End Sub 该过程声明了两个对象变量,变量fdfs返回对FileDialog对象里的FileDialogFilters集合的引用,而对象变量filt则储存对对象FileDialogFilter的引用。FileDialogFilters集合的Count属性返回文件过滤器的总数。之后,过程遍历过滤器集合,并且找到每个过滤器的描述和扩展名。使用FileDialogFilters集合的Add方法,你可以轻易地将你自己的过滤器添加到缺省的过滤器中去。下面修改后代
14、工程ListFilters2示范了如何将临时文件(*.tmp)过滤器添加到过滤器清单中去。该过程里的最后语句将打开文件打开对话框,因此你自己可以检查自定义的过滤器是否已经被添加到了文件类型下拉列表框里。Sub ListFilters2() Dim fdfs As FileDialogFilters Dim filt As FileDialogFilter Dim c As Integer Set fdfs = Application.FileDialog(msoFileDialogOpen).Filters Sheets(3).Cells(1, 1).Select Selection.Form
15、ula = “List of Default Filters“ With fdfs c = .Count For Each filt In fdfs Selection.Offset(1, 0).Formula = filt.Description & _ “: “ & filt.Extensions Selection.Offset(1, 0).Select Next MsgBox c & “ filters were written to Sheet3.“.Add “Temporary Files“, “*.tmp“, 1 c = .Count MsgBox “There are now
16、“ & c & “ filters.“ & vbCrLf _ & “Check for yourself.“ Application.FileDialog(msoFileDialogOpen).Show End With End Sub 你可以使用FileDialogFilters集合的Clear方法清除所有预设的过滤器。修改一下上面的过程,在添加自定义的临时文件(*.tmp)过滤器之前,清除内置的过滤器。当你从文件打开对话框里选择一个文件时,该被选择的文件名称和路径就会被放置在FileDialogSelectedItems集合里。使用SelectedItems属性可以返回FileDialog
17、SelectedItems集合。通过设定FileDialog对象的AllowMultiSelect属性为True,用户就可以同时按下Shift键或者Ctrl键和文件名称,选择一个或多个文件。接下来的过程示范了如何使用上面提及的属性,该过程打开一个新的工作簿并且插入一个列表框控件。允许用户选择一个以上的文件,然后被选择的文件将加入到该列表框控件里,并且加亮第一个文件名。Sub ListSelectedFiles() Dim fd As FileDialog Dim myFile As Variant Dim lbox As Object Set fd = Application.FileDial
18、og(msoFileDialogOpen) With fd .AllowMultiSelect = True If .Show Then Workbooks.Add Set lbox = Worksheets(1).Shapes. _AddFormControl(xlListBox, _Left:=20, Top:=60, Height:=40, Width:=300) lbox.ControlFormat.MultiSelect = xlNone For Each myFile In .SelectedItems lbox.ControlFormat.AddItem myFile Next
19、Range(“B4“).Formula = _ “Youve selected the following “ & _ lbox.ControlFormat.ListCount & “ files:“ lbox.ControlFormat.ListIndex = 1 End If End With End Sub 图10-6 使用过程ListSelectedFiles(见上面)将用户选择的文件添加到工作表中列表框控件中去注意,Show方法不会将用户所选的文件打开,它仅仅显示文件打开对话框。当用户点击“打开”按钮时,文件名称通过SelectedItems属性从SelectedItems集合里获得
20、。如果你希望用户点击“打开”按钮时立即执行文件的打开操作的话,你就应该使用FileDialog对象的Execute方法。下面的过程示范了如何立即打开用户选择的文件:Sub OpenRightAway() Dim fd As FileDialog Dim myFile As Variant Set fd = Application.FileDialog(msoFileDialogOpen) With fd .AllowMultiSelect = True If .Show Then For Each myFile In .SelectedItems .Execute Next End If En
21、d With End Sub 2.GetOpenFilename 和 GetSaveAsFilename 方法从多年以前开始,Excel就给程序员们提供了两种方便的VBA方法来显示文件另存为和文件打开对话框:GetOpenFilename和 GetSaveAsFilename。这些方法只有在Excel里可用,并且在Excel2002里面如果需要向后兼容的话仍然可用。GetOpenFilename方法显示“打开”对话框,在那里你可以选择要打开的文件名称,第二个方法(GetSaveAsFilename)则显示另存为对话框。1. 在立即窗口输入下面的指令:Application.GetOpenFil
22、ename Application.GetSaveAsFilename Application.GetSaveAsFilename (“Plan2.xls“) GetOpenFilename方法从用户处获得文件名称,而不必实际打开某特定的文件。该方法有四个可选的参数,经常使用的是第一和第三个参数,显示入下表:GetOpenFilename参数 描述fileFilter 该参数决定了对话框的文件类型(译者:原文为Save as type,有误)下拉框了的内容。例如,要在文件类型下拉框里显示“Excel Files(*.xls)”的话,你就应该输入下列文本作为fileFilter: “Excel
23、Files(*.xls), *.xls”(译者:“Excel Files, *.xls”也一样。 )过滤器的前面部分(逗号前)决定文件类型下拉框要显示的文本,第二部分(逗号后)明确你要显示的那种类型的文件。确保你按照表格里的例子试验一下。title 这是对话框的标题,如果忽略,对话框将显示标题为“打开”在立即窗口里输入下列语句(确保在一行输入) ,来看看这些参数是如何使用的:Application.GetOpenFilename(“Excel Files(*.xls), *.xls“),“Highlight the File“ GetOpenFilename方法返回所选的或者指定的文件名称,该
24、名称之后可以在你的VBA过程里用来打开该文件,例如:yourFile = Application.GetOpenFilename ?yourFile C:EXCELMark.xls Workbooks.Open Filename:=yourFile 在上面的例子里,文件名称被赋予变量yourFile,接下来的两条输入为询问文件名称(?yourFile)和显示该名称(C:EXCELMark.xls) 。第四条语句打开变量yourFile明确的文件。如果你通过点击Esc键或者对话框上的取消按钮来取消对话框的话,那么GetOpenFilename方法就会返回False。GetSaveAsFilena
25、me方法返回文件名和路径,然而,它不会自动地保存该特定的文件。输入下述指令提供文件名称:Application.GetSaveAsFilename (“Plan2.xls“) 如果你忽略文件名称的话,Excel就会显示当前活动文件的名称。当你使用GetSaveAsFilename方法时,你可以明确文件过滤器和对话框自定义标题:yourFile = Application.GetSaveAsFilename(“Plan2.xls”, “Excel Files(*.xls), *.xls“,“Name your file“) 要显示另存为对话框的话,就要将GetSaveAsFilename方法的结
26、果赋予一个变量,如上所示。3.创建窗体尽管内置的对话框很方便使用,但是它并不能满足你所有的VBA应用程序的要求。除了将对话框显示在屏幕上和初始化它的设置之外,你不能控制对话框的外观,你不能决定增加哪个按钮,删除哪个按钮,而哪个又移动,同样,你不能改变内置对话框的大小。如果你想用提供一个自定义的界面的话,那么你的唯一办法就是创建一个用户窗体。用户窗体看上去就像一个自定义对话框,你可以在上面添加各种各样的控件,给这些控件设置属性以及编写对窗体反应的VBA过程和控制事件。窗体是单独的对象,你可以在VB编辑器菜单里选择“插入”|“用户窗体”来添加窗体。窗体可以在不同的应用程序之间分享使用,例如,你可以在Word或者任何其它使用VB编辑器的应用程序里面,重新使用Excel里设计的窗体。按照下述步骤创建自定义窗体: 切换到VB编辑器窗口 选择“插入”|“用户窗体”一个叫做窗体的文件夹显示在工程浏览器窗口,该文件夹包含一个空白用户窗体。工作区域自动显示窗体和带有添加控件的工具箱。