【问题标题】:Itextsharp - check to see if adding an element will create a new pageItextsharp - 检查添加元素是否会创建新页面
【发布时间】:2012-05-20 05:48:44
【问题描述】:

我正在使用 ITextSharp 将 HTML 文档转换为 PDF。我使用 HTMLWorker.ParseToList 并依次遍历每个项目。这很好用,但是第一页需要与后续页面具有不同的边距大小。我可以通过调用 MyDocument.NewPage() 和调用 MyDocument.SetMargins() 来做到这一点。

尝试检测页面转换时出现我的问题。

我可以使用循环来跟踪页面转换,然后调用 NewPage() 并重置页边距,但是,只有在我实际添加了一个换行到新页面上的段落时才会发生这种情况,从而使整个页面实际上是白色的-空格。

如果我添加某个段落对象,我需要一种预先检测页面是否会更改的方法。 我已经尝试使用 ColumnText.Go(true) 来模拟它(如果结果是 ColumnText.NO_MORE_COLUMN,则将其设为分页符),不幸的是,这似乎充其量是易碎的,并且倾向于检测分页符完全错误的地方。

这是我当前的代码:

            ColumnText simulation = new ColumnText(Writer.DirectContent);
            simulation.SetSimpleColumn(Writer.PageSize);   
            bool FirstPage = true;
            foreach (var item in ItemList)
            {
                var para = new Paragraph("", Normal);
                para.AddAll(item.Chunks);                    
                para.SpacingAfter = 10;
                foreach (Chunk c in item.Chunks)
                {
                    simulation.AddText(c);
                }
                if(FirstPage) {
                    int simresult = simulation.Go(true);
                    if(simresult == (int)ColumnText.NO_MORE_COLUMN)
                    {
                        textDocument.SetMargins(100,100,100,100);
                        textDocument.NewPage();    
                        FirstPage = false;                 
                    }
                }

                textDocument.Add(para);
            }

这导致它直到第 2 页结束才检测到分页符。这不好。

我发现让它工作的唯一方法是将进入simulation.SetSimpleColumn的高度减半。

它有效,但我不知道为什么,老实说,这不好。如果有人能给我任何见解,那就太好了。



感谢亚历克西斯,我已经解决了。 ITextSharp 非常彻底地遵循 Java 事件模型,这很烦人,因为我直接在 Writer 和 Document 中查找事件。 首先,我必须创建一个覆盖 PdfPageEventHelper 的类:
internal class MainTextEventsHandler : PdfPageEventHelper
{
    public override void OnStartPage(PdfWriter writer, Document document)
    {
        document.SetMargins(document.LeftMargin, document.LeftMargin, document.TopMargin, document.BottomMargin); //Mirror the horizontal margins
        document.NewPage(); //do this otherwise the margins won't take
    }
}

接下来,我设置了 Writer 对象的 PageEvent 属性,并修改了循环以移除模拟。

        Writer.PageEvent = new MainTextEventsHandler();
        foreach (var item in ItemList)
        {
            var para = new Paragraph("", Normal);
            para.AddAll(item.Chunks);
            /* per-paragraph stuff here */
            para.SpacingAfter = 10;                    
            textDocument.Add(para);
        }

