基于VBA对Office二次开发的可移植性研究

2014-10-21 11:09李圆
电子世界 2014年12期
关键词:二次开发

【摘要】利用VBA对Word等办公软件进行二次开发的程序,可移植性差,只能在开发机器中运行,不便于开发成果的共享使用。将开发的程序,通过VBA直接导出,然后再导入到其它Word程序的VBA中,并解决好当中Thisdocument文件的代码,可以实现程序的移植共享,但安全性差。利用VB将导出的代码,以DLL文件的形式编译封装,并用批处理指令帮助用户进行注册,可以极好地解决程序的安全性与移植共享问题。

【关键词】可移植性;VBA;二次开发;封装

引言

微软的Office软件在一些特殊的应用中,有力所不及之处。利用VBA(Visual Basic For Application)对Office进行拓展性的二次开发,是当前解决Office功能不足的常见方法。但此法最明显的不足就是所开发的程序不具备可移植性,仅限于开发者所在的机器中能够使用,其它需要同样功能程序的用户或机器,只能重复开发,极大地影响了开发成果的共享。因此, VBA二次开发程序的可移植性问题,是亟待每个程序员研究、解决的问题。下文将以VAB在Word中的二次开发为例,对其可移植性问题的研究进行详细阐述。

1.VBA二次开发的现状

1.1 关于VBA

VBA微软开发出来的宏语言。主要用来扩展Windows的应用程式功能,特别是微软的Office软件。它完全继承了VB(Visual Basic)的语言机制,是VB的一个子集,但又不同于VB,VB是一个可视化的程序开发环境,能够独立创建一个应用程序并编译运行,而VBA则要求有一个宿主应用程序(如Word)才能开发、运行,而且不能用于创建独立的应用程序。

由于VBA必须寄生于宿主程序,离开宿主程序以后,程序便无法被解读与运行。这是制约VBA二次开发程序可移植性的主要因素之一。因此,我们对VBA程序的可移植性研究,主要集中在二次开发程序在其宿主程序中的移植,即如何使开发出来的程序,能够方便、快捷地移植到其它机器中,并在相应的宿主软件中正确运行,使得开发成果能够发挥资源共享的作用。

1.2 VBA对Word的开发与存在问题

1.2.1 录制宏

录制宏是当前VBA对Word最简单、常见的开发模式。这种方法优点是简单,易实现,完全可视化操作,用户不需编写任何代码,只要按照功能需求,一步步操作Word即可,VBA会根据用户的操作,自动生成相应的VBA程序代码,并保存在指定的文件中。

但该法的缺点也很明显,就是能扩展的功能非常有限。所谓录制宏,实际就是利用已有的Word功能,将需要反复进行的一系列操作,組合为一步操作,并作以VBA程序的形式保存下来。用户在打开该文档的同时,启动文档中已保存的VBA程序,并根据用户的指令运行、发挥作用。因此,这种开发完全依赖于Word中已有的可操作功能,只能在功能组合的基础上进行。

1.2.2 VBA环境开发

利用VBA对Word进行二次开发,更重要的方法是在Word中集成的VBA环境里,通过编写程序实现。VBA环境不仅为开发者准备了窗体、按钮、组合框等常用的Windows图形化控件,还继承了VB中的模块、类、对象等概念。开发者不仅可以摆脱Word已有功能的掣肘,还可以像在VB中一样,自由编写出功能强大的程序。甚至可以结合其它软件,相比于“录制宏”,更能扩展Word的功能。

如在日常办公中,有时需将Word与Excel两个软件结合使用。那么,在VBA中,只要以下简单的程序,即可实现Word对Excel的调用:

Set E_obj = CreateObject(“Excel.Applicattion”)

E_obj.visible=True

但无论是利用“录制宏”还是利用VBA环境进行Word的二次开发,其共同的缺点都是所开发出来的程序,必须与Word文件捆绑保存,无法独立于Word程序独立存在运行。因为在VBA程序中的许多对象、系统变量与系统常量都完全来源并被识别于Word,并且只有开发所在的机器与用户能够正常使用。例如若在VBA中有以下程序:

