iTextSharpを使ったPDF作成
.NET環境でPDF出力をする場面があったので自分用まとめ。
基本的にPDF作成は各要素をテーブルにして作成した方が調整するときにやり易い。
using iTextSharp.text; using iTextSharp.text.pdf; /// <summary> /// PDFファイルを作成 /// ※1、フォーマット用のPDFファイルがある場合 /// ※2、複数枚のPDFを連続に出力する場合も対応可能 /// ※3、ウェブ・バッチ両方から呼ばれる場合を想定(共通ロジック) /// </summary> /// <param name="pdfStream">PDFストリーム</param> /// <param name="resPdfModelList">PDF作成用のモデル(リスト)</param> /// <param name="isCallFromBatch">ウェブ/バッチ両方から呼ばれる場合の判定用</param> public void MakePdfStream(MemoryStream pdfStream, List<ResPdfModel> resPdfModelList, bool isCallFromBatch) { var currenAppDatatPath = string.Empty; if (isCallFromBatch) { currenAppDatatPath = AppDomain.CurrentDomain.BaseDirectory + "App_Data"; } else { currenAppDatatPath = HttpContext.Current.Request.PhysicalApplicationPath + "App_Data"; } // Documentオブジェクト作成 var document = new Document(); var writer = PdfWriter.GetInstance(document, pdfStream); // フォントの準備 FontFactory.RegisterDirectories(); // フォント設定 var baseFont = FontFactory.GetFont("MS Gothic", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, 8f); // 初期数値 var paddingDefaultValue = 4f; var BorderDefaultValue = 0f; var leadingDefaultValue = 11f; // フォーマット情報を取得 string pdfFormatPath = string.Empty; PdfReader reader = null; int formatPageCount = 0; PdfImportedPage page1 = null; PdfImportedPage page2 = null; PdfImportedPage page3 = null; bool uniqueFormat = false; if (resPdfModelList.Count == 1 || resPdfModelList.Count == resPdfModelList.Count(x => x.FormatPath == resPdfModelList[0].FormatPath)) { // 全てのデータのフォーマットの値が同じの場合、foreachの前にPdfReaderを作成する。 // もしフォーマットの値が異なる場合はforeachの中で行う。 reader = new PdfReader(currenAppDatatPath + resPdfModelList[0].FormatPath); formatPageCount = reader.NumberOfPages; page1 = writer.GetImportedPage(reader, 1); page2 = writer.GetImportedPage(reader, 2); if (formatPageCount > 2) { page3 = writer.GetImportedPage(reader, 3); } uniqueFormat = true; } // 1P目 document.Open(); var pdfContentByte = writer.DirectContent; var listCount = 0; var count = 1; var tableBaseFont = baseFont; var cell = new PdfPCell(new Phrase(string.Empty, baseFont)); var fixedHeightDefaultValueFor1page = 16.7f; var fixedHeightDefaultValue = 21f; var xPosDefaultValue = 119f; var tableWidthDefaultValue = 434f; foreach (var resPdfModel in resPdfModelList) { // 全てのデータのフォーマットが同じじゃない場合、その都度フォーマットを読み取る if (!uniqueFormat) { reader = new PdfReader(resPdfModel.FormatPath); formatPageCount = reader.NumberOfPages; page1 = writer.GetImportedPage(reader, 1); page2 = writer.GetImportedPage(reader, 2); if (formatPageCount > 2) { page3 = writer.GetImportedPage(reader, 3); } } if (listCount != 0) { document.NewPage(); } // 背景にテンプレートを設定 pdfContentByte.AddTemplate(page1, 0f, 0f); pdfContentByte.BeginText(); pdfContentByte.SetFontAndSize(baseFont.BaseFont, 8); pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, resPdfModel.AccountIDForHeader, 515f, 800f, 0); pdfContentByte.EndText(); #region #### サンプル「内容」 #### var infoTableWidths = new float[] { 0.41f, 0.165f, 0.425f }; var infoTable = new PdfPTable(3); infoTable.SetWidths(infoTableWidths); infoTable.TotalWidth = tableWidthDefaultValue; var infoTableData = new List<string>(); infoTableData.Add(resPdfModel.AccountID); infoTableData.Add(""); infoTableData.Add(resPdfModel.RegisteredPhoneNumber); infoTableData.Add(resPdfModel.ContractName); infoTableData.Add(""); infoTableData.Add(resPdfModel.PaymentMethod); count = 1; foreach (string title in infoTableData) { cell = new PdfPCell(new Phrase(GetChunk(title, tableBaseFont))); cell.BorderWidth = BorderDefaultValue; cell.BorderColor = new BaseColor(255, 153, 255); cell.FixedHeight = fixedHeightDefaultValueFor1page; cell.VerticalAlignment = Element.ALIGN_MIDDLE; cell.PaddingLeft = paddingDefaultValue; infoTable.AddCell(cell); count++; } infoTable.WriteSelectedRows(0, 10, xPosDefaultValue, 754f, pdfContentByte); #endregion // ==== 以下、1pの内容を記述 ==== // 2P目 document.NewPage(); pdfContentByte.AddTemplate(page2, 0f, 0f); pdfContentByte.BeginText(); pdfContentByte.SetFontAndSize(baseFont.BaseFont, 8); pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, resPdfModel.AccountIDForHeader, 525f, 812f, 0); pdfContentByte.EndText(); // ==== 以下、2pの内容を記述 ==== listCount++; } document.Close(); reader.Close(); } /// <summary> /// 文字間隔の設定用 /// </summary> /// <param name="text"></param> /// <param name="font"></param> /// <returns></returns> private Chunk GetChunk(string text, Font font) { Chunk chunk = new Chunk(text, font); chunk.SetCharacterSpacing(-0.6f); return chunk; }
追記:角が丸い四角形を描画する(2017.05.11)
PdfContentByte contentByte = writer.DirectContent; // x軸、y軸、横幅、縦幅、半径範囲(0(完全な四角)~10f(ほぼ円の形))※2~6fくらいが自然な気がする contentByte.RoundRectangle(100f, 200f, 50f, 20f, 6f); contentByte.SetLineWidth(0.5f); contentByte.Stroke();