【问题讨论】:

    标签: c# html pdf itextsharp


    【解决方案1】:

    试试这个代码:

    public const string pageBreakHtmlMarker = "<!-- pageBreak -->";
    public MemoryStream htmlToPdf(string html)
    {
        MemoryStream msOutput = new MemoryStream();
        string[] sep = new string[] { pageBreakHtmlMarker };
        string[] arrHtml = html.Split(sep, 9999, StringSplitOptions.RemoveEmptyEntries);
        htmlToPdf(arrHtml, ref msOutput);
        return msOutput;
    }
    private void htmlToPdf(string[] arrHtmlPages, ref MemoryStream msOutput)
    {
        using (Document document = new Document(PageSize.A4, 30, 30, 30, 30))
        {
            using (HTMLWorker worker = new HTMLWorker(document))
            {
                PdfWriter writer = PdfWriter.GetInstance(document, msOutput); // writer to listen doc ad direct a XML-stream to a file            
                document.Open();
                worker.StartDocument();
                foreach (string html in arrHtmlPages)
                {
                    TextReader reader = new StringReader(html); // parse the html into the document
                    worker.Parse(reader);
                    document.Add(Chunk.NEXTPAGE);
                }
                worker.EndDocument();
            }
        }
    }
    

    【讨论】:

    • 你能解释一下这个答案吗?我不明白这将如何解决 OP 的问题。
    【解决方案2】:

    Visual Basic 中的示例 sn-p

    LoadPage 中使用:

    Dim pdfPageEvents As pdfPageEvents = New pdfPageEvents
    writer = PdfWriter.GetInstance(doc, memMemoryStream)
    writer.CloseStream = False
    writer.PageEvent = pdfPageEvents
    doc.Open()
    

    把这个类放到同一个文件或命名空间中

    Public Class pdfPageEvents
        Inherits iTextSharp.text.pdf.PdfPageEventHelper
        Private _strTitle As String, _strPrintFeatures As String
    
        Public Sub New(ByVal Title As String, ByVal PrintFeatures As String)
            _strTitle = Title
            _strPrintFeatures = PrintFeatures
        End Sub
    
        Public Overrides Sub OnStartPage(ByVal writer As PdfWriter, ByVal doc As Document)
            If InStr(_strPrintFeatures, "header") > 0 Then
                Dim fntFont As Font = FontFactory.GetFont("Tahoma", BaseFont.CP1250, True, 10, Font.NORMAL, New BaseColor(128, 128, 128))
                Dim imgImage As iTextSharp.text.Image = iTextSharp.text.Image.GetInstance(HttpContext.Current.Server.MapPath("../LocalResources/Images/print_company_logo_medium.png"))
                Dim tblTable As New PdfPTable(2)
                Dim celRightCell As PdfPCell
    
                tblTable.WidthPercentage = 100
                tblTable.HorizontalAlignment = Element.ALIGN_CENTER
                imgImage.ScalePercent(70)
    
                Dim celLeftCell As New PdfPCell(New Phrase(_strTitle, fntFont))
                celLeftCell.HorizontalAlignment = Element.ALIGN_LEFT
                celLeftCell.Border = 0
                celLeftCell.BorderWidthBottom = 0.5
                celLeftCell.BorderColorBottom = New BaseColor(128, 128, 128)
                celLeftCell.VerticalAlignment = Element.ALIGN_BOTTOM
                celLeftCell.PaddingBottom = 3
                tblTable.AddCell(celLeftCell)
    
                If InStr(_strPrintFeatures, "logo") > 0 Then
                    celRightCell = New PdfPCell(imgImage)
                Else
                    celRightCell = New PdfPCell(New Paragraph(""))
                End If
    
                celRightCell.HorizontalAlignment = Element.ALIGN_RIGHT
                celRightCell.Border = 0
                celRightCell.BorderWidthBottom = 0.5
                celRightCell.BorderColorBottom = New BaseColor(128, 128, 128)
                celRightCell.VerticalAlignment = Element.ALIGN_BOTTOM
                celRightCell.PaddingBottom = 3
                tblTable.AddCell(celRightCell)
    
                doc.Add(tblTable)
                doc.Add(New Paragraph(vbNewLine))
            End If
        End Sub
    
        Public Overrides Sub OnEndPage(ByVal writer As PdfWriter, ByVal doc As Document)
            If InStr(_strPrintFeatures, "footer") > 0 Then
                Dim fntFont As Font = FontFactory.GetFont("Tahoma", BaseFont.CP1250, True, 10, Font.NORMAL, New BaseColor(128, 128, 128))
                Dim tblTable As New PdfPTable(2)
                Dim strDate As String = IIf(InStr(_strPrintFeatures, "date") > 0, FormatDateTime(Date.Today, DateFormat.GeneralDate), "")
    
                tblTable.TotalWidth = doc.PageSize.Width - doc.LeftMargin - doc.RightMargin
                tblTable.HorizontalAlignment = Element.ALIGN_CENTER
    
                Dim celLeftCell As New PdfPCell(New Phrase(strDate, fntFont))
                celLeftCell.HorizontalAlignment = Element.ALIGN_LEFT
                celLeftCell.Border = 0
                celLeftCell.BorderWidthTop = 0.5
                celLeftCell.BorderColorTop = New BaseColor(128, 128, 128)
                celLeftCell.VerticalAlignment = Element.ALIGN_BOTTOM
                tblTable.AddCell(celLeftCell)
    
                Dim celRightCell As New PdfPCell(New Phrase(CStr(doc.PageNumber), fntFont))
                celRightCell.HorizontalAlignment = Element.ALIGN_RIGHT
                celRightCell.Border = 0
                celRightCell.BorderWidthTop = 0.5
                celRightCell.BorderColorTop = New BaseColor(128, 128, 128)
                celRightCell.VerticalAlignment = Element.ALIGN_BOTTOM
                tblTable.AddCell(celRightCell)
                tblTable.WriteSelectedRows(0, -1, doc.LeftMargin, (doc.BottomMargin), writer.DirectContent)
            End If
        End Sub
    End Class
    

    【讨论】:

    • 你能解释一下这个答案吗?我不明白这将如何解决 OP 的问题。
    【解决方案3】:

    查看Page Events,尤其是onStartPage 和/或onEndPage,以确定您是否必须更改文档的边距。

    请注意,这些示例适用于 Java 版本,但转换为 iTextSharp 应该很简单。

    【讨论】:

    • 看起来他们只是直接将 Java 移植到 C# 并忽略了 C# 事件模型。我必须创建一个单独的迷你类,其中包含一个函数(覆盖 OnStartPage),它继承了 PdfPageEventHelper 并将我的 .SetMargins 和 .NewPage() 调用放在那里。现在工作正常,甚至不需要模拟,但是只给对象本身事件有什么问题?
    • @Canazza 我不是 iText 提交者,所以我真的不知道。也许你可以在iText mailing-list 上问这个问题。请注意,您必须订阅该列表才能在那里发帖。
    猜你喜欢
    • 1970-01-01
    • 2013-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-25
    • 2015-02-08
    相关资源
    最近更新 更多