多くの .NET ベースの業務システムでは、構造化データが DataTable 形式で管理されています。これらのデータを配布、アーカイブ、あるいは読み取り専用のレポートとして提供する場合、C# で DataTable を PDF に出力することは非常に一般的かつ実用的な要件です。 Excel や CSV などのフォーマットと比べ、PDF は版面の安定性、視覚的一貫性、文書の完全性が重要な場面に適しています。データの編集性よりも、レポート、請求書、監査記録、システム自動生成の公式文書などで特に有用です。 本記事では、コード中心のアプローチで C# で DataTable を PDF に変換する方法 を解説します。例は Spire.PDF for .NET を使用し、PdfGrid コンポーネントで DataTable の内容を構造化された表として PDF にレンダリングします。 目次 1. 概要:C#でのDataTableのPDF出力 2. 環境準備 3. コアワークフローとコード実装 4. 表レイアウト、ページフロー、ページ分割制御 5. 表スタイルのカスタマイズ 6. PDF 出力方法:ファイル vs ストリーム 7. 実用的なヒントとよくある問題 1. 概要:C# で DataTable を PDF に出力する 本質的には、DataTable を PDF に出力することは、データバインディング + レンダリング の問題であり、低レベルの描画処理ではありません。 つまり、各行の位置や列幅を手動で計算したり、ページ分割のロジックを自分で処理する必要はありません。合理的な方法は、既存の DataTable を直接 PDF 表コンポーネントにバインドし、レンダリングエンジンにレイアウトとページ分割を自動で行わせることです。 Spire.PDF for .NET では、この役割を PdfGrid クラスが担います。 PdfGrid が適切な抽象レイヤーである理由 PdfGrid は Spire.PDF for .NET のクラスで、PDF ドキュメント内に構造化表データを表示するためのものです。行、列、ヘッダー、ページ分割などの概念を中心に扱い、単なるグラフィック描画ではありません。 技術的には、PdfGrid は以下の重要な機能を提供します: DataSource プロパティで DataTable を直接バインド可能 DataTable の構造に基づき列を自動生成 ヘッダーとデータ行のレンダリングロジックを内蔵 内容がページを超える場合、自動でページ分割 つまり、DataTable の PDF 出力は 宣言的操作 のように扱えます。どのデータをレンダリングするかを指定するだけで、ページ内での配置やページ分割 は PDF エンジンが自動で処理します。 次章以降では、この考え方に基づき、具体的な実装方法や実務での最適化テクニックを解説します。 2. 環境準備 本記事のサンプルコードは .NET Framework および最新 .NET(6 以上) プロジェクトで共通して使用可能です。実装はすべてマネージコードで行うため、プラットフォーム固有の追加設定は不要です。 Spire.PDF for .NET のインストール NuGet を使用して Spire.PDF for .NET をインストールできます: Install-Package Spire.PDF または、Spire.PDF for .NET を直接ダウンロード して、手動でプロジェクトに追加することも可能です。 インストール完了後、PDF ドキュメント作成、ページ管理、表レンダリング、スタイル制御のための API が利用可能になります。 3. C# で DataTable を PDF に出力する:コアワークフローとコード実装 環境準備が整ったら、DataTable の PDF 出力は 線形で実装指向 のプロセスになります。 基本的な考え方は:既存の DataTable を PdfGrid にバインドし、レイアウト、ページ分割、表描画の責任を PDF エンジンに任せることで、行や列、罫線を手動で描画する必要はありません。 実装フローは一般的に次のステップで構成されます: データが入力済みの DataTable を準備 PDF ドキュメントとページを作成 DataTable を PdfGrid にバインド 表をページに描画 PDF を保存 注意:DataTable に日本語や中国語などの文字が含まれる場合、デフォルトフォントでは正しく表示されず空白になることがあります。 レンダリング前に「メイリオ」や「MS ゴシック」などの日本語対応フォントを PdfTrueTypeFont を通して表スタイルに適用する必要があります。 実際のプロジェクトでは、これらのステップを同一コードフロー内で順次実行することが多いです。以下に、すぐに使える完全サンプルを示します。 完全サンプル:DataTable を PDF に出力 using Spire.Pdf; using Spire.Pdf.Graphics; using Spire.Pdf.Grid; using System.Data; using System.Drawing; DataTable dataTable = new DataTable(); dataTable.Columns.Add("OrderId", typeof(int)); dataTable.Columns.Add("CustomerName", typeof(string)); dataTable.Columns.Add("OrderDate", typeof(DateTime)); dataTable.Columns.Add("TotalAmount", typeof(decimal)); // 実務に近い日本向けサンプルデータ dataTable.Rows.Add(1001, "楽天市場", DateTime.Today, 15800.75m); dataTable.Rows.Add(1002, "Amazonジャパン", DateTime.Today, 8900.50m); dataTable.Rows.Add(1003, "ヨドバシカメラ", DateTime.Today, 23400.00m); dataTable.Rows.Add(1004, "ビックカメラ", DateTime.Today, 17600.20m); dataTable.Rows.Add(1005, "メルカリ", DateTime.Today, 11200.00m); dataTable.Rows.Add(1006, "LOHACO", DateTime.Today, 9800.30m); PdfDocument document = new PdfDocument(); PdfPageBase page = document.Pages.Add(); PdfGrid grid = new PdfGrid(); grid.DataSource = dataTable; // 日本語対応フォントを設定(文字化け防止) PdfGridCellStyle cellStyle = new PdfGridCellStyle(); // メイリオフォントを使用し、第二引数 true でフォントを PDF に埋め込む cellStyle.Font = new PdfTrueTypeFont(new Font("メイリオ", 9f), true); grid.Rows.ApplyStyle(cellStyle); // 表格をページ上に描画(ページ上端から40fの位置) grid.Draw(page, new PointF(0, 40f)); // PDF保存 document.SaveToFile("DataTableToPDF.pdf"); document.Close(); 以下は生成されたPDFファイルの効果プレビューです。 このコードで DataTable → PDF の完全な出力が実現できます。 生成される PDF は構造が明確で、ページ分割にも対応しており、多くの実務シナリオでそのまま利用可能です。 もちろん、実際のプロジェクトでは、通常、表の位置、ページサイズ、方向、スタイルに対してより高い要求が課されます。 次の章では、コアのエクスポートロジックを変更せずに、レイアウト、ページ分割、視覚効果を細かく制御する方法に焦点を当てて説明します。 4. 表レイアウト、ページフロー、ページ分割制御 実務文書では、表は通常ページの一部に過ぎません。ページサイズ、表の開始位置、ページ分割方法が、1ページまたは複数ページにわたる表の表示に影響します。 PdfGrid では、これらは表自体が管理するのではなく、ページ作成時や Draw メソッド呼び出し時に解決されます。 PdfGrid は絶対位置指定やページ切り替えを直接担当せず、ページ設定や描画パラメータが実際に機能します。 以下は、実務レポートでよく使われるレイアウトとページ分割の設定例です。 レイアウトとページ分割の例 PdfDocument document = new PdfDocument(); // A4ページを作成し、マージンを設定 PdfPageBase page = document.Pages.Add( PdfPageSize.A4, new PdfMargins(40), PdfPageRotateAngle.RotateAngle0, // ページ座標系の回転角度 PdfPageOrientation.Landscape // ページ方向:横向き ); PdfGrid grid = new PdfGrid(); grid.DataSource = dataTable; // 複数ページにわたる場合、ヘッダーを繰り返し表示 grid.RepeatHeader = true; // 表の描画開始位置を指定 float startX = 40f; float startY = 80f; // 日本語対応フォントを適用 PdfGridCellStyle cellStyle = new PdfGridCellStyle(); cellStyle.Font = new PdfTrueTypeFont(new Font("メイリオ", 9f), true); grid.Rows.ApplyStyle(cellStyle); // 表を描画 grid.Draw(page, new PointF(startX, startY)); この設定で生成される PDF の例: 技術的なポイント PdfPageBase Pages.Add で新しいページを作成。サイズ、マージン、回転角度、方向を設定可能。 RepeatHeader 複数ページにまたがる表の場合、ヘッダーを自動で繰り返し表示。 Draw メソッド PointF パラメータでページ内の表描画開始位置を指定。 描画時に自動でページ分割や内容のオーバーフローを処理。 ページの幾何設定、表の開始位置、ページ分割ルールを統一することで、PdfGrid は手動でページ分割や行ごとのレイアウトを制御することなく、安定した複数ページ表を生成できます。 5. 表スタイルのカスタマイズ レイアウトが安定したら、次は表の外観制御です。PdfGrid は集中型スタイルモデルを提供しており、データバインディングやページ分割に影響を与えず、表全体や列、行のスタイルを設定できます。 以下は、レポートでよく使われるスタイル設定例です。 スタイル例:ヘッダー、行、列 PdfDocument document = new PdfDocument(); PdfPageBase page = document.AppendPage(); PdfGrid grid = new PdfGrid(); grid.DataSource = dataTable; // ヘッダースタイルの作成と適用 PdfGridCellStyle headerStyle = new PdfGridCellStyle(); headerStyle.Font = new PdfFont(PdfFontFamily.Helvetica, 10f, PdfFontStyle.Bold); headerStyle.BackgroundBrush = new PdfSolidBrush(Color.FromArgb(60, 120, 200)); headerStyle.TextBrush = PdfBrushes.White; grid.Headers.ApplyStyle(headerStyle); // 行スタイル PdfGridCellStyle defaultStyle = new PdfGridCellStyle(); defaultStyle.Font = new PdfTrueTypeFont(new Font("メイリオ", 9f), true); PdfGridCellStyle alternateStyle = new PdfGridCellStyle(); alternateStyle.BackgroundBrush = new PdfSolidBrush(Color.LightSkyBlue); alternateStyle.Font = new PdfTrueTypeFont(new Font("メイリオ", 10f), true); // 行の交互色適用 for (int rowIndex = 0; rowIndex < grid.Rows.Count; rowIndex++) { if (rowIndex % 2 == 0) { grid.Rows[rowIndex].ApplyStyle(defaultStyle); } else { grid.Rows[rowIndex].ApplyStyle(alternateStyle); } } // 列幅を明示的に設定 grid.Columns[0].Width = 60f; // OrderId grid.Columns[1].Width = 140f; // CustomerName grid.Columns[2].Width = 90f; // OrderDate grid.Columns[3].Width = 90f; // TotalAmount // 表を描画 grid.Draw(page, new PointF(40f, 80f)); 適用後の PDF の例: スタイルのポイント ヘッダースタイル PdfGridCellStyle で定義し、grid.Headers.ApplyStyle(...) で統一適用。 複数ページでもヘッダーのフォント・背景色・文字色が一貫。 データ行スタイル grid.Rows[i].ApplyStyle(...) で個別設定。交互色の実装も簡単で、条件付きスタイル拡張も容易。 列幅制御 grid.Columns[index].Width で明示的に指定。内容長の差によるレイアウト崩れを防ぐ。 注意:スタイルは grid.Draw(...) を呼ぶ前に設定してください。 すべてのスタイルは描画前に解析され、ページ分割やデータバインディングに影響せず適用されます。 より複雑な表のスタイル制御(枠線、配置、条件付きスタイルなど)が必要な場合は、C# を使用した PDF 表の作成と装飾 を参照してください。 6. PDF 出力方法:ファイル vs ストリーム 表の描画が完了したら、最後に PDF を出力します。 ファイル出力でもメモリストリーム出力でも、表の生成・描画ロジックは同一です。違いは出力先だけです。 6.1 ファイル保存 PDF を直接ファイルに保存。デスクトップアプリやバッチ処理向け。 document.SaveToFile("DataTableReport.pdf"); document.Close(); 適用例: Windows デスクトップアプリ 定期レポート生成のバックグラウンドサービス サーバー側のバッチ処理 6.2 ストリーム出力(Web / API) Web 系では、PDF をディスクに書き込まず、メモリ上で処理しそのままクライアントに返すことが可能。 using (MemoryStream stream = new MemoryStream()) { document.SaveToStream(stream); document.Close(); byte[] pdfBytes = stream.ToArray(); // pdfBytes を HTTP レスポンスとして返す } ASP.NET コントローラや Minimal API との統合も容易で、テンポラリファイル不要です。 参考:ASP.NET で PDF を生成して返す 7. 実用的なヒントとよくある問題 7.1 日付・数値フォーマット制御 PdfGrid はデータを文字列としてレンダリングします。 フォーマット指定が必要な場合、バインド前に統一処理します。 例: DateTime を固定カルチャでフォーマット 金額や数値の小数桁統一 複数地域対応で文化依存フォーマットを避ける データレイヤで処理するのが推奨です。 7.2 空値 (DBNull) の処理 DataTable に DBNull.Value があると、セルが空白になったりレイアウトが崩れる場合があります。 バインド前に正規化すると安全です: row["TotalAmount"] = row["TotalAmount"] == DBNull.Value ? 0m : row["TotalAmount"]; 7.3 表幅がページを超える場合の対策 列が多い、内容が長い場合、表がページ幅を超えることがあります。 対策: 各列幅を明示的に設定 フォントサイズを小さくする ページ方向を横向きに変更 マージンを調整 これらは レイアウト層 で処理するのが正しい方法です。 7.4 大規模 DataTable のパフォーマンス 数百~数千行の DataTable では性能差が顕著になります。 推奨: 各セルや行に個別スタイルを設定しない 表レベルや列レベルでスタイルを適用 システム内蔵フォントを優先 レイアウト計算をシンプルに保つ 例:大規模データで grid.Rows[rowIndex].ApplyStyle(...) をループで繰り返すと負荷増。 不要であれば grid.Rows.ApplyStyle(...) で一括適用が最適。 Web 環境では、PDF生成をリクエストスレッド外で処理すると、応答のブロックを回避できます。 8. まとめ C# で DataTable を PDF に出力 する際、手動で表を構築したり低レベル描画を行う必要はありません。 PdfGrid に DataTable を直接バインドするだけで、自動ページ分割対応の PDF 表を生成でき、レイアウトや外観も容易に制御可能です。 この記事では、実務視点で導出プロセス、レイアウト、スタイル設定、データ準備などの重要ポイントを解説しました。 この方法はシンプルなレポートから、複数ページ・大規模データを含む複雑な文書まで拡張可能です。 試用したい場合は E-ICEBLUE から 一時ライセンス を取得して、フル機能を制限なくテストできます。 よくある質問(FAQ) PdfGrid で DataTable を出力するのに適したケースは? 構造が明確で、ページ分割に対応し、版面が安定した表型 PDF 文書 を作る場合に最適です。 列生成、ヘッダー、ページ分割を自動で処理するため、手動描画よりもレポートや請求書、監査用文書に適しています。 データフォーマットは DataTable 側で処理するべきか、PdfGrid で処理するべきか? 日付形式、数値精度、空値処理などのデータ規格化はバインド前に行います。 PdfGrid はレイアウトやスタイル担当であり、データ変換には使用しません。 PdfGrid は大規模 DataTable を効率的に処理できるか? 可能です。PdfGrid は自動ページ分割とヘッダー繰り返し表示をサポートします。大規模データでは、行・セル単位のスタイル適用を避け、表や列単位のスタイルを使用するとパフォーマンスが維持できます。