VBA编程问答(第1辑)

来源:百度文库 编辑:神马文学网 时间:2024/04/17 05:28:05
VBA编程问答
(第1辑)
在学习ExcelVBA编程的过程中,经常会遇到一些问题,有些可能是新碰到的,有些则是以前已遇到过但暂时忘掉了解决办法的,VBA编程问答将把我所收集到的问题和自已所遇到的问题及解决办法进行归纳整理,以方便查阅和参考。
在下面的内容中,有大量的程序代码,您可以将它们输入或复制到VBE编辑器中进行调试,也可以将它们进行适当的调整和修改后应用到自已的程序中。有些问答提供了参考示例,您可以直接下载后处理。
本辑目录
问题1:如何优化VBA代码并使程序尽可能快的运行?
问题2:如何禁用用户窗体的关闭按钮?
问题3:可以撤销宏所执行的操作吗?
问题4:如何将同一文件夹中的多个文本文件读入到工作簿中?
问题5:如何使用VBA删除所有的空工作表?
问题6:如何获取计算机上可供使用的打印机列表?
问题7:如何基于某个单元格更新其它单元格的日期?
问题8:如何编写一个宏程序运行另一个宏程序特定的次数?
问题9:如何在一个组合框中列出所有工作表中单元格D3中的值?
问题10:如何使工作表中的文本闪烁?
问题11:如何将工作簿中其它工作表名导入到指定的工作表中?
问题12:如何在单元格中快速输入带秒的时间?
=====================================================================
问题1:如何优化VBA代码并使程序尽可能快的运行?
解答:
速度问题一直是VBA程序值得关注的一个方面。当您编写了一个对大量数据进行操作的程序后,在运行时可能会发现程序运行得很慢,有的甚至达好几分钟,就像Excel应用程序已崩溃了一样。但当您发现程序确实在运行,并得到正确的结果后,您可能就会想到如何使程序更快的运行了。当然,代码运行速度慢可能是VBA程序的一个缺点,这也可能是程序语言本身的一个原因,但我们也可以找到一些方法优化VBA代码并使程序尽可能快的运行。
下面是我整理的一些优化VBA代码或提高程序运行速度的方法,有些方法是我们在编程中好的做法和应该养成的好习惯,希望能带给您一些有益的参考。高质量的程序和运行效率是需要不断实践,并在实践中不断总结和积累经验的,也希望您能将在编写程序过程中发现的一些优化方法介绍给大家共享。
1、尽量简化代码
通过简化代码,可以提高程序的性能。您可以将通用过程编写为子过程来调用。例如,假设有一个应用程序需要在不同的地方实现查找一定范围内的某个特殊条目,在一个没有简化代码的应用程序中,不同的过程可能需要应用各自的算法以实现在某个范围内查找某一条目,修改每个过程使其采用一个更有效的算法并不是一件很容易的事。而一个简化的程序则只有一个查找算法,即将该查找算法编写成通用的子程序,需要查找某个范围的过程都调用该子程序,通过在查找方法的子程序中优化查找算法,使得调用该方法的所有过程都享受性能提高所带来的好处。
另外,删除所有无关的代码,这在所录制宏中表现得尤为明显。在录制宏时,经常会产生一些与所实现的功能无关的代码,您可以将这些代码删除,以使得代码得以简化。
在下面将要讲到的设置对象变量代替长对象引用,使用With…End With语句、执行For Each…Next循环语句,根据程序环境尽量减少OLE引用,等等,均是简化代码的好方法。
2、强制声明变量
在VBE编辑器中的菜单“工具——选项”对话框中“编辑器”选项卡中,您应该始终保持“要求变量声明”复选框被选中,这样将在模块代码顶部出现Option Explicit语句,要求您在编写代码时对所有出现的变量均进行声明,这样,在使用变量时减少内存需求并加速性能。
(1)要节省内存资源,必须始终用特定的数据类型声明所有变量。如果不使用特定的数据类型声明变量,VBA会创建Variant类型的变量,这将比任何其他数据类型要求更多的内存。
(2)清楚每种数据类型需要多少内存以及它可以存储的值的范围。除使用较小的数据类型会导致隐性转换的情况外,应始终使用尽可能小的数据类型。例如,因为Integer类型的变量将被转换成Long类型的变量,应该将那些存储整型值的变量声明为Long类型,而不是Integer类型。
(3)除非确实需要,应避免使用浮点数据类型。尽管Currency数据类型更大,但它比 Single 数据类型快,因为Currency数据类型不使用浮点处理器。
(4)如果在一个过程中多次引用一个对象,可以创建对象变量,并将对给对象的引用指派给它。因为对象变量存储对象在内存中的位置,VBA将不必再次查找其位置。
(5)将对象变量声明为特定的类型(不是Object类型),以便利用早期绑定。
3、减少变量的作用范围并及时释放变量
主要是对象变量,在其使用完后,及时释放。例如,
Dim TempObj As AnyObject,AnObj As AnyObject
Set TempObj=New AnyObject
Set AnObj=TempObj
Set TempObj=Nothing ‘释放对象变量
4、尽可能使用早期绑定
绑定是指将程序调用与实际代码相匹配。为了实现早期绑定,先应创建对对象库的引用。早期绑定可以在代码中使用定义在对象库中的常量,可以自动列出对象的方法和属性,但早期绑定只有在所控制的对象拥有独立的类型库或对象库文件才适用且还需要已安装了特定的库。而后期绑定则只是在运行时才知道对象的类型并对对象进行引用,因此不具备上述特点。
使用早期绑定创建对象通常更有效率,使代码能获得更好的性能。因为对象的早期绑定引用在编译时可以通过VBE的解析,而不是通过运行时模块解析,因此早期绑定的性能要好得多。虽然在程序设计时不可能总是使用早期绑定,但应该尽可能使用它。
5、关闭屏幕刷新
在Excel中,其ScreenUpdating属性值的默认值为True,这样当写数据到工作表或者执行任何导致其显示属性变化的动作时,Excel的屏幕界面将会不断的刷新,不仅影响显示,而且影响程序运行的速度。您可以在进入主程序运行前将屏幕刷新属性关闭,即用Application.ScreenUpdating = False语句关闭屏幕刷新,这样将大大改善程序的运行速度。
但在程序运行完成前,要确保将其恢复为原来的设置,即将ScreenUpdating属性的值设置为True。因为您对该属性的修改是永久性的修改,Excel不会为您自动恢复其默认值,您必须用语句Application.ScreenUpdating = True恢复设置。
6、设置计算模式为手动
如果您的工作表中含有多个公式,在每次单元格中的值发生变化时,公式都将会重新计算,这会影响程序运行速度。您可以在进入主程序运行前,将计算模式设置为手动,即使用如下语句Application.Calculation = xlCalculationManual,以避免不必要的计算。
当程序运行结束前,您要恢复Excel的默认计算模式设置,即设置为自动重算,可使用下面的语句Application.Calculation = xlCalculationAutomatic,这同ScreenUpdating属性一样,Excel不会自动恢复其为默认值。Calculation属性是对所有工作簿进行的设置,您也可以用工作表的EnableCalculation属性来设置对某个工作表是否进行重新计算。
7、使用For Each…Next循环
可以使用For Each…Next循环来保证程序代码更快地执行。在使用For Each…Next循环时,对于存储在集合或数组中的每个对象执行一组语句,程序更简洁,也更容易阅读、调试和维护。当For Each…Next语句迭代集合时,自动指定一个对集合当前成员的引用,然后在到达集合的尾部时跳出循环语句。
8、使用With…End With语句
可以使用With…End With语句来尽量减少对象引用。使用With语句对指定的对象完成一系列的任务,而不用重复引用对象。也可以使用嵌套的With语句进一步提高程序代码的效率。例如,下面的使用With…End With语句是在同一个单元格中执行多个操作。
With Workbooks(“Book1.xls”).Worksheets(“Sheet1”).Range(“A1”)
.Formula=”=SQRT(20)”
With .Font
.Name=”Arial”
.Bold=True
.Size=10
End With
End With
同理,可使用With…End With语句在同一个单元格区域中执行多个操作。
9、在执行循环时考虑如何能够尽可能地节省资源
(1)分析循环以查看是否正在不必要地执行一些消耗内存的重复操作。例如,是否可以在循环外(而不是在循环中)设置某些变量?每次都通过循环执行的转换过程是否可以在循环之外执行?
(2)考虑是否必须在满足特定的条件时才执行循环。如果是,也许可以更早地退出循环。例如,假设正在对一个不应该包含数字字符的字符串进行数据验证。如果循环要检查字符串中的每个字符以确定其中是否包含数字字符,那么您可以在找到第一个数字字符时立即退出循环。
(3)如果必须在循环中引用数组的元素,可以创建一个临时变量存储该元素的值,而不是引用数组中的值。从数组中检索值比从相同类型的变量读取值要慢。
10、尽量减少OLE引用
可以通过尽量减少在VBA程序代码中使用OLE(对象链接与嵌入自动识别)引用来优化程序代码。VBA语句中所调用的方法和属性越多,执行语句所用的时间就越多。例如下面的两个语句:
语句1:Workbooks(1).Sheets(1).Range(“A1”).Value=10
语句2:ActiveWindow.Left=200
执行时,语句2比语句1快。
同样,上面所讲的对重复使用的对象引用指定一个变量,通过调用变量从而保证避免多次进行对象引用。
11、避免对象激活或者不需要先进行先择
在使用宏录制器时,所生成的程序代码在应用任何方法或属性之前都会激活或者选择对象。但是,并不是在所有的情况下都需要这样做。所以,在您编写VBA程序代码时,不需要在对对象执行任何任务之前都激活或者选择每个对象。
例如,在Excel中,我们如果要使第一行变成粗体就必须先选项中它。但在VBA中(除在图表操作时需要选中图表对象外),很少需要这样做,即VBA可以在不选中第一行的情况下,将它变成粗体。
宏录制器的代码:
Rows("1:1").Select
Selection.Font.Bold = True
改编后的代码为:
Row(“1:1”).Font.Bold=True
这样做还可以使程序代码更简洁,并且程序可以运行得更快。
12、在一个语句中进行复制或者粘贴
在用宏录制代码时,首先是选择一个区域,然后再执行ActiveSheet.Paste。在使用Copy方法时,可以在一个语句中指定复制的内容及要复制到的目的地。
例如,将B5:C6区域的内容复制到以单元格B8开始的区域中,使用宏录制器的代码为:
Range("B5:C6").Select
Selection.Copy
Range("B8").Select
ActiveSheet.Paste
经修改后的最佳代码是:
Range("B5:C6").Copy Destination:=Range("B8")
13、尽可能少使用“.”
在前面已经介绍过的对长对象引用使用对象变量以及使用With…End With等都是简化”.”的方法。因为在代码中的每个句点都表示至少一个(而且可能是多个)过程调用,而这些过程调用必须在后台执行。真正好的做法是在局部进行缓存对象引用,例如,应该把对象模型中较高层次的对象引用保存到局部对象变量中,然后用这些对象引用创建其他较低层次的对象引用。例如,引用某单元格数据时,可用如下代码:
Dim i As Long
For i=1 to 10
Workbooks(“Book1.xls”).Worksheets(“Sheet1”).Cells(1,i).Value=i
Next i
但下面的代码运行效率更高,因为代码中引用Workbook对象和Worksheet对象的调用命令只执行一次,而上面的代码中却要执行10次。
Dim ws As Worksheet
Dim i As Long
Set ws= Workbooks(“Book1.xls”).Worksheets(“Sheet1”)
For i=1 to 10
ws.Cells(1,i).Value=i
Next i
14、合理地使用消息框和窗体
在一个很长的程序中,偿试着将消息框或者窗体安排显示在程序的最开始或最后面,避免干扰用户。此外,尽管窗体提供了许多功能,但它们能够导致文件大小迅速增加。还有就是尽量避免给工作表单元格链接用户窗体控件,因为这样将会导致链接更新操作,影响程序运行速度。
15、尽可能加速对数字的运算
(1)当对整数进行除法时,您可以使用整型除法运算符(\)而不是浮点除法运算符(/),因为无论参与除法运算的数值类型如何,浮点除法运算符总会返回Double类型的值。
(2)在任何具有整数值的算术表达式中使用Single或Double值时,整数均将被转换成Single或Double值,最后的结果将是Single或Double值。如果要对作为算术运算结果的数字执行多次操作,可能需要明确地将该数字转换为较小的数据类型。
16、提高字符串操作的性能
(1)尽可能少使用连接操作。可以在等号左边使用Mid函数替换字符串中的字符,而不是将它们连接在一起。使用 Mid 函数的缺点是替换字符串必须与要替换的子字符串的长度相同。例如,
Dim strText As String
strText = "this is a test"
Mid(strText, 11, 4) = "tent"
(2)VBA提供许多可用来替换函数调用的内部字符串常量。例如,可以使用vbCrLf常量来表示字符串中的回车/换行组合,而不是使用Chr(13) & Chr(10)。
(3)字符串比较操作的执行速度很慢。有时,可以通过将字符串中的字符转换为 ANSI 值来避免这些操作。例如,下列代码会检查字符串中的第一个字符是否为空格:
If Asc(strText) = 32 Then
上面的代码会比以下代码更快:
If Left(strText, 1) = " " Then
17、使用Asc()检验ANSI的值
在VBA中,可以使用Chr$()函数把数转换成字符,并确定ANSI的值,但是更好的是使用Asc()函数把字符串转换成数值,然后确定它的ANSI值。如果需要进行有限次数的这种检验,对程序代码的效率可能不会产生很大影响,但是,如果需要在多个循环内进行这种检验时,这将节省处理时间并且有助于程序代码更快地执行。
18、使用Len()检验空串
尽管有多种方法可检验空串,但首选的是使用Len()函数。为了测试零长度的串,可以选择把串与””相比较,或者比较串的长度是否为0,但这些方法比用Len()函数要用更多的执行时间。当对字符串应用Len()函数并且函数返回0值时,说明该字符串是空的或者是零长度的字符串。
并且,因为在If语句内非零值被认为是True,所以直接使用Len()函数而不必与””或0比较,减少了处理时间,因此执行更快。
19、有效地使用数组
用VBA数组而不是单元格区域来处理数据,即可以先将数据写入到某个数组,然后用一个语句就可以将数组中的数据传递到单元格区域中。
在创建已知元素的确定数组时,使用Array函数对于节约空间和时间以及写出更具效率的代码是非常理想的。例如,
Dim Names As Variant
Names=Array(“Fan”,“Yang”,“Wu”,“Shen”)
此外,应该尽量使用固定大小的数组。如果确实选择使用了动态数组,应该避免数组每增加一个元素就改变一次数组的大小,最好是每次增加一定数量的元素。
20、使用Excel的内置函数
对于要实现的某一功能,如果有Excel的内置函数能够实现,那么就用Excel的内置函数,不需要另外自定义函数,因为自定义的函数总比Excel内置的函数慢。
附件
Ra8JtKDO.rar (9.37 KB)
2006-8-1 23:55, 下载次数: 84
[原创]VBA编程问答(第1辑)
RDidpODM.rar (53.87 KB)
2006-8-1 23:56, 下载次数: 79
[原创]VBA编程问答(第1辑)
WqtM1Z3M.rar (6.89 KB)
2006-8-1 23:57, 下载次数: 34
[原创]VBA编程问答(第1辑)
嵌入式框架页展示Excel视频教程,包括Excel函数公式、Excel VBA图表应用技巧、Excel教程下载与免费在线学习培训。 资料库http://fanjy.blog.excelhome.net
博客网http://www.excelperfect.com
UID
13913
帖子
902
精华
11
经验
2109
威望
17
阅读权限
100
性别

