【C#】PDFファイルの作成(QuestPDF)

【C#】PDFファイルの作成(QuestPDF)

QuestPDFを使用したPDFファイルの作成例について記載します。
PDFSharpCoreを使用したPDFファイルの作成・編集例については以下に記載しています。
【C#】PDFファイルの作成・編集(PDFSharpCore)

<確認環境>
Windows10 64bit
Visual Studio 2022
.NET6.0
QuestPDF v2022.12.3
QuestPDF.Previewer v2022.12.0

QuestPDFとは

QuestPDFはPDFファイル作成を行うオープンソースのライブラリです。.NET Frameworkおよび.NETCoreで使用できます。ライセンスはMITで提供されています。
https://www.questpdf.com/

インストール

QuestPDFとQuestPDF.Previewerをインストールします。


QuestPDFのインストール

Visual Studio のメニューから[ツール] > [NuGet パッケージマネージャー] > [パッケージマネージャーコンソール] を選択して以下のコマンドを実行します。
Install-Package QuestPDF

または、[プロジェクト] > [NuGet パッケージ管理] でQuestPDFを検索してインストールします。
QuestPDFのインストール

QuestPDF.Previewerのインストール

QuestPDF.Previewerでコードから生成されるPDFの内容をプレビュー表示できます。再コンパイルをすることなくコードを保存するだけでPDFが確認できるため、作業を効率化できます。


QuestPDF.Previewerのインストール


コマンドプロンプトを起動して次のコマンドを実行します。
dotnet tool install QuestPDF.Previewer --global

QuestPDF.Previewerのインストール

ホットリロードの設定


Visual Studio のメニューから[ツール] > [オプション] > [デバッグ] > [.NET/C++ ホット リロード]を選択して[ファイルの保存時にホット リロードを適用する]にチェックします。
ホットリロードの設定

コード修正とデバッグ実行


コードにShowInPreviewerメソッドを追加してデバッグ実行します。するとQuestPDF.Previewerが起動されてコードから生成されるPDFが表示されます。

コード
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using QuestPDF.Previewer;

var document = Document.Create(container =>
{
    container.Page(page =>
    {
        // ページ&フォント設定
        page.Size(PageSizes.A4);
        page.Margin(1, Unit.Centimetre);
        page.DefaultTextStyle(x => x.FontSize(20).FontFamily("Yu Mincho"));

        // テキスト書き込み
        page.Content().Column(column =>
        {
            column.Item().Text("こんにちは!").FontColor(Colors.Black);
        });
    });
});

document.GeneratePdf(@"C:\work\Test.pdf");  // PDF作成
document.ShowInPreviewer();  // PDFプレビュー表示

QuestPDF.Previewerの表示
QuestPDF.Previewerの表示

デバッグ実行中の状態で、コードを変更して保存するとQuestPDF.Previewerの表示内容が更新されます。

コード(変更部分抜粋)
// テキストのフォント色を変更
page.Content().Column(column =>
{
    column.Item().Text("こんにちは!!").FontColor(Colors.Red.Medium);
});

QuestPDF.Previewerの表示(変更コード保存後)
QuestPDF.Previewerの表示(変更コード保存後)

PDFファイルにテキストを書き込む

PDFファイルのテキスト書き込みと、テキストの位置やフォントなどの設定方法を記載します。

ヘッダー、本文、フッダーの書き込み

例はページとデフォルトフォントを設定後に、ヘッダー、本文、フッダーを書き込んでいます。テキストの位置、フォント、背景色などは個別に設定することができます。(詳細は別項目に記載)

コード
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using QuestPDF.Previewer;

var document = Document.Create(container =>
{
    container.Page(page =>
    {
        // ページ&フォント設定
        page.Size(PageSizes.A4);
        page.Margin(1, Unit.Centimetre);    // 余白1cm
        page.DefaultTextStyle(x => x.FontSize(20).FontFamily("Yu Mincho"));

        // ヘッダー書き込み
        page.Header()
            .AlignRight()      // 右揃え
            .Text("令和5年04月22日")
            .FontSize(12);

        // テキスト書き込み
        page.Content().Column(column =>
        {
            column.Item().AlignCenter().Text("本文").Underline().FontSize(28);     // 下線設定
            column.Item().Text("おはよう!");
            column.Item().Text("こんにちは!!").FontColor(Colors.Blue.Medium);    // フォント色:青
            column.Item().Text("こんばんは!!!").BackgroundColor(Colors.Green.Medium);   // 背景色:緑
        });

        // フッダー書き込み
        page.Footer()
        .AlignCenter()    // 中央揃え
        .Text(text =>
        {
            text.CurrentPageNumber().FontSize(12);  // 現在のページ取得
            text.Span(" ページ").FontSize(12);
        });
    });
});
document.GeneratePdf(@"C:\work\Test.pdf");  // PDF作成
document.ShowInPreviewer();  // PDFプレビュー表示

