C#: Excelファイルを読み書きする (COM)

C#やVB.NETではExcelファイルを読み書きするのに COM (Microsoft.Office.Interop.Excel) を使用することができます。

  • ExcelがインストールされていないPCでは動作しない
  • 動作が遅い (裏でExcelを立ち上げるので、それだけで時間がかかる)
  • オブジェクトの解放漏れが1つでもあるとExcelのプロセスが残り続ける

という問題があるので、注意して使用してください。

タスクマネージャー

(Excelのプロセスが残っている例)

既存のExcelファイルを開いて値を書き込む例

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace ExcelTestForm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Execute();
        }

        private void Execute()
        {
            var path = @"c:\work\Book1.xlsx"; // 読み込むExcelファイル

            // Excelのオブジェクトはすべて変数に入れて、使用し終わったら解放を忘れないようにしてください。
            // また、excel.Workbooks.Open() などのようにドットを2回以上続けないでください。
            // (解放漏れが発生して、Excelのプロセスが残り続けるため)
            Microsoft.Office.Interop.Excel.Application excel = null;
            Microsoft.Office.Interop.Excel.Workbooks books = null;
            Microsoft.Office.Interop.Excel.Workbook book = null;
            Microsoft.Office.Interop.Excel.Sheets sheets = null;
            Microsoft.Office.Interop.Excel.Worksheet sheet = null;
            Microsoft.Office.Interop.Excel.Range cells = null;
            Microsoft.Office.Interop.Excel.Range range = null;
            try
            {
                excel = new Microsoft.Office.Interop.Excel.Application();
                excel.DisplayAlerts = false; // アラートを表示しない
                books = excel.Workbooks;
                book = books.Open(path); // Excelを開く (excel.Workbooks.Open() とすると解放漏れが起こるので×です)

                sheets = book.Worksheets;
                sheet = sheets[1]; // 最初のシート。book.Worksheets[1] とするのも×です。
                cells = sheet.Cells; // セル一覧のオブジェクト。
                range = cells[1, 1]; // 左上のセル(Range)。sheet.Cells[1, 1] とするのも×です。
                range.Value = "テスト"; // セルに値を書き込む
                book.Close(SaveChanges: true); // 保存して閉じる
                excel.Quit(); // Excelを終了する

                MessageBox.Show("処理が完了しました。");
            }
            catch (Exception)
            {
                if (book != null) book.Close(SaveChanges: false); // 閉じていなければ閉じる
                if (excel != null) excel.Quit(); // 終了していなければ終了

                MessageBox.Show("処理が失敗しました。");
            }
            finally
            {
                // 解放漏れがないようにしてください。
                FinalReleaseComObject(range);
                FinalReleaseComObject(cells);
                FinalReleaseComObject(sheet);
                FinalReleaseComObject(sheets);
                FinalReleaseComObject(book);
                FinalReleaseComObject(books);
                FinalReleaseComObject(excel);
            }
        }

        /// <summary>
        /// COMオブジェクトの参照を解放します。
        /// </summary>
        /// <param name="o"></param>
        private void FinalReleaseComObject(object o)
        {
            if (o != null) Marshal.FinalReleaseComObject(o);
        }
    }
}