IRONSOFTWAREHOME

Generate Reports in C# Like Crystal Reports (.NET 10)

Curtis Chau
Curtis Chau
Updated: 2026年6月4日

C# .NET での IronPDF による HTML から PDF へのレポート生成は、Crystal Reports の独自デザイナー(.rpt)を標準的な HTML、CSS、および Razor テンプレートに置き換えることで、.NET 開発者が既に持っている Web 開発スキルを活用して、データ駆動型のビジネスレポートを構築できるようにします。 これには、動的なテーブル、JavaScriptを使用したチャート、条件付き書式設定、複数ドキュメントのバッチ処理、および.NETを実行するあらゆる環境でのクロスプラットフォーム展開の完全なサポートが含まれます。

TL;DR: クイックスタート ガイド

このチュートリアルでは、基本的なテンプレートからバッチ処理、スケジュール生成まで、C# .NET での HTML-to-PDF レポート生成による Crystal Reports の置き換えについて説明します。

  • 対象者: .NET開発者がCrystal Reportsを置き換えたり、ゼロから新しいレポートシステムを構築したりする場合。
  • 構築するもの 3つの完全なレポート実装(売上請求書、従業員名簿、在庫レポート)、およびChart.jsによる視覚化、ブランド化されたヘッダー/フッター、目次の生成、サブレポートのマージ、並列バッチ処理。
  • Where it runs: .NET 10、.NET 8 LTS、.NET Framework 4.6.2+、.NET Standard 2.0。WindowsのみのCOM依存はありません。
  • このアプローチを使用する場合 Crystal Reports の .NET Core サポートの欠如、Windows ロックイン、複雑なライセンスがボトルネックになっている場合。
  • 技術的に重要な理由 HTML/CSSは、プラットフォーム間で同じようにレンダリングされ、CI/CDと統合され、チャートのためにJavaScriptを実行します。

コード例を実際に試すには、NuGet (Install-Package IronPdf) 経由で IronPdf をインストールしてください。 わずか数行のコードで最初のレポートを作成します:

  1. 1Install IronPDF with NuGet Package Manager

    PM > Install-Package IronPdf

  2. 2Copy and run this code snippet.

    // Install-Package IronPdf
    var pdf = new IronPdf.ChromePdfRenderer()
        .RenderHtmlAsPdf("<h1>Sales Report</h1><table><tr><td>Q1</td><td>$50,000</td></tr></table>")
        .SaveAs("sales-report.pdf");
    C#
  3. 3Deploy to test on your live environment

    Start using IronPDF in your project today with a free trial
    arrow pointer

IronPDFを購入または30日間のトライアルにサインアップした後、アプリケーションの最初にライセンスキーを追加してください。

IronPdf.License.LicenseKey = "KEY";

Start using IronPDF in your project today with a free trial.

First Step:
arrow pointer
NuGetInstall with NuGet

PM > Install-Package IronPdf

Install IronPDF by running the command above in the NuGet Package Manager Console, or search for the package in the NuGet Package Manager.
目次

C# Report Generator: HTML Templates to PDF

HTMLからPDFへの生成は、線形アーキテクチャのパイプラインに依存しています。独自のファイルフォーマットの代わりに、アプリケーションは標準データモデルを使用してRazorビューまたはHTMLテンプレートを作成します。 生成されたHTML文字列は、IronPdfのようなレンダリングエンジンに渡され、そこで視覚的な出力がPDFドキュメントとしてキャプチャされます。 このアプローチでは、レポートのデザインをホスティング環境から切り離し、.NETをサポートするあらゆるプラットフォームでまったく同じコードを実行できるようにします。

このワークフローは、標準的なウェブ開発を反映しています。 フロントエンド開発者は、CSSを使ってレイアウトを作成し、どのブラウザでもすぐにプレビューできます。 バックエンド開発者は、C#を使用してデータをバインドします。 この分離により、チームは既存のバージョン管理、コードレビュー、継続的デプロイのプロセスを、アプリケーションの他の部分と同じようにレポートに使用することができます。

HTML を使用することで、Crystal Reports では利用できない機能(インタラクティブなチャート、レスポンシブなテーブル、一貫したブランディングのための共有スタイルなど)を実現できます。

.NETアプリケーションでCrystal Reportsを置き換える理由

Crystal Reports からの移行は、致命的な問題や、SAP による突然の放棄によるものではありません。むしろ、摩擦要因が積み重なった結果、このプラットフォームは新規プロジェクトでは正当化されにくくなり、既存ソリューションでは維持が難しくなっているのです。 これらのペインポイントを特定することで、多くのチームが代替案を探している理由と、代替案を評価する際に最も重要な基準が明確になります。

.NET 8または.NET Coreのサポートはありません