ActiveDocument.Paragraphs(3).Range.Characters(2).Font.Size = 14

程序中的ActiveDocument,Paragraphs,Range,Characters都属于Word的专有对象,如果程序被独立运行的话,便会报错中断运行,因为脱离Word环境以后,这些对象就无法再被识别,成为无效引用。

2.解决VBA程序可移植性的方法

2.1 代码导入法

代码导入法即是在Word中的VBA环境下,完成二次开发以后,将全部代码按分类直接导出到一个目录中,发布分享。需要同样的功能程序的用户,再通过VBA将全部代码导入到自己的Word中。其操作流程示意图如图1所示:

图1 操作流程示意图

利用导入法解决VBA程序的可移植性问题,最大的优点是简单、快捷、易实现,对于安全要求不高,面向有限的内部用户群体的二次开发程序,该法是可行的选择。但必须解决的一个问题,就是“ThisDocument”文件中代码的移植。在分析这个问题之前,我们必须先对VBA中的文件结构有所了解。Word将VBA程序文件分为五类,分别存放在Microsoft Word对象、窗体、模块、类模块、引用五个目录中,其结构关系如图2所示。

图2 结构关系

其中,“Microsoft Word对象”目录下,通常只有一个文件,名为ThisDocument。存放的就是控制、操作当前Word文档的相关程序代码以及公开、通用类的声明、函数与过程,如打开文档时触发的“Document_Open()”过程就保存在这里。如果ThisDocument文件中没有任何VBA代码的话,代码导入法解决VBA程序的移植就能正确进行。但是,如果这个文件中增加了开发的代码,就会发现新文档导入代码文件以后,程序失效,也即意味着移植失败。

这是因为在导出代码时,VBA是把ThisDocument文件中的代码,作为一个类文件导出保存的,这个类文件的名字默认为ThisDocument.cls。但是当在新文档中再次导入这个文件中的代码时,VBA却并没有自动将代码覆盖到新文档的“ThisDocument”文件中,而且将其作为一个独立的类文件,以原来的类文件名保存在新文档的“类模块”目录下。这就会导致新文档无法运行该文件中的代码,使程序移植失败。

注意到这个问题以后,只要在导入This-Document.cls文件以后,打开其中的代码并全部复制,然后粘贴到新文档的ThisDocument代码窗口中,再把所导入的ThisDocument.cls文件移除便可保证全部程序的成功移植。

2.2 将VBA程序封装成DLL文件

2.2.1 关于DLL与VBA代码封装

DLL即动态链接库(Dynamic Link Library),是由可被其它程序调用的函数集合组成的可执行文件模块。DLL不是应用程序的组成部分,而是运行时链接到应用程序中。将VBA程序封装成DLL就是通过编译软件,将二次开发的VBA程序编译成DLL文件,以方便地为其它用户引用到各自的Word程序中运行使用。其基本的实现流程如图3所示:

图3 实现流程

具体的实现过程,不是本文阐述的重点,在此不再累述。通过DLL封装进行程序移植,其优点主要有以下几点:

(1)一个DLL可以为多个Word文档同时共享,而且当多个Word文件调用DLL中的同一个函数时,装入的只是该函数的内存地址,从而节省内存和磁盘空间;

(2)便于开发者维护用户程序,即使对动态链接库进行修改也不会影响正在使用的用户程序;

(3)VBA代码通过编译封装成为DLL文件以后,是以二进制的形式保存在磁盘中的,这就可以保证代码的安全。

(4)省去了运行时的编译过程,可以提高代码的运行速度。

因此,不考虑实现过程相对繁琐的话,通过DLL封装,是VBA程序移植的最佳方案。

2.2.2 消除宿主程序的对象模型对封装DLL的影响

Word中的VB编辑器不能够将VBA代码编译成DLL。因此,必须借助微软的VB软件。但直接将VBA代码导入VB进行编译,通常都会报错导致编译中断。错误信息是运行时错误,对象的引用无效。这是因为所编译的代码中,含有Word程序的特有对象,在Word中运行这些代码时,程序能够识别这些对象。代码移植到VB中以后,VB本身并没有这些对象,因此,编译时,就会认为是无效的引用而报错。

