c# - 将整个旧的 Lowagie PDF 生成器迁移到 iText 7 c#。创建目录
问题描述
由于在 API 的早期版本中存在 Anchor 对象,它应该作为文本中的链接工作,我正在尝试在许多教程中寻找一种添加 TOC 的方法,将您从索引重定向到标题所在的页面。
问题是我正在生成基于 XML 文档的 PDF,因此 TOC 会因 XML 内容而异。
我已经从 0 开始使用 iText7 for C# 并且感谢 itextpdf.com 上的教程和一些 stackOverflow 教程,在许多其他人之间,我已经能够制作几乎所有我想要的东西,除了这个。无论如何,我很困惑,因为我只找到旧的 iText5 引用或更旧的 iText7 java 引用,有时我无法“翻译”成 c# 等。
我尝试为包含标题和我想去的页面的单元格设置一个属性。
我还查看了一些谈论从文件中添加内容的地方。但是,这已经在我的代码中完成了,所以我应该直接处理字符串。甚至不是一个数组(或任何类似的),因为我将逐个字符串处理。
pe:我的程序从节点接收 XML 值“第 1 章”,并自动将其添加到字符串中。所以,我会在需要的段落和目录中添加这个字符串。
这样做是因为它是一个非常复杂的 XML 文件(例如,文件中有 848 行)。
Paragraph indice = new Paragraph(new Text("Here the TOC line"));
Paragraph title = new Paragraph(new Text("Here the title"));
/*This goes at page 20. I am making further investigation so as to locate how should I look for the page (Looking for the string at the doc and getting the page, for example)*/
indice.SetProperty(Property.ACTION, PdfAction.CreateGoToR(@"C:\aplic\pdfPruebasIText\pdfPruebasIText\docPrueba.pdf", 20));
(Document) docPDF.add(indice);//TOC goes first
//More content
docPDF.add(title);//What I want indexed
我正在我的 docPrueba.pdf 文档中添加更多文本、段落、表格等。刚刚添加了我认为是我的问题的主线。如有必要,我会添加更多行
理论上,它应该转到我的文档 docPrueba.pdf 的第 20 页实际上,它什么也不做,除了让鼠标指针改变它的形状。
没有显示错误消息,也没有任何错误。我添加的所有内容都生成了,除了这个失败。
解决方案
基于此线程:iText7 目录
我编写了代码,以便在处理文档时可以向 TOC 添加行。
现在的主要问题是目录是在文档的末尾创建的(哎呀!)。所以我现在正在努力解决这个问题。
现在,我将在此处添加修改后的代码:
string tit0 = "Titulo 0";//Title strings to add to a Dictionary
string tit1 = "Titulo 1";
string tit2 = "Titulo 2";
Dictionary<string, KeyValuePair<string, int>> indiceRelaciones = new Dictionary<string, KeyValuePair<string, int>>();
indiceRelaciones=EscribirIndicePDF(innerDoc, DocPDF, tit0, indiceRelaciones);//HERE the title is added to the document and the dictionary flushed
DocPDF.Add(parrafo1);//Paragraphs, tables and stuff
DocPDF.Add(tabla1);
DocPDF.Add(tabla2);
indiceRelaciones = EscribirIndicePDF(innerDoc, DocPDF, tit1, indiceRelaciones);
DocPDF.Add(parrafo2);
indiceRelaciones = EscribirIndicePDF(innerDoc, DocPDF, tit2, indiceRelaciones);
DocPDF.Add(parrafo3);
crearIndice(innerDoc, DocPDF, indiceRelaciones);//This method generates the TOC
DocPDF.Close();
private static Dictionary<string, KeyValuePair<string, int>> EscribirIndicePDF(PdfDocument innerDoc, Document docPDF, string tit, Dictionary<string, KeyValuePair<string, int>> indice)
{
Paragraph titulo = new Paragraph().Add(new Text(tit));
titulo.SetKeepTogether(true);
outline = CreateOutline(outline, innerDoc, tit);
KeyValuePair<string, int> paginaTitulo = new KeyValuePair<string, int>(tit, innerDoc.GetNumberOfPages());
titulo.SetFontColor(ColorConstants.BLUE).SetDestination(tit).SetKeepWithNext(true).SetNextRenderer(new UpdatePageRenderer(titulo, paginaTitulo));
docPDF.Add(titulo);
indice.Add(tit, paginaTitulo);
return indice;
}
private static void crearIndice(PdfDocument innerDoc, Document docPDF, Dictionary<string, KeyValuePair<string, int>> indiceRelaciones)
{//¡Este método crea en la primera página el índice! Este no se toca. Se modifica el otro para que se llame y se agreguen entradas al diccionario.
List<TabStop> tabStops = new List<TabStop>();
tabStops.Add(new TabStop(580, TabAlignment.RIGHT, new DottedLine()));
foreach (KeyValuePair<string, KeyValuePair<string, int>> entrada in indiceRelaciones) {
KeyValuePair<string, int> texto = entrada.Value;
string claveEntrada = entrada.Key;
string claveTexto = texto.Key;
string valorTexto = texto.Value.ToString();
Paragraph p = new Paragraph().AddTabStops(tabStops).Add(claveTexto).Add(new Tab()).Add(valorTexto).SetAction(PdfAction.CreateGoTo(claveEntrada));
docPDF.Add(p);
}
}
private static PdfOutline CreateOutline(PdfOutline outline, PdfDocument innerDoc, string line)
{
if (outline == null)
{
outline = innerDoc.GetOutlines(false);
outline = outline.AddOutline(line);
outline.AddDestination(PdfDestination.MakeDestination(new PdfString(line)));
return outline;
}
PdfOutline hijo = outline.AddOutline(line);
hijo.AddDestination(PdfDestination.MakeDestination(new PdfString(line)));
return outline;
}
internal class UpdatePageRenderer : ParagraphRenderer
{
private KeyValuePair<string, int> Entrada;
public UpdatePageRenderer(Paragraph modelElement, KeyValuePair<string, int> entrada) : base(modelElement)
{
Entrada = entrada;
}
public override LayoutResult Layout(LayoutContext layoutContext)
{
LayoutResult result = base.Layout(layoutContext);
int pagina = layoutContext.GetArea().GetPageNumber();
Entrada = new KeyValuePair<string, int>(Entrada.Key, pagina);
return result;
}
}
我为使用西班牙名字道歉。我将编辑这篇文章以使用英文名称,以便每个人都能理解代码。
现在...
我将尝试在第一页获取目录(应该如此)
推荐阅读
- php - 使用 max_length form_validation 时出错
- c# - 'Microsoft.Azure.Devices.Client' 中的 ReceiveAsync 方法是否消耗 Internet?
- java - 使用 MOXY 的 Jersey JSON 到对象转换不起作用
- r - 如何将此垂直数据集转换为水平数据集?
- assembly - 如何计算汇编指令的时钟周期
- google-colaboratory - 从 Google Colab 的工作区本地下载文件会使用我的互联网还是 Colab 的互联网?
- java - 我使用从 maven 生成的 jar 通过 install4j 为我的应用程序创建了一个安装程序。为什么执行.exe时找不到主类?
- java - 使用 AOP 进行注释 - 在方法级别工作,而只有类被注释
- typescript - 在 typescript 中使用 SES 发送电子邮件
- flutter - 我们如何使用 Flutter 中的底部导航栏触发有状态小部件以通过导航重建自身?