PDFファイルの内容
QuestPDF_テキスト書き込み


フォントの設定

フォントの設定方法について記載します。
  • フォント種類
  • FontFamilyメソッドでフォント種類を指定します。「C:\Windows\Fonts」にないフォントは独自のFontManager.RegisterFontメソッドで読み込む必要があります。
    サンプルコードのフォントから取得しました。
    ・解星オプティ:https://free-fonts.jp/kaiseiopti/

  • フォントサイズ
  • FontSizeメソッドでフォントサイズを設定します。

  • フォント色
  • FontColorメソッドでフォント色を設定します。

  • フォントの太さ
  • 以下のメソッドでフォントの太さを設定します。
    .Weight(FontWeight.Normal)
    .Thin()
    .ExtraLight()
    .Light()
    .NormalWeight()
    .Medium()
    .SemiBold()
    .Bold()
    .ExtraBold()
    .Black()
    .ExtraBlack()

コード
using QuestPDF.Drawing;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using QuestPDF.Previewer;

// フォントファイル読み込み
FontManager.RegisterFont(File.OpenRead(@"C:\work\fonts\KaiseiOpti-Regular.ttf"));
FontManager.RegisterFont(File.OpenRead(@"C:\work\fonts\KaiseiHarunoUmi-Regular.ttf"));

var document = Document.Create(container =>
{
    container.Page(page =>
    {
        // ページ&フォント設定
        page.Size(PageSizes.A4);
        page.Margin(1, Unit.Centimetre);
        page.DefaultTextStyle(x => x.FontSize(20).FontFamily("MS Gothic")); // デフォルトフォント設定(MSゴシック・サイズ20)

        // テキスト書き込み
        page.Content().Column(column =>
        {
            // デフォルトフォント設定で書き込む
            column.Item().Text("フォントテスト");

            // フォント種類、フォントサイズ、フォント色を設定して書き込む
            column.Item().Text("フォントテスト")
                  .FontFamily("Kaisei Opti").FontSize(26).FontColor(Colors.Blue.Medium);

            column.Item().Text("フォントテスト")
                  .FontFamily("Kaisei HarunoUmi").FontSize(32).FontColor(Colors.Red.Medium);

            // フォント種類、太字・斜字体・細字を設定して書き込む
            column.Item().Text("フォントテスト").FontFamily("Yu Mincho").Bold();           // 游明朝・太字
            column.Item().Text("フォントテスト").FontFamily("Yu Mincho").Bold().Italic();  // 游明朝・太字/斜字体
            column.Item().Text("フォントテスト").FontFamily("Yu Mincho").Italic();         // 游明朝・斜字体
            column.Item().Text("フォントテスト").FontFamily("Yu Mincho").Thin();           // 游明朝・細字
        });

    });
});

document.GeneratePdf(@"C:\work\Test.pdf");
document.ShowInPreviewer();  // PDFプレビュー表示

PDFファイルの内容
QuestPDF_フォント設定

テキスト間隔・行間隔・配置位置の設定

テキスト間隔・行間隔・配置位置について記載します。
  • テキスト間隔
  • LetterSpacingメソッドでテキスト間隔を指定します。

  • 行間隔
  • LineHeightメソッドで行間隔を設定します。

  • テキスト配置位置
  • 以下のメソッドでテキスト配置位置を設定します。
    左揃え :.AlignLeft()
    中央揃え:.AlignCenter()
    右揃え :.AlignRight()
    上揃え :.AlignTop()
    中央揃え:.AlignMiddle()
    下揃え :.AlignBottom()

コード(設定部分抜粋)
page.Content().Column(column =>
{
    // テキスト間隔
    column.Item().Text("あいうえお");
    column.Item().Text("かきくけこ").LetterSpacing(1);  // テキスト間隔を指定
    column.Item().Text("さしすせそ").LineHeight(4);     // 行間隔を指定
    column.Item().Text("たちつてと").LetterSpacing(2).LineHeight(4);// テキスト間隔&行間隔を指定

    // テキスト配置位置
    // 水平方向のテキスト位置指定
    column.Item().AlignLeft().Text("Left");     // 左揃え
    column.Item().AlignCenter().Text("Center"); // 中央揃え
    column.Item().AlignRight().Text("Right");   // 右揃え

    // 垂直方向のテキスト位置指定
    column.Item().Row(row =>
    {
        row.RelativeItem().AlignTop().Text("Top");       // 上揃え
        row.RelativeItem().AlignMiddle().Text("Middle"); // 中央揃え
        row.RelativeItem().AlignBottom().Text("Buttom"); // 下揃え
    });
});