因此,将VBA代码移到VB中进行编译工作之前,必须详细了解Word的对象模型,并对VB中的代码进行修改,使其能够通过VB的语法检查,又能为Word所运行,才能完成DLL的编译封装。

编译前的代码修改,主要从以下两个方面检查:

(1)修改VBA代码中Word所特有的对象。如果所要编译移植的代码中,含有Document、Selection、Tables等等Word所特有类型的对象(如图4所示),那么VB是无法识别的。必须给这些对象所在的过程或函数,定义一个数据类型为Object的参数,将这些对象通过这个参数进行传递调用。如在一个过程Removal_Test中要访问对象Tables,即Removal_Test可定义为Removal_Test (Test_Tab As Object)。那么Tables對象就可以用以下程序进行调用:

Dim new_table as object

Set new_table=CreateObject(“,”Word.Application”) ‘

Removal_Test(new_table)

(2)修改Word的VBA专属常量。Word的 VBA专属常量以“wd”开头,不同的宿主程序的VBA专属常量具体有所区别,必须根据实际情况,进行代码的修改编写。比如代码中有设置段落格式的命令“.ParagraphFormat.Alignment = wdAlignParagraphCenter”。其中的wdAlignParagraphCenter就属于Word的专属常量。如果在VB中直接编译,就会出现“类型不匹配”或“该属性值不是一个有效值”的错误。解决的方法是需要使用常量的地方,用“常量值”来替代“常量名”。.ParagraphFormat.Alignment = 1。常量值的获取,可以查阅有关文档资料,也可以在Word的VB编辑器中用Msgbox方法,让Word自己将值返回。如Msgbox wdAlignParagraphCenter 。

2.2.3 相关类库的引用

VB环境中,许多对象,依然需要相关的类库文件来支持,才能支持识别其相关的属性与方法。

因此,将程序编译封装前,还必须在VB环境中的【工程】菜单下,通过【引用】菜单项,调出“引用”对话框,然后将所需的类库引用到VB中来,如图4所示。

图4

在Word中利用VBA进行的二次开发程序,必须引用的至少有两个类库:Microsoft Word 12.0 Object Library与Microsoft Office 12.0 Object Library。不同版本的Office,类库的版本也相应不同。如果在开发的过程中,还曾经引用过其他类库,在VB中编译时也必须先将这些类库引用进来。

3.DLL文件的移植

3.1 常见的DLL文件移植问题

封装成为DLL文件(实验名为Test_VBA.dll,下同)以后,当中的程序能否为其它Word用户所运行使用,是决定VBA程序的移植是否成功的关键。通常在编译工作所在的机器中,这个DLL文件的使用是没有任何障碍的,但把这个DLL文件转移到其它机器上以后,将其引用到Word中时,却容易出现各样的错误,程序无法运行,也即意味着程序移植的最后一步失败。常见的错误类型主要有以下几种:

(1)找不到工程或库:

这是由于在Windows平台中,DLL文件未被注册,因此,无法被引用。

(2)引用的动态链接库(DLL)丢失:

即使一个DLL文件的注册信息已经写入系统注册表,但是文件的存放路径相对于注册时的路径发生了改变,系统就会认为DLL文件丢失而报错。

(3)自动化(Automation)错误:

错误的原因是DLL文件注册并被Word引用以后,在运行的过程中,文件的路径再次发生改变。

3.2 解决DLL文件移植问题的对策

解决DLL文件移植过程中出现的各类问题,可以通过批处理程序完成。程序首先将DLL文件复制到system目录下,然后运行Regsvr32命令进行注册。将批处理指令保存成为批处理文件以后,随同DLL文件一起打包发布。用户在获得文件包以后,运行批处理文件,由批处理文件自动完成DLL文件的复制与注册,完成后,用户在Word中进行DLL文件的引用运行即可。批处理指令如下:

