2011-12-15 3 views
4

사전 정의 된 회사 템플릿을 사용하여 PDF로 송장 리포트를 생성해야한다는 요구 사항이 있습니다. 나는 iTextSharp를 사용하여 SINGLE PAGE PDF 보고서를 생성/생성 할 수 있습니다.미리 정의 된 템플릿에서 여러 페이지 PDF 문서

문제점 : 인보이스 명세서가 여러 페이지에 걸쳐 인 경우 문제가 발생합니다. 보고서 (송장 명세서)를 다음 (2 번째) 페이지까지 연장 할 수 없습니다. 모든 데이터를 한 페이지에 저장할 수없는 경우 회사 템플릿을 사용하면서 두 번째 페이지에 작성해야합니다.

템플릿은 다음 경로에 존재 : 나는 문서를 만들 iTextSharp 라이브러리를 사용하고

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

. 다음은 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(); 
    } 
} 
+0

당신이 모든 페이지에 대한 ** 템플리트 ** 같은-사용하고, 또는 ** 다른를 사용하고 있습니까 * * 두 번째 페이지의 템플릿? – kuujinbo

+0

모든 페이지에 동일한 템플릿을 사용하고 있습니다. – 14578446

답변

6

코드가 잘 보이며 몇 가지 중간 단계가 누락되어 있습니다.

는 모든 페이지 (두 개 이상의 페이지를 생성 할 필요가있을 때)에 대해 동일한 PDF 템플릿을 사용하여, 대신 Document에 직접 콘텐츠를 추가 할 PdfStamper를 사용하고 있기 때문에, 당신은 PdfSmartCopy 또는 PdfCopy 객체를 사용합니다.

PdfStamper은 여전히 ​​필요합니다. 그러나이 경우에는 Models.Statement 컬렉션을 반복 할 때 데이터를 채운 메모리 내 (단일) 페이지를 만드는 데 사용됩니다.

즉, PdfSmartCopy/PdfCopy은 전체 구문 (전체 페이지)을 유지하며 PdfStamper은 개별 구문을 페이지별로 페이지에 추가하는 버퍼로 사용됩니다. 다음은 HTTP 작업자 (.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's 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; 
    } 
    } 
} 

인라인 코멘트가 도움이되기를 바랍니다. 그리고 분명히 예제 코드를 테스트 할 때 사용했던 부분을 제거해야합니다.

+0

하나의 질문 : 나는 ** context **를 위해 무엇을 전달해야 할 것인가? 나는 public void ProcessRequest (HttpContext context); 이 메서드를 호출 할 메서드를 붙여 넣을 수 있습니까? – 14578446

+0

'ProcessRequest'는'IHttpHandler' 인터페이스를 구현하는 HTTP 핸들러 (.ashx)에만 적용됩니다. 따라서 HTTP 처리기를 통해 웹 컨텍스트에서 PDF를 제공하지 않으면 **이 메서드를 호출 할 수 없습니다. 위의 부분을'using (Document document ...'block/statement를 사용하십시오.) Windows Forms/desktop 응용 프로그램을 사용하고 있다면'Response.OutputStream'을'FileStream'으로 바꿔야합니다 .. – kuujinbo

+0

beginnr 인치NET에서 위의 귀하의 의견을 이해할 수 없습니다. 나는이 웹 응용에서만 사용하고 있습니다. 내 응용 프로그램에 대한 자세한 내용을 제공하기 위해 코드를 편집했습니다. 내가 MVC3을 사용하고 그래서 내 클래스 컨트롤러 클래스를 inherrits. 나는 당신의 코드가 나를 위해 일할 수 있다는 것을 알고있다. 안녕하세요 여기 hhtp 컨텍스트 개체를 찾으려면 – 14578446

0

마지막 답변은 매우 좋은 답변이며 내 문제를 해결하는 데 도움이되었지만 질문을 요약 해두고 있습니다.

문제점 : 회사에서 제공하는 템플릿에 여러 페이지 PDF 문서를 생성하는 시나리오가있었습니다. 송장 명세서를 생성하고 Microsoft Outlook 전자 메일 클라이언트를 통해 전자 메일에 첨부해야했습니다.

나는 MVC3, ASP.NET 4.0, 엔티티 프레임 워크를 사용

솔루션 :

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) 
     { 

     } 

    } 
관련 문제