在线时间
99 小时
查看个人网站
查看详细资料
引用使用道具报告回复 TOP
fanjy

版主

积分
8009
财富
4733 ¥
技术
117
注册时间
2003-3-19
总积分排名
55
发短消息
加为好友
2楼 大 中 小 发表于 2006-8-2 00:03 只看该作者
★你以前不知道的Word:《Word实战技巧精粹》视频教程★

问题2:如何禁用用户窗体的关闭按钮?
解答:您可能不想用户在单击窗体右上角的X图标后关闭窗体,您可以在用户窗体代码模块中将UserForm_QueryClose过程的Cancel参数值设置为True,此时虽然X图标仍然存在,但当您单击它时已不起作用,因此可以防止用户通过单击该图标按钮来关闭用户窗体。例如,下面的示例提示用户只能通过单击用户窗体上的“确定”按钮来关闭该用户窗体。您可以在VBE编辑器中插入一个用户窗体,并在用户窗体上放置一个名为“Ok”的按钮,在用户窗体代码模块中输入下面的代码进行调试。
‘**************************************************
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
‘CloseMode参数表明事件发生的原因
‘若其值等于vbFormControlMenu则意味着用户单击了X图标按钮
If CloseMode = vbFormControlMenu Then
MsgBox "请单击""确定""按钮关闭本窗体"
Cancel = True
End If
End Sub
‘**************************************************
Private Sub Ok_Click()
Unload UserForm1
End Sub
===================================================================
问题3:可以撤销宏所执行的操作吗?
解答:可以,但不能通过Excel内置的功能自动实现。您可以使用VBA代码记录下运行宏程序前单元格或单元格区域原先的内容,在“撤销”命令中调用以恢复程序运行前的状态。
您可以使用Application对象的OnUndo方法作为宏程序结束前的最后一个代码,该方法允许您指定出现在“撤销”菜单项中的文本以及点击该文本后所运行的过程。如下面的代码所示:
Application.Onundo “撤销最后一个宏”,”恢复宏程序”
为说明上述方法,下面列出了一个完整的示例。示例的完整代码以及代码说明如下:
‘**************************************************
Type RangeCellInfo '自定义类型存储宏运行所作出的改变
CellContent As Variant
CellAddress As String
End Type
Public OrgWB As Workbook
Public OrgWS As Worksheet
Public OrgCells() As RangeCellInfo
‘**************************************************
Sub EditRange()
' 在所有被选取的单元格中插入X
Dim i As Integer, cl As Range
If TypeName(Selection) <> "Range" Then Exit Sub
Application.ScreenUpdating = False
ReDim OrgCells(Selection.Count)
Set OrgWB = ActiveWorkbook
Set OrgWS = ActiveSheet
i = 1
‘记录下宏程序对工作表作出改变前的状态
For Each cl In Selection
OrgCells(i).CellContent = cl.Formula
OrgCells(i).CellAddress = cl.Address
i = i + 1
Next cl
‘在所选单元格中填允X
Selection.Formula = "X"
‘指定在“撤销”菜单项中的文字及选择该命令时所执行的宏程序
Application.OnUndo "撤销最后运行的宏过程操作", "UndoEditRange"
End Sub
‘**************************************************
‘恢复工作表原先的状态
Sub UndoEditRange()
Dim i As Integer
Application.ScreenUpdating = False
On Error GoTo NoWBorWS
OrgWB.Activate
OrgWS.Activate
On Error GoTo 0
'恢复宏运行所作的改变
For i = 1 To UBound(OrgCells)
Range(OrgCells(i).CellAddress).Formula = OrgCells(i).CellContent
Next i
Set OrgWB = Nothing
Set OrgWS = Nothing
Erase OrgCells
NoWBorWS:
End Sub
示例文档见撤销宏示例.xls。krV0Zt8k.rar (9.37 KB)
krV0Zt8k.rar (9.37 KB)
[原创]VBA编程问答(第1辑)
下载次数: 81
2006-8-2 00:03
 
