未分類

C# Excel のファイルを扱う

準備

1. 参照設定を追加します。
– Microsoft Excel 14.0 Object Library
2. 以下のデータを D:\test.xlsx の Sheet1 シートに作成します。

A 列 B 列
パソコン 15000

デザイン

1. フォーム (Form1) にボタン (button1) を配置します。
2. フォーム (Form1) にリストボックス (listBox1) を配置します。

サンプルコード (C#)

// 名前空間の追加
using System.Runtime.InteropServices;
using XL = Microsoft.Office.Interop.Excel;

// コード
private void button1_Click(object sender, EventArgs e)
{
  XL.Application xlApp = new XL.Application();
  XL.Workbooks xlWorkbooks = xlApp.Workbooks;
  XL.Workbook xlWorkbook;
  XL.Sheets xlSheets;
  XL.Worksheet xlWorksheet;
  XL.Range xlName;
  XL.Range xlPrice;
  
  xlWorkbook = xlWorkbooks.Open(@"D:\test.xlsx",
  Type.Missing,
  Type.Missing,
  Type.Missing,
  Type.Missing,
  Type.Missing,
  Type.Missing,
  Type.Missing,
  Type.Missing,
  Type.Missing,
  Type.Missing,
  Type.Missing,
  Type.Missing,
  Type.Missing,
  Type.Missing);
  xlSheets = xlWorkbook.Worksheets;
  xlWorksheet = xlSheets["Sheet1"];
  xlName = xlWorksheet.Range["A1"];
  xlPrice = xlName.Offset[0, 1];
  
  listBox1.Items.Add(xlName.Value + "の値段は " + xlPrice.Value.ToString() + " です。");
  
  xlWorkbook.Close();
  xlApp.Quit();
  
  Marshal.ReleaseComObject(xlPrice);
  Marshal.ReleaseComObject(xlName);
  Marshal.ReleaseComObject(xlWorksheet);
  Marshal.ReleaseComObject(xlSheets);
  Marshal.ReleaseComObject(xlWorkbook);
  Marshal.ReleaseComObject(xlWorkbooks);
  Marshal.ReleaseComObject(xlApp);
}

解説

通常、VBA から Excel ファイルを扱うよりもコード量が多くなっています。これにはいくつかの理由があります。

Excel ファイルは、Workbooks オブジェクトの Open メソッドを使ってオープンしますが、C# からこのメソッドを呼ぶ際には、引数の省略ができないようです。そのため、不要な引数には、Type.Missing を指定しています。これだけで 14 個も指定しないといけませんので、コード量が多くなります。

そしてここからが一番重要なのですが、VBA と同じように C# から Excel ファイルを扱うと、Excel プロセスが解放されずに残ってしまいます。一般的に考えれば、Excel アプリケーションオブジェクトを作成した際に COM の参照カウンタが増え、Quit した際に、参照カウンタが減り、プロセスが消えそうですが、C# から Excel (COM) を扱う場合には、プロセスが消えません。

いろいろと実験したのですが、Excel アプリケーションオブジェクトだけでなく、Workbooks / Workbook / Sheets / Worksheet / Range オブジェクトを扱った際にも、参照カウンタが増えるようです。そのため、参照カウンタを確実に減らす必要があります。減らすために使うメソッドが Marshal クラスの ReleaseComObject メソッドです。

ReleaseComObject メソッドでオブジェクトの参照カウンタを減らすためには、Workbooks / Workbook / Sheets / Worksheet / Range オブジェクトを扱う際には、一度変数に代入しておく必要があります。このためにさらにコード量は多くなります。

Range オブジェクトについては、Offset による参照も同じように扱う必要があります。そのため、一つの起点から Offset により複数のセルを参照している場合でも、すべて Range オブジェクトの変数を作成して、ReleaseComOject を呼ぶ必要があります。

もちろん、ReleaseComObject を呼ぶ前にワークブックの Close と、アプリケーションの Quit は必ず必要です。

結果

動作確認環境

Visual Studio 2015 Professional (C# 6.0)

-未分類