@echo off

if exist Test_VBA.dll goto A

if not exist Test_VBA.dll goto B

:A

copy Test_VBA.dll %windir%\system32

regsvr32 %windir%\system32\Test_VBA.dll /s

echo 文件注册成功,请打开Word并在VBA环境中引用运行

pause

exit

:B

echo DLL文件丢失,请重新下载

pause

exit

对于已注册的DLL文件的引用,比较稳定且高效的方法,是通过VBA中的CreateObject方法实现引用。关键代码如下:

Dim New_obj As Object ‘定义一个新对象

Set New_obj = CreateObject(“Test_VBA.Ulogin”) ‘ 将定义的对象实例化

……

Set New_obj = Nothing ‘释放对象

至此,即可解决VBA二次开发程序的移植过程中的全部问题。我们可以将问题解决的方法与过程用图6简要表述。

图6

4.结语

VBA使Word等一系列软件的功能得到了更广的拓展,但VBA本身能力的不足,使VBA的二次开发程序不能直接移植,严重影响到Word用户对开发成果的分享。直接将代码导出共享,并在导入使用时,妥当解决好ThisDocument文件中的代码,是可行的方法之一,但程序毫无安全性可言。而将VBA代码导出以后,再借助VB作可移植性的代码修改,然后封装成为DLL动态链接库文件,并利用批处理命令对DLL文件注册,再在Word中进行引用。

这种方法不仅能保证程序代码安全,而且可以提高运行效率,并且在开发者的程序维护与用户的继续使用之间,不存在任何冲突,是当前解决VBA程序可移植性问题中,最佳的選择。

参考文献

[1]周静,袁方等. 基于VSTO的Office二次开发[J].福建电脑,2011(9):22-23.

[2]王燕.VBA在办公中的编程应用[J].福建电脑,2013(10): 177-179.

[3]江云林.DLL巧注册 系统更随心[J].电脑爱好者,2013(3): 59-59.

[4]张发凌.批处理命令在Windows操作中的典型应用[M].北京:人民邮电出版社,2008,2.

[5]Word对象模型概述[EB/OL].http://msdn.microsoft.com/zh-cn/library/d2tx7z6d(v=vs.80).aspx.

[6]黄聪会,陈靖等.软件移植理论与技术研究[J].计算机应用研究,2012(6):2024-2027.

[7][英]Lan Sommerville.软件工程(第九版)[M] .北京:机械工业出版社,2011,5.

[8]李殿勋.浅谈Windows环境下对象的链接与嵌入[J].中国科技博览,2011(37):157-157.

[9]何振林,胡绿慧.MS Office与VBA高级应用案例教程[M].北京:水利水电出版社,2010,09.

[10]刘春裕.基于VBA开发技术的接口测试技术研究[J].计算机技术与发展,2014(1):69-72.

[11]梁洁.利用VB实现OFFICE对象的访问控制[J]成都医学院学报,2007(1):48-51.

[12]梁德强,王省书等.基于ActiveX控件的视频跟踪系统软件设计[J].微计算机信息,2010(19):201-202.

[13]祝晋.office的二次开发及在工业设计中的应用[J].自动化与仪器仪表,2012(1):86-87.

[14]陈永松.Office操作题自动阅卷组件设计[J].实验室研究与探索,2013(8):64-67.

[15]周维京.VBA封装技术分析[J].电脑与电信,2008(4): 34-35.

[16]罗雨滋.在应用程序中使用Office对象的方法[J].辽宁师专学报(自然科学版),2007(1):37-38.

作者简介:李圆(1984—),女,广东河源人,惠州商贸旅游高级职业技术学校讲师,研究方向:计算机应用与程序设计。

猜你喜欢
二次开发
浅谈基于Revit平台的二次开发
西门子Operate高级编程的旋转坐标系二次开发
浅谈Mastercam后处理器的二次开发
西门子Easy Screen对倒棱机床界面二次开发
Micaps3.2 版本二次开发入门浅析
ANSYS Workbench二次开发在汽车稳定杆CAE分析中的应用