準備
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)