合併 VBA 和文件層級自訂
您可以在屬於文件層級自訂一部分的 Microsoft Office Word 或 Microsoft Office Excel 文件中使用 Visual Basic for Applications (VBA) 程式碼。您可以從自訂組件呼叫文件中的 VBA 程式碼,或是將專案設定為允許文件中的 VBA 程式碼呼叫自訂組件中的程式碼。
**適用於:**本主題中的資訊適用於下列應用程式的文件層級專案:Excel 2013 和 Excel 2010、Word 2013 和 Word 2010。如需詳細資訊,請參閱依 Office 應用程式和專案類型提供的功能。
文件層級自訂中的 VBA 程式碼行為
在 Visual Studio 中開啟專案時,文件是以設計模式開啟。文件在設計模式中時,VBA 程式碼不會執行,因此您可以編輯文件和程式碼,而不執行 VBA 程式碼。
執行方案時,VBA 和自訂組件中的事件處理常式都會取得文件中所引發的事件,而導致兩組程式碼同時執行。您不能事先決定程式碼執行的先後順序,必須透過每個個案測試才能知道順序。如果兩組程式碼並未經過仔細地協調及測試,可能會產生無法預期的後果。
從自訂組件中呼叫 VBA 程式碼
您可以呼叫 Word 文件中的巨集,而且可以呼叫 Excel 活頁簿中的巨集和函式。若要這麼做,請使用下列其中一種方法:
在 Word 中,呼叫 Microsoft.Office.Interop.Word.Application 類別 (Class) 的 Run 方法。
在 Excel 中,呼叫 Microsoft.Office.Interop.Excel.Application 類別的 Run 方法。
在這兩個方法中,第一個參數會識別您希望呼叫的巨集或函式名稱,而剩下的選用參數則是指定要傳遞給巨集或函式的參數。第一個參數對於 Word 和 Excel 來說各有不同的格式:
對於 Word 來說,第一個參數可以是一個包含範本名稱、模組名稱和巨集名稱的任意組合字串。如果您指定文件名稱,則巨集必須位在與目前內容相關的文件中,程式碼才能加以執行 (不是任何文件中的巨集都可以執行)。
對於 Excel 來說,第一個參數可以是指定巨集名稱的字串、指出函式位置的 Range,或是已註冊之 DLL (XLL) 函式的註冊 ID。如果您傳送字串,該字串就會透過使用中工作表的內容進行評估。
下列程式碼範例說明如何從 Excel 的文件層級專案呼叫名為 MyMacro 的巨集。這個範例假設已在 Sheet1 中定義了 MyMacro。
Globals.Sheet1.Application.Run("MyMacro")
Globals.Sheet1.Application.Run("MyMacro", missing, missing, missing,
missing, missing, missing, missing, missing, missing, missing,
missing, missing, missing, missing, missing, missing, missing,
missing, missing, missing, missing, missing, missing, missing,
missing, missing, missing, missing, missing, missing);
注意事項 |
---|
如需使用全域 missing 變數來取代 Visual C# 中選擇性 (Optional) 參數的詳細資訊,請參閱撰寫 Office 方案中的程式碼。 |
會在文件層級自訂中的程式碼從 VBA
您可以為 Word 或 Excel 設定文件層級專案,如此文件中的 Visual Basic for Applications (VBA) 程式碼就能呼叫自訂組件中的程式碼。這在下列案例中十分有用:
您要在文件層級自訂中使用與同一份文件相關的功能,以擴充文件中現有的 VBA 程式碼。
您要將在文件層級自訂中開發的服務提供給使用者,讓他們在文件中撰寫 VBA 程式碼以存取服務。
Visual Studio 中的 Office 開發工具提供與應用程式層級增益集類似的功能。如果您正在開發增益集,可以呼叫來自其他 Microsoft Office 方案增益集的程式碼。如需詳細資訊,請參閱在應用程式層級增益集中呼叫其他 Office 方案的程式碼。
注意事項 |
---|
這項功能不適用於 Word 範本專案。它只適用於 Word 文件、Excel 活頁簿或 Excel 範本專案。 |
需求
在您啟用 VBA 程式碼以呼叫自訂組件之前,專案必須符合下列必要需求:
文件必須具備下列其中一項副檔名:
如果是 Word:.docm 或 .doc
如果是 Excel:.xlsm、.xltm、.xls 或 .xlt
文件必須已經包含了內含 VBA 程式碼的 VBA 專案。
文件中的 VBA 程式碼必須可以執行,而不需提示使用者啟用巨集。您可以將 Office 專案的位置加入至 Word 或 Excel 之 [信任中心] 設定中的信任位置清單,藉以信任要執行的 VBA 程式碼。
Office 專案必須至少包含一個公用類別,且該類別包含一個或多個要公開至 VBA 的公用成員。
您可以將方法、屬性,與事件公開至 VBA。您公開的類別可以是主項目類別 (例如適用 Word 的 ThisDocument,或是適用 Excel 的 ThisWorkbook 和 Sheet1) 或是其他在專案中定義的類別。如需主項目的詳細資訊,請參閱主項目和主控制項概觀。
啟用 VBA 程式碼以呼叫自訂組件
您可以使用兩種不同的方式,將自訂組件中的成員公開至文件中的 VBA 程式碼。
您可以將 Visual Basic 專案中的主項目類別成員公開至 VBA。若要執行這項操作,請在主項目 (也就是文件、工作表或活頁簿) 於設計工具中開啟時,於 [屬性] 視窗中將主項目的 EnableVbaCallers 屬性設定為 True。Visual Studio 會自動執行所有必要的工作,讓 VBA 程式碼呼叫類別的成員。
您可以將 Visual C# 專案裡任何公用類別中的成員,或是 Visual Basic 專案中非主項目類別中的成員,公開至 VBA。此選項可讓您更彈性地選擇要公開至 VBA 的類別,但是同時需要進行更多的手動設定。
若要這麼做,您必須執行下列主要步驟:
將類別公開至 COM。
覆寫專案裡主項目類別的 GetAutomationObject 方法,以傳回要公開給 VBA 的類別執行個體 (Instance)。
將專案中任何主項目類別的 ReferenceAssemblyFromVbaProject 屬性設定為 True。這樣會將自訂組件的型別程式庫嵌入組件,並將型別程式庫的參考加入文件的 VBA 專案中。
如需詳細指示,請參閱 HOW TO:公開程式碼給 Visual Basic 專案中的 VBA 和 HOW TO:公開程式碼給 Visual C# 專案中的 VBA。
EnableVbaCallers 和 ReferenceAssemblyFromVbaProject 屬性只能在設計階段在 [屬性] 視窗中使用,而無法在執行階段使用。若要檢視屬性,請在 Visual Studio 中開啟主項目的設計工具。如需在您設定這些屬性時 Visual Studio 所執行之特定工作的詳細資訊,請參閱主項目屬性所執行的工作。
注意事項 |
---|
如果活頁簿或文件尚未包含 VBA 程式碼,或文件中的 VBA 程式碼未受到信任無法執行,則在將 [EnableVbaCallers] 或 [ReferenceAssemblyFromVbaProject] 屬性設定為 [True] 時收到錯誤訊息。這是因為在這個情況下,Visual Studio 無法修改文件中的 VBA 專案。 |
使用 VBA 程式碼中的成員以呼叫自訂組件
在您設定好專案讓 VBA 程式碼呼叫自訂組件之後,Visual Studio 會將下列成員加入至文件的 VBA 專案中:
Visual Studio 會針對所有專案加入名為 GetManagedClass 的全域方法。
當您使用 EnableVbaCallers 屬性在 Visual Basic 專案中公開主項目類別成員時,Visual Studio 也會將名為 CallVSTOAssembly 的屬性加入至 VBA 專案中的 ThisDocument、ThisWorkbook、Sheet1、Sheet2 或 Sheet3 模組。
您可以使用 CallVSTOAssembly 屬性或 GetManagedClass 方法,存取您已在專案中公開至 VBA 程式碼的類別公用成員。
注意事項 |
---|
在開發與部署方案時,可以透過各種不同的文件來加入 VBA 程式碼。如需詳細資訊,請參閱將 VBA 程式碼加入至文件的方針。 |
使用 Visual Basic 專案中的 CallVSTOAssembly 屬性
使用 CallVSTOAssembly 屬性來存取加入至主項目類別的公用成員。例如,下列 VBA 巨集會呼叫名為 MyVSTOMethod 的方法 (會在 Excel 活頁簿專案的 Sheet1 類別中定義)。
Sub MyMacro()
Sheet1.CallVSTOAssembly.MyVSTOMethod()
End Sub
呼叫自訂組件時,這個屬性是比直接使用 GetManagedClass 方法更方便的方式。CallVSTOAssembly 會傳回物件,這個物件代表您公開至 VBA 的主項目類別。傳回的物件成員與方法參數會出現在 IntelliSense 中。
CallVSTOAssembly 屬性內含的宣告,與下列程式碼類似。此程式碼假定您已將名為 ExcelWorkbook1 的 Excel 活頁簿專案中的 Sheet1 主項目類別公開至 VBA。
Property Get CallVSTOAssembly() As ExcelWorkbook1.Sheet1
Set CallVSTOAssembly = GetManagedClass(Me)
End Property
使用 GetManagedClass 方法
若要使用全域 GetManagedClass 方法,請傳入 VBA 物件,這個物件會對應至包含您的 GetAutomationObject 方法覆寫的主項目類別。接著,請使用傳回物件來存取公開至 VBA 的類別。
例如,下列 VBA 巨集會呼叫名為 MyVSTOMethod 的方法 (會在名為 ExcelWorkbook1 的 Excel 活頁簿專案的 Sheet1 主項目類別中定義)。
Sub CallVSTOMethod
Dim VSTOSheet1 As ExcelWorkbook1.Sheet1
Set VSTOSheet1 = GetManagedClass(Sheet1)
VSTOSheet1.MyVSTOMethod
End Sub
GetManagedClass 方法具有下列宣告。
GetManagedClass(pdispInteropObject Object) As Object
此方法會傳回物件,代表公開至 VBA 的類別。傳回的物件成員與方法參數會出現在 IntelliSense 中。
將 VBA 程式碼加入至文件的方針
您可以在多個不同的文件複本中加入 VBA 程式碼,以呼叫文件層級自訂。
在開發與測試方案時,您會在 Visual Studio 中偵錯或執行專案,此時所開啟的文件可供您用來撰寫 VBA 程式碼 (亦即,建置輸出資料夾中的文件)。但是,任何加入至此文件的 VBA 程式碼會在下一次建置專案時被覆寫,因為 Visual Studio 會使用主要專案資料夾中的文件複本來取代建置輸出資料夾中的文件。
如果您想要在偵錯或執行方案期間,一併將加入至文件的 VBA 程式碼儲存起來,請將 VBA 程式碼複製到專案資料夾的文件中。如需建置處理序的詳細資訊,請參閱 建置 Office 方案。
在您準備好部署方案時,還有三個主要的文件位置可供您加入 VBA 程式碼。
在開發電腦上的專案資料夾
如果您對文件中的 VBA 程式碼與自訂程式碼擁有完全控制權,則這是最方便的位置。因為文件位於開發電腦上,如果您變更了自訂程式碼,還可以輕易地修改 VBA 程式碼。當您建置、偵錯與發行自己的方案時,加入至此文件複本的 VBA 程式碼會保留在文件中。
如果設計工具已經開啟此文件,則您無法將 VBA 程式碼加入其中。您必須先關閉設計工具中的文件,然後直接透過 Word 或 Excel 開啟文件。
警告 |
---|
如果在文件開啟時加入正在執行的 VBA 程式碼,在很罕見的情況中,此程式碼可能會損毀文件,或讓文件無法在設計工具中順利開啟。 |
在發行或安裝資料夾
在某些情況中,也許可以將 VBA 程式碼加入至發行或安裝資料夾中的文件。例如,如果是在尚未安裝 Visual Studio 的電腦上由不同的程式開發人員撰寫並測試 VBA 程式碼,則可以選擇這個選項。
如果使用者直接從發行資料夾安裝方案,每次在您發行方案時,都必須將 VBA 程式碼加入至文件中。Visual Studio 會在您發行方案時,覆寫發行位置中的文件。
如果使用者從不同於發行資料夾的安裝資料夾中安裝方案,則每次在您發行方案時,可以不必將 VBA 程式碼加入至文件中。當您準備將發行更新從發行資料夾移至安裝資料夾時,請將文件以外的所有檔案複製到安裝資料夾。
在使用者電腦上
如果使用者是 VBA 開發人員並且在文件層級自訂中呼叫您提供的服務,您可以告訴這些使用者如何使用 CallVSTOAssembly 屬性或是所擁有之文件複本中的 GetManagedClass 方法呼叫您的程式碼。當您發行更新至方案時,將不會覆寫使用者電腦上文件中的 VBA 程式碼,因為文件不是被發行更新所修改。
主項目屬性所執行的工作
當您使用 EnableVbaCallers 和 ReferenceAssemblyFromVbaProject 屬性時,Visual Studio 會執行不同的工作集。
EnableVbaCallers
當您在 Visual Basic 專案中將主項目的 EnableVbaCallers 屬性設定為 True 時,Visual Studio 會執行下列工作:
它會將 ComClassAttribute 和 ComVisibleAttribute 屬性加入至主項目類別中。
它會覆寫主項目類別的 GetAutomationObject 方法。
它會將主項目的 ReferenceAssemblyFromVbaProject 屬性設定為 True。
當您將 EnableVbaCallers 屬性設回 False 時,Visual Studio 會執行下列工作:
它會從 ThisDocument 類別移除 ComClassAttribute 和 ComVisibleAttribute 屬性。
它會從主項目類別移除 GetAutomationObject 方法。
注意事項 Visual Studio 不會自動將 ReferenceAssemblyFromVbaProject 屬性設回 False。您可以使用 [屬性] 視窗,手動將此屬性設定為 False。
ReferenceAssemblyFromVbaProject
當 Visual Basic 或 Visual C# 專案中任何主項目的 ReferenceAssemblyFromVbaProject 屬性設定為 True 時,Visual Studio 會執行下列工作:
它會產生自訂組件的型別程式庫,並將型別程式庫嵌入組件中。
它會將參考加入至下列型別程式庫 (屬於文件的 VBA 專案):
自訂組件的型別程式庫。
Microsoft Visual Studio Tools for Office Execution Engine 9.0 型別程式庫。此型別程式庫包含在 Visual Studio Tools for Office Runtime 中。
當 ReferenceAssemblyFromVbaProject 屬性設回 False 時,Visual Studio 會執行下列工作:
它會從文件的 VBA 專案中移除型別程式庫參考。
它會從組件移除內嵌的型別程式庫。
疑難排解
下表列出一些常見錯誤與修正錯誤的建議。
錯誤 |
建議 |
---|---|
在設定好 EnableVbaCallers 或 ReferenceAssemblyFromVbaProject 屬性後,會顯示一則錯誤訊息,告知文件不包含 VBA 專案,或是您沒有存取文件中 VBA 專案的權限。 |
請確定專案文件至少包含一個 VBA 巨集,VBA 專案擁有足夠的信任以便執行,以及 VBA 專案未受到密碼保護。 |
在設定好 EnableVbaCallers 或 ReferenceAssemblyFromVbaProject 屬性之後,會出現一則錯誤訊息,告知 GuidAttribute 宣告遺失或損毀。 |
請確定 GuidAttribute 宣告位於專案的 AssemblyInfo.cs 或 AssemblyInfo.vb 檔案中,而且此屬性已設為有效的 GUID。 |
在設定好 EnableVbaCallers 或 ReferenceAssemblyFromVbaProject 屬性之後,會出現一則錯誤訊息,告知 AssemblyVersionAttribute 指定了無效的版本號碼。 |
請確定位於專案的 AssemblyInfo.cs 或 AssemblyInfo.vb 檔案中的 AssemblyVersionAttribute 宣告已設為有效的組件版本號碼。如需有效的組件版本號碼詳細資訊,請參閱 AssemblyVersionAttribute 類別。 |
在重新命名自訂組件之後,呼叫自訂組件的 VBA 程式碼會停止運作。 |
如果您變更已公開至 VBA 程式碼的自訂組件名稱,則文件的 VBA 專案與自訂組件之間的連結就會中斷。若要解決這個問題,請將專案中的 ReferenceFromVbaAssembly 屬性變更為 False,然後再變更為 True,接著使用新的組件名稱取代 VBA 程式碼中舊組件名稱的任何參考。 |
請參閱
工作
HOW TO:公開程式碼給 Visual Basic 專案中的 VBA
HOW TO:公開程式碼給 Visual C# 專案中的 VBA
逐步解說:在 Visual Basic 專案中呼叫 VBA 的程式碼
逐步解說:在 Visual C# 專案中呼叫 VBA 的程式碼
概念
VBA 和 Office 方案 (在 Visual Studio 中) 比較