Kathleen McGrath
Microsoft Corporation
2003 年 6 月
適用于:
Microsoft? "Visual Studio Tools for Office" Beta
Microsoft Office Word 2003 Beta 2
Microsoft Office Excel 2003 Beta 2
Microsoft Visual Basic? for Applications (VBA)
Microsoft Visual Studio? .NET 2003
Microsoft Visual Basic .NET
摘要:介紹將 Microsoft Office 解決方案從 Visual Basic for Applications (VBA) 轉(zhuǎn)換到 Visual Basic .NET 中時(shí)需要考慮的問(wèn)題。概述了兩者之間的差異,并使用來(lái)自 Word 和 Excel 的示例來(lái)說(shuō)明如何使用“Visual Studio Tools for Office”轉(zhuǎn)換代碼。(本文包含一些指向英文站點(diǎn)的鏈接。)
目錄
簡(jiǎn)介
本文介紹將 Microsoft? Visual Basic? for Applications (VBA) 代碼轉(zhuǎn)換到 Microsoft Visual Basic .NET 時(shí)開(kāi)始可能會(huì)遇到的問(wèn)題。并幫助您學(xué)習(xí)當(dāng)從 VBA 代碼(非托管代碼)遷移到由 Microsoft .NET Framework 管理的代碼(托管代碼)時(shí),需要進(jìn)行哪些更改。首先討論是否將代碼轉(zhuǎn)換到 Visual Basic .NET 的依據(jù)。然后介紹轉(zhuǎn)換代碼時(shí)會(huì)出現(xiàn)的多種變化,包括集成開(kāi)發(fā)環(huán)境 (IDE) 中的差異、語(yǔ)言差異、用戶窗體差異、安全性差異和部署差異。最后向您展示如何使用 Microsoft 的“Visual Studio Tools for Office”將現(xiàn)有 Word 和 Excel 代碼模塊中的 VBA 代碼轉(zhuǎn)換到 Visual Basic .NET。
是否應(yīng)該將 VBA 代碼轉(zhuǎn)換到 Visual Basic .NET
在開(kāi)始將 VBA 代碼轉(zhuǎn)換到 Visual Basic .NET 之前,您可能希望了解兩者的優(yōu)缺點(diǎn)。使用“Visual Studio Tools for Office”,您可以在 Microsoft Office Word 2003 文檔和 Microsoft Office Excel 2003 工作簿背后編寫(xiě)托管代碼。能夠使用自定義屬性鏈接到托管代碼程序集的文檔或工作簿被稱為具有“托管代碼擴(kuò)展”功能。使用托管代碼擴(kuò)展,您可以利用 Microsoft Visual Studio? .NET 和 Microsoft .NET Framework 中的資源,包括安全性、部署、完全支持 XML Web Service、結(jié)構(gòu)化異常處理和 Microsoft Windows? 窗體。但是,也可能存在因沒(méi)有轉(zhuǎn)換 VBA 代碼而受益的情況。
當(dāng)考慮是否將 VBA 代碼轉(zhuǎn)換到 Visual Basic .NET 時(shí),請(qǐng)考慮以下信息:
使用 VBA...
當(dāng)代碼需要與文檔緊密綁定時(shí);例如,代碼需要與文檔一起移動(dòng)時(shí)。
當(dāng)組織中存在部署限制時(shí),例如,.NET Framework 對(duì)最終用戶不可用時(shí)。
當(dāng)需要使用 Excel 自定義函數(shù)時(shí)。
當(dāng)需要?jiǎng)?chuàng)建截取 Word 自有命令的方法時(shí)。
當(dāng)自定義除 Microsoft Office Word 2003 和 Microsoft Office Excel 2003 以外的 Microsoft Office 應(yīng)用程序時(shí)?!癡isual Studio Tools for Office”不支持這些應(yīng)用程序。
使用 Visual Basic .NET...
當(dāng)需要利用 Visual Studio .NET 環(huán)境(包括服務(wù)器資源管理器和增強(qiáng)的智能感知功能)時(shí)。
當(dāng)您的解決方案可以從 .NET Framework 的全部資源中受益時(shí),例如,內(nèi)置 Web 服務(wù)支持、更容易進(jìn)行 XML 分析和可以訪問(wèn) .NET Framework 中的所有類。
當(dāng)需要更簡(jiǎn)單的代碼維護(hù)時(shí)。程序集中的代碼與文檔分離,多個(gè)文檔能夠引用同一個(gè)程序集。
當(dāng)需要靈活的部署選項(xiàng)時(shí)。程序集可以部署為網(wǎng)絡(luò)共享;此后,當(dāng)用戶每次打開(kāi)連接到網(wǎng)絡(luò)的 Excel 或 Word 文檔時(shí),可以立即使用程序集中更新后的代碼。
當(dāng)要實(shí)現(xiàn)更靈活的安全模式時(shí)。
VBA 與 Visual Basic .NET 之間的差異
了解 VBA 與 Visual Basic .NET 之間的差異有助于您在轉(zhuǎn)換代碼時(shí)作出更明智的決定。本節(jié)介紹以下方面的差異:
語(yǔ)言
項(xiàng)目管理
安全性
部署
語(yǔ)言差異
由于 Visual Basic .NET 是為利用 .NET Framework 而設(shè)計(jì)的,它包含非常多的改動(dòng),在許多地方已經(jīng)不再與以前的語(yǔ)言版本兼容。以下列出了 Visual Basic .NET 中 Visual Basic 語(yǔ)言的部分修改。有關(guān)詳細(xì)信息,請(qǐng)參閱
Introduction to Visual Basic .NET for Visual Basic Veterans。
后期綁定:VBA 和 Visual Basic .NET 都支持后期綁定;但是,使用早期綁定對(duì)象可以使代碼更易于閱讀和維護(hù),同時(shí)還可以啟用智能感知。Visual Basic .NET 引入 Option Strict On 語(yǔ)句,該語(yǔ)句強(qiáng)制進(jìn)行早期綁定并禁止進(jìn)行可能導(dǎo)致數(shù)據(jù)丟失的隱式轉(zhuǎn)換。編譯器默認(rèn)情況下使用 Option Strict Off。這非常重要的一個(gè)原因是 Office 對(duì)象的許多方法和屬性的返回類型為 Object,您必須顯式地將對(duì)象轉(zhuǎn)換為正確的類型,如下例所示: ' 使用 Ctype 將 Sheet1 返回的對(duì)象轉(zhuǎn)換成工作表。MsgBox(CType(ThisWorkbook.Worksheets("Sheet1"), Excel.Worksheet).Name)
聲明變量:在 VBA 中,可以使用 Option Explicit 語(yǔ)句來(lái)強(qiáng)制進(jìn)行顯式變量聲明。也可以通過(guò)選中 VBA IDE 選項(xiàng)中的 Require Variable Declaration(需要變量聲明)復(fù)選框來(lái)自動(dòng)設(shè)定這項(xiàng)功能,該復(fù)選框默認(rèn)情況下為未選中狀態(tài)。所有隱式聲明的變量都是 Variant 類型。
Visual Basic .NET 編譯器強(qiáng)制進(jìn)行顯式聲明,要求聲明每個(gè)變量。可以使用語(yǔ)句 Option Explicit Off 取消使用這項(xiàng)功能。所有隱式聲明的變量都是 Object 類型。當(dāng)將代碼從 VBA 復(fù)制并粘貼到 Visual Basic .NET 中時(shí),應(yīng)該考慮這一點(diǎn),因?yàn)?Variant 數(shù)據(jù)類型不再被支持,而且會(huì)被自動(dòng)轉(zhuǎn)換成 Object 數(shù)據(jù)類型。應(yīng)該顯式指定項(xiàng)目中所有已聲明變量的類型。
默認(rèn)屬性:在 Visual Basic .NET 中,僅支持具有參數(shù)的默認(rèn)屬性。而在 VBA 中,通過(guò)消除默認(rèn)屬性,鍵入代碼時(shí)可以使用快捷方式。例如: ActiveDocument.Tables(1).Cell(1, 1).Range = "Name"
當(dāng)將此代碼轉(zhuǎn)換到 Visual Basic .NET 時(shí),必須指定 Range 對(duì)象的默認(rèn)屬性,即 Text:
ThisApplication.ActiveDocument.Tables(1).Cell(1, 1).Range.Text = "Name"
請(qǐng)注意,不需要指出 Tables 對(duì)象的默認(rèn)屬性 Item,因?yàn)樵搶?duì)象具有索引參數(shù)。然而,如果包含所有默認(rèn)屬性,代碼將更易于閱讀:
ThisApplication.ActiveDocment.Tables.Item(1).Cell(1, 1).Range.Text _ = "Name"
ByVal、ByRef 參數(shù):在 VBA 中,默認(rèn)情況下“按引用”傳遞參數(shù)。而在 Visual Basic .NET 中,默認(rèn)情況下“按值”傳遞參數(shù)。當(dāng)準(zhǔn)備將代碼轉(zhuǎn)換到 Visual Basic .NET 時(shí),您可能需要檢查:所有方法都明確定義是按引用還是按值來(lái)傳遞參數(shù)。當(dāng)在沒(méi)有定義參數(shù)的情況下將代碼粘貼到 Visual Studio .NET IDE 中時(shí),ByVal 將被自動(dòng)添加到列表中的每個(gè)參數(shù)上。
枚舉:Visual Basic .NET 中的枚舉常量必須進(jìn)行完全限定。當(dāng)轉(zhuǎn)換 VBA 代碼時(shí),必須將完全限定的枚舉名稱添加到 Word 和 Excel 常量中。例如,在 Word VBA 中執(zhí)行搜索時(shí),可以使用 wd 常量指定 Selection 或 Range 的 FindWrap 值。給出了三個(gè)選項(xiàng):wdFindStop、wdFindAsk 和 wdFindContinue。在 VBA 中,您可以僅指定常量,因?yàn)槊杜e常量在項(xiàng)目中是全局有效的: Selection.Find.Wrap = wdFindContinue
而在 Visual Basic .NET 中,常量必須具有完全限定的枚舉名稱:
ThisApplication.Selection.Find.Wrap = Word.WdFindWrap.wdFindContinue
這看起來(lái)像是額外鍵入許多內(nèi)容,但如果您使用 Visual Studio .NET 的智能感知功能,定位和鍵入限定的常量就相當(dāng)容易,而且會(huì)使代碼更易于閱讀。如果您熟悉常量名稱,將會(huì)發(fā)現(xiàn)枚舉名稱與常量名稱通常完全匹配。在上面的示例中,兩者都包含 wdFind。要瀏覽可用枚舉,可以鍵入 Word.Wd 并滾動(dòng)智能感知下拉列表中的項(xiàng)目(鍵入 Excel.XL 以滾動(dòng) Excel 的可用枚舉列表)。
非零下限數(shù)組:在 VBA 中,數(shù)組維數(shù)的默認(rèn)下限為 0(零)。使用 Option Base,您可以將下限改為 1。在 Visual Basic .NET 中,不支持 Option Base 語(yǔ)句,并且每個(gè)數(shù)組維數(shù)的下限必須為 0。此外,不能使用 ReDim 聲明數(shù)組。當(dāng)使用 Visual Basic .NET 中的 Office 集合時(shí),請(qǐng)注意大多數(shù) Office 集合的數(shù)組下限從 1 開(kāi)始。
方法調(diào)用時(shí)括號(hào)的使用:在 VBA 中,當(dāng)調(diào)用子例程時(shí),括號(hào)在某些情況下是可選的,并且需要括號(hào)時(shí)有時(shí)很難想起使用括號(hào)。而在 Visual Basic .NET 中,在方法調(diào)用過(guò)程中,傳遞參數(shù)時(shí)需要使用括號(hào)。
Set 關(guān)鍵字:在 VBA 中,區(qū)分對(duì)象賦值和對(duì)象的默認(rèn)屬性賦值時(shí),需要使用 Set 關(guān)鍵字。由于 Visual Basic .NET 不支持默認(rèn)屬性,因此不需要使用 Set 關(guān)鍵字,也不再支持該關(guān)鍵字。以下示例說(shuō)明了這一變化: ' VBADim mySelection as SelectionDim myOtherSelection as StringSet mySelection = SelectionmyOtherSelection = Selection' Visual Basic .NETDim mySelection As Word.SelectionDim myOtherSelection As StringmySelection = ThisApplication.SelectionmyOtherSelection = ThisApplication.Selection.Text
數(shù)據(jù)訪問(wèn):Microsoft Visual Basic .NET 不支持?jǐn)?shù)據(jù)訪問(wèn)對(duì)象 (DAO) 和遠(yuǎn)程數(shù)據(jù)對(duì)象 (RDO) 數(shù)據(jù)源的數(shù)據(jù)綁定。為了向后兼容,支持 ActiveX? Data Objects (ADO) 數(shù)據(jù)綁定;但您可能會(huì)考慮轉(zhuǎn)換到 ADO.NET。有關(guān)詳細(xì)信息,請(qǐng)參閱
Comparison of ADO.NET and ADO。
將用戶窗體轉(zhuǎn)換成 Windows 窗體:VBA 用戶窗體不能被復(fù)制或?qū)氲?Visual Studio .NET 中。大多數(shù)情況下,您需要重新將窗體創(chuàng)建為 Windows 窗體。拖放控件與 VBA 中創(chuàng)建窗體時(shí)相同,但對(duì) Windows 窗體控件的事件處理程序的處理不同。獲得的許多新功能使創(chuàng)建窗體比以前更容易,例如: 控件鎖定現(xiàn)在成為可能,因此當(dāng)用戶調(diào)整窗體大小時(shí),控件將自動(dòng)調(diào)整尺寸并正確地進(jìn)行重定位。
使用 Windows 窗體使設(shè)置 Tab 鍵順序更容易。單擊 View(視圖)菜單上的 Tab Order(Tab 鍵順序)啟用 Tab 鍵順序。然后只要單擊首選順序中的每個(gè)控件。
創(chuàng)建內(nèi)嵌菜單是對(duì) VBA 中菜單創(chuàng)建的改善。
在 VBA 中,可以將窗體顯示為 vbModal 或 vbModeless。而在 Visual Basic .NET 中,ShowDialog 方法用于以模式方式顯示窗體;Show 方法用于以無(wú)模式方式顯示窗體。但是,請(qǐng)注意,盡管窗體將以無(wú)模式方式顯示,但在 Word 或 Excel 文檔中單擊時(shí),窗體將移至背景,這可能會(huì)使用戶產(chǎn)生疑惑。
Visual Basic .NET 中提供了許多新的窗體控件,例如數(shù)據(jù)輸入驗(yàn)證器、標(biāo)準(zhǔn)對(duì)話框、超鏈接標(biāo)簽、系統(tǒng)任務(wù)欄圖標(biāo)、面板、數(shù)字升降、迅速可設(shè)計(jì)樹(shù)視圖、幫助文件鏈接器以及工具提示擴(kuò)展程序等。
項(xiàng)目管理差異
當(dāng)開(kāi)始使用 Visual Basic .NET 來(lái)創(chuàng)建 Office 解決方案時(shí),您將注意到代碼在項(xiàng)目中的位置發(fā)生了改變。當(dāng)使用 VBA 創(chuàng)建 Office 解決方案時(shí),代碼位于 Word 模板、Word 文檔或 Excel 工作簿的模塊、用戶窗體和類模塊中。當(dāng)使用“Visual Studio Tools for Office”時(shí),代碼位于被編譯到程序集的類和 Windows 窗體中,并被 Word 或 Excel 文檔引用。
雖然 Visual Studio .NET IDE 具有增強(qiáng)功能,但在許多方面與 VBA IDE 相似。兩者都具有查看項(xiàng)目、模塊、窗體和參考的資源管理器。兩者都提供屬性窗口、工具箱、對(duì)象瀏覽器和調(diào)試功能。表 1 列出了管理項(xiàng)目時(shí)您可能會(huì)注意到的一些差異。
表 1:VBA 與 Visual Studio .NET IDE 之間的差異
VBA IDE Visual Studio .NET IDE
項(xiàng)目資源管理器包含當(dāng)前打開(kāi)的所有項(xiàng)目(模板、文檔和外接程序)的動(dòng)態(tài)列表。 解決方案瀏覽器包含打開(kāi)的解決方案中的一個(gè)或多個(gè)項(xiàng)目的靜態(tài)列表。
項(xiàng)目文件存儲(chǔ)在子文件夾中:用戶窗體、模塊和類模塊。 項(xiàng)目文件按字母順序存儲(chǔ)到子文件夾中,且不進(jìn)行分類。
在 Word 中,項(xiàng)目包含一個(gè)文件夾,該文件夾顯示共用模板的引用。在 Word 和 Excel 中,使用 Tools(工具)菜單中的 References(引用)命令來(lái)設(shè)置外部引用。
如果使用 Web 服務(wù)工具包創(chuàng)建 Web 引用,將為 Web 服務(wù)及其所有方法創(chuàng)建類。這些類位于類模塊文件夾中。
項(xiàng)目包含一個(gè)文件夾,該文件夾顯示使用 Projects(項(xiàng)目)菜單中的 Add Reference(添加引用)命令設(shè)置的引用。
如果創(chuàng)建 Web 引用,引用將位于 Web 引用文件夾中。
不同的項(xiàng)目文件具有不同的文件擴(kuò)展名:用戶窗體 (.frm)、類模塊 (.cls) 和模塊 (.bas)。 窗體、模塊和類模塊的項(xiàng)目文件具有相同的 .vb 擴(kuò)展名。支持文件具有其他擴(kuò)展名(.xml、.aspx 等)。
在 Word 模板或文檔的 VBA 解決方案中,ThisDocument 位于 Microsoft Word 對(duì)象文件夾中。
在 Excel 文檔的 VBA 解決方案中,ThisWorkbook 和工作表位于 Microsoft Excel 對(duì)象文件夾中。
Visual Basic .NET Word 項(xiàng)目包含 ThisDocument 代碼文件。
Visual Basic .NET Excel 項(xiàng)目包含 ThisWorkbook 代碼文件。
在使用 ActiveX 控件過(guò)程中,您將發(fā)現(xiàn)兩者之間的另一個(gè)不同之處。在 VBA 中,ActiveX 控件是頂級(jí)對(duì)象并支持智能感知。而在 Visual Basic .NET 中,必須使用“Visual Studio Tools for Office”中的 FindControl 方法為控件定義變量并將它們轉(zhuǎn)換成嚴(yán)格類型以便使用智能感知。
安全性差異
Microsoft .NET Framework 提供了 VBA 中沒(méi)有提供的安全功能。在 VBA 中,有三種基本的安全選項(xiàng):
在用戶計(jì)算機(jī)上將安全性設(shè)置成高并對(duì)代碼進(jìn)行數(shù)字簽名。
當(dāng)顯示宏病毒警告時(shí),讓用戶決定是否信任代碼。
將安全性設(shè)置成低以允許所有代碼運(yùn)行(包括惡意代碼)。請(qǐng)注意,應(yīng)從不使用第三種選項(xiàng)。
具有使用 Visual Basic .NET 創(chuàng)建的托管代碼擴(kuò)展功能的 Word 和 Excel 文檔不使用依賴于 Office 證書(shū)存儲(chǔ)的 Office 宏安全。它們?nèi)诤狭?Microsoft .NET Framework 1.1 中的標(biāo)準(zhǔn)安全功能,例如:
不再需要代碼簽名,因?yàn)?NET Framework 中有多種類型的安全措施,包括應(yīng)用程序目錄、嚴(yán)格命名、URL 等。
管理員可以使用標(biāo)準(zhǔn)工具來(lái)設(shè)置安全策略。安全策略必須向程序集授予完全信任,否則代碼不能運(yùn)行。
最終用戶無(wú)法更改 Word 或 Excel 中的安全選項(xiàng)來(lái)允許運(yùn)行未授予信任的代碼。如果最終用戶打開(kāi)帶有未授予信任代碼的文檔,代碼將不能運(yùn)行。
有關(guān)設(shè)置 .NET Framework 中安全措施的詳細(xì)信息,請(qǐng)參閱“Visual Studio Tools for Office”幫助主題“使用托管代碼擴(kuò)展的 Office 解決方案中的安全性”或參閱
An Overview of Security in the .NET Framework。
部署差異
部署 Visual Basic .NET 應(yīng)用程序與部署 VBA 應(yīng)用程序存在非常大的差異?!癡isual Studio Tools for Office”項(xiàng)目通常由兩個(gè)文件組成:包含編譯代碼的程序集和包含指向該程序集的自定義屬性的文檔(Excel 工作表或者是 Word 文檔或模板)。文檔和程序集被單獨(dú)進(jìn)行部署。與在文檔中嵌入代碼的許多 VBA 項(xiàng)目不同,在“Visual Studio Tools for Office”項(xiàng)目中,程序集可以存儲(chǔ)在共享的網(wǎng)絡(luò)位置中,也可以被復(fù)制到每個(gè)最終用戶的計(jì)算機(jī)中。在網(wǎng)絡(luò)位置中部署程序集的優(yōu)點(diǎn)在于更易于更新代碼,因?yàn)榫W(wǎng)絡(luò)共享中只有一份程序集。用戶可以修改和自定義自己的文檔,每次打開(kāi)文檔時(shí),可以訪問(wèn)更新后的程序集。這會(huì)自動(dòng)發(fā)生,無(wú)需用戶的參與。
轉(zhuǎn)換 VBA 代碼
本節(jié)介紹如何使用“Visual Studio Tools for Office”將 VBA 代碼轉(zhuǎn)換到 Visual Basic .NET,并列舉分別來(lái)自 Word 和 Excel 的兩個(gè)例子。中提供了這兩個(gè)例子的完整 Visual Basic .NET 代碼。
Word 中的 VBA 代碼示例
以下 Word 宏創(chuàng)建一個(gè)新樣式(如果該樣式不存在),然后將該樣式應(yīng)用到活動(dòng)文檔中所有左對(duì)齊的段落。
' VBAPrivate Sub Document_Open() Dim currentParagraph As Paragraph ' 調(diào)用 CreateStyle,傳遞樣式名稱和有關(guān)屬性。 CreateStyle "MyNewStyle", "Arial", 9.5, True, False, 0.5 ' 將樣式應(yīng)用到每個(gè)左對(duì)齊的段落。 For Each currentParagraph In ActiveDocument.Paragraphs If currentParagraph.Alignment = wdAlignParagraphLeft Then currentParagraph.Style = "MyNewStyle" End If Next currentParagraphEnd SubPrivate Function StyleExists(styleName As String) As Boolean Dim currentStyle As Style Dim stylePresent As Boolean stylePresent = False ' 檢查活動(dòng)文檔中是否存在該樣式。 For Each currentStyle In ActiveDocument.Styles If currentStyle.NameLocal = styleName Then stylePresent = True Exit For End If Next currentStyle ' 返回。 StyleExists = stylePresentEnd FunctionPrivate Sub CreateStyle(styleName As String, styleFontName As String, _ styleFontSize As Single, styleBold As Boolean, _ styleItalic As Boolean, Optional styleFirstLineIndent As Single, _ Optional styleSpaceBefore As Single) ' 檢查樣式是否已經(jīng)存在。 If Not StyleExists(styleName) Then ' 通過(guò)傳遞的屬性創(chuàng)建樣式。 ActiveDocument.Styles.Add styleName With ActiveDocument.Styles(styleName) .Font.Name = styleFontName .Font.Size = styleFontSize .Font.Bold = styleBold .Font.Italic = styleItalic .ParagraphFormat.FirstLineIndent = _ InchesToPoints(styleFirstLineIndent) .ParagraphFormat.SpaceBefore = _ InchesToPoints(styleSpaceBefore) .ParagraphFormat.Alignment = wdAlignParagraphLeft End With End IfEnd Sub 創(chuàng)建 Visual Basic .NET 項(xiàng)目
要轉(zhuǎn)換 VBA 代碼,必須使用“Visual Studio Tools for Office”在 Visual Studio .NET 中創(chuàng)建 Word 文檔項(xiàng)目。
要?jiǎng)?chuàng)建新的 Word 文檔項(xiàng)目
從 File(文件)菜單中,指向 New(新建),然后單擊 Project(項(xiàng)目)。
在 New Project(新建項(xiàng)目)對(duì)話框中,展開(kāi) Microsoft Office 2003 Projects(Microsoft Office 2003 項(xiàng)目),然后選擇 Visual Basic Projects(Visual Basic 項(xiàng)目)。
在 Templates(模板)窗格中,選擇 Word Document(Word 文檔)。
將項(xiàng)目命名為 Create Word Style(創(chuàng)建 Word 樣式),然后單擊 OK(確定)。
當(dāng)出現(xiàn) Microsoft Office Project Wizard(Microsoft Office 項(xiàng)目向?qū)Вr(shí),確保選擇了 Create new document(創(chuàng)建新文檔),然后單擊 Finish(完成)。
然后向 Word 文檔添加文本。
要向文檔添加文本
打開(kāi) Microsoft Office Word 2003 中的 Create Word Style.doc 文檔。
因?yàn)槟€沒(méi)有編譯該程序集,可能會(huì)出現(xiàn)一個(gè)警告,提示程序集名稱或程序集鏈接位置屬性被破壞。單擊 OK(確定)關(guān)閉警告。
添加多段文本,設(shè)置不同的段落對(duì)齊。例如,居中對(duì)齊標(biāo)題,左對(duì)齊一些段落并右對(duì)齊另一些段落。
保存并關(guān)閉 Word 文檔。
復(fù)制代碼
然后,必須將 VBA 代碼復(fù)制并粘貼到 Visual Studio .NET 的新 Word 文檔項(xiàng)目中。
要將 VBA 代碼復(fù)制并粘貼到 Word 項(xiàng)目中
在 Visual Basic .NET 項(xiàng)目中,定位 OfficeCodeBehind 類。
復(fù)制 Document_Open 子例程中的 VBA 代碼(不包括 Sub 和 End Sub 關(guān)鍵字)并粘貼到 ThisDocument_Open 方法中。
將完整的 StyleExists 函數(shù)和 CreateStyle 子例程復(fù)制并粘貼到 ThisDocument_Close 方法下面(未包含在此方法中)的 OfficeCodeBehind 類中。
請(qǐng)注意,某些對(duì)象(Style、ActiveDocument)具有藍(lán)色波浪下劃線,這說(shuō)明代碼中的這些對(duì)象存在問(wèn)題。還要注意,在粘貼代碼時(shí),ByVal 將自動(dòng)添加到函數(shù) StyleExists 的參數(shù)列表中,而不是添加到 CreateStyle 子例程的參數(shù)列表中。這是因?yàn)?CreateStyle 子例程具有需要默認(rèn)值的可選參數(shù),這將在本文后面介紹。
提示:您可能已經(jīng)注意到 Visual Studio .NET Tools(工具)菜單包含 Upgrade Visual Basic 6 Code(升級(jí) Visual Basic 6 代碼)菜單項(xiàng)。此工具將轉(zhuǎn)換 Visual Basic 6 語(yǔ)言差異;但是,“Visual Studio Tools for Office”使用 Microsoft Office Word 2003 主互用程序集 (PIA) 作為訪問(wèn) Word 對(duì)象模型的方法(托管代碼與 COM 互用的方式),而不能使用升級(jí)工具來(lái)解決。相反,問(wèn)題和警告將以注釋形式出現(xiàn)在整個(gè)代碼中。利用當(dāng)鼠標(biāo)指針懸停在含有藍(lán)色波浪線的文本上時(shí)出現(xiàn)的智能感知功能,將 VBA 代碼直接粘貼到 Visual Studio .NET IDE 中時(shí),也可以獲得同樣的信息。有關(guān) Office 主互用程序集的詳細(xì)信息,請(qǐng)參閱
Working with the Office XP Primary Interop Assemblies。
轉(zhuǎn)換代碼
將 VBA 代碼復(fù)制到新項(xiàng)目中后,就可以開(kāi)始轉(zhuǎn)換代碼了。
要在 Visual Basic .NET 中轉(zhuǎn)換代碼
在 StyleExists 函數(shù)的聲明語(yǔ)句中: Dim currentStyle as StyleDim stylePresent As BooleanstylePresent = False
Style 對(duì)象屬于 Word 命名空間,因此必須將其更改為 Word.Style 限定引用。也可以將 stylePresent 的聲明語(yǔ)句與將其賦值為 False 的語(yǔ)句合并成一個(gè)語(yǔ)句:
Dim currentStyle as Word.StyleDim stylePresent As Boolean = False
在 For Each 語(yǔ)句的第一行中: For Each currentStyle in ActiveDocument.Styles
在 VBA 中,ActiveDocument 是 Application 對(duì)象的成員。因?yàn)槭窃趹?yīng)用程序中直接編寫(xiě)代碼,所以自動(dòng)引用 Application 對(duì)象。在 VBA 中,您可以(但不是必須)寫(xiě)成 Application.ActiveDocument。
當(dāng)使用“Visual Studio Tools for Office”創(chuàng)建 Word 文檔項(xiàng)目時(shí),將創(chuàng)建 Word.Document (ThisDocument) 和 Word.Application (ThisApplication)。ActiveDocument 必須被更改為 ThisApplication.ActiveDocument。
提示:可以在整個(gè)代碼中通過(guò)執(zhí)行全局查找和替換操作來(lái)快速更改 ActiveDocument。 For Each currentStyle in ThisApplication.ActiveDocument.Styles 提示:如果只使用一個(gè)文檔,ThisDocument 也可以指活動(dòng)文檔。ThisDocument 實(shí)際上是指與程序集相關(guān)的文檔(創(chuàng)建“Visual Studio Tools for Office”項(xiàng)目時(shí)使用的文檔)。
在函數(shù)的最后一行中: StyleExists = stylePresent
可以使用關(guān)鍵字 Return 返回變量。將 StyleExists = 更改為 Return:
Return stylePresent
在 CreateStyle 子例程中: Private Sub CreateStyle(styleName As String, styleFontName As String, _ styleFontSize As Single, styleBold As Boolean, _ styleItalic As Boolean, Optional styleFirstLineIndent As Single, _ Optional styleSpaceBefore As Single )
可選參數(shù)后的逗號(hào)下面出現(xiàn)的藍(lán)色波浪線表明代碼中存在問(wèn)題。將鼠標(biāo)指針?lè)旁诓ɡ司€上,將會(huì)顯示工具提示“可選參數(shù)必須指定默認(rèn)值。”
為每個(gè)可選參數(shù)添加默認(rèn)值 0,如下例所示。
Optional ByVal styleFirstLineIndent as Single = 0, _Optional ByVal styleSpaceBefore As Single = 0)
請(qǐng)注意,當(dāng)可選參數(shù)被解析時(shí),將向每個(gè)參數(shù)自動(dòng)添加 ByVal。
提示:在 Visual Basic .NET 中,使用可選參數(shù)的首選方法是創(chuàng)建重載方法。有關(guān)詳細(xì)信息,請(qǐng)參閱
Overloaded Properties and Methods。
在設(shè)置 FirstLineIndent 的行中: ParagraphFormat.FirstLineIndent = _ InchesToPoints(styleFirstLineIndent)
InchesToPoints 方法是 Application 對(duì)象的成員。將方法更改為 ThisApplication.InchesToPoints。
ParagraphFormat.FirstLineIndent = _ ThisApplication.InchesToPoints(styleFirstLineIndent)
與此類似,在下一行中,將 InchesToPoints 方法更改為 ThisApplication.InchesToPoints。 ParagraphFormat.SpaceBefore = _ ThisApplication.InchesToPoints(styleSpaceBefore)
在下一行中: ParagraphFormat.Alignment = wdAlignParagraphLeft
需要完全限定 wdAlignParagraphLeft 常量的枚舉名稱:
ParagraphFormat.Alignment = _ Word.WdParagraphAlignment.wdAlignParagraphLeft
在 ThisDocument_Open 方法的變量聲明語(yǔ)句中: Dim currentParagraph As Paragraph
Paragraph 對(duì)象屬于 Word 命名空間,因此需要將其更改成 Word.Paragraph 限定引用,如下所示:
Dim currentParagraph As Word.Paragraph
在 For Each 語(yǔ)句中,向 ActiveDocument 添加 ThisApplication 限定符(如果已經(jīng)執(zhí)行了全局查找和替換操作,這可能已經(jīng)被更改): For Each currentParagraph In _ ThisApplication.ActiveDocument.Paragraphs
在下一行中: If currentParagraph.Alignment = wdAlignParagraphLeft Then
需要完全限定 wdAlignParagraphLeft 常量的枚舉名稱:
If currentParagraph.Alignment = _ Word.WdParagraphAlignment.wdAlignParagraphLeft Then
單擊 Build(生成)并選擇 Build Solution(生成解決方案)以生成解決方案。
當(dāng)再次打開(kāi) Word 文檔時(shí),您將發(fā)現(xiàn)所有左對(duì)齊的段落都被應(yīng)用了 NewStyle 樣式。
Excel 中的 VBA 代碼示例
以下 Excel VBA 宏創(chuàng)建一個(gè)新樣式(如果該樣式不存在),并將其應(yīng)用到一個(gè)單元格區(qū)域 (A1-C2)。
Private Sub Workbook_Open() Dim cellRange As Range Dim styleName As String Dim cellFormat As String cellFormat = "_($* #,##0.00_)" styleName = "NewStyle" ' 設(shè)置單元格區(qū)域 A1-C2。 Set cellRange = Range("A1:C2") ' 如果樣式不存在,則創(chuàng)建該樣式并為其設(shè)置格式。 If Not StyleExists(styleName) Then FormatStyle styleName, "Times New Roman", 9, cellFormat End If ' 對(duì)區(qū)域應(yīng)用樣式。 cellRange.Style = styleNameEnd SubFunction StyleExists(styleName As String) As Boolean On Error GoTo StyleExists_Err Dim blnStyleExists As Boolean ' 假定開(kāi)始時(shí)樣式不存在。 blnStyleExists = False ActiveWorkbook.Styles.Add (styleName)StyleExists_End: StyleExists = blnStyleExists Exit FunctionStyleExists_Err: Select Case Err.Number Case 1004 ' 錯(cuò)誤號(hào)為 1004,因此樣式存在。 blnStyleExists = True Case Else ' 處理其他情況。 End Select Resume StyleExists_EndEnd FunctionSub FormatStyle(styleName As String, styleFont As String, _ styleFontSize As Single, styleFormat As String) ' 設(shè)置樣式的格式。 With ActiveWorkbook.Styles(styleName) .Font.Name = styleFont .Font.Size = styleFontSize .NumberFormat = styleFormat End WithEnd Sub 創(chuàng)建項(xiàng)目
要轉(zhuǎn)換 VBA 代碼,必須使用“Visual Studio Tools for Office”在 Visual Studio .NET 中創(chuàng)建 Excel 工作簿項(xiàng)目。
要?jiǎng)?chuàng)建新的 Excel 工作簿項(xiàng)目
從 File(文件)菜單中,指向 New(新建),然后單擊 Project(項(xiàng)目)。
在 New Project(新建項(xiàng)目)對(duì)話框中,展開(kāi) Microsoft Office 2003 Projects(Microsoft Office 2003 項(xiàng)目),然后選擇 Visual Basic Projects(Visual Basic 項(xiàng)目)。
在 Templates(模板)窗格中,選擇 Excel Workbook(Excel 工作簿)。
將項(xiàng)目命名為 Create Excel Style(創(chuàng)建 Excel 樣式),然后單擊 OK(確定)。
當(dāng)出現(xiàn) Microsoft Office Project Wizard(Microsoft Office 項(xiàng)目向?qū)Вr(shí),確保選擇了 Create new document(創(chuàng)建新文檔),然后單擊 Finish(完成)。
然后需要向 Excel 工作簿添加文本。
要向工作簿添加文本
打開(kāi) Microsoft Office Excel 2003 中的 Create Excel Style.xls 工作簿。
因?yàn)槟€沒(méi)有編譯該程序集,可能會(huì)出現(xiàn)一個(gè)警告,提示程序集名稱或程序集鏈接位置屬性被破壞。單擊 OK(確定)關(guān)閉警告。
向 Excel 工作表的區(qū)域 A1-C2 中添加數(shù)值??梢韵蚱渌麊卧裉砑宇~外的文本以作為測(cè)試該代碼僅影響 A1-C2 區(qū)域的一種方法。
保存并關(guān)閉 Excel 工作簿。
復(fù)制代碼
然后需要將 VBA 代碼復(fù)制到新的 Excel 工作簿項(xiàng)目中。將復(fù)制除了 StyleExists 方法以外的所有代碼。
要將 VBA 代碼復(fù)制并粘貼到 Excel 項(xiàng)目中
在 Visual Basic .NET 項(xiàng)目中,定位 OfficeCodeBehind 類。
將 VBA 代碼中的 FormatStyle 子例程復(fù)制并粘貼到 ThisWorkbook_BeforeClose 方法下面(未包含在此方法中)的 OfficeCodeBehind 類中。
請(qǐng)注意,已自動(dòng)添加 ByVal 作為參數(shù)傳遞的默認(rèn)方式。
將 Workbook_Open 子例程中的 VBA 代碼復(fù)制到 Visual Basic .NET 項(xiàng)目的 ThisWorkbook_Open 方法中(不包括 Sub 和 End Sub 關(guān)鍵字)。
轉(zhuǎn)換代碼
將 VBA 代碼復(fù)制到新項(xiàng)目中后,就可以開(kāi)始轉(zhuǎn)換代碼了。
要轉(zhuǎn)換 Visual Basic .NET 中的代碼
在 FormatStyle 子例程的第一行中: With ActiveWorkbook.Styles(styleName)
ActiveWorkbook 對(duì)象屬于 Application 對(duì)象,因此必須添加 ThisApplication 限定符。
With ThisApplication.ActiveWorkbook.Styles(styleName)
另外,可以使用 ThisWorkbook 變量代替 ThisApplication.ActiveWorkbook。請(qǐng)注意,ThisWorkbook 可以不是指活動(dòng)工作簿;實(shí)際上它指的是與項(xiàng)目相關(guān)的工作簿。
在 VBA Workbook_Open 子例程的第一行中: Dim cellRange as Range
Range 對(duì)象屬于 Excel 命名空間;因此,需要將該對(duì)象限定成 Excel.Range。
稍微向下一點(diǎn),注意以下行:
cellRange = Range("A1:C2")
請(qǐng)注意,不支持 Set 關(guān)鍵字并已經(jīng)自動(dòng)從代碼中刪除該關(guān)鍵字。Range 屬性是 Worksheet 對(duì)象的成員。要使用 Worksheet 對(duì)象,請(qǐng)使用 Ctype 函數(shù)初始化對(duì)象變量。需要將 Range 屬性限定成 ThisApplication.Range。還可以將變量聲明及其賦值合并成一個(gè)語(yǔ)句:
Dim ThisWorksheet As Excel.Worksheet = _ CType(ThisWorkbook.Worksheets.Item("Sheet1"), Excel.Worksheet)Dim cellRange As Excel.Range = ThisWorksheet.Range("A1:C2")
更改其他聲明以包含變量賦值: Dim styleName As String = "NewStyle"Dim cellFormat As String = "_($* #,##0.00_)"
可以直接在 ThisWorkbook_Open 方法中添加結(jié)構(gòu)化異常處理以測(cè)試樣式是否存在,而不是調(diào)用 VBA 示例中的 StyleExists 函數(shù)。刪除 If 語(yǔ)句并鍵入以下代碼: ' 如果樣式不存在,則創(chuàng)建該樣式并為其設(shè)置格式。Try ThisApplication.ActiveWorkbook.Styles.Add(styleName)Finally FormatStyle(styleName, "Times New Roman", 9, cellFormat)End Try
單擊 Build(生成)并選擇 Build Solution(生成解決方案)以生成解決方案。
當(dāng)再次打開(kāi) Excel 工作簿時(shí),您將發(fā)現(xiàn)單元格區(qū)域 A1-C2 應(yīng)用了 NewStyle 樣式。
小結(jié)
在決定是否將 VBA 代碼轉(zhuǎn)換到 Visual Basic .NET 時(shí),應(yīng)該考慮兩者在安全性、部署和代碼維護(hù)等方面的差異,以及項(xiàng)目是否能從 Microsoft .NET Framework 提供的功能中受益。您需要根據(jù) Visual Basic .NET 中的語(yǔ)言變化來(lái)調(diào)整自己的代碼,重新將 VBA 用戶窗體創(chuàng)建為 Windows 窗體,并確保最終用戶的計(jì)算機(jī)上安裝有 .NET Framework 和 Office 2003 主互用程序集。在通過(guò)主互用程序集訪問(wèn) Word 和 Excel 對(duì)象模型時(shí),您需要更改代碼;但是對(duì)象模型相同,部分代碼不必進(jìn)行轉(zhuǎn)換。使用“Visual Studio Tools for Office”和本文提供的信息,您可以開(kāi)始將 Word 和 Excel 中的 VBA 代碼轉(zhuǎn)換到 Visual Basic .NET 中。
附錄
本節(jié)包含 Word VBA 和 Excel VBA 示例的完整 Visual Basic .NET 代碼。
Word 示例
' Visual Basic .NET' 當(dāng)文檔被打開(kāi)時(shí)調(diào)用。Private Sub ThisDocument_Open() Handles ThisDocument.Open Dim currentParagraph As Word.Paragraph ' 調(diào)用 CreateStyle,傳遞樣式名稱和有關(guān)屬性。 CreateStyle("MyNewStyle", "Arial", 9.5, True, False, 0.5) ' 將樣式應(yīng)用到每個(gè)左對(duì)齊的段落。 For Each currentParagraph In ThisApplication.ActiveDocument.Paragraphs If currentParagraph.Alignment = _ Word.WdParagraphAlignment.wdAlignParagraphLeft Then currentParagraph.Style = "MyNewStyle" End If Next currentParagraphEnd SubPrivate Function StyleExists(ByVal styleName As String) As Boolean Dim currentStyle As Word.Style Dim stylePresent As Boolean = False ' 檢查活動(dòng)文檔中是否存在該樣式。 For Each currentStyle In ThisApplication.ActiveDocument.Styles If currentStyle.NameLocal = styleName Then stylePresent = True Exit For End If Next currentStyle ' 返回 Return stylePresentEnd FunctionPrivate Sub CreateStyle(ByVal styleName As String, ByVal _ styleFontName As String, ByVal styleFontSize As Single, _ ByVal styleBold As Boolean, ByVal styleItalic As Boolean, _ Optional ByVal styleFirstLineIndent As Single = 0, _ Optional ByVal styleSpaceBefore As Single = 0) ' 檢查樣式是否已經(jīng)存在。 If Not StyleExists(styleName) Then ' 通過(guò)傳遞的屬性創(chuàng)建樣式。 ThisApplication.ActiveDocument.Styles.Add(styleName) With ThisApplication.ActiveDocument.Styles(styleName) .Font.Name = styleFontName .Font.Size = styleFontSize .Font.Bold = styleBold .Font.Italic = styleItalic .ParagraphFormat.FirstLineIndent = _ ThisApplication.InchesToPoints(styleFirstLineIndent). ParagraphFormat.SpaceBefore = _ ThisApplication.InchesToPoints(styleSpaceBefore). ParagraphFormat.Alignment = _ Word.WdParagraphAlignment.wdAlignParagraphLeft End With End IfEnd Sub
Excel 示例
' Visual Basic .NET' 當(dāng)工作簿被打開(kāi)時(shí)調(diào)用。Private Sub ThisWorkbook_Open() Handles ThisWorkbook.Open Dim ThisWorksheet As Excel.Worksheet = _ CType(ThisWorkbook.Worksheets.Item("Sheet1"), Excel.Worksheet) Dim cellRange As Excel.Range = ThisWorksheet.Range("A1:C2") Dim styleName As String = "NewStyle" Dim cellFormat As String = "_($* #,##0.00_)" ' 設(shè)置單元格區(qū)域 A1-C2。 cellRange = ThisApplication.Range("A1:C2") ' 如果樣式不存在,則創(chuàng)建該樣式并為其設(shè)置格式。Try ThisApplication.ActiveWorkbook.Styles.Add(styleName)Finally FormatStyle(styleName, "Times New Roman", 9, cellFormat)End Try ' 對(duì)區(qū)域應(yīng)用樣式。 cellRange.Style = styleNameEnd SubSub FormatStyle(ByVal styleName As String, ByVal styleFont As String, _ ByVal styleFontSize As Single, ByVal styleFormat As String) ' 設(shè)置樣式的格式。 With ThisApplication.ActiveWorkbook.Styles(styleName) .Font.Name = styleFont .Font.Size = styleFontSize .NumberFormat = styleFormat End WithEnd Sub