页脚中的itext7条码

时间:2018-08-21 16:39:27

标签: barcode itext7

我正在研究一个相当复杂的解决方案,该解决方案采用类似html的输入并将其转换为pdf。我要解决的众多问题之一是在文档的页脚中添加条形码(所有类型,共3个,共9个,PDF417和qr码)。

一些细节让我停下来执行:

  1. 条形码将包含当前页码
  2. 条形码将包含总页数
  3. 条形码将位于其他itext元素(如表格单元格或段落)中,并且(在最终解决方案中)需要提前解析

知道了这些细节后,我在如何将条形码与y页面x之类的东西组合起来上有点挣扎,在呈现所有内容后使用模板替换页面数的策略。

由于页数,我认为每个条形码都需要它自己的模板,并跟踪模板,直到呈现所有内容为止,然后使用适当的条形码更新每个单独的模板。但是因为页脚是提前解析的,所以我需要一个代表条形码的模板,以便页脚具有正确的高度,并且可以适当地调整内容。

我认为这些内容中的每一个都需要在事件处理程序中进行处理,这是正确的评估吗?

UPD 已编辑以包含代码示例。我从这个示例中抽出了很多我想完成的其他事情。至于提前解析的方法,不是经过1到20的循环并创建随机元素,而是通过其他一些过程来创建需要在文档上显示的所有元素,并将这些元素列表传递给渲染器。这也包括页脚内容。在这种情况下,我将在HeaderHandler的构造函数中创建页脚表,因为它接近于相同的概念。之所以提出这一点,是因为我将无法像在大多数有关页脚表的示例中看到的那样,在处理程序的HandleEvent中创建表。希望有道理。

void Main()
{
    PdfDocument pdf = new PdfDocument(new PdfWriter(Dest));
    PageSize pageSize = PageSize.A4;
    Document doc = new Document(pdf, pageSize,  true);
    HeaderHandler hh = new HeaderHandler(doc);

    ...
    some other object generation
    ... 

    // create random paragraphs to fill up multiple pages in the final solution this would have already happened.
    for (var i = 0; i < 20; i++)
        AddItemToList(elementList, i, objects);

    // add random elements back to the document 
    foreach (var e in elementList)
    {
        ... add each item just added to elementList to the document ...
    }

    renderer.Flush();

    hh.UpdateTotal(pdf);

    // I think I need to update all the barcodes and print them out here so that page count part of the barcode can be written


    doc.Close();
}

class HeaderHandler : IEventHandler
{
    Table Footer;
    Document Doc;

    public Margin First;
    public Margin Middle;
    public Margin Last;

    public Dictionary<int, Margin> PageMargins { get; set; }

    public float HeaderHeight { get; }
    public float FooterHeight { get; }

    PdfFormXObject PgCount;
    Text PageNumber;

    Dictionary<string, PdfFormXObject> BarcodeImages;   

    public HeaderHandler(Document doc)
    {
        Doc = doc;
        Footer = new Table(new float[] { 4, 2, 4}).SetAutoLayout();
        PageMargins = new Dictionary<int, Margin>();
        BarcodeImages = new Dictionary<string, PdfFormXObject>();

        var pageSize = Doc.GetPdfDocument().GetDefaultPageSize();
        var width = pageSize.GetRight() - pageSize.GetLeft() - Doc.GetLeftMargin() - Doc.GetRightMargin();

        // page total 
        PgCount = new PdfFormXObject(new Rectangle(0,0, 13, 13));

        Footer.AddCell(new Cell().Add(new Paragraph("info 1")));

        PageNumber = new Text("{page}");
        var cell = new Cell().Add(new Paragraph().Add(PageNumber).Add(" of ").Add(new Image(PgCount)).Add(" pages").SetTextAlignment(TextAlignment.CENTER));

        Footer.AddCell(cell);
        Footer.AddCell(new Cell().Add(new Paragraph("info 2")));
        Footer.AddCell("footer 1");
        Footer.AddCell("footer 2");

        //  I think I need to add a template here for the barcode as a placeholder so that when the renderersubtree is ran it provides space for the barcode
        Footer.AddCell(new Cell().Add(new Paragraph("{barcode} {qr code - {page} | {pagect} | doc name}")));

        TableRenderer fRenderer = (TableRenderer)Footer.CreateRendererSubTree();

        using (var s = new MemoryStream())
        {
            fRenderer.SetParent(new Document(new PdfDocument(new PdfWriter(s))).GetRenderer());
            FooterHeight = fRenderer.Layout(new LayoutContext(new LayoutArea(0, PageSize.A4))).GetOccupiedArea().GetBBox().GetHeight();
        }
    }

    public void UpdateTotal(PdfDocument pdf) {
        Canvas canvas = new Canvas(PgCount, pdf);
        canvas.ShowTextAligned(pdf.GetNumberOfPages().ToString(), 0, -3, TextAlignment.LEFT);
    }

    //draw footer and header tables 
    public void HandleEvent(Event e)
    {
        PdfDocumentEvent docEvent = e as PdfDocumentEvent;

        if (docEvent == null)
            return;

        PdfDocument pdf = docEvent.GetDocument();
        PdfPage page = docEvent.GetPage();
        PdfCanvas pdfCanvas = new PdfCanvas(page.GetLastContentStream(), page.GetResources(), pdf);
        int pageNum = pdf.GetPageNumber(page);
        var pageSize = Doc.GetPdfDocument().GetDefaultPageSize();

        Margin activeMargin = new Margin();

        if (PageMargins.ContainsKey(pageNum))
            activeMargin = PageMargins[pageNum];

        var width = pageSize.GetRight() - pageSize.GetLeft() - activeMargin.Left - activeMargin.Right;
        Header.SetWidth(width);
        Footer.SetWidth(width);

        var pageReferences = new List<TextRenderer>();

        // update page number text so it can be written to in the footer
        PageNumber.SetText(pageNum.ToString());

        // draw the footer
        rect = new Rectangle(pdf.GetDefaultPageSize().GetX() + activeMargin.Left, activeMargin.Bottom - GetFooterHeight(), 100, GetFooterHeight());
        canvas = new Canvas(pdfCanvas, pdf, rect);

        // I think it's here that I need to be able to add a barcode placeholder to something that can be called
        canvas.Add(Footer);
    }

    public float GetFooterHeight()
    {
        return FooterHeight;
    }
}

0 个答案:

没有答案