6
10

C#でPDFを操作する

Last updated at Posted at 2023-04-21

結合

複数のpdfファイルを結合して1つのpdfファイルにします。

using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //結合するファイル
            string[] files = { @"C:\work\a.pdf", @"C:\work\b.pdf" };

            //結合後の出力ファイル
            PdfDocument outputPdfDocument = new PdfDocument();

            foreach (string file in files)
            {
                //ファイルを開く
                PdfDocument inputPdfDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);

                //1ページずつ出力ファイルに追加
                for (int i = 0; i < inputPdfDocument.PageCount; i++)
                {
                    outputPdfDocument.AddPage(inputPdfDocument.Pages[i]);
                }

                //ファイルを閉じる
                inputPdfDocument.Close();
            }

            //出力
            outputPdfDocument.Save(@"C:\work\concat.pdf");
        }
    }
}

分割

pdfファイルを1ページ毎に分割します。

using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //分割するファイル
            string file = @"C:\work\a.pdf";

            //ファイルを開く
            PdfDocument inputPdfDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);

            //1ページずつ個別に保存
            for (int i = 0; i < inputPdfDocument.PageCount; i++)
            {
                //出力するファイル
                PdfDocument outputPdfDocument = new PdfDocument();

                //ページ追加
                outputPdfDocument.AddPage(inputPdfDocument.Pages[i]);

                //保存
                outputPdfDocument.Save(@"C:\work\split" + i.ToString() + ".pdf");
            }

            inputPdfDocument.Close();
        }
    }
}

回転

pdfファイルの全ページを回転します。

using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //元ファイル
            string file = @"C:\work\a.pdf";

            //ファイルを開く
            PdfDocument inputPdfDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);

            //出力ファイル
            PdfDocument outputPdfDocument = new PdfDocument();

            for (int i = 0; i < inputPdfDocument.PageCount; i++)
            {
                PdfPage page = inputPdfDocument.Pages[i];
                int deg, deg_next;

                //時計回り90度回転の場合
                deg = 90;

                //反時計回り90度回転の場合
                //deg = -90;

                //180度回転の場合
                //deg = 180;

                //角度設定
                deg_next = (page.Rotate + deg) % 360;
                deg_next += deg_next < 0 ? 360 : 0;
                page.Rotate = deg_next;

                outputPdfDocument.AddPage(page);
            }
            outputPdfDocument.Save(@"C:\work\rotate.pdf");

            inputPdfDocument.Close();
        }
    }
}

ページ追加

pdfファイルの先頭に白紙のA4ページを追加します。

using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //白紙を追加する元ファイル
            string file = @"C:\work\a.pdf";

            //元ファイルを開く
            PdfDocument inputPdfDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);

            //出力ファイル作成
            PdfDocument outputPdfDocument = new PdfDocument();

            //白紙追加
            outputPdfDocument.AddPage(new PdfPage());
            outputPdfDocument.Pages[0].Size = PdfSharp.PageSize.A4;

            //元ファイル結合
            for (int i = 0; i < inputPdfDocument.PageCount; i++)
            {
                outputPdfDocument.AddPage(inputPdfDocument.Pages[i]);
            }

            //元ファイルを閉じる
            inputPdfDocument.Close();

            //保存
            outputPdfDocument.Save(@"C:\work\addblankpage.pdf");
        }
    }
}

pdfファイルの先頭に白紙ページ(サイズは元ファイルの1ページ目と同じサイズ)を追加します。

using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using PdfSharp.Drawing;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //白紙を追加する元ファイル
            string file = @"C:\work\a.pdf";

            //元ファイルを開く
            PdfDocument inputPdfDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);

            //出力ファイル作成
            PdfDocument outputPdfDocument = new PdfDocument();

            //白紙追加
            outputPdfDocument.AddPage(new PdfPage());

            if (inputPdfDocument.Pages[0].CropBox.Height >= 200 && inputPdfDocument.Pages[0].CropBox.Width >= 200)
            {
                //CropBoxのサイズがある場合はCropBoxのサイズで設定
                outputPdfDocument.Pages[0].Width = getUint(inputPdfDocument.Pages[0].CropBox.Width);
                outputPdfDocument.Pages[0].Height = getUint(inputPdfDocument.Pages[0].CropBox.Height);
            }
            else
            {
                //CropBoxのサイズがない場合はMediaBoxのサイズで設定
                outputPdfDocument.Pages[0].Width = getUint(inputPdfDocument.Pages[0].MediaBox.Width);
                outputPdfDocument.Pages[0].Height = getUint(inputPdfDocument.Pages[0].MediaBox.Height);
            }

            //元ファイル結合
            for (int i = 0; i < inputPdfDocument.PageCount; i++)
            {
                outputPdfDocument.AddPage(inputPdfDocument.Pages[i]);
            }

            //元ファイルを閉じる
            inputPdfDocument.Close();

            //保存
            outputPdfDocument.Save(@"C:\work\addblankpage.pdf");
        }
        private static XUnit getUint(double x)
        {
            int[] sizes = { 420, 595, 842, 1191, 1684, 2384, 3370, 516, 729, 1032, 1460, 2064, 2920, 4127 };

            foreach (int size in sizes)
            {
                if (System.Math.Abs(x - size) <= 1.0)
                {
                    return new XUnit(size);
                }
            }

            return new XUnit(x);
        }
    }
}

