V4 V5

請求書や報告書のように見た目が決まっている帳票は、レイアウトをコードで組み立てるより、 Excel で作ったテンプレートを読み込んで値だけ差し込むほうが確実です。 罫線・フォント・列幅・印刷設定はテンプレートが持ったまま往復します。

この方法は画面を必要としません。サーバー上のバッチ処理でもそのまま動きます (ヘッドレスで使う)。

1. テンプレートを Excel で作る

通常どおり Excel で作り、.xlsx で保存します。

差し込む場所は空欄にしておき、書式だけ設定しておきます。金額セルに #,##0、 日付セルに yyyy/mm/dd を設定しておけば、コードからは数値を入れるだけで済みます。

印刷の用紙・余白・印刷範囲も Excel 側で設定しておきます。PrintSettings として 読み込まれ、PDF 出力にそのまま効きます(印刷とページ設定)。

2. 読み込んで差し込む

using unvell.ReoGrid.Core;
using unvell.ReoGrid.IO.Excel;
using unvell.ReoGrid.IO.Pdf;

// テンプレートは書式・罫線・数式・印刷設定を持ったまま読み込まれる
Workbook wb = XlsxReader.Read("invoice-template.xlsx");
Worksheet ws = wb[0];

ws.SetText(1, 4, "2026-08-19");                 // E2 発行日
ws.SetText(3, 0, "株式会社サンプル 御中");        // A4 宛名

XlsxWriter.Write(wb, "invoice-0001.xlsx");
PdfExporter.Export(wb, "invoice-0001.pdf");

読み込みは書式を保ったまま行われます。SetText / SetNumber はセルの値だけを 変えるため、テンプレートで設定した書式・罫線・表示形式はそのまま残ります。

3. 位置は定義名で指定する

行番号を直接書くと、テンプレートに 1 行足しただけでコードが壊れます。 Excel 側で範囲に名前を付けておき、名前で引いてください。

Workbook wb = XlsxReader.Read("invoice-template.xlsx");
Worksheet ws = wb[0];

// テンプレート側で定義しておいた名前で位置を指定する。
// レイアウトを変えても、コードを直す必要がない
RangePosition body = ws.ResolveRange("明細");

var lines = new[]
{
	("設計費", 400_000d),
	("実装費", 850_000d),
	("保守費", 120_000d),
};

for (int i = 0; i < lines.Length; i++)
{
	ws.SetText(body.Row + i, body.Col, lines[i].Item1);
	ws.SetNumber(body.Row + i, body.Col + 1, lines[i].Item2);
}

Excel での定義は「数式」タブ →「名前の定義」です。XLSX の定義名はそのまま読み込まれます (定義名)。

これでテンプレートの行を増やしても、名前が同じ範囲を指していればコードは無変更です。

4. 出力する

XlsxWriter.Write(wb, "invoice-0001.xlsx");     // Excel で開ける
PdfExporter.Export(wb, "invoice-0001.pdf");    // そのまま配布・印刷できる

PDF は日本語フォントを埋め込むため、フォントが入っていない Linux サーバーでも 文字化けしません(PDF 出力)。

テンプレートをアプリに埋め込む

テンプレートファイルを別途配布したくない場合は、プロジェクトの埋め込みリソースにします。

// テンプレートをアセンブリに埋め込んでおけば、配布はアプリ 1 つで済む
Workbook wb = XlsxReader.Read(templateStream);

.csproj 側:

<ItemGroup>
  <EmbeddedResource Include="Templates\invoice-template.xlsx" />
</ItemGroup>
using Stream s = typeof(Program).Assembly
    .GetManifestResourceStream("MyApp.Templates.invoice-template.xlsx")!;
Workbook wb = XlsxReader.Read(s);

明細の行数が可変のとき

明細が 3 行のときと 30 行のときがある帳票では、テンプレートに十分な行数の書式を 用意しておき、余った行を隠すのが最も簡単です。

for (int r = body.Row + lines.Length; r <= body.EndRow; r++)
    ws.Rows.SetHidden(r, true);

非表示行は印刷・PDF でも高さ 0 として扱われ、紙にも出ません (行と列)。

行を挿入して増やすこともできますが、挿入した行は上の行の書式を引き継がないため、 罫線の設定が別途必要になります。隠すほうを勧めます。

テンプレートで使えないもの

XLSX から読み込めないものは、テンプレートに入れても失われます。

  • チャート・図形・テキストボックス — V5 は未対応
  • ピボットテーブル — V5 は未対応
  • スレッド形式のコメント — 従来の「メモ」は往復します
  • 共有数式 — 展開に未対応

対応状況は XLSX 対応状況 にまとめてあります。 ロゴなどの画像は読み込めます画像)。

次に読む

ページの内容は役に立ちましたか?