はじめに
ExcelVBAはよく使っていたんですが、いかんせんレガシーだろうということで、ClosedXML+C#でいろいろやってみたので、そのメモ。
前提など
ClosedXMLは[こちら]より取得。
ClosedXML操作サンプル
ブックの読み込み・作成・保存
//新たなブックを作成
var workBook = new XLWorkbook();
//既存のブックを開く
var workBook2 = new XLWorkbook("C:\\work\\text.xlsx");
//ブックを保存する
workBook.SaveAs("C:\\work\\text3.xlsx");
注意点として、保存するときは、「new XLWorkbook()」するだけではだめで、シートがひとつでもないとエラーになるようです。
ワークシートの読み込み・作成
var workBook = new XLWorkbook();
//既存ワークシートを取得
var workSheet = workBook.Worksheet("sheet1");
//新たなワークシートを追加
var workSheet2 = workBook.Worksheets.Add("sheet2");
セルの参照など
var workBook = new XLWorkbook();
var workSheet = workBook.Worksheet("sheet1");
//sheet1のセルA1から値を取得します
var cellItem = workSheet.Cell(1, 1).Value;
//同様に”A1”形式指定で取得します
var cellItem2 = workSheet.Cell("A1").Value;
//値の取得には種々のメソッドが用意されているようです
var cellStr = workSheet.Cell(1, 1).GetString();
var cellInt = workSheet.Cell(1, 1).GetValue<int>();
Cell、Rangeの扱いはVBAなんかと同じですね。Range(Cell(1,1),Cell(2,2)) みたいな使い方もできるようです。
ちなみに、Valueで取得すると、object形式となるようで、対象のセルに設定される値が決まっている場合は、型指定して取得したほうが安全で扱いやすいかもしれません。
文字列検索、セルのアドレス・行列番号取得
var workBook = new XLWorkbook();
var workSheet = workBook.Worksheet("sheet1");
//シート内を文字列検索します
var resultCells = workSheet.Search("hoge");
foreach (var resultCell in resultCells)
{
//該当セルのアドレスを返却
Console.WriteLine(resultCell.Address);
//該当セルの行番号を返却
Console.WriteLine(resultCell.Address.RowNumber);
//該当セルの列番号を返却
Console.WriteLine(resultCell.Address.ColumnNumber);
}
Searchメソッドで文字列を検索し、結果が配列で帰ってきます。Linqも使えるので以下のような方法も可能。AddressメソッドでCell番地情報を取得します。
var resultCell = workSheet.Search("hoge").LastOrDefault().Address.RowNumber
シート内で入力されているセルから最終行・列を取得
var workBook = new XLWorkbook();
var workSheet = workBook.Worksheet("sheet1");
//最終行を取得
var lastRow = workSheet.LastRowUsed().RowNumber();
//最終列を取得
var lastCol = workSheet.LastColumnUsed().ColumnNumber();
VBAだと、「.End(xlDown)」とかで取得してたやつに近いかもしれないです。ループ処理で制御するために使うことになりそうです。
シート内から範囲をテーブル形式で取得
var workBook = new XLWorkbook();
var workSheet = workBook.Worksheet("sheet1");
//値が入力されている範囲をテーブル形式で取得
var tbl = workSheet.RangeUsed().AsTable();
//取得結果を行単位でループ
foreach(var rowData in tbl.Rows())
{
//列単位でループ
foreach(var cellData in rowData.Cells())
{
Console.WriteLine(cellData.Address);
Console.WriteLine(cellData.Value);
}
}
AsTableメソッドでテーブルイメージで一気に値を取得できます。そのあとは行列をループ制御したり、直接セルにアクセスしたりもできるようです。一回でまとめて情報を取得できるので、処理スピードが速くなるかもしれないです。
ちなみに、以下のように範囲を指定して取得することもできます。
var tbl = workSheet2.Range("A1:B3").AsTable();
使いこなすとかなり便利かもしれないです。
おわり