ページレイアウト変更

pdfファイルをビューワで開いた時の見え方(ページレイアウト)を変更します。

using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //元ファイル
            string file = @"C:\work\a.pdf";

            //ファイルを開く
            PdfDocument inputPdfDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);

            //出力ファイルを作成し元ファイルをコピー
            PdfDocument outputPdfDocument = new PdfDocument();
            for (int i = 0; i < inputPdfDocument.PageCount; i++)
            {
                outputPdfDocument.AddPage(inputPdfDocument.Pages[i]);
            }
            inputPdfDocument.Close();

            //非連続、単一ページとして保存
            outputPdfDocument.PageLayout = PdfPageLayout.SinglePage;
            outputPdfDocument.Save(@"C:\work\output_layout_SinglePage.pdf");

            //非連続、見開きとして保存
            outputPdfDocument.PageLayout = PdfPageLayout.TwoPageLeft;
            outputPdfDocument.Save(@"C:\work\output_layout_TwoPageLeft.pdf");

            //非連続、見開き(1ページ目表紙)として保存
            outputPdfDocument.PageLayout = PdfPageLayout.TwoPageRight;
            outputPdfDocument.Save(@"C:\work\output_layout_TwoPageRight.pdf");

            //連続、単一ページとして保存
            outputPdfDocument.PageLayout = PdfPageLayout.OneColumn;
            outputPdfDocument.Save(@"C:\work\output_layout_OneColumn.pdf");

            //連続、見開きとして保存
            outputPdfDocument.PageLayout = PdfPageLayout.TwoColumnLeft;
            outputPdfDocument.Save(@"C:\work\output_layout_TwoColumnLeft.pdf");

            //連続、見開き(1ページ目表紙)として保存
            outputPdfDocument.PageLayout = PdfPageLayout.TwoColumnRight;
            outputPdfDocument.Save(@"C:\work\output_layout_TwoColumnRight.pdf");
        }
    }
}

ページ2分割

pdfファイルの各ページを上下に2分割します。

using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //元ファイル
            string file = @"C:\work\a.pdf";

            //出力ファイル
            PdfDocument outputPdfDocument = new PdfDocument();

            //元ファイルのページを出力ファイルへコピー
            PdfDocument inputPdfDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);
            for (int i = 0; i < inputPdfDocument.PageCount; i++)
            {
                PdfPage page1 = inputPdfDocument.Pages[i];

                //同じページを2回追加
                outputPdfDocument.AddPage(page1);
                outputPdfDocument.AddPage(page1);
            }
            inputPdfDocument.Close();

            //必要箇所のみ抜粋 PDFは左下が座標(0,0)
            for (int i = 0; i < outputPdfDocument.PageCount; i++)
            {
                PdfPage page = outputPdfDocument.Pages[i];

                if (i % 2 == 0)//奇数ページ
                {
                    page.MediaBox = new PdfRectangle(new PdfSharp.Drawing.XRect(0, page.Height / 2, page.Width, page.Height / 2));
                }
                else//偶数ページ
                {
                    page.MediaBox = new PdfRectangle(new PdfSharp.Drawing.XRect(0, 0, page.Width, page.Height / 2));
                }
            }

            //保存
            outputPdfDocument.Save(@"C:\work\cut_up_down.pdf");
        }
    }
}

pdfファイルの各ページを上下に2分割します。分割する際、ページ毎の回転角度を考慮して分割します。

