我需要使用一些预定义的公司模板以PDF格式生成发票报告。我可以使用iTextSharp创建/生成 SINGLE PAGE PDF报告。
问题:当发票声明跨越 MULTIPLE PAGES 时出现问题。我无法将报告(发票声明)扩展到下一页(第2页)。如果所有数据都不能容纳在一个页面上,那么它应该写在第二页上,同时仍然使用公司模板。
模板位于以下路径:
HostingEnvironment.MapPath("~/Content/InvoiceTemplate/invoiceTemplate.pdf")
我正在使用iTextSharp库来创建文档。以下是用于生成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 :(得分:7)
您的代码看起来不错,只缺少几个中间步骤。
由于您为每个页面使用相同的PDF模板(当需要生成两个或更多页面时),而不是使用PdfStamper
直接向Document
添加内容,一个PdfSmartCopy
或PdfCopy
对象。
仍然需要PdfStamper
。但是,在这种情况下,当您迭代Models.Statement
集合时,它用于创建填充数据的内存(单个)页面。
换句话说,PdfSmartCopy/PdfCopy
维护整个语句(总页数),PdfStamper
用作缓冲区,逐页将各个语句添加到PDF中。这是一个简单的工作示例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'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;
}
}
}
希望内联评论有所帮助。你显然需要删除替换我用来测试示例代码的一些部分。
答案 1 :(得分: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)
{
}
}