はじめに
C#でCOMコンポーネントを作成し、Microsoft Office のマクロでオブジェクトを列挙したいな (For Each ... Next) と思い立って、調べてみました。
COM のコード
「.NET クラスライブラリ」としてプロジェクトを作成し、アプリケーション>アセンブリ情報の「アセンブリをCOM参照可能にする」とビルド>出力の「COM相互運用機能の登録」を有効にします。GUID 値はツールで生成します。管理者として Visual Studio を実行してビルドすれば、その過程で COM を登録してくれます。尤も「COM コンポーネントをC#で作成しよう」と考えておられるプロフェッショナルの皆様には、COM の細かな説明を語る必要はないでしょう...
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace MyCOM
{
[Guid("1???????-????-????-????-????????????")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IPerson
{
string FirstName { get; }
string LastName { get; }
int Age { get; }
string GetInfo();
}
[Guid("2???????-????-????-????-????????????")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IPerson))]
public class Person : IPerson
{
public string FirstName { get; }
public string LastName { get; }
public int Age { get; }
public Person(string firstName, string lastName, int age)
{
FirstName = firstName;
LastName = lastName;
Age = age;
}
public string GetInfo() {
return string.Format("{0} {1} ({2})", FirstName, LastName, Age);
}
}
[Guid("3???????-????-????-????-????????????")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
public interface IPersons : IEnumerable
{
new IEnumerator GetEnumerator();
}
[Guid("4???????-????-????-????-????????????")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IPersons))]
public class Persons : IPersons
{
System.Collections.Generic.List<Person> _data = new List<Person>();
public Persons()
{
// SAMPLE DATA
_data.Add(new Person("なまえ", "みょうじ", 20));
_data.Add(new Person("名前", "苗字", 21));
}
public IEnumerator GetEnumerator()
{
return _data.GetEnumerator();
}
}
}
出来たオブジェクトの型
System.Collections.IEnumerator(非ジェネリックのほう)は、IEnumVARIANTを自動的にインプリメントしてくれるようです。
利用例
エクセルやワードのマクロから呼び出してみます。参照設定を忘れずに...
Sub Sample()
'
' Sample Macro
'
'
Dim persons As New MyCOM.persons
Dim item As MyCOM.Person
For Each item In persons
MsgBox item.GetInfo()
Next
End Sub
参考サイト(感謝!)
- Exposing an Enumerator from Managed Code to COM - LIM BIO LIONG さん
- オートメーション / コレクションオブジェクト - EternalWindows