barcode - 页脚中的 itext7 条码
问题描述
我正在研究一个相当复杂的解决方案,该解决方案采用类似 html 的输入并将其转换为 pdf。我试图解决的众多问题之一是将条形码(所有类型、9 种中的 3 种、PDF417 和 qr 码)添加到文档的页脚。
一些细节让我暂停了如何实施:
- 条形码将包含当前页码
- 条形码将包含总页数
- 条形码将位于其他 itext 元素(如表格单元格或段落)中,并且(在最终解决方案中)需要提前解析
了解了这些细节后,我在如何将条形码与页面 x of y 策略相结合时遇到了一些困难,即在呈现所有内容后使用模板替换页数。
我假设每个条形码都需要它自己的模板,因为页数,并跟踪模板,直到呈现所有内容,然后用适当的条形码更新每个单独的模板。但是由于页脚被提前解析出来,我需要一个代表条形码的模板,以便页脚具有正确的高度并且可以适当地调整内容。
我相信这些部分中的每一个都需要在页面结束的事件处理程序中处理,这是一个正确的评估吗?
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;
}
}
解决方案
推荐阅读
- gremlin - 有没有办法知道 gremlin 查询是读查询还是写查询
- mongodb - 在 mongodb 的不同集合中搜索覆盖的字段
- php - PHP substr 不剥离文件扩展名
- multithreading - 如何在 HostedService 中引发事件并在 Blazor 组件中使用它?
- python - 从 Azure Blob 存储加载文件内容
- python - 使用 exec() 获取类实例
- apache-spark - 将选定的列从 csv 文件加载到 Spark 中的数据框
- node.js - 是否可以手动在 simplecrawler(npm) 中完成操作?
- docker - 在运行 rabbitmq 实例的系统中使用 docker 部署 Alfresco
- python - 如何在 Python + Windows 中使用 LibreOffice API (UNO)?