C#でExcelを読み書きするライブリとして、NetOffice、CLosedOffice、NPOIが有名ですが、この記事ではCLosedOfficeの基本的な使い方をサンプルを交えて紹介したいと思います。
直感的に理解していただけるよう、最初にクラスの構成(概要)を紹介し、その上でよく使われそうなメソッドやプロパティについて、出来るだけ短いサンプルを例に解説していきます。
ClosedXmlとは
Office の文書データをC#から扱えるようにするため、 Open XML SDK というライブラリがMicrosoftから提供されています。
EXCELに限らず、WordやPowerPoint の文書も扱えるがゆえに汎用的になりすぎていて、EXCEL文書を扱うにはコードが煩雑になるという弱点がありました。
その問題を解決するため、EXCELに特化して使いやすくしたライブラリが ClosedXml です。
MicrosoftがOpen XMLなので、こちらはClosed XML と名づけられました。
特長としては、NPOIと同じくOfficeがインストールされていなくてもExcelファイルが作成できるという点が挙げられます。
確かに使い勝手は良く、DataTableの内容を一発でEXCELに張り付けることが可能なのですが、既存のExcelブックを何度も書き換えるような用途では、けっこう考慮しないとすぐエラーになってしまいます。
特にDataTableを書き出す際は、Excel上の出力範囲に「名前」が自動的に登録されるため、一度開いて上書きする場合に既に「名前」が存在するというエラーになってしまいます。
Excel上でテンプレートを作って、そこにOpenXMLで上書きするという用途なら良いのですが、一旦それで書き出したExcelブックを再び読み込んで追加するような用途だとけっこう大変です。
そういう用途の場合は、NPOIを使った方が遥かに楽です。
逆に、DataTableで書き出す際は、Excel上に自動的にフィルターが挿入されるため、作成したEXCELで絞り込み表示したいとう場合はNPOI
よりも便利です。
インストール方法
Nugetでインストールが可能です。
Nugetの使い方が知りたい方は、こちらの記事をご覧ください。
Visual Studio のヘッダメニュー「ツール」⇒「Nuget パッケージマネージャ」⇒「ソリューションのNuGetパッケージの管理」で下記を表示して、Closed で検索すると表示されます。
後は、インストールしたいプロジェクトをチェックし、「インストール」ボタンをクリックすればOKです。
ClosedXMLのクラス構成(概要)
Excelには、ワークブック(いわゆる拡張子が xlsx のEXCELファイル)があって、その中に複数のシートが含まれています。
シートには行と列があり、行と列で示されるセルがあります。
ClosedXMLにも、それに対応するクラスがあり次の様な関係になっています。
では、それぞれのクラスにどのようなメソッドがあるかについて見ていきましょう。
ClosedXMLの場合、XLWorkBook⇒IXLWorkSheet⇒IXLCell というクラスの紐づけになっていますが、ワークシートの追加だけは IXLWorksheetsクラスのAddメソッドを使う必要があります。
操作するワークシートは XLWorkbookのWorksheet メソッドにシート番号かシート名を渡せば取得できます。
ワークシートを削除するのは、IWorkSheets かと思いきや、個々のワークシート(IXLWorksheet)に実装されているDeleteメソッドを使います。
セルへの値の代入と参照は object型のValue プロパティを使います。
おもしろいのは InsertTable というメソッドで、指定したセル位置にDataTableの中身を挿入してくれます。
機能別解説
では、個々の機能について解説していきます。
あくまでも実用本位であり、ClosetXMLを使ってExcelを読み書きするのに必要なものに限定していますので、全ての機能を網羅しているわけではないことをあらかじめご了承下さい。
それから、ClosetXML使う場合は、ソースのヘッダ部に下記の参照設定を記述しておいて下さい。
using System.IO;
using ClosedXML.Excel;
ちなみに、サンプルソースコードには _workBook という変数が登場しますが、これは new された IWorkbook のインスタンスが格納されているという前提です。
通常の使い方ではXLWorkbook のインスタンスを生成し、シートやセルを追加(又は変更)した後で、最後にファイルに保存することになりますので、そのインスタンスが格納されているものと解釈して下さい。
EXCELファイルの読み込み
EXCELブックをゼロから作りたい場合は、new XLWorkbook() と記述し、インスタンスを生成します。
新規作成してもシートは自動で作成されないので、必ずCreateSheetメソッドでシートを最低1枚は追加しておいて下さい。
一方、既存のEXCELブックを開きたい場合は、 WorkbookFactory.Create(ファイル名) と記述します。
//新規のExcelブックを作成する
XLWorkbook book = new XLWorkbook();
book.Worksheets.Add("Sheet1");
//既存のExcelブックを読み込む
XLWorkbook book = XLWorkbook(@"book1.xlsx");
CreateSheet の引数にシート名を指定していますが、省略することも可能です。
省略すると、追加した分だけ "Sheet0"、"Sheet1"、・・・・・ の名前でシートが作成されます。
EXCELファイルの保存
保存は XLWorkbookクラスの Save メソッド、又は SaveAs メソッドを使います。
//既存ファイルを開いた場合、ファイル名は指定しなくてよい
XLWorkbook book = XLWorkbook(@"book1.xlsx");
book.Save();
//ファイル名を指定して保存する場合(book1⇒book2)
XLWorkbook book = XLWorkbook(@"book1.xlsx");
book.SaveAs(@"book2.xlsx");
シートの追加
シートは IXLWorkbook の追加は Worksheets.Addメソッドを使います。
引数にシート名省略すると"Sheet"+連番で名前が付加されます。
ちなみに、連番は1から始まります。
//自動でシート名を付ける場合
_workBook.Worksheets.Add()
//明示的にシート名を指定する場合
_workBook.Worksheets.Add("Sheet1")
//DataTableの中身を使ってSheetDTという名前のシートを作成する場合
//引数の dt は任意のDataTable
_workBook.Worksheets.Add(dt,"SheetDT”)
おもしろいのは、Addメソッドの引数にDataTableを直接指定できることです。
この方法でシートを追加すると、次のようなシートが作成されます。
DataTableを張り付けた範囲には、第二引数で指定したシート名と同じ名前(今回はSheetDT)が割り当てされていますね。
この様に、OpenXMLのメソッドでDataTableを直接貼り付けると、その範囲には何らかの名前(指定しなければTable+連番)が付与されます。
既存のExcelブックを開いてDataTableの中身をシートに書き出す場合、事前にシートを削除しておく等の対処をしないと、次の様な重複エラーが出ますので、ご注意ください。
これは、任意のセルに ImportTable メソッドでDataTableを書き込む場合も同様で、2回目に書き込んだ時は名前が重複してしまい、エラーになります。
ClosedXMLを使って既存のExcelブックに編集を加える場合、こまごまとした考慮が必要になるので、あくまでもExcelブックへの書き出しだけに利用を限定する方が無難だと思います。
シートの取得
シートを取得する場合、_workBook.Worksheetの引数に、シート名又はシート番号を指定します。
//シート名を指摘して取得
_workBook.Worksheet("MySheet");
//シート番号を指定して取得
_workBook.Worksheet(3);
シートの削除
シートを削除するには、IXLWorksheet の Deleteメソッドを使います。
//指定したシート番号のシートをActiveにする
_workBook.Worksheet(3).Delete();
//指定したシート名のシートをActiveにする
_workBook.Worksheet("Sheet3").Delete();;
シートのアクティブ化
シートをアクティブにする場合、IXLWorksheet の SetTabActive を使います。
//指定したシート番号のシートをActiveにする
_workBook.Worksheet(3).SetTabActive();
//指定したシート名のシートをActiveにする
_workBook.Worksheet("Sheet3").SetTabActive();
現在アクティブになっているシート番号を取得するには、IXLWorksheet の TabActive プロパティを参照します。
IXLWorksheets クラスが ワークシートのコレクションになっているので、LINQを使って TabActive が true のものを取得します。
var sheet = _workBook.Worksheets.First(i => i.TabActive).Worksheet;
指定した位置のセルを取得(R1C1による指定)
IXLWorksheet クラスのCellメソッドに行番号、列番号を指定するだけです。
番号はExcelと同じく1から始まる数値になります。
//シート番号2のシートに対して、5行3列の位置にあるセルを取得
IXLWorksheet sheet = _workBook.Worksheet(2);
IXLCell cell = sheet.Cell(5, 3);
シート番号ではなく、シート番号で指定する場合は次の様になります。
//MySheetという名前のシートに対して、5行3列の位置にあるセルを取得
IXLWorksheet sheet = _workBook.Worksheet("MySheet");
IXLCell cell = sheet.Cell(5, 3);
指定した位置のセルを取得(A1形式による指定)
IXLWorksheet クラスの Cell メソッドにA1型式のアドレスを指定するだけです。
//シート番号2のシートに対して、C5の位置にあるセルを取得
IXLWorksheet sheet = _workBook.Worksheet(2);
IXLCell cell = sheet.Cell("C5");
セルから値を取得
セルから値を取得するには、IXLCellクラスのValueプロパティを使います。
object型なので、必要に応じて型変換が必要です。
//シート番号=1 の5行3列のセルから文字列を取得する例
IXLWorksheet sheet = _workBook.Worksheet(1);
string str = sheet.cell(5,3).Value.ToString();
セルに値を代入
セルに値を代入する場合は、IXLCellクラスのValueプロパティに値をセットするだけになります。
//シート番号=1 の5行3列のセルに、実数の12345.6を代入する例
IXLWorksheet sheet = _workBook.Worksheet(1);
sheet.cell(5,3).Value = 12345.6;
計算式については Value ではなく FormulaA1 プロパティ、又はFormulaR1C1を使います。
//シート番号=1 の5行3列のセルに、計算式 B3*E3+8 を代入する例
IXLWorksheet sheet = _workBook.Worksheet(1);
sheet.cell(5,3).FormulaA1 = "B3*E3+8";
セルのスタイル指定
セルのスタイルは、 IXLCell クラスの Style プロパティに様々な項目が用意されていますので、こちらを使います。
色の指定は 挙型のXLColor で指定します。
例えば赤色の場合、 XLColor.Red となります。
//セルの取得
IXLWorksheet sheet = _workBook.Worksheet(1);
IXLCell cell = sheet.cell(5,3);
//セルにスタイルを設定
cell.Value = "ABCDEFG"; //値の代入
cell.FormulaA1 = "B5*C3+3"; //計算式の代入
cell.Style.Border.BottomBorder = XLBorderStyleValues.DashDot; //セルの下部ボーダーの設定
cell.Style.Fill.BackgroundColor = XLColor.Red; //セルの背景色
セルのフォント設定
フォントについても Style の Font プロパティが用意されていて、様々な設定が可能です。
//セルの取得
IXLWorksheet sheet = _workBook.Worksheet(1);
IXLCell cell = sheet.cell(5,3);
//セルにフォントのスタイルを設定
cell.Style.Font.FontColor = XLColor.White; //文字色を設定
cell.Style.Font.Size = 12; //フォントサイズを設定
cell.Style.Font.Bold = true; //太字にする
まとめ
今回はOpenXML の基本的な使い方について解説しました。
NPOIと同様、ExcelをインストールしなくてもExcelブックが作成できるところが便利です。
Excelをインストールしなくてよい分、NPOIど同様にグラフなどを挿入することは出来ませんが、あらかじめExcelに数式やグラフを設定しておき、そこにOpenXMLでデータを張り付けて使う用途だと非常に便利に使えます。
特に Addメソッドで DataTable を簡単に張り付けることができ、しかも自動でフィルターまで付加される点は優れていると思います。
同じExcelブックを何度も読み書きする用途ではお薦め出来ませんが、出力の度にExcelブックを作り変えてもよく、またDataTableを多用するのであれば、OpenXML がお薦めです。