Crystal Reports は .NET Core または .NET 5-10 をサポートしていません。SAP はフォーラムで、サポートを追加する予定はないと述べています。 SDKはCOMコンポーネントを使用しており、クロスプラットフォーム for .NETとは互換性がありません。 最新 for .NETをサポートするには、完全な書き換えが必要ですが、SAPはこれを拒否しています。

そのため、現行の .NET バージョンで新しいアプリケーションを開発するチームは Crystal Reports を使用できません。 .NET 8または.NET 10で標準化されている組織は統合できません。 既存のアプリケーションを最新 for .NETランタイムにアップグレードするには、まずレポートシステムを置き換える必要があります。

複雑なライセンスと隠れたコスト

Crystal Reports のライセンスは、デザイナーライセンス、ランタイムライセンス、サーバー展開、組み込み用途を区別しています。 ルールは、デスクトップ、ウェブ、ターミナルサービスによって異なります。 あるセットアップでコンプライアンスを遵守しても、別のセットアップでは余分なライセンスが必要になることがあります。 導入後にギャップが生じると、予期せぬコストが発生します。多くの組織は、ライセンスが明確なソリューションに移行するよりも、不確実性の方が悪いと判断します。

Windowsのみのプラットフォーム ロックイン

Crystal Reports は、レガシーの .NET Framework を搭載した Windows 上でのみ動作します。 これらのアプリケーションをLinuxコンテナ、Azure App Service on Linux、AWS Lambda、Google Cloud Runにデプロイすることはできません。 組織がコンテナ化、プラットフォーム非依存、サーバーレスシステムを使用するにつれて、これらの制限はより重要になります。

マイクロサービスを構築する開発チームは、さらなる課題に直面しています。 9つのサービスが軽量のLinuxコンテナで実行され、1つのサービスがCrystal ReportsのためにWindowsを必要とする場合、デプロイはより複雑になります。 Windowsコンテナイメージ、Windows互換ホスティング、個別のデプロイ設定が必要です。 レポーティング・サービスは例外となり、標準化を阻む。

Set Up a C# Report Generator in .NET 10

IronPDFを使い始めるのは簡単です。 他 for .NET依存ライブラリと同様に、NuGetを通してライブラリをインストールしてください。 追加のソフトウェアをダウンロードしたり、本番サーバー用に別のランタイム・インストーラーをインストールしたりする必要はありません。

テンプレートアプローチの選択:Razor、HTML、ハイブリッド

IronPDFはレポートテンプレートを作成するための3つの異なるアプローチをサポートしています。 各アプローチは、チームの構成、プロジェクトの要件、長期的なメンテナンスの考慮事項に応じて、特定の利点を提供します。

Razor Views は、すでに .NET エコシステムで作業しているチームに最も豊かな開発体験を提供します。 Visual StudioおよびVS Codeのインテリセンス、コンパイル時チェック、ループ、条件分岐、NULL処理、文字列フォーマットなど、C#の全機能をサポートする強力な型付けモデルが使用可能です。 Razorのシンタックスは、ASP.NET Coreアプリケーションを構築したことがある人にはなじみがあり、他のエコシステムのテンプレートエンジンに関連する学習曲線を排除します。 テンプレートは、他のソースファイルと一緒にプロジェクトに存在し、リファクタリング作業に参加し、通常のビルドプロセスの一部としてコンパイルされます。

文字列補間によるプレーンHTMLは、よりシンプルなレポートや、テンプレートを.NETコードから完全に分離することを好むチームには効果的です。 HTMLテンプレートは、アセンブリにコンパイルされた埋め込みリソースとして、アプリケーションと共にデプロイされる外部ファイルとして、あるいは実行時にデータベースやコンテンツ管理システムから取得される形式で保存できます。基本的なデータバインディングには、単一の値に対してstring.Replace()を使用するか、より高度なシナリオではScribanやFluidのような軽量なテンプレートライブラリを使用します。 このアプローチは移植性を最大限に高め、デザイナーが.NETツールをインストールせずに、テキストエディタとプレビュー用のWebブラウザだけでテンプレートを編集できるようにします。

ハイブリッドアプローチは、柔軟性を必要とするシナリオのために、両方のテクニックを組み合わせたものです。 例えば、Razorのビューは、メインのHTML構造を生成するためにレンダリングされ、ビューモデルにきれいに収まらない動的要素のために文字列置換を追加して後処理されるかもしれません。 また、開発者以外がデザインしたHTMLテンプレートを読み込み、Razorのパーシャルビューを使用して、複雑なデータ駆動部分のみをレンダリングしてから、すべてを結合することもできます。 HTMLからPDFへの変換は、HTMLソースに依存しないため、各レポートのニーズに応じてアプローチを組み合わせることができます。

