我正在研究一个相当复杂的解决方案,该解决方案采用类似html的输入并将其转换为pdf。我要解决的众多问题之一是在文档的页脚中添加条形码(所有类型,共3个,共9个,PDF417和qr码)。
一些细节让我停下来执行:
知道了这些细节后,我在如何将条形码与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;
}
}