Excel帳票出力
業務システムやWindowsアプリから、Excel形式(またはExcelを経由したPDF等)の帳票を作成すること。
Excelレポート出力
テンプレート差し込み方式
帳票の見た目・数式・印刷設定をExcelテンプレート側に持たせ、コードは名前付き範囲やテーブルへのデータ差し込みに徹する帳票出力方式。
テンプレート+直接生成
Excel COM自動化(Excel COM Interop)
C#などの外部プログラムからCOM経由でExcelアプリケーション本体を起動・操作する自動化方式。
.xlsx直接生成
Excelを起動せず、Open XML形式の.xlsxファイルをライブラリでプログラム側から直接組み立てる帳票出力方式。
Excelファイル直接生成
サーバーサイドのOffice自動化
ASP.NET、DCOM、NTサービスなど無人・非対話のクライアントアプリケーションやコンポーネントからOfficeアプリを自動操作すること。Microsoftは推奨せずサポートもしないと明言している。
無人・非対話のOffice Automation
ClosedXML
Open XML APIの上にブック・シート・セルという直感的なAPIを被せた、Excelのインストールなしに.xlsx/.xlsmを扱えるMITライセンスのOSSライブラリ。
Open XML SDK
ECMA-376/ISO・IEC 29500として標準化されたOfficeのファイル形式を、Excel本体を起動せずに強く型付けされたクラスで読み書きできるMicrosoft製ライブラリ。
NPOI
JavaのApache POIを.NETへ移植した、.xlsの古い形式も扱えるApache License 2.0のOSSライブラリ。
EPPlus
高機能な.NET向けExcel操作ライブラリ。バージョン5以降はPolyform Noncommercialまたは商用ライセンスで、商用利用には有償ライセンスが必要になる。
名前付き範囲
Excelでセルやセル範囲に付けられる名前で、セル番地の代わりにこの名前を通してデータの差し込み先を指定できる。
テーブル(ListObject)
Excelの「テーブルとして書式設定」で作る構造。行を追加すると書式と数式が自動で伸びるため、明細の入口に向く。
Excelテーブル
Binder層
名前付き範囲やテーブルへ、ReportModelの値をTemplateの複製ブックへ書き込む層。ビジネス判断を持ち込まない。
Binderレイヤー
ReportModel層
帳票に必要な値を、セル番地を知らない形で整形して保持する層。DB/API/ファイルなどの生データを受け取る。
Template層
帳票の見た目・数式・印刷設定・グラフを持つ.xlsx/.xlsmのテンプレートそのものを表す層。DBや業務ロジックを知らない。
Templateレイヤー
Finisher層
必要なときだけVBA呼び出し・COM自動化・PDF化などを行う、Binderの後段に位置する層。元データ取得は行わない。
Finisherレイヤー
一時ファイル経由の安全な保存パターン
出力先へ直接書かず、同じフォルダーの一時ファイルへ書き切ってからFile.Moveで本来のファイル名へ付け替える保存方式。
途中で切れたファイルの残留リスク
出力先へ直接書き込んでいる途中でディスク満杯や共有切断などにより失敗すると、業務上のファイル名のまま不完全なファイルが残ってしまうリスク。
FileMode.CreateNew
指定したパスに既にファイルがある場合はIOExceptionを送出し、新規作成に失敗させる.NETのFileModeオプション。
同名ファイルの黙った上書きリスク
既に同名の帳票ファイルが存在するときに、それと気づかず上書きしてしまうリスク。
明細あふれの例外化
テンプレートに用意した明細行数を明細件数が超えたとき、黙って切り捨てず例外を送出して処理を止める実装方針。
明細の黙った切り捨てリスク
テンプレートの用意行数を超えた明細データが、エラーにならないまま切り捨てられて失われるリスク。
セル番地の業務仕様化
Cells[12, 7]のようなセル番地に業務ルールを直接埋め込む実装。レイアウト変更がそのまま仕様変更になり壊れやすい。
Cells[row, col]直書き
Excel 1シートの上限(1,048,576行×16,384列)
Excelの1ワークシートが持てる最大行数・列数の上限。明細が大きい場合はシート分割やファイル分割を先に決めておく必要がある。
Excelの行数・列数上限
Microsoft Graph Excel API
OneDrive/SharePoint上のExcelファイルをWeb/モバイルアプリなどから操作するMicrosoft Graphのブック・グラフ操作API。
既存VBA資産を残す方式
既存の.xlsmやVBAマクロをブック側の振る舞いとして残し、データ取得や業務処理はC#/.NET側に分担させる帳票出力方式。
VBA併用方式
Excel帳票出力の実装方式の1つとして、Excelアプリを実際に起動して操作するCOM自動化がある。
Excel帳票出力の実装方式の1つとして、Excelを起動せず.xlsxを直接組み立てる直接生成がある。
利用者があとでExcelを開いて編集する帳票では、テンプレート差し込み方式が第一候補として推奨される。
Excel COM自動化をサーバーサイドのOffice自動化に用いることは、Microsoftが推奨せずサポートもしないと明言している。
本記事のサンプル実装では、テンプレート差し込み方式をClosedXMLで開いたテンプレートへ名前付き範囲経由で値を書き込む形で実装している。
ClosedXMLはOpen XML SDKの上に、ブック・シート・セルという直感的なインターフェイスを提供するラッパーである。
xlsx直接生成をOpen XML SDKで実装する場合、ワークブック・シート・セル・スタイル・テーブルを直接操作する。4つは比較表の選択肢で、通常はどれか1つを選ぶ
xlsx直接生成をMITライセンスのラッパーであるClosedXMLで実装することもできる。4つは比較表の選択肢で、通常はどれか1つを選ぶ
xlsx直接生成を、.xlsの古い形式も扱えるNPOIで実装することもできる。4つは比較表の選択肢で、通常はどれか1つを選ぶ
xlsx直接生成を高機能なEPPlusで実装することもできるが、バージョン5以降は商用利用にライセンス費用が必要になる。4つは比較表の選択肢で、通常はどれか1つを選ぶ
テンプレート差し込み方式では、コードは名前付き範囲を入口としてデータを書き込み、セル番地には依存しない。
テンプレート差し込み方式では、行が自動で伸びるテーブル(ListObject)を明細の入口として使える。
Binder層は、名前付き範囲へReportModelの値を書き込む。
Binder層は、テーブル(ListObject)へReportModelの値を書き込む。
Binder層は、名前と値の組をReportModel層から受け取ることを前提とする。
Binder層は、複製したTemplate層のブックが持つ名前付き範囲やテーブルへ書き込むことを前提とする。
Finisher層は、Binder層が値を書き込んだ後のブックを受け取ってPDF化やVBA呼び出しなどを行う。
Finisher層は、本当にExcelアプリの挙動(PDF化やマクロ呼び出し)が必要なときだけCOM自動化を使う。
同じフォルダーの一時ファイルへ書き切ってからFile.Moveで付け替えると、途中で失敗しても業務上のファイル名では不完全なファイルが残らない。
一時ファイルへの書き込みはFileMode.CreateNewで行い、想定外の同名ファイルへの上書きを避ける。
FileMode.CreateNewは既存ファイルがあるとIOExceptionを送出するため、同名ファイルを黙って上書きすることを防ぐ。
明細件数がテンプレートの用意行数を超えたときに例外を送出することで、明細が黙って切り捨てられるリスクを防ぐ。
Cells[12, 7]のようなセル番地を業務仕様として直書きすることは、レイアウト変更がそのまま仕様変更になるためExcel帳票出力には推奨されない。
大量の明細を扱う直接生成では、1シートの上限(1,048,576行×16,384列)を踏まえてシート分割・ファイル分割の方針を先に決める必要がある。
Microsoft Graph Excel APIはOneDrive/SharePoint上の共同利用に用途が限定され、ローカルPC上の任意ファイルを量産する一般解ではないため、多くの帳票出力には推奨されない。
既存VBA資産を残す方式では、VBA側と.NET側の境界を名前付き範囲で固定する。
既存VBA資産を残す方式では、VBA側と.NET側の境界をテーブル(ListObject)で固定する。
テンプレート差し込み方式の保存では、一時ファイル経由の安全な保存パターンで出力先ファイルを確定させる。
テンプレート差し込み方式の実装では、明細がテンプレートの用意行数を超えた場合に備えて明細あふれの例外化を行う。