これらの選択肢の中で、このチュートリアルは主にRazorビューに焦点を当てます。なぜなら、Razorビューは典型的なビジネスレポーティングシナリオにおいて、型の安全性、保守性、機能の豊富さのバランスが最も優れているからです。 どちらの方法でもHTML文字列が生成されるため、将来的にプレーンなHTMLテンプレートでの作業が必要になった場合でも、スキルはそのまま引き継がれます。

Build a Data-Driven PDF Report in C#

このセクションでは、最初から最後まで、売上請求書レポートの完全な作成を示します。 データを構造化するモデルを定義し、データをフォーマットされたHTMLに変換するRazorテンプレートを作成し、そのテンプレートをHTML文字列にレンダリングし、HTMLを閲覧、電子メール送信、またはアーカイブに適したPDFドキュメントに変換します。

HTML/CSSレポートテンプレートの作成

最初のステップは、データモデルを定義することです。 実際の請求書には、顧客情報、説明と価格を含む行項目、計算された合計、税処理、会社のブランディング要素が必要です。 モデルクラスは、これらのグループ分けを反映した構造になっている必要があります:

// Invoice data model with customer, company, and line item details
public class InvoiceModel
{
    public string InvoiceNumber { get; set; } = string.Empty;
    public DateTime InvoiceDate { get; set; }
    public DateTime DueDate { get; set; }

    public CompanyInfo Company { get; set; } = new();
    public CustomerInfo Customer { get; set; } = new();
    public List<LineItem> Items { get; set; } = new();

    // Computed totals - business logic stays in the model
    public decimal Subtotal => Items.Sum(x => x.Total);
    public decimal TaxRate { get; set; } = 0.08m;
    public decimal TaxAmount => Subtotal * TaxRate;
    public decimal GrandTotal => Subtotal + TaxAmount;
}

// Company details for invoice header
public class CompanyInfo
{
    public string Name { get; set; } = string.Empty;
    public string Address { get; set; } = string.Empty;
    public string City { get; set; } = string.Empty;
    public string Phone { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string LogoPath { get; set; } = string.Empty;
}

// Customer billing information
public class CustomerInfo
{
    public string Name { get; set; } = string.Empty;
    public string Address { get; set; } = string.Empty;
    public string City { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
}

// Individual invoice line item
public class LineItem
{
    public string Description { get; set; } = string.Empty;
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal Total => Quantity * UnitPrice;
}

GrandTotalの計算プロパティがモデルに含まれています。 これらの計算はテンプレートではなくモデルに属し、Razorビューをプレゼンテーションに集中させ、モデルがビジネスロジックを処理します。 この分離により、単体テストが容易になり、HTMLをレンダリングすることなく計算を検証できるようになります。

次に、このモデルを Professional 書式の請求書に変換する Razor ビューを作成します。これを Views フォルダに InvoiceTemplate.cshtml として保存してください:

@model InvoiceModel
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <style>
        /* Reset and base styles */
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: 'Segoe UI', Arial, sans-serif; font-size: 12px; color: #333; line-height: 1.5; }
        .invoice-container { max-width: 800px; margin: 0 auto; padding: 40px; }

