【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ブロックを抜けると自動的に開放してくれるので便利です。
次回は更に色々と試して見れたらと思います。
何かのお役に立てれば。
ではでは。
ディスカッション
コメント一覧
まだ、コメントがありません