PDFファイルの内容
QuestPDF_テキスト間隔/位置

テキストライン・背景色の設定

テキストライン・背景色の設定について記載します。
  • テキストに下線設定
  • Underlineメソッドでテキストに下線を指定します。

  • テキスト間に水平線を設定
  • PaddingVerticalメソッドで行間隔、LineHorizontalメソッドで線の太さを設定します。

  • テキスト間に垂直線を設定
  • PaddingHorizontalメソッドでテキスト間隔、LineVerticalメソッドで線の太さ配置位置を設定します。

  • テキスト背景色設定
  • BackgroundColorメソッドでテキストの背景色を設定します。

  • 水平方向または垂直方向の背景色設定
  • Backgroundメソッドで水平方向または垂直方向の背景色を設定します。

コード(テキスト書き込み部分抜粋)
// テキストに下線設定
column.Item().Text("テキスト").Underline();

// テキスト間に水平線を設定
column.Item().Text("Above text");
column.Item().PaddingVertical(5).LineHorizontal(1).LineColor(Colors.Grey.Medium);
column.Item().Text("Below text");

// テキスト間に垂直線を設定
column.Item().Row(row =>
{
    row.AutoItem().Text("Left text");
    row.AutoItem().PaddingHorizontal(10).LineVertical(1).LineColor(Colors.Grey.Medium);
    row.AutoItem().Text("Right text");
});

// テキスト背景色設定
column.Item().Text("レッド").BackgroundColor(Colors.Red.Accent1);
column.Item().Text("ライトグリーン").BackgroundColor("#00FF00");
// 水平方向の背景色設定
column.Item().Background(Colors.Blue.Lighten1).Text("ブルー");
column.Item().Background("#ffa500").Text("オレンジ");

column.Item().Row(row =>
{
    // テキストに背景色設定
    row.RelativeItem().Text("AAA\nAAA").BackgroundColor(Colors.Green.Medium);
    row.RelativeItem().Text("BBB\nBBB").BackgroundColor("#fff520");
    // 垂直方向の背景色設定
    row.RelativeItem().Background(Colors.Purple.Lighten1).Text("CCC\nCCC");
    row.RelativeItem().Background("#e3f520").Text("DDD\nDDD");
});

PDFファイルの内容
QuestPDF_テキストライン

テキストにハイパーリンク設定

Hyperlinkメソッドでurlを設定します。

コード(ハイパーリンク設定部分抜粋)
// テキスト書き込み
page.Content().Column(column =>
{
    column.Item().Hyperlink("https://ma-noblog.blogspot.com/").Text("ブログハイパーリンク");
});

PDFファイルの内容
PDFファイルのテキストをクリックするとHyperlinkメソッドで設定したurlに移動します。
QuestPDF_ハイパーリンク

PDFファイルに表を書き込む

Tableメソッドを使用して単純な表を作成する例を記載します。QuestPDFは、さまざまなスタイルや機能を使用して複雑な表も作成できます。

コード
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using QuestPDF.Previewer;

// 商品データ(name: 商品名, price: 単価, num: 個数)
var datas = new List<(string name, int price, int num)>
{
    ( "商品A", 1000, 95 ),
    ( "商品B", 3000, 100 ),
    ( "商品C", 2500, 20 ),
    ( "商品D", 1500, 70 ),
    ( "商品E", 2000, 50 )
};

