代码之家  ›  专栏  ›  技术社区  ›  th1rdey3

关闭文档时调用IText7结束页事件

  •  0
  • th1rdey3  · 技术社区  · 8 年前

    我正试图遵循中给出的示例 https://developers.itextpdf.com/examples/page-events/clone-page-events-headers-and-footers#2656-variableheader.java 创建具有可变标题的PDF文档。但这些事件并没有被正确触发。这是我测试过的代码-

    class Program
    {
        public static String DEST = "test.pdf";
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
    
            manipulatePdf(DEST);
        }
    
    
        public static List<int> getFactors(int n)
        {
            List<int> factors = new List<int>();
            for (int i = 2; i <= n; i++)
            {
                while (n % i == 0)
                {
                    factors.Add(i);
                    n /= i;
                }
            }
            return factors;
        }
    
        protected static void manipulatePdf(String dest)
        {
            PdfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
            Document doc = new Document(pdfDoc, PageSize.A4, true);
            VariableHeaderEventHandler handler = new VariableHeaderEventHandler();
            pdfDoc.AddEventHandler(PdfDocumentEvent.END_PAGE, handler);
            List<int> factors;
            for (int i = 2; i < 4; i++)
            {
                factors = getFactors(i);
                if (factors.Count == 1)
                {
                    doc.Add(new Paragraph("This is a prime number!"));
                }
                foreach (int factor in factors)
                {
                    doc.Add(new Paragraph("Factor: " + factor));
                }
    
                handler.setHeader(String.Format("THE FACTORS OF {0}", i));
                if (300 != i)
                {
                    doc.Add(new AreaBreak());
                }
            }
            doc.Close();
        }
    
    
        protected class VariableHeaderEventHandler : IEventHandler
        {
            protected String header;
    
            public void setHeader(String header)
            {
                this.header = header;
            }
    
            public void HandleEvent(Event @event)
            {
                PdfDocumentEvent documentEvent = (PdfDocumentEvent)@event;
                try
                {
                    new PdfCanvas(documentEvent.GetPage())
                            .BeginText()
                            .SetFontAndSize(PdfFontFactory.CreateFont(StandardFonts.HELVETICA), 12)
                            .MoveText(450, 806)
                            .ShowText(header)
                            .EndText()
                            .Stroke();
                }
                catch (IOException e)
                {
                }
            }
        }
    }
    

    如果我运行这段代码,所有页面的标题都显示为“系数3”。但是他们应该在第一页显示“系数2”,在第二页显示“系数3”,在第三页显示“系数4”。我不知道怎么修。有什么建议吗?

    1 回复  |  直到 8 年前
        1
  •  0
  •   mkl    8 年前

    如前所述 earlier answer IText 7页面事件会被延迟触发 -不过,通常不会像您在问题标题中假定的那样,直到文档关闭,而是页面 N+ 1 在page事件发生之前可能已经快完成了 n 已处理。

    因此,设置 新建页眉 作为事件处理程序的属性,还必须告诉事件处理程序何时开始使用它。所以…

    改进的处理程序

    protected class ImprovedVariableHeaderEventHandler : IEventHandler
    {
        Dictionary<PdfPage, String> headers = new Dictionary<PdfPage, string>();
        protected String header = "";
    
        public void setHeaderFor(String header, PdfPage page)
        {
            headers[page] = header;
        }
    
        public void HandleEvent(Event @event)
        {
            PdfDocumentEvent documentEvent = (PdfDocumentEvent)@event;
            PdfPage page = documentEvent.GetPage();
            if (headers.ContainsKey(page))
            {
                header = headers[page];
                headers.Remove(page);
            }
            new PdfCanvas(page)
                    .BeginText()
                    .SetFontAndSize(PdfFontFactory.CreateFont(StandardFonts.HELVETICA), 12)
                    .MoveText(450, 806)
                    .ShowText(header)
                    .EndText()
                    .Stroke();
        }
    }
    

    这个改进的处理程序可以这样使用:

    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    Document doc = new Document(pdfDoc, PageSize.A4, true);
    ImprovedVariableHeaderEventHandler handler = new ImprovedVariableHeaderEventHandler();
    pdfDoc.AddEventHandler(PdfDocumentEvent.END_PAGE, handler);
    List<int> factors;
    for (int i = 2; i < 40; i++)
    {
        if (2 != i)
        {
            doc.Add(new AreaBreak());
        }
    
        factors = getFactors(i);
        if (factors.Count == 1)
        {
            doc.Add(new Paragraph("This is a prime number!"));
        }
        foreach (int factor in factors)
        {
            doc.Add(new Paragraph("Factor: " + factor));
        }
    
        handler.setHeaderFor(String.Format("THE FACTORS OF {0}", i), pdfDoc.GetLastPage());
    }
    doc.Close();
    

    结果是您期望的输出。

    具有多个标题元素的变体

    我们可能不想为了那么少的内容浪费那么多的页面。在这种情况下,多个数字的因式分解应该放在一个页面上,我们希望在标题中提到所有这些数字。这可以通过使用类似以下的替代事件侦听器来实现:

    protected class ImprovedVariableHeaderEventHandlerAlt : IEventHandler
    {
        Dictionary<PdfPage, String> headers = new Dictionary<PdfPage, string>();
        protected String header = "";
    
        public void addHeaderDetailFor(string header, PdfPage page)
        {
            if (headers.ContainsKey(page))
                headers[page] += ", " + header;
            else
                headers[page] = header;
        }
    
        public void HandleEvent(Event @event)
        {
            PdfDocumentEvent documentEvent = (PdfDocumentEvent)@event;
            PdfPage page = documentEvent.GetPage();
            if (headers.ContainsKey(page))
            {
                header = String.Format("THE FACTORS OF {0}", headers[page]);
                headers.Remove(page);
            }
            new PdfCanvas(page)
                    .BeginText()
                    .SetFontAndSize(PdfFontFactory.CreateFont(StandardFonts.HELVETICA), 12)
                    .MoveText(150, 806)
                    .ShowText(header)
                    .EndText()
                    .Stroke();
        }
    }
    

    使用此代码:

    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    Document doc = new Document(pdfDoc, PageSize.A4, true);
    ImprovedVariableHeaderEventHandlerAlt handler = new ImprovedVariableHeaderEventHandlerAlt();
    pdfDoc.AddEventHandler(PdfDocumentEvent.END_PAGE, handler);
    List<int> factors;
    for (int i = 2; i < 40; i++)
    {
        doc.Add(new Paragraph(String.Format("The factors of {0}", i)).SetBold());
        handler.addHeaderDetailFor(i.ToString(), pdfDoc.GetLastPage());
    
        factors = getFactors(i);
        if (factors.Count == 1)
        {
            doc.Add(new Paragraph("This is a prime number!"));
        }
        foreach (int factor in factors)
        {
            doc.Add(new Paragraph("Factor: " + factor));
        }
    }
    doc.Close();
    

    通过在为一个新数字绘制节头之后立即通知事件侦听器,该数字将在打印此节头的页的页头中提到,而实际的因子分解可能在下一页中。

    推荐文章