itext7 end_page 文档关闭时调用事件
itext7 end_page events are called when document is closed
我正在尝试按照 https://developers.itextpdf.com/examples/page-events/clone-page-events-headers-and-footers#2656-variableheader.java 中给出的示例创建一个带有变量 header 的 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)
{
}
}
}
}
如果我 运行 此代码,所有页面将 header 显示为 "THE FACTORS OF 3"。但他们应该在第一页显示 "THE FACTORS OF 2",在第二页显示 "THE FACTORS OF 3",在第三页显示 "THE FACTORS OF 4"。我不确定如何修复它。有什么建议吗?
正如在 earlier answer iText 7 页面事件中提到的那样,有一些延迟 - 通常直到文档关闭,但是,正如您在您的问题标题,但页面 n+1 可能确实在处理页面 n 的事件之前已经接近完成。
因此,将新页面header设置为事件处理程序的属性是不够的,还必须告诉事件处理程序何时开始使用它。所以...
改进的处理程序
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();
结果是你期望的输出。
具有多个 header 元素的变体
我们可能不想为这么少的内容浪费这么多页面。在那种情况下,多个数字的因式分解应该放在一个页面上,我们希望在 header 中提到所有这些。这可以使用这样的替代事件侦听器来实现:
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();
通过在为新号码绘制部分 header 后立即通知事件侦听器,该号码将在该部分 header 所在页面的页面 header 中提及打印出来,而实际的因式分解可能在下一页。
我正在尝试按照 https://developers.itextpdf.com/examples/page-events/clone-page-events-headers-and-footers#2656-variableheader.java 中给出的示例创建一个带有变量 header 的 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)
{
}
}
}
}
如果我 运行 此代码,所有页面将 header 显示为 "THE FACTORS OF 3"。但他们应该在第一页显示 "THE FACTORS OF 2",在第二页显示 "THE FACTORS OF 3",在第三页显示 "THE FACTORS OF 4"。我不确定如何修复它。有什么建议吗?
正如在 earlier answer iText 7 页面事件中提到的那样,有一些延迟 - 通常直到文档关闭,但是,正如您在您的问题标题,但页面 n+1 可能确实在处理页面 n 的事件之前已经接近完成。
因此,将新页面header设置为事件处理程序的属性是不够的,还必须告诉事件处理程序何时开始使用它。所以...
改进的处理程序
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();
结果是你期望的输出。
具有多个 header 元素的变体
我们可能不想为这么少的内容浪费这么多页面。在那种情况下,多个数字的因式分解应该放在一个页面上,我们希望在 header 中提到所有这些。这可以使用这样的替代事件侦听器来实现:
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();
通过在为新号码绘制部分 header 后立即通知事件侦听器,该号码将在该部分 header 所在页面的页面 header 中提及打印出来,而实际的因式分解可能在下一页。