        /* Header with company info and invoice title */
        .header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 40px; padding-bottom: 20px; border-bottom: 2px solid #3498db; }
        .company-info h1 { font-size: 24px; color: #2c3e50; margin-bottom: 10px; }
        .company-info p { color: #7f8c8d; font-size: 11px; }
        .invoice-title { text-align: right; }
        .invoice-title h2 { font-size: 32px; color: #3498db; margin-bottom: 10px; }
        .invoice-title p { font-size: 12px; color: #7f8c8d; }

        /* Address blocks */
        .addresses { display: flex; justify-content: space-between; margin-bottom: 30px; }
        .address-block { width: 45%; }
        .address-block h3 { font-size: 11px; text-transform: uppercase; color: #95a5a6; margin-bottom: 8px; letter-spacing: 1px; }
        .address-block p { font-size: 12px; }

        /* Line items table */
        .items-table { width: 100%; border-collapse: collapse; margin-bottom: 30px; }
        .items-table th { background-color: #3498db; color: white; padding: 12px; text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; }
        .items-table th:last-child, .items-table td:last-child { text-align: right; }
        .items-table td { padding: 12px; border-bottom: 1px solid #ecf0f1; }
        .items-table tr:nth-child(even) { background-color: #f9f9f9; }

        /* Totals section */
        .totals { float: right; width: 300px; }
        .totals-row { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #ecf0f1; }
        .totals-row.grand-total { border-bottom: none; border-top: 2px solid #3498db; font-size: 16px; font-weight: bold; color: #2c3e50; padding-top: 12px; }

        /* Footer */
        .footer { clear: both; margin-top: 60px; padding-top: 20px; border-top: 1px solid #ecf0f1; text-align: center; color: #95a5a6; font-size: 10px; }
    </style>
</head>
<body>
    <div class="invoice-container">
        <!-- Company header and invoice details -->
        <div class="header">
            <div class="company-info">
                <h1>@Model.Company.Name</h1>
                <p>@Model.Company.Address</p>
                <p>@Model.Company.City</p>
                <p>@Model.Company.Phone | @Model.Company.Email</p>
            </div>
            <div class="invoice-title">
                <h2>INVOICE</h2>
                <p>Invoice #: @Model.InvoiceNumber</p>
                <p>Date: @Model.InvoiceDate.ToString("MMMM dd, yyyy")</p>
                <p>Due Date: @Model.DueDate.ToString("MMMM dd, yyyy")</p>
            </div>
        </div>

        <!-- Bill to address -->
        <div class="addresses">
            <div class="address-block">
                <h3>Bill To</h3>
                <p>@Model.Customer.Name</p>
                <p>@Model.Customer.Address</p>
                <p>@Model.Customer.City</p>
                <p>@Model.Customer.Email</p>
            </div>
        </div>

        <!-- Line items table -->
        <table class="items-table">
            <thead>
                <tr><th>Description</th><th>Quantity</th><th>Unit Price</th><th>Total</th></tr>
            </thead>
            <tbody>
                @foreach (var item in Model.Items)
                {
                    <tr>
                        <td>@item.Description</td>
                        <td>@item.Quantity</td>
                        <td>@item.UnitPrice.ToString("C")</td>
                        <td>@item.Total.ToString("C")</td>
                    </tr>
                }
            </tbody>
        </table>

        <!-- Totals -->
        <div class="totals">
            <div class="totals-row"><span>Subtotal:</span><span>@Model.Subtotal.ToString("C")</span></div>
            <div class="totals-row"><span>Tax (@(Model.TaxRate * 100)%):</span><span>@Model.TaxAmount.ToString("C")</span></div>
            <div class="totals-row grand-total"><span>Total Due:</span><span>@Model.GrandTotal.ToString("C")</span></div>
        </div>

        <!-- Footer message -->
        <div class="footer">
            <p>Thank you for your business!</p>
            <p>Payment is due within 30 days. Please include invoice number with your payment.</p>
        </div>
    </div>
</body>
</html>
HTML

このテンプレートに埋め込まれたCSSは、色、フォント、スペーシング、テーブルのフォーマットなど、視覚的なスタイリングをすべて処理します。 IronPDFはフレックスボックス、グリッドレイアウト、CSS変数のような最新のCSS機能もサポートしています。 レンダリングされたPDFは、Chromeの印刷プレビューと完全に一致します。そのため、デバッグが簡単です。PDFで何か問題があるように見える場合は、ブラウザでHTMLを開き、開発者ツールを使用してスタイルを検査し、調整します。

テンプレートにデータをバインドする

モデルとテンプレートが準備できたら、PDFを生成するには、IronPDFのChromePdfRendererを通じてそれらを接続する必要があります。 重要なステップは、Razor のビューを HTML 文字列に変換し、その文字列をレンダラーに渡すことです:

using IronPdf;

// Service class for generating invoice PDFs from Razor views
public class InvoiceReportService
{
    private readonly IRazorViewEngine _razorViewEngine;
    private readonly ITempDataProvider _tempDataProvider;
    private readonly IServiceProvider _serviceProvider;

    public InvoiceReportService(
        IRazorViewEngine razorViewEngine,
        ITempDataProvider tempDataProvider,
        IServiceProvider serviceProvider)
    {
        _razorViewEngine = razorViewEngine;
        _tempDataProvider = tempDataProvider;
        _serviceProvider = serviceProvider;
    }

    // Generate PDF from invoice model
    public async Task<byte[]> GenerateInvoicePdfAsync(InvoiceModel invoice)
    {
        // Render Razor view to HTML string
        string html = await RenderViewToStringAsync("InvoiceTemplate", invoice);

        // Configure PDF renderer with margins and paper size
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.MarginTop = 10;
        renderer.RenderingOptions.MarginBottom = 10;
        renderer.RenderingOptions.MarginLeft = 10;
        renderer.RenderingOptions.MarginRight = 10;
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;

        // Convert HTML to PDF and return bytes
        var pdfDocument = renderer.RenderHtmlAsPdf(html);
        return pdfDocument.BinaryData;
    }

    // Helper method to render a Razor view to string
    private async Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model)
    {
        var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };
        var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

        using var stringWriter = new StringWriter();
        var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);

        if (!viewResult.Success)
            throw new InvalidOperationException($"View '{viewName}' not found.");

        var viewDictionary = new ViewDataDictionary<TModel>(
            new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = model };

        var viewContext = new ViewContext(actionContext, viewResult.View, viewDictionary,
            new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
            stringWriter, new HtmlHelperOptions());

        await viewResult.View.RenderAsync(viewContext);
        return stringWriter.ToString();
    }
}

コンソールアプリやバックグラウンドサービスなど、完全な ASP.NET Core MVC のセットアップを必要としないシンプルなシナリオでは、動的な部分に対して、補間機能と StringBuilder を使用した HTML 文字列をそのまま使用できます。

サンプル出力

ヘッダー、フッター、ページ番号を追加する

Professionalなレポートには通常、すべてのページで一貫したヘッダーとフッターが含まれ、会社のブランド名、文書のタイトル、生成日、ページ番号が表示されます。 IronPDFはこれらの要素を実装するために2つのアプローチを提供します: テキストベースのヘッダーは最小限のフォーマットでシンプルなコンテンツを、HTMLヘッダーはロゴやカスタムレイアウトで完全なスタイルコントロールを実現します。

Text-based headers work well for basic information and render faster since they don't require additional HTML parsing:

using IronPdf;
using IronSoftware.Drawing;

// Configure text-based headers and footers
var renderer = new ChromePdfRenderer();

// Set starting page number
renderer.RenderingOptions.FirstPageNumber = 1;

// Add centered header with divider line
renderer.RenderingOptions.TextHeader = new TextHeaderFooter
{
    CenterText = "CONFIDENTIAL - Internal Use Only",
    DrawDividerLine = true,
    Font = FontTypes.Arial,
    FontSize = 10
};

// Add footer with date on left, page numbers on right
renderer.RenderingOptions.TextFooter = new TextHeaderFooter
{
    LeftText = "{date} {time}",
    RightText = "Page {page} of {total-pages}",
    DrawDividerLine = true,
    Font = FontTypes.Arial,
    FontSize = 9
};

// Set margins to accommodate header/footer
renderer.RenderingOptions.MarginTop = 25;
renderer.RenderingOptions.MarginBottom = 20;

利用可能なマージフィールドには、現在のページ番号を表す {page}、ドキュメントの総ページ数を表す {total-pages}、生成日時を表す {date} および {time}、Web ページからレンダリングする場合のソース URL 用の {url}(Webページからレンダリングする場合のソースURL)、および {html-title}{pdf-title}(ドキュメントのタイトル)が含まれます。 これらのプレースホルダーは、レンダリング中に自動的に置き換えられます。

ロゴ、カスタムフォント、複雑な複数カラムレイアウトのヘッダーには、完全なCSSスタイリングをサポートするHTMLヘッダーを使用してください:

using IronPdf;
using System;

var renderer = new ChromePdfRenderer();

// Configure HTML header with logo and custom layout
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    MaxHeight = 30,
    HtmlFragment = @"
<div style='display: flex; justify-content: space-between; align-items: center;
            width: 100%; font-family: Arial; font-size: 10px; color: #666;'>
    <img src='logo.png' style='height: 25px;'>
    <span>Company Name Inc.</span>
    <span>Invoice Report</span>
</div>",
    BaseUrl = new Uri(@"C:\assets\images\").AbsoluteUri
};

// Configure HTML footer with page info and generation date
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    MaxHeight = 20,
    HtmlFragment = @"
<div style='text-align: center; font-size: 9px; color: #999;
            border-top: 1px solid #ddd; padding-top: 5px;'>
    Page {page} of {total-pages} | Generated on {date}
</div>",
    DrawDividerLine = false
};

サンプル出力

動的なテーブルと繰り返しセクションを作成する

レポートは、複数のページにまたがるデータの集合を表示する必要があることがよくあります。 Razorのループ構造は、コレクションを繰り返し処理し、各項目についてテーブルの行やカードの要素を生成することで、この処理を自然に行います。

以下は、部門ごとにグループ化されたデータ表示を示す、完全な従業員名簿の例です:

// Employee directory data models
public class EmployeeDirectoryModel
{
    public List<Department> Departments { get; set; } = new();
    public DateTime GeneratedDate { get; set; } = DateTime.Now;
}

// Department grouping with manager info
public class Department
{
    public string Name { get; set; } = string.Empty;
    public string ManagerName { get; set; } = string.Empty;
    public List<Employee> Employees { get; set; } = new();
}

// Individual employee details
public class Employee
{
    public string Name { get; set; } = string.Empty;
    public string Title { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string Phone { get; set; } = string.Empty;
    public string PhotoUrl { get; set; } = string.Empty;
    public DateTime HireDate { get; set; }
}

departmentクラスに指定されたCSSプロパティpage-break-inside: avoidは、PDFレンダラーに対し、可能な限りdepartmentセクションを1ページにまとめて表示するよう指示します。 部門のコンテンツがセクションの途中で改ページされる場合は、レンダラがセクション全体を次のページに移動します。 セレクタ .department:not(:first-child)page-break-before: always を使用することで、最初のセクション以降の各セクションを新しいページから開始させ、ディレクトリ全体を通じてセクションの区切りを明確にします。

サンプル出力

Advanced C# Report Generation With IronPDF

ビジネスレポートでは、静的な表やテキスト以上の機能が求められることがよくあります。 グラフは、表形式では理解するのが面倒なトレンドを視覚化します。 条件付き書式は、アクションを必要とする項目に注意を向けます。 サブレポートは、複数のソースからのデータを統合した文書です。 このセクションでは、IronPDFのChromiumレンダリングエンジンを使ってそれぞれの機能を実装することについて説明します。

PDFレポートにチャートとグラフを追加する

JavaScriptはレンダリング中に実行されるため、任意のクライアント側チャートライブラリを使用して、レポートに直接ビジュアライゼーションを生成することができます。 図表はページの一部としてラスタライズされ、最終的なPDFには画面とまったく同じように表示されます。 Chart.jsは、ほとんどのレポーティングニーズに対して、シンプルさ、機能、ドキュメントの優れたバランスを提供します。

CDNからChart.jsをインクルードし、C#モデルからシリアライズされたデータでチャートを構成します:

@model SalesReportModel

<!-- Include Chart.js library from CDN -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<!-- Canvas element for chart rendering -->
<canvas id="salesChart"></canvas>

<script>
    // Initialize bar chart with data from C# model
    const ctx = document.getElementById('salesChart').getContext('2d');
    new Chart(ctx, {
        type: 'bar',
        data: {
            // Serialize model data to JavaScript arrays
            labels: @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.MonthLabels)),
            datasets: [{
                label: 'Monthly Sales',
                data: @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.MonthlySales)),
                backgroundColor: 'rgba(52, 152, 219, 0.7)'
            }]
        }
    });
</script>
HTML

JavaScriptで生成されたコンテンツを含むページをレンダリングする場合は、スクリプトの実行が完了するまで待ってからページをキャプチャするようにレンダラーを設定してください:

using IronPdf;

string html = "<h1>Report</h1>";

// Configure renderer to wait for JavaScript execution
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.JavaScript(500); // Wait 500ms for JS to complete
var pdf = renderer.RenderHtmlAsPdf(html);

サンプル出力

条件付き書式とビジネスロジックを適用する

インベントリレポートは、アクションが必要な項目にすぐに注意を向けることができる視覚的なインジケータが役立ちます。 ユーザーが何百行もの行をスキャンして問題を探すのではなく、条件付き書式を使用することで、例外を視覚的に明らかにすることができます。 Razor のインライン式を使用して、データ値に基づいて CSS クラスを適用します:

<!-- Iterate through inventory items sorted by quantity -->
@foreach (var item in Model.Items.OrderBy(x => x.Quantity))
{
    // Apply CSS class based on stock level thresholds
    var rowClass = item.Quantity <= Model.CriticalStockThreshold ? "stock-critical" :
                   item.Quantity <= Model.LowStockThreshold ? "stock-low" : "";

    <tr class="@rowClass">
        <td>@item.SKU</td>
        <td>@item.ProductName</td>
        <td class="text-right">
            <!-- Badge styling for critical stock items -->
            <span class="quantity-badge @(item.Quantity <= 5 ? "badge-critical" : "badge-ok")">
                @item.Quantity
            </span>
        </td>
    </tr>
}
HTML

サンプル出力

サブレポートとセクション区切りを作成する

別々に作成されたレポートを1つのドキュメントにまとめるには、IronPDFのマージ機能を使用してください:

using IronPdf;

// Combine multiple reports into a single PDF document
public byte[] GenerateCombinedReport(SalesReportModel sales, InventoryReportModel inventory)
{
    var renderer = new ChromePdfRenderer();

    // Render each report section separately
    var salesPdf = renderer.RenderHtmlAsPdf(RenderSalesReport(sales));
    var inventoryPdf = renderer.RenderHtmlAsPdf(RenderInventoryReport(inventory));

    // Merge PDFs into one document
    var combined = PdfDocument.Merge(salesPdf, inventoryPdf);
    return combined.BinaryData;
}

サンプル出力

目次の生成

IronPDFはHTMLの見出し要素に基づいて目次を自動的に生成することができます:

using IronPdf;

// Generate PDF with automatic table of contents
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TableOfContents = TableOfContentsTypes.WithPageNumbers;
var pdf = renderer.RenderHtmlFileAsPdf("report.html");

私のお気に入りのこの種のライブラリはIronPDFです。PDFファイルの迅速で効率的な操作が可能です。また、PDF/A形式へのエクスポートやPDF文書へのデジタル署名といった多くの貴重な機能も備えています。

Milan Jovanovic

Microsoft MVP

ケーススタディを見る

IronOCRのおかげで私たちは年間$40,000を手作業の処理から節約し、生産性を向上させ、高影響のタスクにリソースを充てることができます。非常にお勧めします。

Brent Matzelle

最高技術責任者, OPYN

ケーススタディを見る

IronSuiteは私たちの業務において重要な役割を果たしています。これらは、フロアプランの作成や在庫管理の改善を含め、ビジネス全体の効率を向上させるツールです。

David Jones

リードソフトウェアエンジニア、Agorus Build

ケーススタディを見る

クリスタルレポートからIronPDFへ移行する

確立されたレポートシステムを移行するには、混乱を最小限に抑えつつ、近代化と簡素化の機会を捉えるための慎重な計画が必要です。 Crystal Reports のコンセプトを HTML ベースのアプローチにどのように対応させるかを理解することで、元のレポートの機能を忠実に再現したり、癖を残したりする必要がなくなります。

クリスタルレポートの概念をIronPDFにマップする

概念マッピングを理解することで、既存のレポートを体系的に翻訳することができます:

Crystal ReportsIronPDF 同等物
レポートセクションHTML divs with CSS page-break プロパティ
パラメータフィールドRazor ビューに渡されるモデルプロパティ
数式フィールドC# モデルクラスの計算プロパティ
合計LINQ集約
サブレポート部分的なビューまたはマージされたPDFドキュメント
グループ化/ソートテンプレートにデータを渡す前のLINQ操作
クロスタブレポートネストされたループを使用したHTMLテーブル
条件付き書式設定CSSクラスによるRazor @ifブロック

.rptテンプレートを変換するための最善の戦略

.rptファイルをプログラムで解析しようとしないでください。 その代わりに、既存のPDF出力を視覚的な仕様書として扱い、体系的な4つのステップ戦略を使用してロジックを再構築します:

1.**インベントリ:**すべての.rptファイルを、その目的、データソース、使用頻度とともにカタログ化します。 古いレポートを削除し、移行範囲を縮小する。

2.優先順位: 頻度の高いレポートを最初に移行します。シンプルなレイアウトのレポートや、メンテナンスに問題があるレポートを対象とします。

3.参考資料 既存のCrystal ReportsをPDFとしてエクスポートする。 開発者向けの視覚的な仕様書として使用してください。

4.**検証:**本番のデータ量でテストします。 10行で瞬時にレンダリングされるテンプレートは、10,000行では遅くなる可能性があります。

.NETにおけるレポートのバッチ生成とスケジューリング

プロダクションシステムでは、多くのレポートを同時に生成したり、スケジュールに従ってレポートジョブを実行したりする必要があります。 IronPDFのスレッドセーフデザインは両方のシナリオを効率的にサポートします。

複数のレポートを並行して生成する

バッチ処理については、Parallel.ForEachAsync または Task.WhenAll を使用した非同期パターンを使用してください:

using IronPdf;
using System.Collections.Concurrent;

// Generate multiple invoices in parallel using async processing
public async Task<List<ReportResult>> GenerateInvoiceBatchAsync(List<InvoiceModel> invoices)
{
    var results = new ConcurrentBag<ReportResult>();

    // Process invoices concurrently with controlled parallelism
    await Parallel.ForEachAsync(invoices,
        new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
        async (invoice, token) =>
        {
            // Each thread gets its own renderer instance
            var renderer = new ChromePdfRenderer();
            string html = BuildInvoiceHtml(invoice);
            var pdf = await renderer.RenderHtmlAsPdfAsync(html);

            // Save individual invoice PDF
            string filename = $"Invoice_{invoice.InvoiceNumber}.pdf";
            await pdf.SaveAsAsync(filename);

            results.Add(new ReportResult { InvoiceNumber = invoice.InvoiceNumber, Success = true });
        });

    return results.ToList();
}

サンプル出力

バッチ処理の例では、複数の請求書を並行して作成します。 生成されたバッチ請求書の1つです:

レポート生成をASP.NET Coreバックグラウンドサービスと統合する

スケジュールされたレポート生成は、.NET Coreのホストされたサービスインフラに自然に適合します:

// Background service for scheduled report generation
public class DailyReportService : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            // Calculate next run time (6 AM daily)
            var nextRun = DateTime.Now.Date.AddDays(1).AddHours(6);
            await Task.Delay(nextRun - DateTime.Now, stoppingToken);

            // Create scoped service for report generation
            using var scope = _serviceProvider.CreateScope();
            var reportService = scope.ServiceProvider.GetRequiredService<IReportGenerationService>();

            // Generate and distribute daily report
            var salesReport = await reportService.GenerateDailySalesSummaryAsync();
            // Email or save reports as needed
        }
    }
}

完全なテスト プロジェクトをダウンロードする

このチュートリアルのすべてのコード例は、すぐに実行できる.NET 10テストプロジェクトで利用できます。 ダウンロードには、完全なソースコード、データモデル、HTMLテンプレート、および上記のすべてのサンプルPDFを生成するテストランナーが含まれています。

次のステップ

本ガイドの例では、IronPDFがあらゆるビジネスレポーティングのニーズに対応できることを実証しています:シンプルな行項目と合計を含む請求書、グループ化されたデータと写真を含む複雑な従業員名簿、条件付き書式とグラフを含む在庫レポート数百のドキュメントの並列バッチ処理、およびバックグラウンドサービスによるスケジュール生成などです。

既存の Crystal Reports の代替案を検討する場合は、価値の高いレポートを 1 つ作成することから始めます。 ここに示したHTML-to-PDFパターンを使って再構築し、開発経験と出力品質を比較し、そこから拡張してください。 多くのチームは、最初に変換したレポートは、パターンと基本テンプレートを確立するのに数時間かかり、その後のレポートは、Razorテンプレートとスタイリングを再利用するため、数分で組み立てることができます。 レイアウトの精度については、ピクセルパーフェクトレンダリングガイドで、CSS を使用して Crystal Reports の出力を正確に一致させる方法を説明しています。

構築開始の準備はできましたか? IronPDFをダウンロードして、無料トライアルで試してください。 同じライブラリで、単一のレポート レンダリングから、.NET 環境間での 大容量バッチ生成まで、すべてを処理します。 レポートの移行について質問がある場合、またはアーキテクチャのガイダンスが必要な場合は、当社のエンジニアリング・サポート・チームにお問い合わせください。

Frequently Asked Questions

IronPDFとは?

IronPDFは開発者がプログラムでPDFドキュメントを作成、編集、生成することを可能にするC#ライブラリで、Crystal Reportsのような伝統的なレポートツールに代わる最新のツールを提供します。

IronPDFはどのようにCrystal Reportsの代替となるのですか?

IronPDFは、Crystal Reportsの堅苦しい構造とは対照的に、スタイリングや変更が容易なHTML/CSSテンプレートを開発者が使用できるようにすることで、レポート生成に柔軟でモダンなアプローチを提供します。

IronPDFを使って請求書を作成できますか?

IronPDFのHTML/CSSテンプレートを使って、詳細でカスタマイズされた請求書を作成することができます。

IronPDFで従業員名簿を作成することはできますか?

もちろんです。IronPDFを使えば、ダイナミックデータとHTML/CSSを活用して、わかりやすく整理された包括的な従業員名簿を作成することができます。

IronPDFはインベントリーレポートでどのようにお役に立てますか?

IronPDFはHTML/CSSテンプレートを使用することでインベントリレポートの作成を効率化し、動的にデータを入力することで、最新かつ視覚的に魅力的なレポートを提供します。

IronPDFでHTML/CSSテンプレートを使う利点は何ですか?

IronPDFでHTML/CSSテンプレートを使用することで、デザインの柔軟性、更新のしやすさ、ウェブテクノロジーとの互換性を提供し、レポートレイアウトの維持と拡張を容易にします。

IronPDF は .NET 10 をサポートしていますか?

IronPDFは.NET 10と互換性があり、開発者はレポート生成のニーズに対して最新 for .NET機能と改良を利用することができます。

IronPDFはどのようにレポート作成速度を向上させるのですか?

IronPDFはパフォーマンスのために最適化されており、HTML/CSSを効率的に処理し、高品質のPDFドキュメントにレンダリングすることで、レポートを素早く生成することができます。

Curtis Chau
Technical Writer

Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.

...
Read More

準備はできましたか?

Nuget Downloads 20,389,208バージョン:2026.7リリースされたばかり

あなたの無料30日間の試用キーをすぐに入手。
クレジットカードやアカウントの作成は不要です。

試用版の IronPDF を無料でお試しください

5分でセットアップ完了

C# PDF DLL

DLLをダウンロード

今すぐダウンロード

またはここからWindowsインストーラーをダウンロードする。

  1. IronPDFを~/Libsなどの場所に解凍し、ソリューションディレクトリ内に配置する
  2. Visual Studioソリューションエクスプローラーで参照を右クリックし、"IronPDF.dll"をブラウズして選択
PDF用C# NuGetライブラリ

NuGetでインストール

                  Install-Package IronPdf
                
nuget.org/packages/IronPdf/
  1. ソリューションエクスプローラーで参照を右クリックし、NuGetパッケージを管理を選択
  2. ブラウズを選択し、"IronPDF"を検索
  3. パッケージを選択してインストール
Key in blue circle

無料の30日間トライアルキーをすぐに入手してください。

bullet_checkedクレジットカードやアカウントの作成は不要です。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
無料のライブデモを予約する
Booking Badge related to IronPDF Product Demo

世界中の数百万人のエンジニアから信頼されています。

ライセンスはより安く
義務のない相談を受ける
下記のフォームを記入するか、sales@ironsoftware.comにメールしてください。
あなたの詳細は常に守秘されます。
世界中の数百万人のエンジニアから信頼されています。
ライセンスはより安く
あなたの無料30日間の試用キーをすぐに入手。
クレジットカードやアカウントの作成は不要です。