iTextSharp HTMLWorker ParseHTML表样式和PDFStamper

本文关键字:PDFStamper 样式 HTMLWorker ParseHTML iTextSharp | 更新日期: 2023-09-27 18:17:07

嗨,我已经成功地使用HTMLWorker来转换使用asp的gridview。. NET/c# .

(1)我已经对结果表应用了一些有限的样式,但不知道如何应用表格样式,例如网格线或应用其他格式样式,例如大列宽度,例如用于特定列。(2)我实际上想把这个文本到一个预先存在的模板,其中包含一个标志等。我以前使用过PDFStamper,但不能看到我如何同时使用PDFStamper和HTMLWorker。HTMLWorker需要一个文档来实现iDocListener…但这似乎与使用PDFStamper不兼容。我想我要找的是一种方法来创建PDFStamper,写标题等,然后从网格中添加解析的HTML。另一个问题是解析的内容不与页面上的其他内容交互。例如,下面我在页面上添加了一个标题块。解析后的HTML不是从下面开始写,而是从上面开始写。如何将解析后的HTML内容与PDF文档中的其余内容放置/交互?

提前感谢Rob

这是我已经写好的代码

            Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 30f, 0f);
            HTMLWorker htmlWorker = new HTMLWorker(pdfDoc);
            StyleSheet styles = new StyleSheet();
            styles.LoadTagStyle("th", "size", "12px");
            styles.LoadTagStyle("th", "face", "helvetica");
            styles.LoadTagStyle("span", "size", "10px");
            styles.LoadTagStyle("span", "face", "helvetica");                
            styles.LoadTagStyle("td", "size", "10px");
            styles.LoadTagStyle("td", "face", "helvetica");     
            htmlWorker.SetStyleSheet(styles);
            PdfWriter.GetInstance(pdfDoc, HttpContext.Current.Response.OutputStream);
            pdfDoc.Open();
            //Title - but this gets obsured by data, doesnt move it down
            Font font = new Font(Font.FontFamily.HELVETICA, 14, Font.BOLD);
            Chunk chunk = new Chunk(title, font);                
            pdfDoc.Add(chunk);

            //Body
            htmlWorker.Parse(sr);

iTextSharp HTMLWorker ParseHTML表样式和PDFStamper

让我先给你几个链接,当你有机会的时候看看:

  1. ItextSharp支持HTML和CSS
  2. 如何在使用itextsharp传递html到pdf时应用字体属性

这些答案更深入地探讨了正在发生的事情,我建议你有机会的时候读一读。具体来说,第二个示例将向您展示为什么需要使用pt而不是px

为了回答你的第一个问题,让我向你展示使用HTMLWorker类的不同方法。该类上有一个称为ParseToList的静态方法,它将HTML转换为List<IElement>。该列表中的对象都是HTML的iTextSharp特定版本。通常你会对这些做一个foreach,只是把它们添加到一个文档,但你可以修改它们之前添加,这是你想要做的。下面是接受静态字符串并执行以下操作的代码:

string file1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "File1.pdf");
using (FileStream fs = new FileStream(file1, FileMode.Create, FileAccess.Write, FileShare.None))
{
    using (Document doc = new Document(PageSize.LETTER))
    {
        using (PdfWriter writer = PdfWriter.GetInstance(doc, fs))
        {
            doc.Open();
            //Our HTML
            string html = "<table><tr><th>First Name</th><th>Last Name</th></tr><tr><td>Chris</td><td>Haas</td></tr></table>";
            //ParseToList requires a StreamReader instead of just a string so just wrap it
            using (StringReader sr = new StringReader(html))
            {
                //Create a style sheet
                StyleSheet styles = new StyleSheet();
                //...styles omitted for brevity
                //Convert our HTML to iTextSharp elements
                List<IElement> elements = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(sr, styles);
                //Loop through each element (in this case there's actually just one PdfPTable)
                foreach (IElement el in elements)
                {
                    //If the element is a PdfPTable
                    if (el is PdfPTable)
                    {
                        //Cast it
                        PdfPTable tt = (PdfPTable)el;
                        //Change the widths, these are relative width by the way
                        tt.SetWidths(new float[] { 75, 25 });
                    }
                    //Add the element to the document
                    doc.Add(el);
                }
            }
            doc.Close();
        }
    }
}

希望你能看到,一旦你获得了原始的PdfPTable,你可以根据需要调整它。

