LoginSignup
4

More than 5 years have passed since last update.

C#でVBAから列挙できるCOMオブジェクトを作成する

Posted at

はじめに

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();
        }
    }
}

出来たオブジェクトの型

image.png
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

image.png

参考サイト(感謝!)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4