我正在尝试使用iTextSharp在我的pdf中添加指向另一个页面的链接。 旋转单元格中的链接不起作用。其他细胞按预期工作:
FileStream fs = new FileStream("TestPDF.pdf", FileMode.Create, FileAccess.Write, FileShare.None);
Document doc = new Document();
PdfWriter writer = PdfWriter.GetInstance(doc, fs);
doc.Open();
PdfPTable linkTable = new PdfPTable(2);
PdfPCell linkCell = new PdfPCell();
linkCell.HorizontalAlignment = Element.ALIGN_CENTER;
linkCell.Rotation = 90;
linkCell.FixedHeight = 70;
Anchor linkAnchor = new Anchor("Click here");
linkAnchor.Reference = "#target";
Paragraph linkPara = new Paragraph();
linkPara.Add(linkAnchor);
linkCell.AddElement(linkPara);
linkTable.AddCell(linkCell);
PdfPCell linkCell2 = new PdfPCell();
Anchor linkAnchor2 = new Anchor("Click here 2");
linkAnchor2.Reference = "#target";
Paragraph linkPara2 = new Paragraph();
linkPara2.Add(linkAnchor2);
linkCell2.AddElement(linkPara2);
linkTable.AddCell(linkCell2);
linkTable.AddCell(new PdfPCell(new Phrase("cell 3")));
linkTable.AddCell(new PdfPCell(new Phrase("cell 4")));
doc.Add(linkTable);
doc.NewPage();
Anchor destAnchor = new Anchor("top");
destAnchor.Name = "target";
PdfPTable destTable = new PdfPTable(1);
PdfPCell destCell = new PdfPCell();
Paragraph destPara = new Paragraph();
destPara.Add(destAnchor);
destCell.AddElement(destPara);
destTable.AddCell(destCell);
destTable.AddCell(new PdfPCell(new Phrase("cell 2")));
destTable.AddCell(new PdfPCell(new Phrase("cell 3")));
destTable.AddCell(new PdfPCell(new Phrase("cell 4")));
doc.Add(destTable);
doc.Close();
我正在使用'iTextSharp 5.5.8'。我尝试过使用Chunk.SetAction PdfAction.GotoLocalPage和Chunk.SetLocalGoto。什么都不适合我
谢谢。
答案 0 :(得分:3)
实际上iText(夏普)确实为旋转单元格中的锚点创建了链接注释,但其坐标完全错误:
/Rect[-0.003 0 53.34 12]
这些坐标甚至部分偏离页面,这可能解释了一些PDF查看器的特殊行为。
(我分析了具有相同问题的iText Java代码,因为我更喜欢使用Java。匹配的iTextSharp C#代码非常相似。)
原因是处理PdfDocument
的{{1}}代码假定当前坐标系是使用 MediaBox 数据初始化的原始用户空间坐标系。因此,它使用当前坐标而不进行任何转换来生成本地链接注释:
PdfChunk
(PdfDocument.writeLineToContent(PdfLine,PdfContentByte,PdfContentByte,Object [],float))
然而,不幸的是,通过用户坐标系变化来实现单元旋转,例如,旋转90°:float xMarker = text.getXTLM();
float baseXMarker = xMarker;
float yMarker = text.getYTLM();
...
if (chunk.isAttribute(Chunk.LOCALGOTO)) {
float subtract = lastBaseFactor;
if (nextChunk != null && nextChunk.isAttribute(Chunk.LOCALGOTO))
subtract = 0;
if (nextChunk == null)
subtract += hangingCorrection;
localGoto((String)chunk.getAttribute(Chunk.LOCALGOTO), xMarker, yMarker, xMarker + width - subtract, yMarker + fontSize);
}
(PdfPRow.writeCells(int,int,float,float,PdfContentByte [],boolean))
因此,上面调用旋转锚点的ct.setSimpleColumn(-0.003f, -0.001f, netWidth + 0.003f, calcHeight);
...
pivotY = cell.getTop() + yPos - currentMaxHeight + cell.getEffectivePaddingBottom();
switch (cell.getVerticalAlignment()) {
case Element.ALIGN_BOTTOM:
pivotX = cell.getLeft() + xPos + cell.getWidth() - cell.getEffectivePaddingRight();
break;
case Element.ALIGN_MIDDLE:
pivotX = cell.getLeft() + xPos + (cell.getWidth() + cell.getEffectivePaddingLeft() - cell.getEffectivePaddingRight() + calcHeight) / 2;
break;
default: //top
pivotX = cell.getLeft() + xPos + cell.getEffectivePaddingLeft() + calcHeight;
break;
}
saveAndRotateCanvases(canvases, 0, 1, -1, 0, pivotX, pivotY);
代码将位于一个完全错误的位置。
顺便说一句,这不仅涉及本地链接注释,还涉及为块生成的各种注释。一个特别邪恶的情况是泛型标记的情况:如果页面事件监听器对PdfDocument
事件做出反应,它可以在调用期间使用坐标进行某些绘制操作,但不能作为相对于 MediaBox <的坐标/强>
对此的修复很可能需要发信号通知GenericTag
的任何坐标系更改并更新其中的代码,以便在将坐标用于不受这些转换影响的目的时将此信息考虑在内。特别是PdfDocument
事件应该扩展为接收转换坐标和原始坐标。
我建议将此修复程序留给iText开发。
答案 1 :(得分:2)
包含不适合您的代码会非常有用,因此人们可以专注于特定的问题。
当链接和目的地都在表格中时(PdfPCell
),我已经验证了通常创建本地链接。此代码按预期工作:
PdfPTable linkTable = new PdfPTable(2);
PdfPCell linkCell = new PdfPCell();
Anchor linkAnchor = new Anchor("Click here to go to top of next page.");
linkAnchor.Reference = "#target";
Paragraph linkPara = new Paragraph();
linkPara.Add(linkAnchor);
linkCell.AddElement(linkPara);
linkTable.AddCell(linkCell);
linkTable.AddCell(new PdfPCell(new Phrase("cell 2")));
linkTable.AddCell(new PdfPCell(new Phrase("cell 3")));
linkTable.AddCell(new PdfPCell(new Phrase("cell 4")));
doc.Add(linkTable);
doc.NewPage();
Anchor destAnchor = new Anchor("top");
destAnchor.Name = "target";
PdfPTable destTable = new PdfPTable(1);
PdfPCell destCell = new PdfPCell();
Paragraph destPara = new Paragraph();
destPara.Add(destAnchor);
destCell.AddElement(destPara);
destTable.AddCell(destCell);
destTable.AddCell(new PdfPCell(new Phrase("cell 2")));
destTable.AddCell(new PdfPCell(new Phrase("cell 3")));
destTable.AddCell(new PdfPCell(new Phrase("cell 4")));
doc.Add(destTable);