using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //元ファイル
            string file = @"C:\work\a.pdf";

            //出力ファイル
            PdfDocument outputPdfDocument = new PdfDocument();

            //元ファイルのページを出力ファイルへコピー
            PdfDocument inputPdfDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);
            for (int i = 0; i < inputPdfDocument.PageCount; i++)
            {
                PdfPage page1 = inputPdfDocument.Pages[i];

                //同じページを2回追加
                outputPdfDocument.AddPage(page1);
                outputPdfDocument.AddPage(page1);
            }
            inputPdfDocument.Close();

            //必要箇所のみ抜粋 PDFは左下が座標(0,0)
            for (int i = 0; i < outputPdfDocument.PageCount; i++)
            {
                PdfPage page = outputPdfDocument.Pages[i];

                //回転角度確認
                int deg = page.Rotate % 360;
                deg += deg < 0 ? 360 : 0;

                if (deg == 90 || deg == 270)
                {
                    if (i % 2 == 0)//奇数ページ
                    {
                        page.MediaBox = new PdfRectangle(new PdfSharp.Drawing.XRect(deg == 90 ? 0 : page.Width / 2, 0, page.Width / 2, page.Height));
                    }
                    else//偶数ページ
                    {
                        page.MediaBox = new PdfRectangle(new PdfSharp.Drawing.XRect(deg == 90 ? page.Width / 2 : 0, 0, page.Width / 2, page.Height));
                    }
                }
                else
                {
                    if (i % 2 == 0)//奇数ページ
                    {
                        page.MediaBox = new PdfRectangle(new PdfSharp.Drawing.XRect(0, deg == 180 ? 0 : page.Height / 2, page.Width, page.Height / 2));
                    }
                    else//偶数ページ
                    {
                        page.MediaBox = new PdfRectangle(new PdfSharp.Drawing.XRect(0, deg == 180 ? page.Height / 2 : 0, page.Width, page.Height / 2));
                    }
                }
            }

            //保存
            outputPdfDocument.Save(@"C:\work\cut_up_down.pdf");
        }
    }
}

pdfファイルの各ページを左右に2分割します。分割する際、ページ毎の回転角度を考慮して分割します。

using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //元ファイル
            string file = @"C:\work\a.pdf";

            //出力ファイル
            PdfDocument outputPdfDocument = new PdfDocument();

            //元ファイルのページを出力ファイルへコピー
            PdfDocument inputPdfDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);
            for (int i = 0; i < inputPdfDocument.PageCount; i++)
            {
                PdfPage page1 = inputPdfDocument.Pages[i];

                //同じページを2回追加
                outputPdfDocument.AddPage(page1);
                outputPdfDocument.AddPage(page1);
            }
            inputPdfDocument.Close();

            //必要箇所のみ抜粋 PDFは左下が座標(0,0)
            for (int i = 0; i < outputPdfDocument.PageCount; i++)
            {
                PdfPage page = outputPdfDocument.Pages[i];

                //回転角度確認
                int deg = page.Rotate % 360;
                deg += deg < 0 ? 360 : 0;

                if (deg == 90 || deg == 270)
                {
                    if (i % 2 == 0)//奇数ページ
                    {
                        page.MediaBox = new PdfRectangle(new PdfSharp.Drawing.XRect(0, deg == 90 ? 0 : page.Height / 2, page.Width, page.Height / 2));
                    }
                    else//偶数ページ
                    {
                        page.MediaBox = new PdfRectangle(new PdfSharp.Drawing.XRect(0, deg == 90 ? page.Height / 2 : 0, page.Width, page.Height / 2));
                    }
                }
                else
                {
                    if (i % 2 == 0)//奇数ページ
                    {
                        page.MediaBox = new PdfRectangle(new PdfSharp.Drawing.XRect(deg == 180 ? page.Width / 2 : 0, 0, page.Width / 2, page.Height));
                    }
                    else//偶数ページ
                    {
                        page.MediaBox = new PdfRectangle(new PdfSharp.Drawing.XRect(deg == 180 ? 0 : page.Width / 2, 0, page.Width / 2, page.Height));
                    }
                }
            }

            //保存
            outputPdfDocument.Save(@"C:\work\cut_left_right.pdf");
        }
    }
}

文字追加

pdfファイルの各ページの下部に「ページ番号/総ページ番号」を追記します。

using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using PdfSharp.Drawing;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //元ファイル
            string file = @"C:\work\a.pdf";

            //ファイルを開く
            PdfDocument inputPdfDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);

            //出力するファイル
            PdfDocument outputPdfDocument = new PdfDocument();

            for (int i = 0; i < inputPdfDocument.PageCount; i++)
            {
                var pdfPage = outputPdfDocument.AddPage(inputPdfDocument.Pages[i]);

                //フォントの設定
                XFont xFont = new XFont("Arial", 14, XFontStyle.Regular);

                //入力するテキスト(ページ番号/総ページ番号)
                string text = (i + 1).ToString() + "/" + inputPdfDocument.PageCount.ToString();

                //テキストの追加
                XGraphics.FromPdfPage(pdfPage).DrawString(text, xFont, XBrushes.Black, new XRect(0, 0, pdfPage.Width, pdfPage.Height), XStringFormats.BottomCenter);
            }

            inputPdfDocument.Close();

            //保存
            outputPdfDocument.Save(@"C:\work\pagenum.pdf");

        }
    }
}

情報表示

pdfファイルの情報を表示します。

