iTextSharp HTMLWorker ParseHTML Tablestyle和PDFStamper

时间:2011-12-07 11:34:24

标签: c# asp.net itextsharp

您好我已成功使用HTMLWorker使用asp.NET / C#转换gridview。

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

提前致谢 罗布

这里是我已经编码的代码

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

2 个答案:

答案 0 :(得分:12)

让我先给你一些链接,以便在有机会时查看:

  1. ItextSharp support for HTML and CSS
  2. How to apply font properties on while passing html to pdf using itextsharp
  3. 这些答案会更深入地了解正在发生的事情,我建议您在有机会时阅读它们。具体而言,第二个将向您展示为什么需要使用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的访问权限,您就可以根据需要进行调整。

    要回答您的第二个问题,如果您想将ParagraphChunk对象与PdfStamper一起使用,则需要使用PdfContentByte个对象。您可以通过以下两种方式之一从压模获取此信息,方法是要求位于现有内容“{1}}之上的”stamper.GetOverContent(int)或位于“现有内容”stamper.GetUnderContent(int)“下方的内容。两个版本都使用一个参数来说明要使用的页面。获得PdfContentByte后,您可以创建绑定到它的ColumnText对象,并使用此对象的AddElement()方法添加常规元素。在执行此操作之前(这将回答您的第三个问题),您将需要创建至少一个“列”。当我这样做时,我通常创建一个基本上覆盖整个页面的。 (这部分可能听起来很奇怪,但我们基本上只需要一行,单列表格单元格来添加我们的对象。)

    以下是针对iTextSharp 5.1.1.0的全功能C#2010 WinForms应用程序,它展示了上述所有内容。首先,它在桌面上创建通用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();
            }
        }
    }
    

答案 1 :(得分:-2)

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();
}