var document = Document.Create(container =>
{
    container.Page(page =>
    {
        // ページ&フォント設定
        page.Size(PageSizes.A4);
        page.Margin(1, Unit.Centimetre);
        page.DefaultTextStyle(x => x.FontSize(12).FontFamily("Yu Mincho"));

        page.Content().Column(column =>
        {
            // テーブル作成
            column.Item().Table(table =>
            {
                // テーブル列定義
                table.ColumnsDefinition(columns =>
                {
                    columns.ConstantColumn(26);  // 列幅:26
                    columns.ConstantColumn(300); // 列幅:300
                    columns.RelativeColumn();    // 列幅を等分
                    columns.RelativeColumn();
                    columns.RelativeColumn();
                });

                // ヘッダー行作成(枠線、背景色、テキスト配位置を設定してテキスト追加)
                table.Header(header =>
                {
                    header.Cell().Border(1).Background(Colors.Grey.Medium).AlignCenter().Text("No.");
                    header.Cell().Border(1).Background(Colors.Grey.Medium).AlignCenter().Text("商品名");
                    header.Cell().Border(1).Background(Colors.Grey.Medium).AlignCenter().Text("単価");
                    header.Cell().Border(1).Background(Colors.Grey.Medium).AlignCenter().Text("個数");
                    header.Cell().Border(1).Background(Colors.Grey.Medium).AlignCenter().Text("金額");
                });

                // データ行作成(枠線、余白、テキスト配置位置を設定してテキスト追加)
                int no = 1;
                foreach(var data in datas)
                {
                    table.Cell().Border(1).Padding(5).AlignCenter().Text(no.ToString());              // No.列
                    table.Cell().Border(1).Padding(5).AlignLeft().Text(data.name);                    // 商品名列
                    table.Cell().Border(1).Padding(5).AlignRight().Text(data.price.ToString("#,0"));  // 単価列
                    table.Cell().Border(1).Padding(5).AlignRight().Text(data.num.ToString());         // 個数列
                    
                    var total = data.num * data.price;
                    table.Cell().Border(1).Padding(5).AlignRight().Text(total.ToString("#,0"));       // 金額列
                    no++;
                }

                // 合計(行番号、列番号、枠線、背景色、余白、テキスト配置位置を設定してテキスト追加)
                var rowcount = (uint)(datas.Count() + 1);
                table.Cell().Row(rowcount).Column(4).Border(1)
                     .Background(Colors.Grey.Medium).Padding(5).AlignCenter().Text("合計");

                // 合計金額(行番号、列番号、枠線、余白、テキスト配置位置を設定してテキスト追加)
                var sum = datas.Sum(x => x.price * x.num).ToString("#,0");
                table.Cell().Row(rowcount).Column(5).Border(1).Padding(5).AlignRight().Text(sum);
            });
        });
    });
});

document.GeneratePdf(@"C:\work\Test.pdf");
document.ShowInPreviewer();

PDFファイルの内容
QuestPDF_表

PDFファイルに画像を埋め込む

Imageメソッドを使用して画像を埋め込みます。

コード(画像を埋め込み部分抜粋)
page.Content().Column(column =>
{
    // テキスト書き込み
    column.Item().Width(200).AlignCenter().Text("ねこ");
    // 画像埋め込み
    column.Item().Row(row =>
    {
        row.RelativeItem().Width(200)    // 幅:200
        .Image(@"C:\work\cat.png", ImageScaling.FitWidth);  // 幅に合わせて画像サイズ調整
    });
});

PDFファイルの内容
QuestPDF_画像

図形を書き込む

canvasメソッドを使用して単純な図形を書き込みます。描画はSkiaSharpを使用します。

コード(図形書き込み部分抜粋)
page.Content().Canvas((canvas, size) =>
{
    using var paint = new SKPaint
    {
        Color = SKColors.Red,  // 色
        StrokeWidth = 5,       // 線の太さ
        IsStroke = true        // 塗りつぶし有無(true:なし、false:あり)
    };

    canvas.Translate(0, 50);

    // 45度の線を描く
    canvas.DrawLine(0, 0, 50, 50, paint);

    // 円を描く
    canvas.Translate(100, 25);
    canvas.DrawCircle(0, 0, 25, paint);

    // 四角形を描く
    canvas.Translate(75, -25);
    canvas.DrawRect(new SKRect(0, 0, 50, 50), paint);

    // 三角形を描く
    canvas.Translate(100, 0);
    var path = new SKPath();
    path.MoveTo(0, 0);
    path.LineTo(25, 50);
    path.LineTo(50, 0);
    path.Close();
    canvas.DrawPath(path, paint);
});

PDFファイルの内容
QuestPDF_図形

改ページの設定

PageBreakメソッドを使用して改ページします。例は3ページのPDFファイルを作成しています。

コード(改ページ部分抜粋)
page.Content().Column(column=>
{
    column.Item().Text("1ページ目");
    column.Item().PageBreak();  // 改ページ

    column.Item().Row(row =>
    {
        row.RelativeItem().Text("2ページ目");
        row.RelativeItem().PageBreak();   // 改ページ
    });

    column.Item().Text("3ページ目");
});


Next Post Previous Post