using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using PdfSharp.Pdf.Security;
using System;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string file = @"C:\work\a.pdf";

            PdfDocument inputPdfDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);

            //ドキュメント情報
            PdfDocumentInformation info = inputPdfDocument.Info;
            Console.WriteLine(info.Title);
            Console.WriteLine(info.Subject);
            Console.WriteLine(info.Keywords);
            Console.WriteLine(info.Owner);
            Console.WriteLine(info.Reference);
            Console.WriteLine(info.Author);
            Console.WriteLine(info.Creator);
            Console.WriteLine(info.Producer);

            //セキュリティ設定
            PdfSecuritySettings security = inputPdfDocument.SecuritySettings;
            Console.WriteLine(security.PermitAccessibilityExtractContent.ToString());
            Console.WriteLine(security.PermitAnnotations.ToString());
            Console.WriteLine(security.PermitAssembleDocument.ToString());
            Console.WriteLine(security.PermitExtractContent.ToString());
            Console.WriteLine(security.PermitFormsFill.ToString());
            Console.WriteLine(security.PermitFullQualityPrint.ToString());
            Console.WriteLine(security.PermitModifyDocument.ToString());
            Console.WriteLine(security.PermitPrint.ToString());

            inputPdfDocument.Close();
        }
    }
}

画像として保存

pdfファイルの各ページをPNGとして保存します。

using System.IO;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string file = @"C:\work\a.pdf";

            //ファイルを開く
            FileStream fs = new FileStream(file, FileMode.Open);

            //ページごとに画像として保存
            int page = 0;
            foreach (var img in PDFtoImage.Conversion.ToImages(fs))
            {
                page++;
                string outfile = @"C:\work\" + page.ToString() + ".png";
                SkiaSharp.Views.Desktop.Extensions.ToBitmap(img).Save(outfile, System.Drawing.Imaging.ImageFormat.Png);
            }

            //ファイルを閉じる
            fs.Close();
        }
    }
}
//x64
using PdfiumViewer;
using System;

namespace ConsoleApp1
{
    internal static class Program
    {
        [STAThread]
        static void Main()
        {
            string file = @"C:\work\a.pdf";
            PdfDocument inputpdfDocument = PdfDocument.Load(file);

            //解像度
            int dpi = 300;

            for (int i = 0; i < inputpdfDocument.PageCount; i++)
            {
                string outfile = @"C:\work\" + i.ToString() + ".png";
                int w = (int)inputpdfDocument.PageSizes[i].Width * dpi / 72;
                int h = (int)inputpdfDocument.PageSizes[i].Height * dpi / 72;
                System.Drawing.Image img = inputpdfDocument.Render(i, w, h, dpi, dpi, true);
                img.Save(outfile, System.Drawing.Imaging.ImageFormat.Png);
            }
        }
    }
}

表データ抽出

pdfファイル内にある全ての表のデータを抽出します。データはcsv形式で取得します。

using System;
using System.Linq;
using System.Collections.Generic;
using Tabula.Extractors;
using Tabula;
using UglyToad.PdfPig;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using (PdfDocument document = PdfDocument.Open(@"C:\work\a.pdf", new ParsingOptions() { ClipPaths = true }))
            {
                ObjectExtractor oe = new ObjectExtractor(document);

                //出力用
                System.Text.StringBuilder sb = new System.Text.StringBuilder();

                //すべてのページで処理
                for (int i = 1; i <= document.GetPages().Count(); i++)
                {
                    PageArea page = oe.Extract(i);

                    IExtractionAlgorithm ea = new SpreadsheetExtractionAlgorithm();
                    List<Table> tables = ea.Extract(page);

                    //すべての表を処理
                    foreach (var table in tables)
                    {
                        //すべての行を処理
                        foreach (var row in table.Rows)
                        {
                            //すべてのセルを処理
                            foreach (var cell in row)
                            {
                                sb.Append(cell.GetText());
                                sb.Append(",");
                            }
                            sb.Append(System.Environment.NewLine);
                        }
                        sb.Append(System.Environment.NewLine);
                    }
                }

                //結果出力
                Console.WriteLine(sb.ToString());
            }
        }
    }
}

テキスト抽出

pdfファイル内の全テキストを抽出します。

//x64
using PdfiumViewer;
using System;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string file = @"C:\work\a.pdf";
            PdfDocument inputpdfDocument = PdfDocument.Load(file);

            for (int i = 0; i < inputpdfDocument.PageCount; i++)
            {
                Console.WriteLine(inputpdfDocument.GetPdfText(i));
            }
        }
    }
}
using System;
using UglyToad.PdfPig;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using (PdfDocument document = PdfDocument.Open(@"C:\work\a.pdf", new ParsingOptions() { ClipPaths = true }))
            {
                foreach (var page in document.GetPages())
                {
                    Console.WriteLine(page.Text);
                }
            }
        }
    }
}

参考URL

PDF座標の原点

ボックスサイズ

用紙サイズ

ページレイアウト

6
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
10