D&DしたPDFファイルをSQL Serverに登録+プレビューする方法の記事の一部になります。
#4. C#:Excelファイル書き換え
Excelファイルのセル読取/書込処理の忘備録になります。
##1) C#でExcelファイルを書き換える方法
大きく分けて、下記の2つがあります。
-
Microsoft.Office.Interop.Excel
を使った COM 参照による方法 - オープンソースライブラリを使用する方法
##2) Microsoft.Office.Interop.Excelを使う方法
###メリット
- COM 参照なので、現行形式 (.xlsx) だけでなく、旧型式 (.xls)、CSV 形式 (.csv)、マクロ付きも利用可能です。
###デメリット
- 処理が遅い
- Excelのインストールが必須
- プロセス解放漏れのリスクがある
###サンプルコード
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
class ExcelManager : IDisposable
{
/// <summary>
/// Excel操作用オブジェクト
/// </summary>
private Application _application = null;
private Workbook _workbook = null;
private Worksheet _worksheet = null;
// Dispose処理は、下記のページを参考にしています。
// [アンマネージドリソースをDisposeパターンで管理する]
// (https://days-of-programming.blogspot.com/2018/04/dispose.html)
#region "IDisposable Support"
private bool disposedValue = false;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: Managed Objectの破棄
}
if (_workbook != null)
{
_workbook.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject(_workbook);
_workbook = null;
}
if (_application != null)
{
_application.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(_application);
_application = null;
}
disposedValue = true;
}
}
~ExcelManager()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion "IDisposable Support"
/// <summary>
/// Excelワークブックを開く
/// </summary>
public void Open()
{
try
{
// Excelアプリケーション生成
_application = new Application()
{
// 非表示
//Visible = true
Visible = false
};
// Bookを開く
_workbook = _application.Workbooks.Open(@"e:\book1.xlsx");
// 対象シートを設定する
_worksheet = _workbook.Worksheets["Sheet1"];
}
catch (Exception ex)
{
throw (ex);
}
}
/// <summary>
/// Excelワークブックをファイル名を指定して保存する
/// </summary>
/// <returns>True:正常終了、False:保存失敗</returns>
public bool SaveAs()
{
try
{
// ファイル名を指定して保存する
_workbook.SaveCopyAs(@"e:\book2.xlsx");
}
catch
{
return false;
}
return true;
}
/// <summary>
/// セル設定
/// </summary>
/// <param name="rowIndex">row</param>
/// <param name="columnIndex">col</param>
/// <param name="value">value</param>
public void WriteCell(int rowIndex, int columnIndex, object value)
{
// セルを指定
var cells = _worksheet.Cells;
var range = cells[rowIndex, columnIndex] as Range;
// 値を設定
range.Value = value;
// cell解放
Marshal.ReleaseComObject(range);
Marshal.ReleaseComObject(cells);
}
}
##参考
Excelファイルを C# と VB.NET で読み込む "正しい" 方法
アンマネージドリソースをDisposeパターンで管理する
Excel操作クラス
Excel操作クラス
##3) オープンソースライブラリを使用する方法
オープンソースライブラリとして EPPlus
を想定しています。
(当初は NPOI
を試用しましたが、透過図形がコピーできず、諦めました)
###メリット
- コア部分が Microsoft の純正ライブラリであるという安心感?
-
NPOI
よりも扱いやすい
###デメリット
- Open XML 規格用に作られたものであるため、旧形式ファイル (.xls) を読み込むことができない
###準備
メニューの [ツール] - [NuGet パッケージ マネージャー] から、「EPPlus」を検索してインストールします。
###サンプルコード
ExcelManagerEx.cs
using OfficeOpenXml;
class ExcelManagerEx
{
/// <summary>
/// Excel操作用オブジェクト
/// </summary>
private ExcelPackage _excelPackage = null;
private ExcelWorksheet _excelWorksheet = null;
/// <summary>
/// Excelワークブックを開く
/// </summary>
public void Open()
{
try
{
// Excelファイルを開く
var fileInfo = new FileInfo(@"e:\book1.xlsx");
_excelPackage = new ExcelPackage(fileInfo);
// シート名で参照
_excelWorksheet = _excelPackage.Workbook.Worksheets["Sheet1"];
}
catch (Exception ex)
{
throw (ex);
}
}
/// <summary>
/// Excelワークブックをファイル名を指定して保存する
/// </summary>
/// <param name="filename">ファイル名</param>
/// <returns>True:正常終了、False:保存失敗</returns>
public bool SaveAs(string filename)
{
try
{
var fileInfo = new FileInfo(filename);
_excelPackage.SaveAs(fileInfo);
}
catch
{
return false;
}
return true;
}
/// <summary>
/// セル書込(R1C1形式)
/// </summary>
/// <param name="row">row</param>
/// <param name="col">col</param>
/// <param name="value">value</param>
public void WriteCell(int row, int col, object value)
{
// 値を書込
_excelWorksheet.Cells[row, col].Value = value;
}
/// <summary>
/// セル書込("A1"形式)
/// </summary>
/// <param name="address">address("A1"形式)</param>
/// <param name="value">value</param>
public void WriteCell(string address, object value)
{
// 値を書込
_excelWorksheet.Cells[address].Value = value;
}
/// <summary>
/// セル読取(R1C1形式)
/// </summary>
/// <param name="row">row</param>
/// <param name="col">col</param>
/// <returns>セルの値</returns>
public object ReadCell(int row, int col)
{
// セル読取
return _excelWorksheet.Cells[row, col].Value;
}
/// <summary>
/// セル読取("A1"形式)
/// </summary>
/// <param name="address">address("A1"形式)</param>
/// <returns>セルの値</returns>
public object ReadCell(string address)
{
// セル読取
return _excelWorksheet.Cells[address].Value;
}
/// <summary>
/// レンジ読取(R1C1R2C2形式)
/// </summary>
/// <param name="rowFrom">row From</param>
/// <param name="colFrom">col From</param>
/// <param name="rowTo">row To</param>
/// <param name="colTo">col To</param>
/// <returns>レンジ</returns>
public object[,] ReadRange(int rowFrom, int colFrom, int rowTo, int colTo)
{
// レンジ読取
return (object[,])_excelWorksheet.Cells[rowFrom, colFrom, rowTo, colTo].Value;
}
/// <summary>
/// レンジ読取("A1:B2"形式)
/// </summary>
/// <param name="address">address("A1"形式)</param>
/// <returns>レンジ</returns>
public object[,] ReadRange(string addresso)
{
// レンジ読取
return (object[,])_excelWorksheet.Cells[addresso].Value;
}
}
test.cs
using System;
using System.Windows.Forms;
public partial class test: Form
{
public test()
{
InitializeComponent();
}
private void Btn1_Click(object sender, EventArgs e)
{
var excelEx = new ExcelManagerEx();
excelEx.Open();
// セル書込(R1C1形式)
excelEx.WriteCell(row: 1, col: 1, value : "test");
// セル書込("A1"形式)
excelEx.WriteCell(address: "A1", value: 3.1415926538);
// セル読取(R1C1形式)
var cellValue1 = excelEx.ReadCell(row: 1, col: 1);
// セル読取("A1"形式)
var cellValue2 = excelEx.ReadCell("A1");
// レンジ読取(R1C1R2C2形式)
var rangeValue1 = excelEx.ReadRange(rowFrom: 1, colFrom: 1, rowTo: 2, colTo: 2);
// レンジ読取("A1:B2"形式)
var rangeValue2 = excelEx.ReadRange("A1:B2");
// 2次元配列(0始まり)から要素を参照
var a = rangeValue2[0, 0]; // aには、3.1415926538が入る
// 名前を付けて保存する
if (excelEx.SaveAs(@"e:\book2.xlsx") == false)
{
MessageBox.Show("ファイルが既に開かれています。\n閉じてから、再試行してください。",
"エラー",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}