Help us understand the problem. What is going on with this article?

iTextSharpでPDF出力

More than 3 years have passed since last update.

ASP.NETでのPDF出力でiTextSharpを使用したのでメモ。

前準備

nugetでiTextSharpをインストールしておく
https://www.nuget.org/packages/iTextSharp/

1からPDFを作成する方法

PDFの内容自体を1から記述して作成する方法。

HomeController.cs
public ActionResult CreatePdf()
{
    // A4横でドキュメントを作成
    var doc = new Document(PageSize.A4.Rotate());
    var stream = new MemoryStream();
    //ファイルの出力先を設定
    var pw = PdfWriter.GetInstance(doc, stream);
    //ドキュメントを開く
    doc.Open();

    ////////////////////////////////////////////////////////////////
    //
    // ドキュメントの内容を記述
    //   
    ////////////////////////////////////////////////////////////////

    //ドキュメントを閉じる
    doc.Close();

    return File(stream.ToArray(), "application/pdf", "result.pdf");
}

テンプレートに文字や画像を追加していく方法

元々のpdfに文字や画像を追加していく方法です

HomeController.cs
public ActionResult CreatePdf()
{
    // テンプレートにするファイルのパス
    var oldFile = HostingEnvironment.MapPath(@"~/App_Data/template.pdf");

    // 作成後のファイルのパス
    var newFile = HostingEnvironment.MapPath(string.Format("~/App_Data/temp/{0}.pdf", DateTime.Now.ToString("yyyyMMddhhmmss")));

    // リーダを開く
    var reader = new PdfReader(oldFile);

    // テンプレの1ページ目のページサイズを取得
    var size = reader.GetPageSize(1);
    // 開いたファイルのサイズでドキュメントを作成
    var document = new Document(size);

    // ライタを作成
    var fs = new FileStream(newFile, FileMode.Create, FileAccess.Write);
    var writer = PdfWriter.GetInstance(document, fs);
    document.Open();

    // 新しいpdfに既存のpdfのページを貼り付ける
    var pdfContentByte = writer.DirectContent;
    var page = writer.GetImportedPage(reader, 1);
    pdfContentByte.AddTemplate(page, 0, 0);

    ////////////////////////////////////////////////////////////////
    //
    // ドキュメントの内容を記述
    //   
    ////////////////////////////////////////////////////////////////  

    document.Close();

    fs.Close();
    writer.Close();
    reader.Close();

    return File(newFile, "application/pdf", "result.pdf");
}

ドキュメントの内容を記述

上記2つに共通する、pdfの内容の記述方法。
コード内の座標(x,y)は、ページの左下が原点(0, 0)となることに注意。

文字列の記述

下記コードはデフォルトで左寄せにしているが、これは指定座標から始まって左寄せで文字が記述される。
逆に右寄せにすると、指定座標を右端にして右寄せで文字が記述される。

文字を記述するときはBeginText()とEndText()で囲む必要が有るためメソッド化しておくことをオススメ。

HomeController.cs
private void ShowTextAligned(PdfContentByte pdfContentByte, float x, float y, string text, int alignment = Element.ALIGN_LEFT, float rotaion = 0)
{
    pdfContentByte.BeginText();
    pdfContentByte.ShowTextAligned(alignment, text, x, y, rotaion);
    pdfContentByte.EndText();
}

文字や画像を追加するための準備。
フォントやフォントサイズは予め指定しておかないと実行時エラーになる。

HomeController.cs
// pdfContent
var pdfContentByte = writer.DirectContent;

// ベースフォント。日本語フォントはパスを直接指定してやる必要がある。
// Font.Factoryを使用しても可。
var bf = BaseFont.CreateFont(@"c:\windows\fonts\msgothic.ttc,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

// ベースフォントとフォントサイズを指定する。
pdfContentByte.SetFontAndSize(bf, 9);

// 指定箇所に文字列を記述
this.ShowTextAligned(pdfContentByte, 100, 200, "文字列");

文字列が定まっていない場合、文字数によってははみ出す場合があります。
文字列とベースフォントのフォントサイズを用いて、予め文字列がはみ出さないよう調整することが出来ます。

HomeController.cs
// 11から0.5刻みでフォントサイズを小さくしていく
for(float tempFont = 11; 0 < tempFont; tempFont -= 0.5f){

    // 現在のフォントサイズを設定
    pdfContentByte.SetFontAndSize(bf, tempFont);

    // 文字幅を取得
    var widthPoint = bf.GetWidthPoint("書き込む予定の文字列", tempFont);

    // 文字幅が想定以内ならフォントサイズを確定して抜ける
    if(widthPoint < 200){
        break;
    }
}

画像の追加

画像を読み込んだ後、絶対座標を指定して追加する。

HomeController.cs
// pdfContent
var pdfContentByte = writer.DirectContent;

// 画像を追加
var image = Image.GetInstance(HostingEnvironment.MapPath(@"~/App_Data/image.png"));
// 表示座標の設定
image.SetAbsolutePosition(100, 200);
pdfContentByte.AddImage(image);

線を引く

1からpdfを作っていく場合は線を引くことなどもあると思います。

HomeController.cs
private void DrawLine(PdfContentByte pdfContentByte, float fromX, float fromY, float toX, float toY)
{
    pdfContentByte.MoveTo(fromX, fromY);
    pdfContentByte.LineTo(toX, toY);
    pdfContentByte.ClosePathStroke();
}

ページを追加する

pdfに新しいページを追加することが出来ます。

HomeController.cs
// ページを追加
document.NewPage();

// 追加したページにテンプレートを適用する
pdfContentByte.AddTemplate(writer.GetImportedPage(reader, 1), 1.0F, 0, 0, 1.0F, 0, 0);

終わり

他にはページを間に追加したり(←追記しました)、向きを変更したりも出来るようです。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away