はじめに
今回実装するライブラリはすでにOSSとしてGitHubとNuGetに公開しています。そのライブラリを利用した帳票生成は今すぐに試すことができます。DioDocs自体がNuGetに公開されており、評価版の申し込みなしにある程度利用できるためです。これはうれしいですね。
さあ、それでは改めてDioDocsの世界へ足を踏み入れてみましょう!
本稿の構成
主に次の3つの内容を取り扱います。
- GitHubとNuGetに公開しているライブラリの紹介と設計の解説
- エンタープライズ領域において、DioDocsが.NET Standardをサポートする価値とは
- 汎用帳票ライブラリを組み込んだアプリケーション アーキテクチャ例の紹介
まずはNuGetで公開しているパッケージを利用して帳票生成するコードを紹介し、DioDocsを利用するとどれだけ簡単に帳票が生成できるか見ていただきます。また、ライブラリの実装を解説します。
続いて、前回の記事でも記載しましたが、いまひとつ正しく伝わりきっていなかったようなので、改めてDioDocsが.NET Frameworkではなく.NET Standardをサポートしている価値の大きさを、もう一歩踏み込んで説明したいと思います。
そして最後に、帳票生成を扱うアプリケーション全体のアーキテクチャ例について紹介します。1.の内容では帳票生成にフォーカスした狭い視点での解説になりますが、それを利用して実際のアプリケーションレベルでどのように取り込むべきか、その一例を示します。
そして、最初に種明かしをしましょう。「1.は.NET Frameworkで」「3.は.NET Coreで」そして「汎用帳票生成ライブラリは .NET Standardで」書かれています。そして、1.と3.から同じバイナリを利用しています。
ほら、興味をひかれませんか?
なお本稿のソースコードは、すべてこちらのリポジトリに公開しています。併せてご覧ください。
筆者について
私は普段、主に金融業界向けの受託開発のアーキテクトを務めています。このため本稿はエンタープライズ領域でのアプリケーション開発者の視点で記載しています。
本稿では.NET Standardや.NET Core、.NET Frameworkに対する今後の取り組み方の指針について触れますが、実務の領域が異なれば大きな考え方の相違が生じるかもしれません。仮にそうであっても、特定の分野から見るとそういう考えもあるものと捉えていただければ幸いです。
汎用帳票生成ライブラリの仕様
早速、DioDocsを利用した帳票生成ライブラリを見ていただきましょう。
完成イメージ
まずは下の図をご覧ください。
上図の左のExcelのテンプレートを用意し、下のコードを実行すると右の帳票が生成されます。
var reportBuilder = new ReportBuilder<InvoiceDetail>(template) // 単一項目のSetterを設定 .AddSetter("$SalesOrderId", cell => cell.Value = invoice.SalesOrderId) .AddSetter("$OrderDate", cell => cell.Value = invoice.OrderDate) .AddSetter("$CompanyName", cell => cell.Value = invoice.CompanyName) .AddSetter("$Name", cell => cell.Value = invoice.Name) .AddSetter("$Address", cell => cell.Value = invoice.Address) .AddSetter("$PostalCode", cell => cell.Value = invoice.PostalCode) // テーブルのセルに対するSetterを設定 .AddTableSetter("$ProductName", (cell, detail) => cell.Value = detail.ProductName) .AddTableSetter("$UnitPrice", (cell, detail) => cell.Value = detail.UnitPrice) .AddTableSetter("$OrderQuantity", (cell, detail) => cell.Value = detail.OrderQuantity); reportBuilder.Build(invoice.InvoiceDetails, outputStream, SaveFileFormat.Pdf);
ライブラリの利用者は、Excelのテンプレートと上のコード(とデータを生成するビジネスロジック)以外、何も用意する必要はありません。驚異的な生産性なのが見て取れるでしょう。
では、もう少し手順を追って解説していきます。
利用方法
まずは完成した帳票生成ライブラリを使って、どのように帳票を出力するのか見ていきましょう。
GitHubのこちらから完成したすべてのコードが確認できます。
まず .NET Frameworkのプロジェクトを作成し、NuGetから今回の対象となる帳票生成ライブラリ「DioDocs.FastReportBuilder」をインストールします。
次のようにPackage Managerからコマンドを入力してもいいですし、GUIからインストールしてもいいでしょう。
PM> Install-Package DioDocs.FastReportBuilder -Version 0.1.0
その上で帳票に表示する情報を保持した、次のような請求書クラスと請求明細クラスを作ります。
請求書クラスは複数の請求明細をListとして保持しています。実際のコードは次の通りです。
public class Invoice { public int SalesOrderId { get; set; } public DateTime OrderDate { get; set; } public string CompanyName { get; set; } public string Name { get; set; } public string Address { get; set; } public string PostalCode { get; set; } public List<InvoiceDetail> InvoiceDetails { get; } = new List<InvoiceDetail>(); } public class InvoiceDetail { public int OrderQuantity { get; set; } public int UnitPrice { get; set; } public string ProductName { get; set; } }
続いて次のような帳票のテンプレートをExcelを用意しましょう。こちらからダウンロードできます。
先のクラスのプロパティ名がExcelの中に「$プロパティ名」で定義されているのが見て取れるかと思います。
では実際に帳票生成ライブラリを使って帳票を生成します。まずは、次のように実行して帳票生成ライブラリをセットアップします。
var reportBuilder = new ReportBuilder<InvoiceDetail>(stream) // 単一項目のSetterを設定 .AddSetter("$SalesOrderId", cell => cell.Value = invoice.SalesOrderId) .AddSetter("$OrderDate", cell => cell.Value = invoice.OrderDate) .AddSetter("$CompanyName", cell => cell.Value = invoice.CompanyName) .AddSetter("$Name", cell => cell.Value = invoice.Name) .AddSetter("$Address", cell => cell.Value = invoice.Address) .AddSetter("$PostalCode", cell => cell.Value = invoice.PostalCode) // テーブルのセルに対するSetterを設定 .AddTableSetter("$ProductName", (cell, detail) => cell.Value = detail.ProductName) .AddTableSetter("$UnitPrice", (cell, detail) => cell.Value = detail.UnitPrice) .AddTableSetter("$OrderQuantity", (cell, detail) => cell.Value = detail.OrderQuantity);
Excelのテンプレートに定義した「$プロパティ名」に対して、値を設定させるためのセッターをラムダ式で指定します。
ラムダ式をコールバックさせることで型安全性を損なわず、リフレクションも利用せず、文字列ではなくオブジェクトをセルに設定できます。書式設定を利用するためには文字列ではなく、オブジェクトを設定する方が柔軟に対応できます。
セッターを追加するには2種類の方法があります。AddSetterでは単項目に対するコールバック関数を登録し、AddTableSetterでは表の列に対して値を設定するコールバック関数を登録します。AddTableSetterではコールバックの引数に1行を表すオブジェクトを受け取ります。この時、ReportBuilderクラスのインスタンス生成時に指定した型パラメーターのオブジェクトを受け取ります。
これで準備は完了です。おもむろに次の通り実行します。
reportBuilder.Build( invoice.InvoiceDetails, outputStream, SaveFileFormat.Pdf);
表の行を表すオブジェクトのリストと、生成した帳票を出力するためのストリーム、そして出力形式を渡します。そしてでき上がったのが次のPDFです。
よく見ていただきたい点がたくさんあります。
- テンプレートは1ページだったがPDFはページングされている
- 2ページ目のテーブルにも列ヘッダーが表示されている
- 日付や金額が適切にフォーマットされている
-
C#のコードから設定したのは明細の品目・単価・数量だけだが、次が正しく表示されている
- 単価×数量から求めた「金額」
- 小計
- 消費税
- 合計
- ご請求額
- 同様に請求書情報から請求年月日を設定しただけだが、「お支払期限」が表示されている
これほどに簡単に、ページング可能な帳票を作れた記憶が私にはありません。DioDocsの使い勝手が良い事もありますが、私自身が日頃からExcelに慣れ親しんでいたことも大きな要素だと思います。とは言え、特別にExcelをよく理解しているという程でもなく、ありふれたレベルでしかありません。自身が持っているExcelスキルを100%活用できるのがDioDocsの魅力です。
では、帳票生成ライブラリの実装を見ていきましょう。