【摘要】利用VBA對(duì)Word等辦公軟件進(jìn)行二次開發(fā)的程序,可移植性差,只能在開發(fā)機(jī)器中運(yùn)行,不便于開發(fā)成果的共享使用。將開發(fā)的程序,通過VBA直接導(dǎo)出,然后再導(dǎo)入到其它Word程序的VBA中,并解決好當(dāng)中Thisdocument文件的代碼,可以實(shí)現(xiàn)程序的移植共享,但安全性差。利用VB將導(dǎo)出的代碼,以DLL文件的形式編譯封裝,并用批處理指令幫助用戶進(jìn)行注冊(cè),可以極好地解決程序的安全性與移植共享問題。
【關(guān)鍵詞】可移植性;VBA;二次開發(fā);封裝
引言
微軟的Office軟件在一些特殊的應(yīng)用中,有力所不及之處。利用VBA(Visual Basic For Application)對(duì)Office進(jìn)行拓展性的二次開發(fā),是當(dāng)前解決Office功能不足的常見方法。但此法最明顯的不足就是所開發(fā)的程序不具備可移植性,僅限于開發(fā)者所在的機(jī)器中能夠使用,其它需要同樣功能程序的用戶或機(jī)器,只能重復(fù)開發(fā),極大地影響了開發(fā)成果的共享。因此, VBA二次開發(fā)程序的可移植性問題,是亟待每個(gè)程序員研究、解決的問題。下文將以VAB在Word中的二次開發(fā)為例,對(duì)其可移植性問題的研究進(jìn)行詳細(xì)闡述。
1.VBA二次開發(fā)的現(xiàn)狀
1.1 關(guān)于VBA
VBA微軟開發(fā)出來的宏語言。主要用來擴(kuò)展Windows的應(yīng)用程式功能,特別是微軟的Office軟件。它完全繼承了VB(Visual Basic)的語言機(jī)制,是VB的一個(gè)子集,但又不同于VB,VB是一個(gè)可視化的程序開發(fā)環(huán)境,能夠獨(dú)立創(chuàng)建一個(gè)應(yīng)用程序并編譯運(yùn)行,而VBA則要求有一個(gè)宿主應(yīng)用程序(如Word)才能開發(fā)、運(yùn)行,而且不能用于創(chuàng)建獨(dú)立的應(yīng)用程序。
由于VBA必須寄生于宿主程序,離開宿主程序以后,程序便無法被解讀與運(yùn)行。這是制約VBA二次開發(fā)程序可移植性的主要因素之一。因此,我們對(duì)VBA程序的可移植性研究,主要集中在二次開發(fā)程序在其宿主程序中的移植,即如何使開發(fā)出來的程序,能夠方便、快捷地移植到其它機(jī)器中,并在相應(yīng)的宿主軟件中正確運(yùn)行,使得開發(fā)成果能夠發(fā)揮資源共享的作用。
1.2 VBA對(duì)Word的開發(fā)與存在問題
1.2.1 錄制宏
錄制宏是當(dāng)前VBA對(duì)Word最簡(jiǎn)單、常見的開發(fā)模式。這種方法優(yōu)點(diǎn)是簡(jiǎn)單,易實(shí)現(xiàn),完全可視化操作,用戶不需編寫任何代碼,只要按照功能需求,一步步操作Word即可,VBA會(huì)根據(jù)用戶的操作,自動(dòng)生成相應(yīng)的VBA程序代碼,并保存在指定的文件中。
但該法的缺點(diǎn)也很明顯,就是能擴(kuò)展的功能非常有限。所謂錄制宏,實(shí)際就是利用已有的Word功能,將需要反復(fù)進(jìn)行的一系列操作,組合為一步操作,并作以VBA程序的形式保存下來。用戶在打開該文檔的同時(shí),啟動(dòng)文檔中已保存的VBA程序,并根據(jù)用戶的指令運(yùn)行、發(fā)揮作用。因此,這種開發(fā)完全依賴于Word中已有的可操作功能,只能在功能組合的基礎(chǔ)上進(jìn)行。
1.2.2 VBA環(huán)境開發(fā)
利用VBA對(duì)Word進(jìn)行二次開發(fā),更重要的方法是在Word中集成的VBA環(huán)境里,通過編寫程序?qū)崿F(xiàn)。VBA環(huán)境不僅為開發(fā)者準(zhǔn)備了窗體、按鈕、組合框等常用的Windows圖形化控件,還繼承了VB中的模塊、類、對(duì)象等概念。開發(fā)者不僅可以擺脫Word已有功能的掣肘,還可以像在VB中一樣,自由編寫出功能強(qiáng)大的程序。甚至可以結(jié)合其它軟件,相比于“錄制宏”,更能擴(kuò)展Word的功能。
如在日常辦公中,有時(shí)需將Word與Excel兩個(gè)軟件結(jié)合使用。那么,在VBA中,只要以下簡(jiǎn)單的程序,即可實(shí)現(xiàn)Word對(duì)Excel的調(diào)用:
Set E_obj = CreateObject(“Excel.Applicattion”)
E_obj.visible=True
但無論是利用“錄制宏”還是利用VBA環(huán)境進(jìn)行Word的二次開發(fā),其共同的缺點(diǎn)都是所開發(fā)出來的程序,必須與Word文件捆綁保存,無法獨(dú)立于Word程序獨(dú)立存在運(yùn)行。因?yàn)樵赩BA程序中的許多對(duì)象、系統(tǒng)變量與系統(tǒng)常量都完全來源并被識(shí)別于Word,并且只有開發(fā)所在的機(jī)器與用戶能夠正常使用。例如若在VBA中有以下程序:
ActiveDocument.Paragraphs(3).Range.Characters(2).Font.Size = 14
程序中的ActiveDocument,Paragraphs,Range,Characters都屬于Word的專有對(duì)象,如果程序被獨(dú)立運(yùn)行的話,便會(huì)報(bào)錯(cuò)中斷運(yùn)行,因?yàn)槊撾xWord環(huán)境以后,這些對(duì)象就無法再被識(shí)別,成為無效引用。
2.解決VBA程序可移植性的方法
2.1 代碼導(dǎo)入法
代碼導(dǎo)入法即是在Word中的VBA環(huán)境下,完成二次開發(fā)以后,將全部代碼按分類直接導(dǎo)出到一個(gè)目錄中,發(fā)布分享。需要同樣的功能程序的用戶,再通過VBA將全部代碼導(dǎo)入到自己的Word中。其操作流程示意圖如圖1所示:
圖1 操作流程示意圖
利用導(dǎo)入法解決VBA程序的可移植性問題,最大的優(yōu)點(diǎn)是簡(jiǎn)單、快捷、易實(shí)現(xiàn),對(duì)于安全要求不高,面向有限的內(nèi)部用戶群體的二次開發(fā)程序,該法是可行的選擇。但必須解決的一個(gè)問題,就是“ThisDocument”文件中代碼的移植。在分析這個(gè)問題之前,我們必須先對(duì)VBA中的文件結(jié)構(gòu)有所了解。Word將VBA程序文件分為五類,分別存放在Microsoft Word對(duì)象、窗體、模塊、類模塊、引用五個(gè)目錄中,其結(jié)構(gòu)關(guān)系如圖2所示。
圖2 結(jié)構(gòu)關(guān)系
其中,“Microsoft Word對(duì)象”目錄下,通常只有一個(gè)文件,名為ThisDocument。存放的就是控制、操作當(dāng)前Word文檔的相關(guān)程序代碼以及公開、通用類的聲明、函數(shù)與過程,如打開文檔時(shí)觸發(fā)的“Document_Open()”過程就保存在這里。如果ThisDocument文件中沒有任何VBA代碼的話,代碼導(dǎo)入法解決VBA程序的移植就能正確進(jìn)行。但是,如果這個(gè)文件中增加了開發(fā)的代碼,就會(huì)發(fā)現(xiàn)新文檔導(dǎo)入代碼文件以后,程序失效,也即意味著移植失敗。
這是因?yàn)樵趯?dǎo)出代碼時(shí),VBA是把ThisDocument文件中的代碼,作為一個(gè)類文件導(dǎo)出保存的,這個(gè)類文件的名字默認(rèn)為ThisDocument.cls。但是當(dāng)在新文檔中再次導(dǎo)入這個(gè)文件中的代碼時(shí),VBA卻并沒有自動(dòng)將代碼覆蓋到新文檔的“ThisDocument”文件中,而且將其作為一個(gè)獨(dú)立的類文件,以原來的類文件名保存在新文檔的“類模塊”目錄下。這就會(huì)導(dǎo)致新文檔無法運(yùn)行該文件中的代碼,使程序移植失敗。
注意到這個(gè)問題以后,只要在導(dǎo)入This-Document.cls文件以后,打開其中的代碼并全部復(fù)制,然后粘貼到新文檔的ThisDocument代碼窗口中,再把所導(dǎo)入的ThisDocument.cls文件移除便可保證全部程序的成功移植。
2.2 將VBA程序封裝成DLL文件
2.2.1 關(guān)于DLL與VBA代碼封裝
DLL即動(dòng)態(tài)鏈接庫(kù)(Dynamic Link Library),是由可被其它程序調(diào)用的函數(shù)集合組成的可執(zhí)行文件模塊。DLL不是應(yīng)用程序的組成部分,而是運(yùn)行時(shí)鏈接到應(yīng)用程序中。將VBA程序封裝成DLL就是通過編譯軟件,將二次開發(fā)的VBA程序編譯成DLL文件,以方便地為其它用戶引用到各自的Word程序中運(yùn)行使用。其基本的實(shí)現(xiàn)流程如圖3所示:
圖3 實(shí)現(xiàn)流程
具體的實(shí)現(xiàn)過程,不是本文闡述的重點(diǎn),在此不再累述。通過DLL封裝進(jìn)行程序移植,其優(yōu)點(diǎn)主要有以下幾點(diǎn):
(1)一個(gè)DLL可以為多個(gè)Word文檔同時(shí)共享,而且當(dāng)多個(gè)Word文件調(diào)用DLL中的同一個(gè)函數(shù)時(shí),裝入的只是該函數(shù)的內(nèi)存地址,從而節(jié)省內(nèi)存和磁盤空間;
(2)便于開發(fā)者維護(hù)用戶程序,即使對(duì)動(dòng)態(tài)鏈接庫(kù)進(jìn)行修改也不會(huì)影響正在使用的用戶程序;
(3)VBA代碼通過編譯封裝成為DLL文件以后,是以二進(jìn)制的形式保存在磁盤中的,這就可以保證代碼的安全。
(4)省去了運(yùn)行時(shí)的編譯過程,可以提高代碼的運(yùn)行速度。
因此,不考慮實(shí)現(xiàn)過程相對(duì)繁瑣的話,通過DLL封裝,是VBA程序移植的最佳方案。
2.2.2 消除宿主程序的對(duì)象模型對(duì)封裝DLL的影響
Word中的VB編輯器不能夠?qū)BA代碼編譯成DLL。因此,必須借助微軟的VB軟件。但直接將VBA代碼導(dǎo)入VB進(jìn)行編譯,通常都會(huì)報(bào)錯(cuò)導(dǎo)致編譯中斷。錯(cuò)誤信息是運(yùn)行時(shí)錯(cuò)誤,對(duì)象的引用無效。這是因?yàn)樗幾g的代碼中,含有Word程序的特有對(duì)象,在Word中運(yùn)行這些代碼時(shí),程序能夠識(shí)別這些對(duì)象。代碼移植到VB中以后,VB本身并沒有這些對(duì)象,因此,編譯時(shí),就會(huì)認(rèn)為是無效的引用而報(bào)錯(cuò)。
因此,將VBA代碼移到VB中進(jìn)行編譯工作之前,必須詳細(xì)了解Word的對(duì)象模型,并對(duì)VB中的代碼進(jìn)行修改,使其能夠通過VB的語法檢查,又能為Word所運(yùn)行,才能完成DLL的編譯封裝。
編譯前的代碼修改,主要從以下兩個(gè)方面檢查:
(1)修改VBA代碼中Word所特有的對(duì)象。如果所要編譯移植的代碼中,含有Document、Selection、Tables等等Word所特有類型的對(duì)象(如圖4所示),那么VB是無法識(shí)別的。必須給這些對(duì)象所在的過程或函數(shù),定義一個(gè)數(shù)據(jù)類型為Object的參數(shù),將這些對(duì)象通過這個(gè)參數(shù)進(jìn)行傳遞調(diào)用。如在一個(gè)過程Removal_Test中要訪問對(duì)象Tables,即Removal_Test可定義為Removal_Test (Test_Tab As Object)。那么Tables對(duì)象就可以用以下程序進(jìn)行調(diào)用:
Dim new_table as object
Set new_table=CreateObject(“,”Word.Application”) ‘
Removal_Test(new_table)
(2)修改Word的VBA專屬常量。Word的 VBA專屬常量以“wd”開頭,不同的宿主程序的VBA專屬常量具體有所區(qū)別,必須根據(jù)實(shí)際情況,進(jìn)行代碼的修改編寫。比如代碼中有設(shè)置段落格式的命令“.ParagraphFormat.Alignment = wdAlignParagraphCenter”。其中的wdAlignParagraphCenter就屬于Word的專屬常量。如果在VB中直接編譯,就會(huì)出現(xiàn)“類型不匹配”或“該屬性值不是一個(gè)有效值”的錯(cuò)誤。解決的方法是需要使用常量的地方,用“常量值”來替代“常量名”。.ParagraphFormat.Alignment = 1。常量值的獲取,可以查閱有關(guān)文檔資料,也可以在Word的VB編輯器中用Msgbox方法,讓W(xué)ord自己將值返回。如Msgbox wdAlignParagraphCenter 。
2.2.3 相關(guān)類庫(kù)的引用
VB環(huán)境中,許多對(duì)象,依然需要相關(guān)的類庫(kù)文件來支持,才能支持識(shí)別其相關(guān)的屬性與方法。
因此,將程序編譯封裝前,還必須在VB環(huán)境中的【工程】菜單下,通過【引用】菜單項(xiàng),調(diào)出“引用”對(duì)話框,然后將所需的類庫(kù)引用到VB中來,如圖4所示。
圖4
在Word中利用VBA進(jìn)行的二次開發(fā)程序,必須引用的至少有兩個(gè)類庫(kù):Microsoft Word 12.0 Object Library與Microsoft Office 12.0 Object Library。不同版本的Office,類庫(kù)的版本也相應(yīng)不同。如果在開發(fā)的過程中,還曾經(jīng)引用過其他類庫(kù),在VB中編譯時(shí)也必須先將這些類庫(kù)引用進(jìn)來。
3.DLL文件的移植
3.1 常見的DLL文件移植問題
封裝成為DLL文件(實(shí)驗(yàn)名為Test_VBA.dll,下同)以后,當(dāng)中的程序能否為其它Word用戶所運(yùn)行使用,是決定VBA程序的移植是否成功的關(guān)鍵。通常在編譯工作所在的機(jī)器中,這個(gè)DLL文件的使用是沒有任何障礙的,但把這個(gè)DLL文件轉(zhuǎn)移到其它機(jī)器上以后,將其引用到Word中時(shí),卻容易出現(xiàn)各樣的錯(cuò)誤,程序無法運(yùn)行,也即意味著程序移植的最后一步失敗。常見的錯(cuò)誤類型主要有以下幾種:
(1)找不到工程或庫(kù):
這是由于在Windows平臺(tái)中,DLL文件未被注冊(cè),因此,無法被引用。
(2)引用的動(dòng)態(tài)鏈接庫(kù)(DLL)丟失:
即使一個(gè)DLL文件的注冊(cè)信息已經(jīng)寫入系統(tǒng)注冊(cè)表,但是文件的存放路徑相對(duì)于注冊(cè)時(shí)的路徑發(fā)生了改變,系統(tǒng)就會(huì)認(rèn)為DLL文件丟失而報(bào)錯(cuò)。
(3)自動(dòng)化(Automation)錯(cuò)誤:
錯(cuò)誤的原因是DLL文件注冊(cè)并被Word引用以后,在運(yùn)行的過程中,文件的路徑再次發(fā)生改變。
3.2 解決DLL文件移植問題的對(duì)策
解決DLL文件移植過程中出現(xiàn)的各類問題,可以通過批處理程序完成。程序首先將DLL文件復(fù)制到system目錄下,然后運(yùn)行Regsvr32命令進(jìn)行注冊(cè)。將批處理指令保存成為批處理文件以后,隨同DLL文件一起打包發(fā)布。用戶在獲得文件包以后,運(yùn)行批處理文件,由批處理文件自動(dòng)完成DLL文件的復(fù)制與注冊(cè),完成后,用戶在Word中進(jìn)行DLL文件的引用運(yùn)行即可。批處理指令如下:
@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 文件注冊(cè)成功,請(qǐng)打開Word并在VBA環(huán)境中引用運(yùn)行
pause
exit
:B
echo DLL文件丟失,請(qǐng)重新下載
pause
exit
對(duì)于已注冊(cè)的DLL文件的引用,比較穩(wěn)定且高效的方法,是通過VBA中的CreateObject方法實(shí)現(xiàn)引用。關(guān)鍵代碼如下:
Dim New_obj As Object ‘定義一個(gè)新對(duì)象
Set New_obj = CreateObject(“Test_VBA.Ulogin”) ‘ 將定義的對(duì)象實(shí)例化
……
Set New_obj = Nothing ‘釋放對(duì)象
至此,即可解決VBA二次開發(fā)程序的移植過程中的全部問題。我們可以將問題解決的方法與過程用圖6簡(jiǎn)要表述。
圖6
4.結(jié)語
VBA使Word等一系列軟件的功能得到了更廣的拓展,但VBA本身能力的不足,使VBA的二次開發(fā)程序不能直接移植,嚴(yán)重影響到Word用戶對(duì)開發(fā)成果的分享。直接將代碼導(dǎo)出共享,并在導(dǎo)入使用時(shí),妥當(dāng)解決好ThisDocument文件中的代碼,是可行的方法之一,但程序毫無安全性可言。而將VBA代碼導(dǎo)出以后,再借助VB作可移植性的代碼修改,然后封裝成為DLL動(dòng)態(tài)鏈接庫(kù)文件,并利用批處理命令對(duì)DLL文件注冊(cè),再在Word中進(jìn)行引用。
這種方法不僅能保證程序代碼安全,而且可以提高運(yùn)行效率,并且在開發(fā)者的程序維護(hù)與用戶的繼續(xù)使用之間,不存在任何沖突,是當(dāng)前解決VBA程序可移植性問題中,最佳的選擇。
參考文獻(xiàn)
[1]周靜,袁方等. 基于VSTO的Office二次開發(fā)[J].福建電腦,2011(9):22-23.
[2]王燕.VBA在辦公中的編程應(yīng)用[J].福建電腦,2013(10): 177-179.
[3]江云林.DLL巧注冊(cè) 系統(tǒng)更隨心[J].電腦愛好者,2013(3): 59-59.
[4]張發(fā)凌.批處理命令在Windows操作中的典型應(yīng)用[M].北京:人民郵電出版社,2008,2.
[5]Word對(duì)象模型概述[EB/OL].http://msdn.microsoft.com/zh-cn/library/d2tx7z6d(v=vs.80).aspx.
[6]黃聰會(huì),陳靖等.軟件移植理論與技術(shù)研究[J].計(jì)算機(jī)應(yīng)用研究,2012(6):2024-2027.
[7][英]Lan Sommerville.軟件工程(第九版)[M] .北京:機(jī)械工業(yè)出版社,2011,5.
[8]李殿勛.淺談Windows環(huán)境下對(duì)象的鏈接與嵌入[J].中國(guó)科技博覽,2011(37):157-157.
[9]何振林,胡綠慧.MS Office與VBA高級(jí)應(yīng)用案例教程[M].北京:水利水電出版社,2010,09.
[10]劉春裕.基于VBA開發(fā)技術(shù)的接口測(cè)試技術(shù)研究[J].計(jì)算機(jī)技術(shù)與發(fā)展,2014(1):69-72.
[11]梁潔.利用VB實(shí)現(xiàn)OFFICE對(duì)象的訪問控制[J]成都醫(yī)學(xué)院學(xué)報(bào),2007(1):48-51.
[12]梁德強(qiáng),王省書等.基于ActiveX控件的視頻跟蹤系統(tǒng)軟件設(shè)計(jì)[J].微計(jì)算機(jī)信息,2010(19):201-202.
[13]祝晉.office的二次開發(fā)及在工業(yè)設(shè)計(jì)中的應(yīng)用[J].自動(dòng)化與儀器儀表,2012(1):86-87.
[14]陳永松.Office操作題自動(dòng)閱卷組件設(shè)計(jì)[J].實(shí)驗(yàn)室研究與探索,2013(8):64-67.
[15]周維京.VBA封裝技術(shù)分析[J].電腦與電信,2008(4): 34-35.
[16]羅雨滋.在應(yīng)用程序中使用Office對(duì)象的方法[J].遼寧師專學(xué)報(bào)(自然科學(xué)版),2007(1):37-38.
作者簡(jiǎn)介:李圓(1984—),女,廣東河源人,惠州商貿(mào)旅游高級(jí)職業(yè)技術(shù)學(xué)校講師,研究方向:計(jì)算機(jī)應(yīng)用與程序設(shè)計(jì)。