【C#】Excelの読み込みと書き込みをしてみる(その2)
おはようございます。
前回に引き続き、Excelの操作をやっていきます。
今回は Excelの操作後に、COMオブジェクトを解放しやすくするために
IDisposable を実装した Excel操作用クラスを作成しました。
プログラムは前回のものを流用します。
スポンサーリンク
プログラムの修正
クラス追加
ExcelManager.cs
using System; using System.Runtime.InteropServices; using Microsoft.Office.Interop.Excel; namespace SampleExcel { class ExcelManager : IDisposable { #region IDisposable Support /// <summary> /// 重複する呼び出しを検出するには /// </summary> private bool disposedValue = false; private Application _app = null; private Workbooks _books = null; private Workbook _book = null; private Sheets _sheets = null; private Worksheet _sheet = null; private Ranges _ranges = null; private Range _range = null; /// <summary> /// Excelを表示するかどうか(デフォルト非表示) /// </summary> private bool _application_visible = false; /// <summary> /// デフォルトコンストラクタ /// </summary> public ExcelManager() { _app = new Application(); _app.Visible = _application_visible; } /// <summary> /// ファイル名を指定 /// </summary> /// <param name="filePath"></param> public ExcelManager(String filePath) { _app = new Application(); _app.Visible = _application_visible; _books = _app.Workbooks; _book = _books.Open(filePath); _sheets = _book.Worksheets; _sheet = _book.ActiveSheet; } /// <summary> /// ファイル名、シート名を指定 /// </summary> /// <param name="filePath"></param> /// <param name="sheetName"></param> public ExcelManager(string filePath, string sheetName) { _app = new Application(); _app.Visible = _application_visible; _books = _app.Workbooks; _book = _books.Open(filePath); _sheets = _book.Worksheets; for (int sheetId = 1; sheetId <= _sheets.Count; sheetId++) { _sheet = _sheets[sheetId]; if (_sheet.Name == sheetName) { _sheet.Activate(); break; } } } /// <summary> /// セルレンジを指定して値を読み込む /// </summary> /// <param name="cell_range"></param> /// <returns></returns> public string ReadCellStringValue(string cell_range) { _range = _sheet.Range[cell_range]; if (_range.Value is string) { return _range.Value; } else if (_range.Value is double) { return ((double)_range.Value).ToString(); } return _range.Value; } /// <summary> /// セルに値を書き込みます /// </summary> /// <param name="cell_range"></param> /// <param name="value"></param> public void WriteValue(string cell_range, string value) { _range = _sheet.Range[cell_range]; _range.Value = value; } /// <summary> /// ファイルを保存します. /// </summary> /// <param name="isOverwrite"></param> public void SaveFile(bool isOverwrite) { if (isOverwrite) { _book.Save(); } else { System.Windows.Forms.OpenFileDialog ofDialog = new System.Windows.Forms.OpenFileDialog(); ofDialog.InitialDirectory = @"C:\wk\tmp"; ofDialog.RestoreDirectory = true; ofDialog.Title = "名前を付けて保存"; //ダイアログを表示する if (ofDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { _book.SaveAs(ofDialog.FileName); } } } /// <summary> /// COMオブジェクトの解放、破棄をする. /// </summary> /// <param name="disposing"></param> protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { // TODO: マネージ状態を破棄します (マネージ オブジェクト)。 } // 小さい単位から解放していく if (_range != null) { Marshal.ReleaseComObject(_range); } if (_ranges != null) { Marshal.ReleaseComObject(_ranges); } if (_sheet != null) { Marshal.ReleaseComObject(_sheet); } if (_sheets != null) { Marshal.ReleaseComObject(_sheets); } if (_book != null) { _book.Close(); Marshal.ReleaseComObject(_book); } if (_books != null) { _books.Close(); Marshal.ReleaseComObject(_books); } if (_app != null) { _app.Quit(); Marshal.ReleaseComObject(_app); } disposedValue = true; } } /// <summary> /// ファイナライザー /// </summary> ~ExcelManager() { // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。 Dispose(false); } /// <summary> /// 破棄します /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion } }
フォームの修正
using System; using System.Windows.Forms; namespace SampleExcel { public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// 参照ボタンクリック /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_file_Click(object sender, EventArgs e) { OpenFileDialog ofDialog = new OpenFileDialog(); ofDialog.InitialDirectory = @"C:\wk\tmp"; ofDialog.RestoreDirectory = true; ofDialog.Title = "対象ファイルを選択"; //ダイアログを表示する if (ofDialog.ShowDialog() == DialogResult.OK) { this.txb_file.Text = ofDialog.FileName; } } /// <summary> /// 書き込みボタンクリック /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_output_Click(object sender, EventArgs e) { try { // ファイルを指定して ExcelManager を生成 using (var excel = new ExcelManager(txb_file.Text)) { excel.WriteValue(txb_cell_range.Text, txb_value.Text); excel.SaveFile(true); } MessageBox.Show("書き込みました。", "Excelサンプル"); } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// <summary> /// 読み込みボタンクリック /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_input_Click(object sender, EventArgs e) { try { // ファイルを指定して ExcelManager を生成 using (var excel = new ExcelManager(txb_file.Text)) { // 指定した箇所の値を読み込み表示 MessageBox.Show(excel.ReadCellStringValue(txb_cell_range.Text), "Excelサンプル"); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } }
まとめ
フォームの方も大分すっきりしました。
エラー処理が完全ではないため、確実に Excel を終了出来るわけではありませんが、
IDisposable を実装したクラスを別途用意することで、using 構文が使えるようになり、usingブロックを抜けると自動的に開放してくれるので便利です。
次回は更に色々と試して見れたらと思います。
何かのお役に立てれば。
ではでは。
ディスカッション
コメント一覧
まだ、コメントがありません