资料库http://fanjy.blog.excelhome.net
博客网http://www.excelperfect.com
UID
13913
帖子
902
精华
11
经验
2109
威望
17
阅读权限
100
性别

在线时间
99 小时
查看个人网站
查看详细资料
引用使用道具报告回复 TOP
fanjy

版主

积分
8009
财富
4733 ¥
技术
117
注册时间
2003-3-19
总积分排名
55
发短消息
加为好友
3楼 大 中 小 发表于 2006-8-2 00:05 只看该作者
NetExcel软件!会Excel就可以编程,快速实现报表系统、进销存、生产管理、工资绩效等系统!
问题4:如何将同一文件夹中的多个文本文件读入到工作簿中?
解答:通常,我们所看到的例子都是在工作簿中读入一个文本文件中的内容。假设有几个文本文件,我们把它们放在与工作簿相同的文件夹中,那么,现在如何在该工作簿中一次性读取这几个文本文件的内容。下面的程序演示了上述过程,示例工作簿附后,其中源数据引用了lichaobin网友在他的提问贴中所附的数据。
分两种情况:
(一)所读入的文本文件总行数小于65536行,您可以使用以下代码。
‘**************************************************
Sub Sample1()
Dim n As Long, a(), ff As Integer, txt As String, myDir As String, x
Dim myF As String, i As Long
myDir = ThisWorkbook.Path & Application.PathSeparator
myF = Dir(myDir & "*.txt")
Do While myF <> ""
ff = FreeFile
Open myDir & myF For Input As #ff
Do While Not EOF(ff)
Line Input #ff, txt
x = Split(txt, "|")
n = n + 1
ReDim Preserve a(1 To n)
a(n) = x
Loop
Close #ff
myF = Dir()
Loop
Cells.Clear
With ThisWorkbook.Worksheets("Sheet1").Range("a1")
For i = 1 To UBound(a)
.Offset(i - 1).Resize(, UBound(a(i)) + 1) = a(i)
Next
End With
End Sub
‘**************************************************
(二)所读入的文本文件总行数大于65536行,您可以使用以下代码。其中使用了一个变量t和一个判断语句,当多于65536行时,将剩下的数据写入另一工作表中。
Sub Sample2()
Dim n As Long, a(), ff As Integer, txt As String, myDir As String, x
Dim myF As String, i As Long, t As Integer
t = 1
myDir = ThisWorkbook.Path & Application.PathSeparator
myF = Dir(myDir & "*.txt")
Do While myF <> ""
ff = FreeFile
Open myDir & myF For Input As #ff
Do While Not EOF(ff)
Line Input #ff, txt
x = Split(txt, "|")
n = n + 1
ReDim Preserve a(1 To n)
a(n) = x
If n = 65536 Then
With ThisWorkbook.Sheets(t).Range("a1")
For i = 1 To UBound(a)
.Offset(i - 1).Resize(, UBound(a(i)) + 1) = a(i)
Next
End With
n = 0: Erase a: t = t + 1
End If
Loop
Close #ff
myF = Dir()
Loop
If n > 0 Then
With ThisWorkbook.Sheets(t).Range("a1")
For i = 1 To UBound(a)
.Offset(i - 1).Resize(, UBound(a(i)) + 1) = a(i)
Next
End With
End If
End Sub
示例文档见读取多个文本文件.rar。E27ouF6l.rar (53.87 KB)E27ouF6l.rar (53.87 KB)
[原创]VBA编程问答(第1辑)
下载次数: 84
2006-8-2 00:05
资料库http://fanjy.blog.excelhome.net
博客网http://www.excelperfect.com
UID
13913
帖子
902
精华
11
经验
2109
威望
17
阅读权限
100
性别

