封裝我們的VBA程式碼

zhengnx發表於2012-02-17
Visual Basic for Applications(簡稱VBA)是新一代標準宏語言,是基於Visual Basic for Windows 發展而來的。VBA 提供了物件導向的程式設計方法,提供了相當完整的程式設計語言。VBA 易於學習掌握,使用者可以容易地將日常工作轉換為VBA程式程式碼,使工作自動化。
但是VBA在程式碼的保護上卻存在著缺陷。如果不對VBA工程設定密碼保護,程式碼很容易被人瀏覽乃至竊取。而且即使設定了密碼保護,也很容易被人破解。筆者就曾用破解工具officekey輕鬆地破解了他人設定的密碼保護,不費吹灰之力便瀏覽了其中的程式碼,而且從中發現了文件保護密碼。可見,要想保護自己的VBA程式碼,僅僅設定密碼保護是不夠的。
我們知道,Visual C++、Visual Basic和C++ Builder以及Delphi等編譯器所編譯出來的程式不容易被人破解(相對來說),這是因為程式碼被編譯成了可執行檔案或者動態連結庫檔案。那麼,我們是否可以將VBA程式碼封裝到動態連結庫檔案中,然後用Word呼叫呢?回答是肯定的。而且這樣做還有一個好處,即可以加快程式碼的執行速度。
一、將VBA程式碼封裝成動態連結庫
假如我們已經寫好了一個VBA工程,而且執行無誤。
1.建立VB工程及一般性操作
首先,我們需要兩種工具,其中當然包括Microsoft Word,另外一種是Microsoft Basic 6.0。
開啟Microsoft Basic 6.0,在“新建工程”中選取“ActiveX DLL”,新建一個工程。在屬性視窗中將工程名改為VBAPrj,類模組名改為VBACls。然後在“工程”選單下開啟“引用”,選取“Microsoft Office 11.0 Object Library”——這一步很是關鍵,切不可遺漏,然後儲存工程。下面我們所做的是向工程內新增程式碼。
將VBA工程中的一個名為Test過程的程式碼選定後複製,然後切換到VB編輯器,選中VB的工程管理器中的類模組VBACls,將程式碼貼上至程式碼編輯視窗中,於是這段程式碼便成了類模組VBACls一個方法,然後將工程編譯生成dll檔案(如果編譯成功的話)。在Word中,我們就可以透過類模組VBACls建立的物件來呼叫此方法(具體怎麼呼叫,我們將後面介紹)。當然,我們可以繼續向工程裡新增程式碼。
2.修改程式碼
雖然VBA源於VB,但是兩者畢竟存在著一些差異。因此,需要對轉移到VB中的VBA程式碼做一些必要的修改。
(1)修改VBA程式碼中所特有型別的物件。
如果我們所新增的程式碼裡有VBA所特有型別——如Document、Rang、BookMark等所建立的物件,編譯時會提示錯誤,因為VB不能夠識別這些物件。此時修改的方法是,將這些物件作為過程或函式的引數進行傳遞。需要注意的是,這些引數的型別都一律設為Object。
例如,我們在過程Test中要訪問物件ThisDocument,但是VB無法識別ThisDocument,於是我們就為過程test新增一個引數Doc來傳遞ThisDocument,即Test可定義為Test(Doc As Object)。
(2)修改VBA所特有一般變數。
VB也無法識別VBA特有的一般變數,如ProtectType,同樣,我們也將其作為過程後函式的引數進行傳遞,不過其型別名都一律設為Variant。
(3)修改VBA所特有常量。
如果在VBA程式碼中出現了這樣的語句:
ProtectionType = wdNoProtection
很明顯,wdNoProtection是Word所獨有的常量,不為VB所能識別,因而無法透過編譯。怎樣解決這個問題呢?當然,我們可以用修改變數的方法予以修改。但是聰明的讀者會想到:如果我們知道了wdNoProtection的值,就可以直接將值賦給ProtectionType。但是接下來的一個問題是:我們怎樣才能獲得wdNoProtection的值呢?方法很簡單,就是讓Word“開口”告訴我們。
在Word一個事件中新增以下語句:
MsgBox CStr (wdNoProtection)
其中CStr是型別轉換函式,返回引數相應的字串。只要在Word中觸發此事件,會彈出一個對話窗,顯示“-1”,這就是Word所告訴我們的:wdNoProtection 的值是-1。於是我們就可以將語句 ProtectionType = wdNoProtection 改為 ProtectionType = -1,問題到此就迎刃而解了。
3.封裝使用者窗體
我們也可以將使用者窗體封裝到動態連結庫檔案裡。首先開啟Word的VBA編輯器,選中工程資源管理器中的使用者窗體,點選右鍵,選擇“匯出檔案”,選定路徑後,將窗體檔案儲存。然後切換到VB編輯器,在“工程”選單中選擇“新增檔案”命令,新增儲存的窗體檔案。新增結束後,我們會發現VB編輯器中的工程資源管理器中的設計器出現了剛新增的窗體名,選中後雙擊,在窗體編輯器中就會顯現所新增的使用者窗體。
到了這裡,讀者會問:窗體還有程式碼呢,怎麼辦?先別急,試一試下面的操作,你就會明白,問題早已不再是問題了。選中工程資源管理器中的使用者窗體,點選右鍵,選擇“檢視程式碼”,你就會高興發現,在程式碼編輯框中出現了窗體所對應的程式碼。原來,在我們匯入窗體檔案的同時也匯入了窗體的程式碼!當然高興之餘,不要忘了還要對這些程式碼按照我們上述的方法進行必要修改,以保證程式碼順利地透過編譯。這樣Word就可以透過類模組VBACls間接地呼叫窗體。
二、在Word中引用動態連結庫
假如經過我們編譯已生成了一個動態連結庫檔案VBAPrj.dll,其中有一類模組VBACls,此類模組有一個方法Test(Doc As Object)。
接下來我們所要做的是用Word呼叫Test,有三種方法可供選擇:
1.開啟Word的VBA編輯器中ThisDocument程式碼視窗,點"工具"選單下的"引用"命令,在引用對話方塊中引用該動態連結庫。
呼叫程式碼如下:
Dim VBACls As New VBAPrj.VBACls
VBACls.Test(ThisDocument)
2.如果知道該動態連結庫檔案的位置,可以在ThisDocument程式碼視窗以程式碼形式引用, 程式碼如下:
Private Sub Document_Open()
On Error Resume Next
Me.VBProject.References.AddFromFile "D:VBAPrj.dll"
End Sub
3.將動態連結庫檔案複製到Word文件同一目錄下,可在ThisDocument程式碼視窗中建立如下引用函式:
Private Function GetProjectDoc() As Object
On Error Resume Next
Dim VBACls As Object
Set VBACls = CreateObject("VBAPrj.VBACls")
If VBACls Is Nothing Then
MsgBox "VBAPrj.dll必須和文件在同一目錄下!"
Exit Function
End If
Set GetProjectDoc = VBACls
End Function
然後以以下程式碼形式呼叫Test:
Dim objPrjDoc As Object
Set objPrjDoc = GetProjectDoc
Call objPrjDoc.Test(ThisDocument)
Set objPrjDoc = Nothing
筆者更傾向使用第三種方法,雖然這種方法相對麻煩,但是隻要動態連結庫與Word文件處於同一目錄下,可保證程式的可移植性。
到目前為止,我們已完成了我們所要達的目的。此時,即便我們不對VBA工程設定密碼保護,別人也將很難窺視到我們的程式碼。[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7868752/viewspace-1057385/,如需轉載,請註明出處,否則將追究法律責任。

相關文章