Help us understand the problem. What is going on with this article?

VBAまたはVBSからCOM経由で使用できる.NETのライブラリの作成方法

More than 5 years have passed since last update.

このドキュメントではVBAやVBScriptからCOM経由で.NETの処理を実行する方法について記述する。

環境

・Visual Studio2008 Pro
・.NET Framework 2.0 を対象とする。
・32ビットのOffice2010

.NETを使用したクラスモジュールをCOMにする方法

1.Visual Studio 2008 を管理者権限で起動する。
 これはCOM登録時にレジストリを変更するため。

2.プロジェクトの追加で「.NET Framework 2.0」 と 「クラスライブラリ」を選択
5sban21z.png

3. ビルドにてプラットフォームのターゲットを「x86」または「x64」とする。
これは使用するExcelに合わせる。

1w04banj.png

4. ビルドにてCOM相互運用機能の登録にチェックをつける。
1w04banj.png

5. アプリケーションのアセンブリ情報で、「アセンブリをCOM参照可能にする」
1w04banj.png

6. 公開したいインターフェイスとその実態について以下のように記述する

using System.Runtime.InteropServices;
namespace NMeCabCom
{
    [ComVisible(true)]
    public interface INmcTagger
    {
        void Create();
        NmcNode[] Parse(string text);
    }

    [ClassInterface(ClassInterfaceType.None)]
    public class NmcTagger : INmcTagger
    {
        private MeCabTagger nmcab;
        public NmcTagger()
        {
        }

        public void Create()
        {
            MeCabParam p = new MeCabParam();
            p.DicDir = @"C:\dev\NMeCab\dic\ipadic";

            this.nmcab = MeCabTagger.Create(p);
        }

        public NmcNode[] Parse(string text)
        {
            List<NmcNode> result = new List<NmcNode>();
            if (this.nmcab == null)
            {
                return result.ToArray();
            }
            MeCabNode node = this.nmcab.ParseToNode(text);
            while (node != null)
            {
                result.Add(new NmcNode(node));
                node = node.Next;
            }
            return result.ToArray();
        }

    }
}

まず、公開するインターフェイスの直前に「ComVisible(true)」と記述する。

    [ComVisible(true)]
    public interface INmcTagger
    {
        void Create();
        NmcNode[] Parse(string text);
    }

そして、そのインターフェイスの実装部分はClassInterfaceType.Noneとする。

    [ClassInterface(ClassInterfaceType.None)]
    public class NmcTagger : INmcTagger

7. ビルドを行うことでCOMの登録まで行われる

インターフェイスの設計時に注意すべきこと。

・List<>などのジェネリック型はCOMとしては公開できない

・ClassInterfaceTypeにAutoDualを記述すると、インターフェイス不要にできるがすべきでない
http://msdn.microsoft.com/ja-jp/library/ms182205.aspx

・Uint、ULONG等のUnsignedの型をインターフェイスに使用してはいけない
COMとしては使用できても、VBAやVBSはUnsignedをサポートしていないので、ULONGなどのインターフェイスは使用できない。

・オブジェクトの配列は返えしてはいけない

以下のようなCOMのインターフェイスがあったとする。

    public interface INmcTagger
    {
        string GetModulePath();
        void Create(NmcParam p);
        NmcNode[] Parse(string text);
    }

このインターフェイスの場合、VBAやC#などの型を明示できるプログラミング言語では適切に処理できる

Dim ret As NmcNode()
ret = t.Parse("This is a pen.")

しかし、VBSの場合、型が明示できないため、Unknownとなり処理できなくなる。

Dim ret ' As NmcNode()
ret = t.Parse("This is a pen.")
WScript.Echo TypeName(ret) ' Unknownとなり、以降処理できない。

こういう場合は、配列を管理するインターフェイスを作成して、それを経由するようにする。

    public interface INmcNodeCollection
    {
        int Count { get; }
        NmcNode GetItem(int index);
    }

配列ではないオブジェクトを返した場合は、VBSでも処理ができる

set ret = t.Parse("This is a pen.")
For i = 0 To ret.Count- 1
  WScript.Echo TypeName(ret.GetItem(i))
  WScript.Echo ret.GetItem(i).Surface
Next

利用方法

開発環境以外の登録方法

.NET Frameworkのフォルダに存在するregasmを使用する。
作成したdllに対して /tlb と /codebase を付与してregasmを実行する。
regasmは各バージョンの.NETに存在する。

SET BIN=C:\Windows\Microsoft.NET\Framework\v2.0.50727

REM 登録
%BIN%\regasm  C:\dev\NMeCabCom\NMeCabCom\bin\Debug\NMeCabCom.dll /tlb /codebase

この際、以下のメッセージが出力される場合がある。

「RegAsm : warning RA0000 : 署名されていないアセンブリを /codebase を使用して登録すると、同じコンピュータにインストールされるその他のアプリケーションとの競合が生じる可能性があります。/codebase スイッチは署名されたアセンブリのみに使用できます。アセンブリに厳密な名前を付けて、再登録してください。」

これは、警告だけであり、COMの登録はされている。
この警告を消すには、プロジェクトの設定で「署名」→「アセンブリの署名」 厳密な名前のキーファイルを選択する必要がある。

1w04banj.png

依存するすべてのDLLが同様に厳密な名前を有しなければならないので気をつけること。

COMの削除方法

/tlb と /unregister を付与したregasmコマンドを実行後、ファイルを消すればよい。

regasm /tlb C:\dev\NMeCabCom\NMeCabCom\bin\Debug\NMeCabCom.dll  /unregister

ExcelVBAで利用する方法

参照設定してやれば、使用できるようになる
1w04banj.png

以下のようにインテリセンスが効く。
1w04banj.png

VBSからの利用方法

以下のようにCreateObjectを利用する。

set t = CreateObject("NMeCabCom.NmcTagger")

実際のサンプル

VBAやVBScriptで形態素解析を行う方法
http://qiita.com/mima_ita/items/bc2aeb060ee12d280d7b

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした