LoginSignup
5
3

More than 3 years have passed since last update.

C# から参照設定なしで Excel を操作する

Last updated at Posted at 2019-06-08

はじめに

参照設定をしないだけで、Excel がインストールされていないと動作しません。

サンプル

Excel を開いて、別名で保存するだけです。
インスタンスの生成、プロパティの設定・取得、メソッドの呼び出しの一通りはあるので、後は応用かと。

Program.cs

using System;
using System.Reflection;
using System.Runtime.InteropServices;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            object app = null;
            object books = null;
            object book = null;
            try
            {
                app = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
                app.GetType().InvokeMember("DisplayAlerts", BindingFlags.SetProperty, null, app, new object[] { false });
                books = app.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, books, null);
                book = books.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, book, new object[] { @"c:\hoge.xlsx" });
                book.GetType().InvokeMember("SaveAs", BindingFlags.InvokeMethod, null, book, new object[] { @"c:\poge.xlsx" });
                book.GetType().InvokeMember("Close", BindingFlags.InvokeMethod, null, book, null);
                app.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, app, null);
            }
            finally
            {
                if (book != null && Marshal.IsComObject(book))
                {
                    Marshal.FinalReleaseComObject(book);
                    book = null;
                }
                if (books != null && Marshal.IsComObject(books))
                {
                    Marshal.FinalReleaseComObject(books);
                    books = null;
                }
                if (app != null && Marshal.IsComObject(app))
                {
                    Marshal.FinalReleaseComObject(app);
                    app = null;
                }
            }
        }
    }
}

おわりに

諸事情により、動作確認できないので、動かなかったらごめんなさい。

お知恵を拝借したい

せっかくなので、Application、Books、Book クラスを作って参照設定と同じ実装できるようにしようと思ったのですが、実装方法が分からず悩んでます。

各クラスのコンストラクタで、生成したインスタンスをクラス変数に格納しておいて、各メソッドでクラス変数の InvokeMember を呼び出す実装を考えました。
この場合、以下のように実装したのですが、 Workbooks のコンストラクタは呼ばれないため、Workbooks クラス内で、クラス変数に app.Workbooks の値を格納できないでいます。

困った
Applicationapp = new Application();
Workbooks books = app.Workbooks;
books.Open(@"c:hoge.xlsx");

以下の実装だと、処理する度に books と this のどっちを使うか判断せにゃならんし。。。
(※これも諸事情により動作確認できないので、そもそも動くかも分からないです。)

一応は考えてみた
public class Workbooks 
{
    private object books;
    public void Open(string path)
    {
        object o = this.books != null ? this.books : this;
        o.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, o, new object[] { path });
    }
}
5
3
3

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
5
3