回答你的第二个问题,如果你想用PdfStamper使用正常的ParagraphChunk对象,那么你需要使用PdfContentByte对象。您可以通过以下两种方式从您的模板中获取此信息,要么要求位于现有内容"之上"的内容(stamper.GetOverContent(int)),要么位于现有内容"之下"的内容(stamper.GetUnderContent(int))。两个版本都使用一个参数来表示要处理哪个页面。一旦你有了一个PdfContentByte,你可以创建一个ColumnText对象绑定到它,并使用这个对象的AddElement()方法来添加你的普通元素。在此之前(这将回答您的第三个问题),您需要创建至少一个"列"。当我这样做时,我通常会创建一个覆盖整个页面的页面。(这部分可能听起来很奇怪,但我们实际上是创建一个单行,单列的表格单元格来添加我们的对象)

下面是一个完整的c# 2010 WinForms应用程序,目标是iTextSharp 5.1.1.0,它展示了上面的所有内容。首先,它在桌面上创建一个通用的PDF。然后在第一个文档的基础上创建第二个文档,添加一个段落和一些HTML。如有任何问题,请参阅代码中的注释。

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using iTextSharp.text;
using iTextSharp.text.html.simpleparser;
using iTextSharp.text.pdf;
using System.IO;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            //The two files that we are creating
            string file1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "File1.pdf");
            string file2 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "File2.pdf");
            //Create a base file to write on top of
            using (FileStream fs = new FileStream(file1, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                using (Document doc = new Document(PageSize.LETTER))
                {
                    using (PdfWriter writer = PdfWriter.GetInstance(doc, fs))
                    {
                        doc.Open();
                        doc.Add(new Paragraph("Hello world"));
                        doc.Close();
                    }
                }
            }
            //Bind a reader to our first document
            PdfReader reader = new PdfReader(file1);
            //Create our second document
            using (FileStream fs = new FileStream(file2, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                using (PdfStamper stamper = new PdfStamper(reader, fs))
                {
                    StyleSheet styles = new StyleSheet();
                    //...styles omitted for brevity
                    //Our HTML
                    string html = "<table><tr><th>First Name</th><th>Last Name</th></tr><tr><td>Chris</td><td>Haas</td></tr></table>";
                    //ParseToList requires a StreamReader instead of just a string so just wrap it
                    using (StringReader sr = new StringReader(html))
                    {
                        //Get our raw PdfContentByte object letting us draw "above" existing content
                        PdfContentByte cb = stamper.GetOverContent(1);
                        //Create a new ColumnText object bound to the above PdfContentByte object
                        ColumnText ct = new ColumnText(cb);
                        //Get the dimensions of the first page of our source document
                        iTextSharp.text.Rectangle page1size = reader.GetPageSize(1);
                        //Create a single column object spanning the entire page
                        ct.SetSimpleColumn(0, 0, page1size.Width, page1size.Height);
                        ct.AddElement(new Paragraph("Hello world!"));
                        //Convert our HTML to iTextSharp elements
                        List<IElement> elements = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(sr, styles);
                        //Loop through each element (in this case there's actually just one PdfPTable)
                        foreach (IElement el in elements)
                        {
                            //If the element is a PdfPTable
                            if (el is PdfPTable)
                            {
                                //Cast it
                                PdfPTable tt = (PdfPTable)el;
                                //Change the widths, these are relative width by the way
                                tt.SetWidths(new float[] { 75, 25 });
                            }
                            //Add the element to the ColumnText
                            ct.AddElement(el);
                        }
                        //IMPORTANT, this actually commits our object to the PDF
                        ct.Go();
                    }
                }
            }
            this.Close();
        }
    }
}
protected void LinkPdf_Click(object sender, EventArgs e)
{
    Response.ContentType = "application/pdf";
    Response.AddHeader("content-disposition", "attachment;filename=TestPage.pdf");
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    StringWriter sw = new StringWriter();
    HtmlTextWriter hw = new HtmlTextWriter(sw);
    this.Page.RenderControl(hw);
    StringReader sr = new StringReader(sw.ToString());
    Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 100f, 0f);
    HTMLWorker htmlparser = new HTMLWorker(pdfDoc);
    PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
    pdfDoc.Open();
    htmlparser.Parse(sr);
    pdfDoc.Close();
    Response.Write(pdfDoc);
    Response.End();
}