如何使用iTextSharp将多页ToC写入由合并文档组成的PDF的末尾?
使用java中的itext库为合并后的pdf创建索引文件(TOC)的答案解释了如何在合并pdf时创建TOC页面(在iTextSharp的书中编目http://developers.itextpdf.com/examples/merging-pdf-documents/merging-documents-and-create-table-contents#795-mergewithtoc.java)。这个答案中的代码是基于这些例子的。
然而,只有当ToC为1页长时,它才有效。如果内容变长,那么它会在同一页上重复,而不是跨到下一页。
尝试通过将链接直接添加到文本中
ct.Add(new Chunk("link").SetLocalGoto("p1"))
导致异常("无法添加批注,文档中的页面不足")。
有人能解释一种方法吗?该方法允许我在合并PDF时将多页内容附加到PDF中(方法越通用越好)。有没有一种方法可以使用document.Add()写入文档,而不必在模板页中复制并在其顶部写入?
(注意,代码在c#中)
此答案基于iTextSharp文档中的示例,但已转换为C#。
为了使添加的文本跨越多个页面,我发现我可以使用ColumnText.HasMoreText(ct.Go())
来告诉我是否有超出当前页面容量的文本。然后,您可以保存当前页面,重新创建新的页面模板,并将列文本移动到新页面。下面是一个名为CheckForNewPage:的函数
private bool CheckForNewPage(PdfCopy copy, ref PdfImportedPage page, ref PdfCopy.PageStamp stamp, ref PdfReader templateReader, ColumnText ct)
{
if (ColumnText.HasMoreText(ct.Go()))
{
//Write current page
stamp.AlterContents();
copy.AddPage(page);
//Start a new page
ct.SetSimpleColumn(36, 36, 559, 778);
templateReader = new PdfReader("template.pdf");
page = copy.GetImportedPage(templateReader, 1);
stamp = copy.CreatePageStamp(page);
ct.Canvas = stamp.GetOverContent();
ct.Go();
return true;
}
return false;
}
每次将文本添加到ct变量时都应调用此函数。
如果CheckForNewPage返回true,则可以增加页面计数,并将y变量重置到新页面的顶部,以便链接注释位于新页面的正确位置。
例如
var tocPageCount = 0;
var para = new iTextSharp.text.Paragraph(documentName);
ct.AddElement(para);
ct.Go();
if (CheckForNewPage(context, copy, ref page, ref stamp, ref tocReader, ct))
{
tocPageCount++;
y = 778;
}
//Add link annotation
action = PdfAction.GotoLocalPage(d.DocumentID.ToString(), false);
link = new PdfAnnotation(copy, TOC_Page.Left, ct.YLine, TOC_Page.Right, y, action);
stamp.AddAnnotation(link);
y = ct.YLine;
这样可以正确创建页面。下面的代码适用于ToC2示例的末尾,以便重新排序页面,以便处理1页以上的页面。
var rdr = new PdfReader(baos.toByteArray());
var totalPageCount = rdr.NumberOfPages;
rdr.SelectPages(String.Format("{0}-{1}, 1-{2}", totalPageCount - tocPageCount +1, totalPageCount, totalPageCount - tocPageCount));
PdfStamper stamper = new PdfStamper(rdr, new FileStream(outputFilePath, FileMode.Create));
stamper.Close();
通过重新使用CheckForNewPage功能,您应该能够将任何内容添加到您创建的新页面中,并使其跨越多个页面。如果你不需要注释,你可以在添加所有内容结束时循环调用CheckForNewPage(只是不要事先调用ct.Go())。