Multipage PDF document from a predefined template

I have a requirement to generate invoice reports in PDF using some predefined company templates. I can create / generate SINGLE PAGE PDF reports using iTextSharp.

Problem: The problem occurs when the invoice operator covers MULTIFUNCTION PAGES . I cannot extend the report (invoice) to the next (second) page. If all the data cannot be placed on one page, this should be written on the 2nd page, while the company template is still used.

The template is present in the following way:

HostingEnvironment.MapPath("~/Content/InvoiceTemplate/invoiceTemplate.pdf") 

I use the iTextSharp library to create documents. The following is the code used to generate the PDF:

 public class pdfStatementController : Controller { Models.DYNAMICS_EXTEntities _db = new Models.DYNAMICS_EXTEntities(); // // GET: /pdfStatement/ public ActionResult SendPdfStatement(string InvoiceNumber) { try { InvoiceNumber = InvoiceNumber.Trim(); ObjectParameter[] parameters = new ObjectParameter[1]; parameters[0] = new ObjectParameter("InvoiceNumber", InvoiceNumber); List<Models.Statement> statementList = new List<Models.Statement>(); statementList = _db.ExecuteFunction<Models.Statement>("uspInvoiceStatement", parameters).ToList<Models.Statement>(); pdfStatementController.WriteInTemplate(statementList); return RedirectToAction("Invoice", "Invoice", new { id = statementList.FirstOrDefault().Customer_ID.ToString().Trim() }); } catch (Exception e) { return View("Error"); } } public static void WriteInTemplate(List<Models.Statement> statementList) { string invoiceNumber = statementList.FirstOrDefault().Invoice.ToString().Trim(); string month = null; string day = null; string year = null; PdfReader pdfReader = new PdfReader( HostingEnvironment.MapPath( "~/Content/InvoiceTemplate/invoiceTemplate.pdf")); FileStream fileStream = new FileStream( HostingEnvironment.MapPath( "~/Content/reports/" + invoiceNumber + ".pdf"), FileMode.Create); PdfStamper pdfStamper = new PdfStamper(pdfReader, fileStream); AcroFields pdfFields = pdfStamper.AcroFields; pdfFields.SetField("BillToCompany", statementList.FirstOrDefault().BillToCompany.ToString().Trim().ToUpper()); pdfFields.SetField("BillToContact", statementList.FirstOrDefault().BillToContact.ToString().Trim().ToUpper()); pdfFields.SetField("CustomerId", statementList.FirstOrDefault().Customer_ID); pdfFields.SetField("InvoiceNumber", statementList.FirstOrDefault().Invoice.ToString().Trim()); pdfFields.SetField("JobNumber", statementList.FirstOrDefault().JobNumber.ToString().Trim()); pdfFields.SetField("Caller", statementList.FirstOrDefault().Caller.ToString().Trim()); pdfStamper.FormFlattening = true; // generate a flat PDF pdfStamper.Close(); pdfReader.Close(); } } 
+4
source share
2 answers

Your code looks good and lacks a few intermediate steps.

Since you use the same PDF template for each page (when you need to create two or more pages), instead of using PdfStamper to add content directly to the Document use PdfSmartCopy or PdfCopy .

PdfStamper required. However, in this case, he used to create an embedded (separate) page filled with data as you Models.Statement over your Models.Statement collection.

In other words, PdfSmartCopy/PdfCopy supports your statements in general, (summary pages) and PdfStamper used as a buffer that adds your individual page instructions to your PDF file. Here is a simple working example of an HTTP hander (.ashx):

 <%@ WebHandler Language="C#" Class="copyFillTemplate" %> using System; using System.Collections.Generic; using System.IO; using System.Web; using iTextSharp.text; using iTextSharp.text.pdf; public class copyFillTemplate : IHttpHandler { public void ProcessRequest (HttpContext context) { HttpServerUtility Server = context.Server; HttpResponse Response = context.Response; Response.ContentType = "application/pdf"; // template used to test __this__ example; // replace with __your__ PDF template string pdfTemplatePath = Server.MapPath( "~/app_data/template.pdf" ); // this example test data; replace with __your__ data collection List<Statement> statementList = Statement.GetStatements(); // COPY FROM HERE using (Document document = new Document()) { // PdfSmartCopy reduces PDF file size by reusing parts // of the PDF template, but uses more memory. you can // replace PdfSmartCopy with PdfCopy if memory is an issue using (PdfSmartCopy copy = new PdfSmartCopy( document, Response.OutputStream) ) { document.Open(); // used to test this example int counter = 0; // generate one page per statement foreach (Statement statment in statementList) { ++counter; // replace this with your PDF form template PdfReader reader = new PdfReader(pdfTemplatePath); using (var ms = new MemoryStream()) { using (PdfStamper stamper = new PdfStamper(reader, ms)) { AcroFields form = stamper.AcroFields; // replace this with your field data for each page form.SetField("title", counter.ToString()); stamper.FormFlattening = true; } reader = new PdfReader(ms.ToArray()); // add one page at a time; assumes your template is only one page. // if your template is more than one page you will need to // call GetImportedPage() for each page in your template copy.AddPage(copy.GetImportedPage(reader, 1)); } } } // COPY TO HERE } } public bool IsReusable { get { return false; } } public class Statement { public string FieldName, FieldValue; public static List<Statement> GetStatements() { List<Statement> s = new List<Statement>(); for (int i = 0; i < 5; ++i) {s.Add(new Statement());} return s; } } } 

Let's hope the tip in the comments. And you obviously need to remove some of the parts that I used to test the sample code.

+6
source

Although the last answer is very good and helped me solve my problem, I put it here to summarize the question.

Problem: I had a script to create a multi-page PDF document in a template provided by the company. You need to create invoice reports and attach them to e-mail through Microsoft Outlook Outlook.

I am using MVC3, ASP.NET 4.0, Entity Framework

Decision:

 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Hosting; using System.Web.Mvc; using System.Data; using System.Data.Objects; using System.IO; using iTextSharp; using iTextSharp.text; using iTextSharp.text.html; using iTextSharp.text.pdf; using iTextSharp.text.xml; namespace InvoiceSearchTool.Controllers { public class pdfStatementController : Controller { Models.DYNAMICS_EXTEntities _db = new Models.DYNAMICS_EXTEntities(); // // GET: /pdfStatement/ public ActionResult SendPdfStatement(string InvoiceNumber) { try { InvoiceNumber = InvoiceNumber.Trim(); List<Models.Statement> statementList = new List<Models.Statement>(); //this is if you use entity framework { ObjectParameter[] parameters = new ObjectParameter[1]; parameters[0] = new ObjectParameter("InvoiceNumber", InvoiceNumber); statementList = _db.ExecuteFunction<Models.Statement>("uspInvoiceStatement", parameters).ToList<Models.Statement>(); } //others can simply use line like //statementList = GetStatementList(inviceNumber); pdfStatementController.WriteInTemplate(statementList); return RedirectToAction("Invoice", "Invoice", new { id = statementList.FirstOrDefault().Customer_ID.ToString().Trim() }); } catch (Exception e) { return View("Error"); } } public static void WriteInTemplate(List<Models.Statement> statementList) { try { string invoiceNumber = statementList.FirstOrDefault().Invoice.ToString().Trim(); using (Document document = new Document()) { FileStream fileStream = new FileStream(HostingEnvironment.MapPath("~/Content/reports/" + invoiceNumber + ".pdf"), FileMode.Create); using (PdfSmartCopy smartCopy = new PdfSmartCopy(document, fileStream)) { document.Open(); PdfReader pdfReader = new PdfReader(HostingEnvironment.MapPath("~/Content/InvoiceTemplate/invoiceTemplate.pdf")); using (var memoryStream = new MemoryStream()) { using (PdfStamper pdfStamper = new PdfStamper(pdfReader, memoryStream)) { string month = null; string day = null; string year = null; AcroFields pdfFields = pdfStamper.AcroFields; {//billing address pdfFields.SetField("BillToCompany", statementList.FirstOrDefault().BillToCompany.ToString().Trim().ToUpper()); pdfFields.SetField("BillToContact", statementList.FirstOrDefault().BillToContact.ToString().Trim().ToUpper()); pdfFields.SetField("ShipToCompany", statementList.FirstOrDefault().ShipToCompany.ToString().Trim().ToUpper()); pdfFields.SetField("ShipToContact", statementList.FirstOrDefault().ShipToContact.ToString().Trim().ToUpper()); pdfFields.SetField("PONumber", statementList.FirstOrDefault().PurchaseOrderNo.ToString().Trim()); pdfFields.SetField("OrderNumber", statementList.FirstOrDefault().Order_Number.ToString().Trim()); pdfFields.SetField("ShippingMethod", statementList.FirstOrDefault().Shipping_Method.ToString().Trim()); pdfFields.SetField("PaymentTerms", statementList.FirstOrDefault().Payment_Terms.ToString().Trim()); } pdfStamper.FormFlattening = true; // generate a flat PDF } pdfReader = new PdfReader(memoryStream.ToArray()); smartCopy.AddPage(smartCopy.GetImportedPage(pdfReader, 1)); } } } emailController.CreateMessageWithAttachment(invoiceNumber); } catch (Exception e) { } } using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Outlook = Microsoft.Office.Interop.Outlook; using System.Net; using System.Net.Mail; using System.Web.Hosting; using System.Net.NetworkInformation; using System.Data.Objects; namespace InvoiceSearchTool.Controllers { public class emailController : Controller { // // GET: /email/ public static void CreateMessageWithAttachment(string invoiceNumber) { try { Outlook.Application oApp = new Outlook.Application(); Outlook.MailItem email = (Outlook.MailItem)(oApp.CreateItem(Outlook.OlItemType.olMailItem)); Models.DYNAMICS_EXTEntities _db = new Models.DYNAMICS_EXTEntities(); string recipient = null; string messageBody = null; #region set email recipients { ObjectParameter[] parameters = new ObjectParameter[1]; parameters[0] = new ObjectParameter("InvoiceNumber", invoiceNumber); List<Models.EmailAddress> emailList = _db.ExecuteFunction<Models.EmailAddress>("uspGetEmailAddress", parameters).ToList<Models.EmailAddress>(); if(!string.IsNullOrEmpty(emailList[0].Email.ToString())) recipient = emailList[0].Email.ToString().Trim(); else recipient = " "; email.Recipients.Add(recipient); } #endregion //email subject email.Subject = "Invoice # " + invoiceNumber; #region set email Text { Models.EmailText emailText = _db.ExecuteFunction<Models.EmailText>("uspEmailText").SingleOrDefault(); messageBody = emailText.EmailTextLine1.ToString().Trim() + "\n\n\n\n\n\n\n\n\n"; messageBody += emailText.EmailTextLine2.ToString().Trim() + "\n"; messageBody += emailText.EmailTextLine3.ToString().Trim(); email.Body = messageBody; } #endregion #region email attachment { string fileName = invoiceNumber.Trim(); string filePath = HostingEnvironment.MapPath("~/Content/reports/"); filePath = filePath + fileName + ".pdf"; fileName += ".pdf"; int iPosition = (int)email.Body.Length + 1; int iAttachType = (int)Outlook.OlAttachmentType.olByValue; Outlook.Attachment oAttach = email.Attachments.Add(filePath, iAttachType, iPosition, fileName); } #endregion email.Display(); //uncomment below line to SendAutomatedEmail emails atomaticallly //((Outlook.MailItem)email).Send(); } catch (Exception e) { } } 
0
source

Source: https://habr.com/ru/post/1386463/


All Articles