在线时间
99 小时
查看个人网站
查看详细资料
引用使用道具报告回复 TOP
fanjy

版主

积分
8009
财富
4733 ¥
技术
117
注册时间
2003-3-19
总积分排名
55
发短消息
加为好友
4楼 大 中 小 发表于 2006-8-2 00:07 只看该作者
NetExcel软件!会Excel就可以编程,快速实现报表系统、进销存、生产管理、工资绩效等系统!

问题5:如何使用VBA删除所有的空工作表?
解答:可以分两种情形来对待。
(一)如果您想删除同一工作簿中的所有空工作表,可以使用下面的两个程序中的其中一个:
‘**************************************************
Sub test1()
Dim ws As Worksheet
Application.DisplayAlerts = False
For Each ws In ActiveWorkbook.Worksheets
ws.Activate
If ActiveWorkbook.Worksheets.Count > 1 Then
If IsEmpty(ActiveSheet.UsedRange) Then
ws.Delete
End If
End If
Next ws
Application.DisplayAlerts = True
End Sub
‘**************************************************
Sub test2()
Dim ws As Worksheet
On Error GoTo Handdle
Application.DisplayAlerts = False
For Each ws In ActiveWorkbook.Worksheets
ws.Activate
With ws
If Application.CountA(.Cells) = 0 Then
.Delete
End If
End With
Next ws
Handdle:
Application.DisplayAlerts = True
End Sub
(二)如果您想删除已打开的工作簿中的所有空工作表,可使用下面的程序:
‘**************************************************
Sub test()
Dim ws As Worksheet
Dim wb As Workbook
Application.DisplayAlerts = False
For Each wb In Workbooks
wb.Activate
For Each ws In ActiveWorkbook.Worksheets
ws.Activate
If ActiveWorkbook.Worksheets.Count > 1 Then
If IsEmpty(ActiveSheet.UsedRange) Then
ws.Delete
End If
End If
Next ws
Next wb
Application.DisplayAlerts = True
End Sub
===================================================================
问题6:如何获取计算机上可供使用的打印机列表?
解答:您可能有时想获取您的计算机上可供使用的打印机列表,然后从中选择打印机输出。最简单的方法是,您可以在代码中添加下面的语句:
Application.Dialogs(xlDialogPrint).Show
===================================================================
问题7:如何基于某个单元格更新其它单元格的日期?
例如:我需要做的一个例行工作是依赖于两个特定单元格的内容添加一些日期到另一个单元格。例如,在单元格J2中有W(代表每周)或者B(代表Bi周)或者M(代表每月),单元格N2中的内容为一个可更新的日期,如果J2中包含一个W我需要在单元格L2中添加7天,或者如果J2中包含一个B我需要在单元格L2中添加14天,或者如果J2中包含一个M则在单元格L2中添加30天,……在单元格J2中包含的信息W,B,或M决定计算的天数,单元格N2中包含原先约定的日期作为开始计算的日期,单元格L2中的这个日期基于上面两个单元格的日期更新。
解答:可以粘贴下面的两个程序之一到工作表代码模块中。
(一)区分大小写,您必须在工作表中输入大写的字母W、B或M。
‘**************************************************
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Range("J2").Text = "W" Then
Range("L2") = Range("N2").Value + 7
ElseIf Range("J2").Text = "B" Then
Range("L2") = Range("N2").Value + 14
ElseIf Range("J2").Text = "M" Then
Range("L2") = Range("N2").Value + 30
End If
End Sub
(二)不区分大小写,并使用了Select Case选择语句。
‘**************************************************
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$N$2" Or Target.Address = "$J$2" Then
Dim iDays As Byte
Application.EnableEvents = False
On Error GoTo ERRORHANDLER
Select Case UCase(Range("J2").Value)
Case "W"
iDays = 7
Case "B"
iDays = 14
Case "M"
iDays = 30
End Select
Range("L2").Value = Range("N2").Value + iDays
Application.EnableEvents = True
Exit Sub
ERRORHANDLER:
Application.EnableEvents = True
End If
End Sub
===================================================================
问题8:如何编写一个宏程序运行另一个宏程序特定的次数?
解答:可以用一个简单的循环来实现。
‘**************************************************
Sub FirstMacro()
Dim RunCount as Long
Const RunMax As Long=10 ‘定义要运行的次数
For RunCount =1 To RunMax
Call SecondMacro ‘调用要运行的宏程序
Next
End Sub
===================================================================
问题9:如何在一个组合框中列出所有工作表中单元格D3中的值?
解答:假设用户窗体中有一个名为ComboBox1的组合框,您可在用户窗体中添加以下代码,当用户窗体被激活时,在组合框中将显示出所有工作表中单元格D3的值。
‘**************************************************
Private Sub UserForm_Activate()
Dim ws As Worksheet
For Each ws In Worksheets
ComboBox1.AddItem ws.Range("D3").Text
Next ws
End Sub
===================================================================
问题10:如何使工作表中的文本闪烁?
解答:为了使文本闪烁,您需要周期性地执行一个程序来变换文本的前景色,OnTime方法可以用于周期性地运行一个程序。
‘**************************************************
Public RunWhen As Double
Sub StartBlink()
If Range("A1").Font.ColorIndex = 2 Then
Range("A1").Font.ColorIndex = xlColorIndexAutomatic
Else
Range("A1").Font.ColorIndex = 2
End If
RunWhen = Now + TimeSerial(0, 0, 1)
Application.OnTime RunWhen, "StartBlink", , True
End Sub
‘**************************************************
Sub StopBlink()
Range("A1").Font.ColorIndex = xlColorIndexAutomatic
Application.OnTime RunWhen, "StartBlink", , False
End Sub
在上面的这些程序中,您可以改变参数A1为您想要使文本闪烁的单元格或单元格区域。在工作簿打开时,您需要初始化这个程序,因此,您可以放置下面的代码到ThisWorkbook代码模块中。
‘**************************************************
Private Sub Workbook_Open()
StartBlink
End Sub
当工作簿关闭时,您需要取消OnTime事件,因此,您需要放置下面的代码到ThisWorkbook代码模块中。
‘**************************************************
Private Sub Workbook_BeforeClose(Cancel As Boolean)
StopBlink
End Sub
示例文档见在Excel中闪烁文本.xls。HL3xux8P.rar (6.89 KB)
HL3xux8P.rar (6.89 KB)
[原创]VBA编程问答(第1辑)
下载次数: 53
2006-8-2 00:07
===================================================================
问题11:如何将工作簿中其它工作表名导入到指定的工作表中?
解答:本问题即将工作簿中除指定的工作表(如名为Name的工作表)外的其它的工作表名导入到指定的工作表中(即Name工作表中)。您可以使用下面的代码。
‘**************************************************
Sub Test()
Dim ws As Worksheet
Dim i As Long, j As Long
Worksheets("Name").Range("A:A").Clear
i = Worksheets("Name").Range("A65536").End(xlUp).Row
For Each ws In Worksheets
If ws.Name <> "Name" Then
Worksheets("Name").Cells(i, 1) = ws.Name
i = Worksheets("Name").Range("A65536").End(xlUp).Row + 1
End If
Next ws
End Sub
===================================================================
问题12:如何在单元格中快速输入带秒的时间?
解答:一般,在Excel中快速输入日期和时间时,可使用快捷键,即按Ctrl+:组合键将快速在单元格中输入当前日期,按Ctrl+Shift+:组合键将快速在单元格中输入当前时间,但所显示的时间为“小时:分钟”格式,不会显示秒。如果您想显示“小时:分钟:秒”这样的格式的话,可以使用Onkey方法修改快捷键的缺省设置,如下所示,运行“设置快捷键”代码即可。
‘**************************************************
Sub 设置快捷键()
Application.OnKey "+^:", "输入时间"
End Sub
‘**************************************************
Sub 恢复快捷键()
Application.OnKey "+^:"
End Sub
‘**************************************************
Sub 输入时间()
With ActiveCell
.Value = Time()
.NumberFormat = "hh:mm:ss"
End With
End Sub
如果您想恢复快捷键的缺省设置,运行“恢复快捷键”过程。
 
By fanjy in 2006-8-1