【C#】PDFファイルの作成・編集(PDFSharpCore)
PDFSharpCoreを使用したPDFファイルの作成・編集例をいくつか記載します。
QuestPDFを使用したPDFファイルの作成例については以下に記載しています。
【C#】PDFファイルの作成(QuestPDF)
<確認環境>
Windows10 64bit
Visual Studio 2022
.NET6.0
PDFSharpCore v1.3.49
Windows10 64bit
Visual Studio 2022
.NET6.0
PDFSharpCore v1.3.49
PDFSharpCoreとは
PdfSharpCoreは.NET Coreに対応したオープンソースライブラリでPDFファイルの作成・編集が行えます。ライセンスはMITで提供されています。PdfSharpCoreは、PdfSharp.XamarinとMigraDocの一部を移植しており、描画はSixLabors.ImageSharp、フォントはSixLabors.Fontsで実装されます。
https://github.com/ststeiger/PdfSharpCore
https://github.com/ststeiger/PdfSharpCore
PDFSharpCoreのインストール
Visual Studio のメニューから[ツール] > [NuGet パッケージマネージャー] > [パッケージマネージャーコンソール] を選択して以下のコマンドを実行します。
Install-Package PDFSharpCore
または、[プロジェクト] > [NuGet パッケージ管理] でPDFSharpCoreを検索してインストールします。
![PDFSharpCoreのインストール](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKpMe7AxzsNXr48-y7eqe--62g9cecgM57bntjzaeYlxELmir2YR1cSCmo8kaN6ct-hpfoPWfja_CJB715sZ_0CIvKrMtVN2FadYvJLQhjYfvUdPaMx7HyYq4T5IyusnWJifm1bkgphJDN_iGXFcfmWyK0MbEcOC0Us0ROqwZw-9hVGyENaRWs7J_VMA/s1600/PDFSharpCore_Install.png)
PDFファイルにテキストを書き込む
例はPDFファイルにテキスト(文字列)を書き込みます。
コード
using PdfSharpCore.Pdf;
using PdfSharpCore.Drawing;
// PDFドキュメント作成
var document = new PdfDocument();
// ページ追加
var page = document.AddPage();
page.Size = PdfSharpCore.PageSize.B4;
// 描画オブジェクト取得
var gfx = XGraphics.FromPdfPage(page);
// フォント作成(游明朝)
var font = new XFont("Yu Mincho", 12, XFontStyle.Regular);
// テキスト描画
gfx.DrawString("おはよう!", font, XBrushes.Black,
new XRect(12, 12, page.Width, page.Height), XStringFormats.TopLeft);
gfx.DrawString("こんにちは!!", font, XBrushes.Red,
new XRect(12, 24, page.Width, page.Height), XStringFormats.TopLeft);
gfx.DrawString("こんばんは!!!", font, XBrushes.Blue,
new XRect(12, 36, page.Width, page.Height), XStringFormats.TopLeft);
// PDFファイルの保存
document.Save(@"C:\work\Test.pdf");
PDFの出力結果
![PDFSharpCoreのテキスト](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk6JBAOCDayeSBlmcQujyXt5KeO1brxvCEGbcyqC4ApeLocWH0PKNJxSkbV4a2gQH3IY2DBvELFFud-zFJwq-4WBZmO5__n6SK1nFTCrLHx9gKfIsEJIpWf8QEvJJzuehwRUGsUODFQxr3x6crxW7rv0bfwlQZcFn64mkyaGR7bWG4sO8KEZaXcmCq7Q/s1600/PDFSharpCore_DrawString.png)
フォント設定
任意のフォントを利用するには、IFontResolverを継承したクラスを作成してフォントソルバーに登録します。作成するクラスでフォントのTTFファイル読み込みます。
任意のフォント(TTFファイル)
フォントファイルをフォルダに配置します。
![PDFSharpCoreで利用する任意のフォント](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix-Spj_SXNWzm9-ikWVon8E8hqWSAzK7MmMOxe8y414F8hZTC-JbMN_KTD1wQ0OzJiWaLNcnE0q_H0llk32onCwmwzMsTw87CQceZL-tlirkbZ4hmfkcFhM4mPI8tDzvx6dHZdFMZ9Muc41xBk1dcd1dZ2wkXhzq53FYPhhol__9_YT9IctTEThfLITQ/s1600/PDFSharpCore_Fonts.png)
フォントファイルは以下を使用しました。
コード
例はフォントソルバークラスで任意のフォントを読み込んでいます。
using PdfSharpCore.Pdf;
using PdfSharpCore.Drawing;
using PdfSharpCore.Fonts;
// PDFドキュメント作成
var document = new PdfDocument();
// ページ追加
var page = document.AddPage();
page.Size = PdfSharpCore.PageSize.B4;
// 描画オブジェクト取得
var gfx = XGraphics.FromPdfPage(page);
// フォント作成
GlobalFontSettings.FontResolver = new MyFontResolver(); // 自作したフォントソルバー登録
var font1 = new XFont("解星 春の海", 12, XFontStyle.Regular);
var font2 = new XFont("解星オプティ", 12, XFontStyle.Bold);
var font3 = new XFont("Yu Mincho", 12, XFontStyle.Regular);
// テキスト描画
gfx.DrawString("おはよう!", font1, XBrushes.Black,
new XRect(12, 12, page.Width, page.Height), XStringFormats.TopLeft);
gfx.DrawString("こんにちは!!", font2, XBrushes.Red,
new XRect(12, 24, page.Width, page.Height), XStringFormats.TopLeft);
gfx.DrawString("こんばんは!!!", font3, XBrushes.Blue,
new XRect(12, 36, page.Width, page.Height), XStringFormats.TopLeft);
// PDFファイルの保存
document.Save(@"C:\work\Test.pdf");
// フォントソルバークラス
public class MyFontResolver : IFontResolver
{
public string DefaultFontName { get; }
public FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
{
// フォントファイル特定
var fontName = familyName;
if (fontName.Equals("解星 春の海"))
{
if (isBold) {
fontName = "KaiseiHarunoUmi-Bold.ttf";
}
else {
fontName = "KaiseiHarunoUmi-Regular.ttf";
}
}
else if (fontName.Equals("解星オプティ"))
{
if (isBold) {
fontName = "KaiseiOpti-Bold.ttf";
}
else {
fontName = "KaiseiOpti-Regular.ttf";
}
}
else
{
fontName= "yumin.ttf"; // 游明朝フォント
}
return new FontResolverInfo(fontName);
}
public byte[] GetFont(string faceName)
{
// フォントファイルのパス作成
var faceNamePath = Path.Join(@"C:\work\fonts", faceName);
try
{
return File.ReadAllBytes(faceNamePath);
}
catch (Exception e)
{
Console.WriteLine(e);
throw new Exception("No Font File Found - " + faceNamePath);
}
}
}
PDFの出力結果
![PDFSharpCoreの任意フォントテキスト](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja9tF_mY8Yx7sLK7gSE8wlOBvjM-30KXozYWcd-SCAiMYGuJLSVmqSEBzPpdDdOlmwtIyjOBOdP8TcpRo6oCuLdLm6Wf1EKk2NtR0GYx3hprLlZKx-deuaRhuDTfur_ztgzMqpyB5KR4-Nj15vat9fBCjs1APi_tyQ3CL7UiFRV_NSdE85btFqBWCspA/s1600/PDFSharpCore_DrawString_Fonts.png)
PDFファイルに透かし文字を書き込む
例は透明度50%の赤色のブラシで、斜めに透かし文字を書き込みます。
コード
using PdfSharpCore.Pdf;
using PdfSharpCore.Drawing;
// PDFドキュメント作成
var document = new PdfDocument();
// ページ追加
var page = document.AddPage();
page.Size = PdfSharpCore.PageSize.B4;
// 描画オブジェクト取得
var gfx = XGraphics.FromPdfPage(page);
// フォント作成
var font1 = new XFont("Yu Mincho", 12, XFontStyle.Regular);
var font2 = new XFont("Yu Mincho", 36, XFontStyle.Regular);
// テキスト描画
var rect = new XRect(0, 0, page.Width, page.Height);
gfx.DrawString("こんにちは!!", font1, XBrushes.Black, rect, XStringFormats.Center);
// 透かし文字描画
var brush = new XSolidBrush(XColor.FromArgb(50, XColors.Red)); // 透明度50%、赤色
var format = new XStringFormat
{
Alignment = XStringAlignment.Center,
LineAlignment = XLineAlignment.Center
};
// 描画範囲を回転する
var matrix = new XMatrix();
matrix.RotateAt(-45, new XPoint(page.Width / 2, page.Height / 2), XMatrixOrder.Append);
gfx.MultiplyTransform(matrix);
gfx.DrawString("社外秘", font2, brush, rect, format);
// PDFファイルの保存
document.Save(@"C:\work\Test.pdf");
PDFの出力結果
![PdfSharpCoreの透かし文字](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCJPd9rI-lmh70iVHwXyqexN58F2xQEwktd1NPFcOHcCQktDKlaeS8tfyW6MUMz1fuJ9We8hegm9U1vWmdC02A9zfgpeq3Jodbu7z02c-74lj-kJPPvm_81880NS6lwcMZxVqjGiNZgljwXrXMuvd2o-01xS8ltWKws9YOQmHmPrJoAtnM1HgLEOIzBQ/s1600/PDFSharpCore_Watermark_.png)
PDFファイルに図形を書き込む
例は線、長方形、三角形、円を書き込んでいます。
コード
using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;
// PDFドキュメント作成
var document = new PdfDocument();
// ページ追加
var page = document.AddPage();
page.Size = PdfSharpCore.PageSize.A4;
// 描画オブジェクト取得
var gfx = XGraphics.FromPdfPage(page);
// ペン作成
var pen = new XPen(XColors.Black, 2);
// 線を描画
gfx.DrawLine(pen, new XPoint(50, 50), new XPoint(150, 50));
// 長方形を描画
gfx.DrawRectangle(pen, new XSolidBrush(XColors.LightBlue), new XRect(50, 100, 100, 50));
// 三角形を描画
var points = new[] { new XPoint(50, 250), new XPoint(150, 250), new XPoint(100, 200) };
gfx.DrawPolygon(pen, new XSolidBrush(XColors.LightGreen), points, XFillMode.Winding);
// 円を描画
gfx.DrawEllipse(pen, new XSolidBrush(XColors.LightPink), new XRect(50, 300, 100, 50));
// PDFドキュメント保存
document.Save(@"C:\work\Shapes.pdf");
PDFの出力結果
![PdfSharpCoreの図形書き込み](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQur3iTOSRL2KWa8CpzcZEbhRAy0QYqoevnF-3MHsiVF3dyz0xCLO2LJ9aytZpCf5zGquM2kO1KXkjuT5XLS0umxwsEOIOn9zQ6eD-wlDyhiwzyMK9nkJU1qS3fHCo2kNhBzUUByAb62Vi3G07TIMtwjakhi-xHedWS0AI4o25L81Lu59JVWTa2o4JoQ/s1600/PDFSharpCore_Shapes.png)
PDFファイルにハイパーリンクを設定する
例はPDFファイルに描画した長方形と同じ範囲に、Webサイトへのハイパーリンクを設定します。長方形の座標を指定する'XRect'は左上隅を(0,0)とし、ハイパーリンクの座標を指定する'PdfRectangle'は左下隅を(0,0)とするため注意が必要です。
コード
using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;
using PdfSharpCore.Pdf.Annotations;
// PDFドキュメント作成
var document = new PdfDocument();
// ページ追加
var page = document.AddPage();
page.Size = PdfSharpCore.PageSize.A4;
// 描画オブジェクト取得
var gfx = XGraphics.FromPdfPage(page);
// ボタンを描画(長方形&テキストの描画)
var rect = new XRect(12, 12, 120, 24);
gfx.DrawRectangle(new XPen(XColors.Black, 1), new XSolidBrush(XColors.LightBlue), rect); // 長方形の描画
var font = new XFont("Yu Mincho", 12, XFontStyle.Bold);
gfx.DrawString(@"ハイパーリンク", font, XBrushes.Black, rect, XStringFormats.Center); // テキストの描画
// ハイパーリンク設定
// PdfRectangleは左下隅を座標(0,0)、XRectは左上隅を座標(0,0)と扱うため変換
var pdfRect = new PdfRectangle(new XRect(rect.X, page.Height - rect.Y - rect.Height, rect.Width, rect.Height));
var link = PdfLinkAnnotation.CreateWebLink(pdfRect, @"https://ma-noblog.blogspot.com/");
page.Annotations.Add(link);
// PDFドキュメント保存
document.Save(@"C:\work\HyperLink.pdf");
PDFの出力結果
ボタンにカーソルをおくとハイパーリンクが表示されます。クリックするとリンク先に移動します。
![PdfSharpCore_ハイパーリンク](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi80_QISYFhsSDeHPfHOrUkQ3Ntst9rQnyFHQuF4vjTtq8eGxpTUkCfWi9Dqt43BPOidaAndjPT4DCf9ytV7zMt_vKdMa5X_vFl0lX6Yz_WRssotfkpHnlXb12GQr_Euk1G7taHEDl9Bv7TfQ-gM4yvIjpDOUlzXTBJfaCzcN353bs3sfXrRrwl-8msLg/s1600/PDFSharpCore_HyperLink.png)
PDFファイルに画像を埋め込む
例は画像サイズを20分の1にして埋め込んでいます。
コード
using PdfSharpCore.Pdf;
using PdfSharpCore.Drawing;
// PDFドキュメント作成
var document = new PdfDocument();
// ページ追加
var page = document.AddPage();
page.Size = PdfSharpCore.PageSize.B4;
// 描画オブジェクト取得
var gfx = XGraphics.FromPdfPage(page);
// 画像の埋め込み
var image = XImage.FromFile(@"C:\work\cat.png");
double posX = 12.0; // 画像位置 X座標
double posY = 12.0; // 画像位置 Y座標
var newWidth = image.PixelWidth / 20; // 画像サイズ調整 幅
var newHeight = image.PixelHeight / 20; // 画像サイズ調整 高さ
gfx.DrawImage(image, posX, posY, newWidth, newHeight);
// PDFファイルの保存
document.Save(@"C:\work\Test.pdf");
PDFの出力結果
![PdfSharpCore_画像埋め込み](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2dLqCJdAMngyjfIkDiRdrtnD7TWyqq7OqWQf8lpgGmobyVH1D-BJSLMxY9uTGUaqj3ikIvzCZ9-xHAPmWBXdQc2cieWZy3yxfocdOQY2Mb1B2Arj50c6PD6DoFlPgljrUU8f9cXSzW7VqxQYCMv1OcDZs6DdC4zuphdL-bNO7zGIlwJd2qQ19hLFE-A/s1600/PDFSharpCore_Cat.png)
PDFファイルの結合
例は3つのPDFファイルを1つのPDFファイルに結合します。
コード
using PdfSharpCore.Pdf;
using PdfSharpCore.Pdf.IO;
// 結合するPDFファイルパス
var pdfFiles = new string[] { @"C:\work\Test01.pdf", @"C:\work\Test02.pdf", @"C:\work\Test03.pdf" };
// PDFドキュメント作成
var outputDocument = new PdfDocument();
// 結合するPDFファイルを順番に追加
foreach (var pdfFile in pdfFiles)
{
// PDFファイルを開く
var inputDocument = PdfReader.Open(pdfFile, PdfDocumentOpenMode.Import);
// 結合するPDFファイルのページを出力PDFファイルに追加
foreach (PdfPage page in inputDocument.Pages)
{
outputDocument.AddPage(page);
}
}
// PDFファイルを保存
outputDocument.Save(@"C:\work\Output.pdf");
PDFファイルの分割
例はページ数が均等になるように3つのPDFファイルに分割します。
コード
using PdfSharpCore.Pdf;
using PdfSharpCore.Pdf.IO;
// 分割後のPDFファイルパス
var outputFiles = new string[] { @"C:\work\Test01.pdf", @"C:\work\Test02.pdf", @"C:\work\Test03.pdf" };
// 分割元のPDFファイルを開く
using (var inputDocument = PdfReader.Open(@"C:\work\Input.pdf", PdfDocumentOpenMode.Import))
{
var outputFileCount = outputFiles.Count();
var inputPageCount = inputDocument.PageCount;
// 分割後のページ数を算出
var outputPageCounts = new int[outputFileCount]; // 各ファイルのページ数
var quotient = inputPageCount / outputFileCount; // 商
var remainder = inputPageCount % outputFileCount; // 余り
for (var i = 0; i < outputFileCount; i++)
{
// 余りを均等に割り振る
outputPageCounts[i] = quotient;
if (0 < remainder) {
outputPageCounts[i]++;
remainder--;
}
else {
break;
}
}
// PDFファイルを分割
var startPage = 0;
for (var i = 0; i < outputFileCount; i++)
{
// 分割後のPDFファイル作成
PdfDocument outputDocument = new PdfDocument();
// ページを追加
for (var j = startPage; j < startPage + outputPageCounts[i]; j++)
{
outputDocument.AddPage(inputDocument.Pages[j]);
}
// 分割後のPDFファイルを保存
outputDocument.Save(outputFiles[i]);
startPage += outputPageCounts[i];
}
}