比如别人给出的VBA应该的近义词怎么用

通用的VBA编程惯例
本文所属图书&>&
本书基于Excel 2003及之后的版本和VSTO.NET 2008开发平台介绍了Excel专业应用程序开发的各种方法和技术,其内容相对第一版有较大的调整和更新。主要包括Excel各类应用程序的结构和开发方法;Excel应用程序的工...&&
本节将介绍几个VBA管理的最佳方法,以帮助开发人员编写出更健壮、更易于维护与更新的代码。
1.模块使用指南
模块指南是指代码模块最开始的声明部分,用以指导VBA如何处理该模块中的代码。尽管这些指南不是必需的,但至少应该使用下面所列的一项到两项:
Option Explicit在所有模块中都应使用这一声明。在实际的过程中无论怎样强调其重要性都不为过。因为,如果不使用这一声明,则VBA会将因拼写失误所产生的错误名称定义为一个新变量。这类错误在运行时可能不会立即出现,具有很强的隐蔽性。当然,由于它的存在必然会使程序产生错误的结果。如果不仔细检查就可能会忽略这类错误,或许要等到将程序发布给用户之后才能发现其中的问题。
Option Explicit表示所有变量必须先进行显式声明,然后才能使用。当单击VBE中的&调试 &编译&菜单时,Option Explicit可让VBA一旦遇到不能识别的标识名,就自动返回一个编译错误,这样能比较容易地发现拼写错误。单击VBE中的&工具&选项&菜单,在弹出的&选项&对话框中选择&编辑器&属性页,勾选&要求变量声明&的复选框,即可将Option Explicit自动填写在每个模块的顶部。在此,强烈推荐采用这种设置。
Option Private Module 如果在模块中使用了Option Private Module声明,则用户接口或其他的Excel工程均不能使用其中用到的所有过程。此项设置可隐藏模块中的过程,使外界的应用程序无法访问。
提示:方法Application.run可使Option Private Module声明失效,运行模块中声明为私有的过程。此外,如果用户知道过程的准确名称,并且过程运行时无须任何参数,那么用户可以直接在宏对话框中输入过程名称,通过手动的方式执行该过程。这种情形不适合用于保护工程,因为私有过程名在对象中是不可见的。
Option Base 1该声明可将所有未指定下界的数组变量的下界值设置为1。通常,不要使用Option Base 1声明,而应该明确指定数组变量的上下边界值。因为,若某个模块采用Option Base 1的声明,则将其中的过程复制到其他没有采用该声明的模块中时,可能会发生错误。由此可见使用Option Base 1声明会影响程序的可重用性。
Option Compare Text该声明表明在比较模块中的字符串时应采用基于文本而不是二进制的标准。所谓基于文本的比较标准就是不区分字母的大小写,而基于二进制的比较标准则要区分字母的大小写。同Option Base 1一样,应尽量避免使用Option Compare Text声明,因为它可能造成同一个过程在采用和有采用Option Compare Text声明的模块中表现出不同的行为特性。基于文本的字符串比较比基于二进制的字符串比较计算开销更大,所以使用Option Compare Text会影响模块中字符串比较的性能。大部分Excel和VBA的字符串比较函数都提供了相应的参数,用于设置是进行基于文本还是基于二进制的字符串比较。除非特别要求,否则应当选用基于参数设置方式来控制字符串的比较。
在某些少数情况下需要使用Option Compare Text。最常见的情况是在VBA中使用 like运算符进行不区分大小写的字符串比较时,必须使用Option Compare Text声明。在这种情况下,应该将使用Option Compare Text声明的过程划分到一个单独的模块中,以便让不使用该声明的其他过程不受影响。同时,在模块中添加相应的注释语句说明这么做的理由。
2.变量和常量的使用惯例
变量和常量是应用程序中最基本的构成单元,我们对它们非常熟悉,以至于有时甚至忽略了必须要正确地使用这些应用程序中的活动单元,否则会影响程序的质量。本节将介绍变量和常量的一些使用惯例。
(1)避免重复使用变量
程序中所声明的变量应该只有一个特定目的。将同一变量用于多种目的时,节约的仅仅是声明变量的语句行,但却会给程序带来大量的潜在问题。比如在查看过程是如何工作时,常常需要确定某些特定区域的变量值,当某个变量第二次出现时,我们自然会认为它所代表的意义与第一次出现时相同。若情况不是这样,即一个变量有多种意义,显然会增加理解程序逻辑的难度。
(2)避免使用变体数据类型
尽可能不使用变体数据类型。VBA并非强类型编程语言,如果在声明变量时未指定其数据类型,会自动指定为变体类型。尽量不使用变体类型的理由如下:
变体类型的效率较低 在VBA编程语言中,变体类型是一种非常复杂的结构,用来存放任何类型的数据。变体类型不像其他基本数据类型,如长整型或双精度类型,可以被直接访问和修改。相反,如果要对变体类型数据执行某种操作,VBA必须在后台执行一系列复杂的Windows API调用。
存储在变体类型中的数据具有不确定性 由于变体类型可以存储任意类型的数据,因此,存入变体时的数据类型可以与从变体中取出时不相同。在访问变体类型中的数据时,默认情况下VBA会将该数据转变为当前条件下它认为最适宜的数据类型。建议在必须使用变体类型时,用相应的VBA函数(如CStr、CLng、CDate等)显式将其转换成所需要的数据类型。
变体类型的一个有用功能是,当通过Range.Value为变体类型分配一个多单元格区域时,会自动生成一个包含该区域所有值的二维数组。当需要处理包含在一个单元格区域中的大量数据时,变体类型能很快地将数据转存为一个变体数组,执行相应的操作并实现数组循环,最后再将变体数组中的值保存回单元格区域中。代码清单3-11给出了实现上述操作的实例。
代码清单3-11& 利用变体数组操作区域值
Sub UseVariantArray()
Dim lRow As Long
Dim lCol As Long
Dim vaArray As Variant
vaArray = Sheet1.Range(&A1:E5&).Value
For lRow = LBound(vaArray, 1) To UBound(vaArray, 1)
&&&&&&&&& For lCol = LBound(vaArray, 2) To UBound(vaArray, 2)
&&&&&&&&&& vaArray(lRow, lCol) = vaArray(lRow, lCol) * 2
&&&&&&&&& Next lCol
Sheet1.Range(&A1:E5&).Value = vaArray
(3)小心错误的类型转换
VBA并非一种强类型语言,这是产生错误类型转换的最主要原因。当VBA自动将一种数据类型转换为其他不相关的数据类型时,就可能会发生错误的类型转换。常见的情况如:将存储数字的字符串转换为整数,或将逻辑值转换为等同的字符串。在VBA程序代码中使用变量时一定要弄清楚变量的类型,不要随意混用,应显式地调用转换函数(如CStr、CLng、CDate等)进行类型转换,以告知VBA该如何处理这些变量。
(4)避免使用 As New声明语法
切记不要使用As New来声明对象变量。比如,决不要使用如下所示对象声明方式:
Dim rsData As New ADODB.Recordset
如果VBA在某句代码中遇到像这样声明的变量,且变量尚未初始化,那么VBA会自动对其进行初始化,创建一个相应的对象实例。然而这决非我们所需要的。在好的编程惯例中,应该由程序员完全控制对象的创建和使用。如果VBA在代码中发现了某个未初始化的对象,几乎可以断定这段代码存在缺陷,并且系统应立即报告该信息。为此,应该按照如下的方式来声明和初始化对象:
Dim rsData As ADODB.Recordset
Set rsData = New ADODB.Recordset
当采用这种声明和初始化的方式时,若在过程中的某处销毁了对象变量,且在之后的其他地方又再次引用了该对象变量,则VBA会马上抛出运行错误&Object variable or With block variable not set&,以提示人员。
(5)尽量使用完整的对象名称
在程序代码中声明变量时,应尽量使用包含类前缀的完整的对象名称。因为有些对象名称在很多对象库中都存在。如果声明对象时仅仅单独使用对象名称,且在应用程序所引用的多个对象库中都含有此对象名称,那么VBA会根据哪一个对象库来创建对象变量呢?此时,VBA将以&工具&引用&列表中第一个能找到该对象名称的类库为标准来创建对象变量。通常条件下,这种处理方式并不是我们所期望的。
现在以用户窗体控件为例,说明由于没有使用完整的对象名称而引发的问题。假设需要声明一个对象变量来引用用户窗体中的文本框控件,可能使用的代码为
Dim txtBox As TextBox
Set txtBox = Me.TextBox1
不幸的是,当VBA执行第二行代码时,就会产生&类型不匹配&的错误。这是因为Excel对象库中也包含一个TextBox对象,同时在&工具&引用&列表中Excel对象库又位于MSForms对象库的前面。所以,正确的代码应为
Dim txtBox As MSForms.TextBox
Set txtBox = Me.TextBox1
(6)不要使用固定数字作为数组的边界
在使用循环方式访问数组时,不要使用固定数字作为数据的边界,而应借助函数LBound和UBound来完成,相关示例如代码清单3-12所示。
代码清单3-12& 循环访问数组的正确方式
Dim lIndex As Long
Dim alListItems(1 To 10) As Long
' Load the array here.
For lIndex = LBound(alListItems) To UBound(alListItems)
&&&& ' Do something with each value.
Next lIndex
因为在应用程序的创建和维护过程中,数组的边界值经常会发生变化。如果在代码清单3-12的循环语句中使用固定数字1和10作为数组的边界,那么每当数组alListItems的边界发生变化时,都需要更改这一循环,否则程序就会发生错误。而使用函数LBound和UBound,可使循环具有很好的自适应性。
(7)在Next语句后总是指定循环的计数变量
从代码清单3-12中,还可看到另一种好的编程习惯,即在Next语句后指定循环的计数变量。尽管这并非VBA的强制要求,然而这样做可使代码更容易理解,特别是在For和Next语句相隔较远时更是如此。
(8)充分利用常量
常量是一种非常有用的编程元素。在代码中,它们常用于以下方面:
利用常量来代替&魔数&,即用一些易于理解的名称来代替数字。比如在下面的代码中,数字50表示什么意思呢?
If lIndex & 50 Then
除非你是代码的设计者,能记得50的含义,否则从代码本身是无法知道的。
而如果引入常量,采用下面的方式编写代码,那么其含义就容易理解了。
Const lMAX_NUM_INPUT_FILES As Long = 50
' More code here.
If lIndex & lMAX_NUM_INPUT_FILES Then
在设计时,如果需要查看常量的值,那么在VBE环境中,可在常量名上单击鼠标右键,从弹出的快捷菜单中选择&定义&,这样就能直接跳转到代码中常量的定义处。如果要在运行时的中断模式下查看常量的值就更加容易,只需将鼠标放到常量位置上,系统就会弹出一个包含常量值的提示标签。
使用常量可以提高代码的效率,并能避免因删除副本数据而引起的错误。在前面的示例中,假设在应用程序中会多次使用&输入文件的最大数量&这个值。在某个时刻,可能会对应用程序进行升级,以便能处理更多的输入文件。如果应用程序中是直接使用数字来表示&输入文件的最大数量&,那么将不得不对程序中凡是用到该数字的地方都逐一进行修改,一旦修改不彻底就会产生错误。而如果是通过常量来表示&输入文件的最大数量&,那么仅仅需要在常量定义处进行修改即可。显然,上面所说的因直接使用数字而引起的修改不彻底错误可通过常量很好地解决。
使用公有变量应该特别注意,因为在应用程序的任何地方都可以直接修改它,且系统不会给出任何提示或警告信息。同时,公有变量的这种访问方式也破坏了一个重要的编程原则:封装性。因此在创建变量时应使其作用域尽可能小。建议在开始创建变量时将其均设置为局部变量,仅在确实需要时才扩大其作用范围。
凡事总有例外,在某些情况下确实需要使用公有变量,如:
一些在使用前必须被压入栈底的变量。假设过程A读取了某个数据,然后将其传给过程B,过程B又将其传给过程C,过程C又将其传给过程D,最终在过程D中使用此数据。针对这种情况,最好的办法是将该数据表示为公有变量,然后由过程A直接传给过程D。
某些固有的公有类。比如应用程序级的事件处理类,将其表示为公共的对象变量就可在应用程序的任何地方使用。
(10)早期绑定与后期绑定
对早期绑定与后期绑定,许多人对其区别的理解常常有误,也没有完全弄清楚其中对象是如何创建的。其实,判定一个对象是早期绑定还是后期绑定只需关注一个因素,即引用该对象的对象变量是如何声明的。若对象变量声明为某种特定的对象数据类型,属于早期绑定。若对象变量声明为Object或变体数据类型,则属于后期绑定。代码清单3-13和3-14分别为后期绑定和早期绑定的例子。
代码清单3-13& 通过后期绑定引用 ADO Connection对象
Dim objConnection As Object
' It doesn't matter how you create the object, it's still
' late bound due to the As Object variable declaration.
Set objConnection = New ADODB.Connection
Set objConnection = CreateObject(&ADODB.Connection&)
代码清单3-14& 通过早期绑定引用ADO Connection对象
Dim cnConnection As ADODB.Connection
' It doesn't matter how you create the object, it's still early
' bound due to the data type used in the variable declaration.
Set cnConnection = New ADODB.Connection
Set cnConnection = CreateObject(&ADODB.Connection&)
注意,如果要对Excel对象库之外的对象使用早期绑定,必须先在VBE的菜单&工具&引用&中指定一个对相关对象库的引用。例如,要创建一个早期绑定ADO对象的变量,必须首先指定一个对Microsoft ActiveX Data Objects 2.x库的引用(此处x表示ADO的版本号),应该尽可能地使用早期绑定。相对后期绑定而言,早期绑定具有以下优点:
性能更好& 编译时,若VBA已知对象变量的数据类型,则VBA可从对象中获取其属性和方法的内存地址,并将其与代码存储在一起。在运行时,如果VBA遇到了早期绑定的属性或方法,只需要执行对应存储位置的代码即可。(为了说明方便,在描述上做了一定程度的简化。实际上VBA存储的是执行代码相对于内存起始地址的偏移量,即相对于对象Vtable的偏移量。)
若变量为后期绑定,则VBA无法知道变量所包含的对象类型。所以,在编译时就不能对属性及方法进行优化。这意味着若VBA需要调用后期绑定变量的属性和方法,每次都必须先确定变量所包括的对象类型,然后再根据属性或方法的名称确定其对应的内存位置,最后才执行相应的代码。显然,这个过程比早期绑定慢得多。
类型检查更严格 在代码清单3-13所示的后期绑定示例中,如果不小心将对象变量所引用的ADO Connection对象写成了ADO Command对象,VBA不会就此给出提示。你只有在代码中使用到Command对象不支持的方法和属性时,才会发现其中潜在的问题。然而,如果对象采用的是早期绑定的方法,那么VBA会立即检测出当前所引用的对象有误,并给出&类型不匹配&的错误提示。这样可在代码尚未运行时就检测出所调用属性或方法的不正确性。在编译时,VBA会在对应的对象库中查找要调用的属性名或方法名,如果没有找到,VBA就会抛出编译时错误。
具有智能感知的功能 采用早期绑定的方式可使编程更为容易,因为VBA能确切地知道变量所代表的对象类型,在用户输入属性或方法名称的一部分时,VBA就会解析相应的对象库,并弹出一个下拉列表框,其中包含了相关的属性名和方法名,方便用户选择。
然而,在某些特殊情况下需要使用后期绑定而非早期绑定。以下是两个最常见的必须使用后期绑定的情况:
1.采用早期绑定的方式时,若程序中需要的对象库版本比计算机中现有的版本更高,则程序的兼容性会被破坏,无法正常运行。
这种情况非常普遍。如果应用程序中引用的是新版的应用程序对象库,而当前运行程序的计算机中采用的却是旧版的应用程序对象库,此时就会产生&无法找到工程或库(Can't find project or library)&的运行错误。而且,这种情况非常容易引起误导,因为产生这种错误的根本原因是代码编写不当,而与对象库没有任何关系。
如果希望避免上述错误的出现,让应用程序在各种版本的对象库中均能正确运行,就需要在引用对象时使用后期绑定。在创建新对象时,也只能使用带有独立参数ProgID的函数CreateObject,而不能使用&=New ObjectName&的语法格式。
2.当不能确定用户是否安装了应用程序所需要的支持软件,而且也不能自行安装这些软件时,只能采用后期绑定的方式。
在这种情况下,采用后期绑定的方式可以避免因为没有相应的对象库而产生的编译错误。在应用程序运行时,它会检查在当前计算机中该对象库是否存在,如果不存在,应用程序就会自动退出。
提示:在编写使用后期绑定的代码时,可以先用早期绑定代替后期绑定,这样可充分利用代码的自动提示,提高编写的效率。而在代码编写完毕后,在最后的测试和发布之前再将早期绑定更改为后期绑定。
3.预防性编代码
预防性的编码是指各种用于预防错误产生,而非错误发生后再进行纠正的编程习惯及其代码。
(1)尽量在早期的Excel版本上设计应用程序
尽管微软的Excel小组在向前兼容方面做了大量卓有成效的工作,但在各版本之间仍然存在不少细微的区别。如果设计者非常熟悉Excel较新的版本,那么其所设计的程序往往不能在早期的Excel版本上运行,因为应用程序中很可能会使用只有最新版Excel才支持的特性或功能。
避免出现上述问题的最佳方法就是尽量在早期版本的Excel中设计应用程序。可以采取以下做法,其效果依次逐渐改善。
在同一计算机上安装多个Excel版本(不推荐)。
在多台独立的计算机上分别安装不同的Excel版本。
使用VMware或Virtual PC等虚拟化软件来保证在同一台计算机上同时维持多个独立的开发环境。
假设设计者是在Excel 2003环境下开发的应用程序,之后发现其在Excel 2000环境下不能正常运行,此时设计者必须对程序进行调试,删掉Excel 2000所不支持的代码。而如果一开始就在Excel 2000环境中开发应用程序,则会节省不少的时间和精力。
(2)显式使用ByRef或ByVal
当过程包含参数时,通常有两种方式来声明这些参数,即ByRef和ByVal
ByRef 表示将变量的地址而非变量值传递给过程。如果在过程中修改了ByRef参数的值,则在该过程调用完成后相应的修改在主调过程中仍然存在。
ByVal 表示将变量的值传递给过程。即使在过程中修改了ByVal参数的值,在该过程调用完毕后这些修改也不会影响到主调过程。实际上,过程是将ByVal参数作为局部变量来处理。
在过程中应该总是显式地声明参数为ByRef或ByVal。如果未显式声明,则在默认条件下,系统会将参数作为ByRef类型。除非特别需要在调用过程后保留参数值的更改情况,否则应该用ByVal来声明参数。将参数声明为ByVal可防止其改变传递回调用的过程。
但是也存在一些特例,比如向过程传递长字符串时,应该使用ByRef的方式,因为其效率更高。或者当过程中的参数是某种特殊的类型时,比如数组,也应该采用ByRef的方式。注意,将过程参数声明为ByVal会更容易发现强制类型转换的错误。如果过程参数为ByRef,则在调用过程时,必须为该参数传递其所声明的数据类型,否则会产生编译错误。而在传递ByVal类型的过程参数时,VBA会将参数值强制转换为兼容的数据类型。
(3)显式调用对象的默认属性
由于集合对象的元素属性可能会发生改变,因此在表达式中不要使用对象名来表示对象默认的属性。在代码清单3-15中,分别给出了一个正确和错误使用控件MSForm.TextBox默认属性的例子(MSForm.TextBox 控件的默认属性是Text)。
代码清单3-15& 默认属性
' The right way.
txtUsername.Text = &My Name&
' The wrong way
txtUsername = &My Name&
为了让代码更具有可读性,应该避免隐式使用对象的默认属性,这样还可防止将来因对象版本升级后默认属性发生变化而引起的错误。
(4)在使用前验证过程参数的有效性
如果过程需要接受外界的输入,就必须采取一定的措施来检验这些输入的正确性。比如,输入值必须在某个确定的范围内。只有当输入值通过有效性检验后才能运行过程。采用这种处理方式,能尽早发现输入中的错误,给出相应的提示信息,同时还能简化过程的调试。
根据需要,创建相应的桩模块来检验程序的有效性。所谓桩模块实际上是一个封装的程序,用于调用需要测试的程序,向其传递一系列的参数,并能明确的显式测试结果是否正确。在第16章&VBA的调试&中将会详细介绍用于测试的桩模块。
(5)通过保护计数器来防止无限循环
此处主要讨论如何防止无限循环的问题。在使用Do&While或While&Wend循环结构时最常见的错误是循环结束条件永远不成立,即发生了&死循环&。(如果幸运,或许可以使用Ctrl+Break组合键来强行中止程序,否则可通过任务管理器来强制结束程序)。为了防止&死循环&的发生,可在循环中引入一个保护计数器,当循环次数超过设定的最高值时(一般不会发生这种情况),就立即结束循环。代码清单3-16为一个在Do...While循环结构中使用了保护计数器的示例。
代码清单3-16& 通过保护计数器来防止无限循环
Dim bContinueLoop As Boolean
Dim lCount As Long
bContinueLoop = True
lCount = 1
&' The code that goes here should set the
&' bContinueLoop variable to False once the
&' loop has achieved its purpose.
&' This infinite loop guard exits the loop
&' with an error after 10000 iterations.
&lCount = lCount + 1
&If lCount & 10000 Then Err.Raise _
&&Number:=9999, Description:=&Infinite Loop Error!&
Loop While bContinueLoop
循环结构中变量lCount的唯一作用是:如果在10 000次迭代后,控制变量仍不能满足循环退出的条件,就强制退出循环。
(当然循环次数最大为多少,应根据具体应用环境来设定。)这种处理方式使循环结构显得稍稍复杂一些。在确保程序不会发生无限循环的条件下,可以将保护计数器删除或注释停用。
(6)尽早并经常点击&调试&编译&菜单项
千万不要在程序进行了大量的修改和确保无误之后才点击&调试&编译&菜单项,这样会导致调试过程过于漫长和低效。
(7)引用工作表对象时使用其代码名称
注意在程序中总使用代码名称来引用工作表和图表。通过表格的标签名来识别表格是非常不安全的,因为用户很可能会修改表格的标签名,从而导致使用标签名的代码无法工作。
(8)验证选定项的数据类型
如果过程是专门用于处理某种特定数据类型的对象,那么必须使用TypeName函数或If Typeof&Is结构来检查用户所选定项的数据类型是否正确。比如,假设过程是工作在Excel的某个范围内,那么在开始工作前,必须首先确保用户所选定的是Range对象。具体代码如代码清单3-17所示。
代码清单3-17& 检验选定的对象是正确的类型
' Code designed to operate on a range.
If TypeOf Selection Is Excel.Range Then
&&&& ' OK, it's a Range object.
&&&& ' Continue code execution.
&&&& ' Error, it's not a Range object.
&&&& MsgBox &Please select a range.&, vbCritical, &Error!&
您对本文章有什么意见或着疑问吗?请到您的关注和建议是我们前行的参考和动力&&
您的浏览器不支持嵌入式框架,或者当前配置为不显示嵌入式框架。更多公众号:gh_da4db6000a32定期发布一些Excel使用过程中的技巧、函数、VBA、SQL查询,与大家共同进步。最新文章相关作者文章搜狗:感谢您阅读你真的会Excel VBA吗? 本文版权归原作者所有,本文由网友投递产生,如有侵权请联系 ,会第一时间为您处理删除。查看: 451|回复: 5
利用公式或者VBA怎么可以快速获取某一天的出勤人数,比如说输入11.2,会获得出勤人数3
阅读权限20
在线时间 小时
还请高手给与帮助,感谢感谢
(25.08 KB, 下载次数: 2)
15:05 上传
(31.36 KB, 下载次数: 2)
15:05 上传
15:05 上传
点击文件名下载附件
8.32 KB, 下载次数: 5
阅读权限95
在线时间 小时
& & & & & & & &
请参考:
Private Sub Worksheet_Change(ByVal Target As Range)
& & If Target.Address(0, 0) && &H11& Then Exit Sub
& & If Target = && Then Exit Sub
& & Dim c As Range
& & Set c = Sheets(&签到表格&).Rows(&2:2&).Find(Target, , , 1)
& & If Not c Is Nothing Then
& && &&&Target.Offset(1).Value = WorksheetFunction.Sum(c.Offset(1).Resize(60000))
& & Else
& && &&&MsgBox &没有查到该日期,请重新输入日期!&
& & End If
End Sub
复制代码
阅读权限95
在线时间 小时
请测试附件
(15.02 KB, 下载次数: 10)
15:15 上传
点击文件名下载附件
阅读权限200
在线时间 小时
H12=SUMPRODUCT((签到表格!B2:F2=H11)*签到表格!B3:F8)
阅读权限20
在线时间 小时
谢谢你 正是我想要的答案
阅读权限20
在线时间 小时
H12=SUMPRODUCT((签到表格!B2:F2=H11)*签到表格!B3:F8)
谢谢老师&&
最新热点 /1
ExcelHome每周都有线上直播公开课,
国内一流讲师真身分享,高手贴身答疑,
赶不上直播还能看录像,
关键居然是免费的!
厚木哥们都已经这么努力了,
你还好意思说学不好Office。
玩命加载中,请稍候
玩命加载中,请稍候
Powered by
本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任! & & 本站特聘法律顾问:徐怀玉律师 李志群律师【整理】word vba学习记录
本帖内容已移至:
【整理】word vba学习记录
Author: green-waste (at)
【看帖前必读】
1.此贴目的:只是为了记录最近在接触学习word vba的过程中,一些心得和体会或者是学习时候要注意的一些方面,特此记录,以备后差或他人借鉴。
2.看之前,读者最好具有基本的编程相关知识和基本的VB的基础,以便更好理解所说的内容。
3. 此贴所写内容,多为本人整理或自己的理解,如果有误,欢迎指正:green-waste (at)
【Word VBA学习记录】
1.什么是word vba? 为何要用VBA?
什么是VBA?为什么要学习VBA?
VBA是Visual Basic For Application的简称,换句话说,就是将VB应用于Application应用程序,此处的Application指的是微软的Excel,word等应用程序。所以,对于我用到的,在word里面写宏,去实现一些操作,用到的VB,就是Word VBA了。而其他常用的,还有Excel里面也会用到用宏去实现一些根据自己需求实现的一些功能,比如自动提取一些内容到一个文档中,否则,自己手动慢慢地复制粘贴,往往效率极低,累死你不说,还不容易保证完全正确,而通过宏来处理,运行一下宏,点击一下某个菜单等,即可实现要做的事情,高效,准确。
就像别人说的,除了“Excel本身的内置函数其实已经很强大了”,但是只是很强大,有些更高级或复杂的操作,还是宏实现起来更方便和快捷。
再简而言之,如果你不是需要对某(些)文档特殊处理,只是一般的使用word或excel文档,多数人都是用不到的。
而如果有类似于我这样的需求,将某个word文档中的很多表格中的符合某些特定条件的某些列的内容,经过一定条件判断,将对应的值提取到一个xml文档中,并且输出的时候,要将该值根据某些约定,再分成几个部分等等,这类的操作,手动实现,要一个个去找对应的表格,然后找到对应的值,然后手动复制,粘贴,一点点做,效率很低,而如果可以用宏实现,只需要写好宏代码,运行一下,即可省去大量的精力。
不过,再引用别人的,提示一下:“但有一点叶枫想要告诉大家,VBA功能很强大,但并不是万能的,也并不是所有工作都需要用VBA来解决,也并不是所有工作用VBA来解决都会很简单,这要根据实际情况而定,有些工作你用VBA来解决的话相反会变得很麻烦。”
2.不等于符号
VBA里面的不等于号,用&&表示,而不是其他C等语言里面的!=.。
&&,即大于号和小于号的组合,意思也很明确,既不大于也不小于,所以就是不等于了。
3。如何选中一行并获得对应的文字 和 wdMove和wdExtend的区别
前提,光标(或叫插入点)已经移动到该行了,但是想要选中该行,并想要获得对应所选Range的文字
此时可以用如下代码:
Selection.MoveDown Unit:=wdLine, Count:=1, Extend:=wdExtend
其中,wdLine是单位(Unit),类似的Unit还有: wdLine, wdParagraph,wdWindow,wdScreen。
WdExtend,对应的还有wdMode,对此,VBA教程的解释是:
“如果是 wdMove,则所选内容折叠到结束位置,并向下移动。如果是 wdExtend,则所选内容向下扩展。默认值为 wdMove。”
没完全理解,但是经过测试得知,如果是mdMove,那就是光标移动到对应位置了,但是没有选择这(光标移动的)起点到终点,此处为整个这一行,的内容,如果是wdExtend,那就是不仅移动光标了,并且同时选中了起点到终点的内容。
4.如何跳转到某一标题 和 如何移动光标/插入点
Selection.GoTo What:=wdGoToHeading, Which:=wdGoToAbsolute, Count:=5
这里主要是利用Goto语句,wdGoToHeading说明掉转的单位是heading标题,wdGoToAbsolute表示是绝对位置的跳转,于此相对应的还有wdGoToAbsolute, wdGoToFirst, wdGoToLast, wdGoToNext, wdGoToPrevious, wdGoToRelative。更多详细内容,请参考附录“Word VBA 教程”。
另外,对于移动光标/插入点,可以借鉴如下做法:
‘本示例将所选内容移至当前文字部分的开头。如果所选内容位于文档正文部分,则本示例将所选内容移至文档的开头。
Selection.HomeKey Unit:=wdStory, Extend:=wdMove
其中wdStory属于wdUnits,其他类似的wdUnits,还有wdColumn,wdLine,wdRow等。
5. 如何获得选中的标题的序号
前提,已经选择某一标题了,想要获得该标题前面的序号
比如对这个标题:
PAPRBY / RubyVerifoneDefaults
想要获得标题的序号,即2.1.
Selection.Bookmarks(“headinglevel“).Range.ListFormat.ListString ‘获得当前标题的序号,即2.1
其中headinglevel是VBA里面的预定义标签。
关于此内容的详细解释,请参考:
6。 如何返回函数的返回值
关于这点,网上找,没几个说的很清楚的,最后还是通过VBA的Help才搞懂如何返回函数返回值的。此处,简单解释如下:
一个Function函数的语法为:
[Public | Private | Friend] [Static] Function name [(arglist)] [As type]
[statements]
[name = expression]
[Exit Function]
[statements]
[name = expression]
End Function
其中,函数内部任何地方都可以出现[name = expression],name即为函数名,expression是表达式,当然也可以是某个变量,常量等,其就代表了返回值。更具体额度解释和例子,摘录如下,很容易看懂的:
“要从函数返回一个值,只需将该值赋给函数名。在过程的任意位置都可以出现这种赋值。如果没有对 name 赋值,则过程将返回一个缺省值:数值函数返回 0,字符串函数返回一个零长度字符串 (“”),Variant 函数则返回 Empty。如果在返回对象引用的 Function 过程中没有将对象引用赋给 name (通过 Set),则函数返回 Nothing。
下面的示例说明如何给一个名为 BinarySearch 的函数赋返回值。在这个示例中,将 False 赋给了该函数名,表示没有找到某个值。
&code&Function BinarySearch(. . .) As Boolean
&b&. . .&/b& &/code& &code&'&/code&值未找到,返回一个&code& False &/code&值。
&code&If lower & upper Then&/code& &code&
BinarySearch = False&/code& &code&
Exit Function&/code& &code&
End If&/code& &b&&code&. . .&/code&&/b& &code&End Function&&/code&
看懂后,多说一句,有问题,还是先找VBA的Help系统,比百度,google等,有时候更准确,方便,易懂。
7.字符换处理函数
关于VBA中的字符串相关的函数,刚发现,office 2010 中的 VBA的help文件里面,有已经总结好的了:
字符串处理关键字总结
比较两个字符串。
变换字符串。
大小写变换。
建立重复字符的字符串。
计算字符串长度。
设置字符串格式。
重排字符串。
处理字符串。
, , , , , RTrim,
设置字符串比较规则。
运用 ASCII 与 ANSI 值。
上述字符串处理相关的函数,多数都是见名知意,容易看懂和使用, 但是也有些不太容易搞懂,或者和普通C语言等里面的字符串处理函数不同的,需要额外说明的,解释如下:
(1) Space, String:其中Space很方便,比如想要输出10个空格,当然你可以通过自己手动的写成“
”,但是有了space,用其更方便,直接写成Space(10),即代表了10个空格。同理,String(number,characterToRepeate)用于输出多个某一字符,而对于前面的空格来说,也可以用string表示,即Space(10)=String(10, 32),其中32=0x20,是space的ASCII值。而String的优点在于,也可以输出其他字符,包括0x0~0x1F之类不可见字符。
(2) InStr, InStrRev:这个InStr,其实就是C语言的strstr,
InStr([start, ]string1, string2[, compare])
意思为:“返回 Variant (Long),指定一字符串在另一字符串中最先出现的位置。”
而InStrRev意思和InStr类似,只不过是“在该字符串中,从后往前查找”,但是特别要注意的是,其返回的值,是从前往后数的第几个,而不是从后往前数算出来的值。
举例说明:
InStr(“abcdefgeh”, “e”) = 5 ‘返回正常的,从前往后数,第5个字母是e。
InStrRev(“abcdefgeh”, “e”) = 8 ’其从后往前查找e。返回的值是,从前往后数 的 第8,而不是 从后往前 的 第2。
(3) Asc, Chr: Asc是将字符转换为ASCII数值,Chr是将数值转换为ASCII字符。举例为:
MyNumber = Asc(“A”)
‘ 返回 65。
MyChar = Chr(97)
‘ 返回 a。
8.如何创建文件和输出信息到文件里面
‘——————方法1——————
Function createFileTest()
‘ the name of the file to be output, including full path
Dim FileName As String
FileName = “D:create_file.txt”
‘ open the file ouput text stream output, overwritng is necessary
Dim fs As Object
Set fs = CreateObject(“Scripting.FileSystemObject”)
Dim file As Object
Set file = fs.CreateTextFile(FileName, True)
file.WriteLine “test string…”
file.Close
End Function
‘——————方法2——————
Public gFileNum As Integer
Function createOutputFile()
Dim outputFileNameWithPath As String
Dim gDestFile As String
Dim outputFileNameWithPath As String
Dim openFileOK As Boolean
openFileOK = True
‘ 1. create an XML file
outputFileNameWithPath = “D:test_output.txt”
gDestFile = outputFileNameWithPath
‘ Obtain next free file handle number.
gFileNum = FreeFile()
‘ Turn error checking off.
On Error Resume Next
‘ Attempt to open destination file for output.
Open gDestFile For Output As #gFileNum
‘ If an error occurs report it and end.
If Err && 0 Then
openFileOK = False
MsgBox “Cannot create file: ” & gDestFile
‘ Turn error checking on.
On Error GoTo 0
createOutputFile = openFileOK
End Function
Sub createFileTest()
Print #gFileNum, “Test output string to this file…”
Print #gFileNum, “Test done.”
Close #gFileNum
9.如何获得当前文件的文件名 和 当前文件所在路径
(1)获得当前文件所在的路径:ActiveDocument.Path
注意:所得结果,最后没有那个路径分隔符””
(2)获得当前文件的文件名:ActiveDocument.Name
(3)获得当前文件的路径和文件名,即全名:ActiveDocument.FullName
10.VB里面的一些常量
office 2010的help文件里面已有总结:
Visual Basic 常数
Visual Basic for Applications 定义了一些常数,使程序设计变得更为简单。下列常数可在程序代码中的任何地方代替实际值:
其中,此处打算把一些我所常用到的一些常数列出来,以供参考:
Miscellaneous 常数
下列常数由 Visual Basic for Applications 中的类型库定义,可用来在代码中的任何地方代替实际值
Chr(13) + Chr(10)
回车符与换行符结合
Chr(13) + Chr(10) or, on the Macintosh, Chr(13)
平台指定的新行字符;适用于当前平台
vbNullChar
值为 0 的字符
vbNullString
值为 0 的字符串
用来调用外部过程;与长度为零的字符串 (“”) 不同
vbObjectError
用户定义的错误号应当大于该值,例如:
Err.Raise Number = vbObjectError + 1000
vbFormFeed
在 Microsoft Windows or on the Macintosh 中没有作用
vbVerticalTab
在 Microsoft or on the Macintosh Windows 中没有作用
10. VBA中如何定义 枚举变量 和 结构体变量,如何使用switch case语句
枚举 和 结构体,分别用Enum 和 Type。
可以自己输入Enum或Type,这两个关键字,然后选择关键字,再按F1以打开Help文件,可以查看详细的语法和举例。
此处列举出其语法:
(1)枚举:
Public | Private] Enum name
membername [= constantexpression]
membername [= constantexpression]
(2)结构体:
[Private | Public] Type varname
elementname [([subscripts])] As type
[elementname [([subscripts])] As type]
(3)vba中的类似C语言的switch case是select case:
Select Case testexpression
[Case expressionlist-n
[statements-n]] ...
[Case Else
[elsestatements]]
End Select
枚举和结构体,简单举例如下:
Enum e_ErrorType
Error_Unknown
Error_Table
Error_Command
Type t_ErrorItem
As e_ErrorType
As Integer
As Integer
Type t_ErrorInfo
errNrPerFunc
As Integer ‘ errors per funciton
curErrItemIdx
As Integer
‘record current error item index
errArray(120)
As t_ErrorItem
Dim gErrInFunc As t_ErrorInfo
‘record error details per function
gErrInFunc.errArray(gErrInFunc.curErrItemIdx).errString = “Error of short len !!!”
select case用help中的例子:
&code&Dim Number
Number = 8
' Initialize variable.
&b&Select Case&/b& Number
' Evaluate Number.
&b&Case&/b& 1 To 5
' Number between 1 and 5, inclusive.
Debug.Print &Between 1 and 5&
' The following is the only Case clause that evaluates to True.
&b&Case&/b& 6, 7, 8
' Number between 6 and 8.
Debug.Print &Between 6 and 8&
&b&Case&/b& 9 To 10
' Number is 9 or 10.
Debug.Print &Greater than 8&
&b&Case Else&/b&
' Other values.
Debug.Print &Not between 1 and 10&
&b&End Select&/b& &/code&
【更多提示】
1.通过VBA内置的Help系统查询不懂的内容
在word里面打开VBA编辑器编辑vba代码后,对于常见的一些对象,属性,方法(函数)等的具体解释,多数都可以通过选择该对象/属性/方法,然后按F1键,打开帮助,其会自动跳转到对应的帮助内容,很是方便,而且很多的细节,解释的也比较详细,可以多多利用。
其中都包括了一些基本知识的详细解释,比如上面提到的,关于VBA中关于Function的返回值,其要去查看Help文件,就可以通过选择某函数,比如
Function funcName()
‘XXXXXX
End Function
中的Function,然后按F1键,系统自动会跳转到Help文件中关于Function的解释,很方便。
2. 一些基本单位(名词)的介绍:story, section, paragrah, line, character,table,cell,row, column
对于所选一段文字后,即引用Selection,其中会包含很多属性,Selection.XXX 其中XXX就有下面列出来的很多种,现在简单说说我对这些属性含义的理解:
Story: 中文直译为 故事,经过测试,感觉对于word文档来说,好像就是整个文档的内容。
Text:不必多解释,就是所选内容的
Sections:节。经测试,好像整个word文档,就一个节,有点像story,具体两者的区别,暂未搞懂。
Paragraphs:段落。按照中文的段落的含义理解,怎么说也应该有个几十行之类的文字,才算一个段落的,这是之前学语文的时候的感觉。结果发现这里的段落和中文意思的段落,差别很大,一个文档里面,没多少行字,结果段落就几百个了,貌似是一个单词,一个换行,一个表格中的值,都算一个段落。
Sentences:句子,同常理,不多解释。
Words:单词,同常理,不多解释。
Characters:字符,同常理,不多解释。
Tables,Cells,Rows,Columns:表格,同常理。其中包含了很多个cell,即单元格。每个cell,都对应不同的行和列。(打印)输出所选Range中(其包含很多个表格)中的第二个表格中的第三行第四列的值,表示为:
Print Selection.Tables(2).Cell(3, 4)
注意,其中第三行第四列,不是Cell(2,3),因为其单元格的下表是从1开始,而不是原以为的类似于C语言或者Excel中的0为起始值的。
End ,Start:即Selection.Start和Selection.End ,都是直接赋值的。所以,如果你想要选中某段内容(文字),那么只要找到你所要的起点和终点,然后将其值赋值给Selection.Start和Selection.End,即可选中该段内容(文字)。当然,也可以利用两者算出所选内容的长度:slection_len
= Selection.End – Selection.Start
3.获得所选range的文字,尝试了一下,发现两种都可以:
Selection.Text
Selection.Range.Text
4.常见函数分类列表
office 2010中VBA的help文件做的很好,里面总结了一些常见的函数,前面列出来的,就是那个字符串处理相关的函数。
下面列出了,其他一些类别,先放到这里,以备后查:
关键字分类
建立、定义与使用数组。
控制编译方式。
循环及过程流程控制。
变换数值及数据类型。
数据类型与 variant 子型态。
变换、使用日期与时间表达式。
控制文件系统与处理文件。
侦测与返回错误值。
进行各种金融运算。
接受输入与显示、打印输出。
完成各种数学运算。
激活其他应用程序与处理事件。
比较表达式与完成其它操作。
处理字符串及字符串数据类型。
声明、定义变量与常数。
5.网上在线查找相关帮助内容:
刚找到的,微软的官方的在线帮助:
1. Word VBA 教程:Microsoft Word Visual Basic 参考
2.菜鸟谈VBA最最基础入门《原创》 –
3. Word VBA内置的Help
共享此文章:
免费的格式化Javascript源码的网站
查询Unicode字符,且还带Oct,Decimal,Hex,HTML Entity
HTML和Javascript都支持,很好用。}

我要回帖

更多关于 应该的近义词 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信