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