アプリケーションの作成 2
.NETマネージクラスのVBAへの公開
Word 2007またはExcel 2007のドキュメントレベルのカスタマイズを作成する場合、.NETで作成したマネージクラスをVBAに対して公開できます。この機能を利用することによって、VBAで作成されている既存のアプリケーションの一部を.NETで機能拡張することができます。また、基本的な部分を.NETで作成しておいて一部をユーザーがカスタマイズ可能なものとしてVBA部分に公開するといった利用方法にすることもできます。
他にも、基本的にはVBAで作成しておき、Webサービス連携やWPF/WCFなどの新しいユーザーエクスペリエンス・ワークフローを実現する機能のうち、使いたい部分だけを.NETで作成するといった使い道など、さまざまな方法を考えることができます。
相互運用用のプロジェクトの作成
さて、実際に利用するまでの手順ですが、1番重要なことはプロジェクトを作成するときの設定にあります。例えば、Excelブックのプロジェクトの場合はドキュメントの形式として「Excelマクロ有効ブック(*.xlsm)」を選択します。
既存のドキュメントをコピーする場合でも、*.xlsmファイルをコピー元に選択する必要があります。Wordの場合も同様に、マクロをサポートする文書をもとにプロジェクトを作成しておく必要があります。マクロをサポートしない文書などの場合、以降で説明する内容ができないので注意してください。
Officeのセキュリティ設定の変更
プロジェクトの作成が終わったら、今後の作業のためにプロジェクトを作成したフォルダ(サブフォルダを含む)を、Officeアプリケーションの信頼できる場所として登録する必要があります。これにはExcelなどのオプションのセキュリティセンターから設定するのが最も簡単です。
この設定をしておかないと、VBAとの連携の設定やその後のテストがうまくいかない場合があるので注意してください。具体的な方法についてはMSDNライブラリのチュートリアル : VBA から Visual Basic プロジェクトのコードを呼び出すの「文書の場所に対する信頼の付与」を参照してください。
VBAマクロの追加
セキュリティ設定が終了したら、作成したプロジェクトのWordやExcelファイルにVBAマクロを追加してください。ドキュメントにマクロプロジェクトが存在していることが重要なため、マクロの内容はなんでも構いません。
すでにVBAマクロを含んだ既存のドキュメントをベースにしている場合にはこの手順は必要ありません。この手順を実施しておかないと最終的にエラーになってしまうため注意してください。
VBA公開用クラスの作成
一通りの設定が完了したら、VBAに公開するクラスを作成します。作成するものはどんなものでも構いませんが、以下の2つのポイントがあります。
- Publicクラスであること
- 2つの属性をクラスに設定すること
また、C#で作成する場合にはCOMに公開する用のパブリックインターフェースの定義も必須となります。VB.NETの場合にはクラスに対して「Microsoft.VisualBasic.ComClass(True)」という属性を付与することで省略可能です。
これらを満たすサンプルのクラスは以下のようなものになります。上記に挙げた2つの属性として、インターフェースには「ComVisibleAttribute」を、クラスには「[ComVisible」と「ClassInterfaceAttribute」を追加しています。これらの属性はCOM相互連携をするときによく使われる属性で、VBAとの連携の際にも変わらず必要となります。おまじないのようなものですので、そのままの形で記憶してしまうと楽です。
using System.Runtime.InteropServices; namespace ExcelWorkbook1 { [ComVisible(true)] public interface IClass1 { void Test(); } [ComVisible(true)] [ClassInterface(ClassInterfaceType.None)] public class Class1 : IClass1 { public void Test() { System.Windows.Forms.MessageBox.Show("Hello World!"); } } }
クラスの作成が終了したら、ホスト項目に公開用の処理を記述します。ここでホスト項目とは、Excelの場合はSheet1やSheet2やThisWorkbook、Wordの場合はThisDocumentになります。このクラスのコードエディタを開き、以下のコードを追加します。
protected override object GetAutomationObject() { return new Class1(); }
なお、VB.NETでExcelブックなどのプロジェクトを作成した場合、ThisWorkbookクラス以外にはすでにGetAutomationObjectメソッドが実装されている(Designerクラスにホスト項目自身を返却する実装があります)ので注意してください。
VBA公開用のプロジェクトの設定
最後に、GetAutomationObjectメソッドを実装したホスト項目のプロパティ設定を変更します。ホスト項目のデザイナを開き、続けてプロパティウィンドウからC#の場合は「ReferenceAssemblyFromVbaProject」をtrueに、VB.NETの場合は「EnableVbaCollers」をTrueに設定します(VB.NETの場合、EnableVbaCollersプロパティをTrueに設定した段階で、ReferenceAssemblyFromVbaProjectプロパティもTrueに設定されます)。
![図10:ReferenceAssemblyFromVbaProjectプロパティの設定(C#) 図10:ReferenceAssemblyFromVbaProjectプロパティの設定(C#)](http://cz-cdn.shoeisha.jp/static/images/article/2481/2481_10.gif)
これら一連の設定と作業により、ExcelブックなどのマクロプロジェクトにはVSTO側からGetManagedClassメソッドが公開されます。このメソッドの引数にホスト項目と同じVBAのオブジェクトを渡すことでGetAutomationObjectメソッドの戻り値のオブジェクトを取得できます。このオブジェクトを通して.NETで作成したメソッドなどにアクセスでき、これによって相互運用を実現しています。
本稿で提供している「ReferenceVBA.zip」は、VBAとの相互連携に必要な一連の手順を実装したものになります。zipを展開し、「ReferenceVBA\ExcelWorkBook2\bin\Debug」の中にある「ExcelWorkbook2.xlsm」を実行します(場合によってはマクロの有効化が必要です)。Visual Basicマクロを起動し、図11にある「TestVBA」関数のようなVBAコードを記述すると、図11右側にあるメッセージダイアログが表示されます。
![図11:VBAからマネージクラスの呼び出し例 図11:VBAからマネージクラスの呼び出し例](http://cz-cdn.shoeisha.jp/static/images/article/2481/2481_11.gif)
また、方法は異なりますが、アプリケーションレベルのアドインの場合でも、VBAに対してマネージクラスを公開する方法が用意されています。こちらについてはMSDNライブラリのチュートリアル : アプリケーション レベルのアドインのコードを VBA から呼び出すを参照してください。さらに、マネージコードからVBAを呼び出す手立ても用意されています。こちらについてはMSDNライブラリのVBA とドキュメント レベルのカスタマイズの結合を参照してください。