简体   繁体   English

如何使用IText7和C#在现有PDF中为内部链接加下划线?

[英]How do I underline internal links in an existing PDF using IText7 and C#?

We regularly use Word to generate large documents with many internal cross-references. 我们经常使用Word生成带有许多内部交叉引用的大型文档。 I'm writing a tool to find and add blue underlining to these clickable internal cross-references. 我正在写一个工具来查找可点击的内部交叉引用并在其中添加蓝色下划线。 (I know I can do this at the Word level, but I need to be able to do this even when I don't have access to the original Word file.) (我知道我可以在Word级别上执行此操作,但是即使我无权访问原始Word文件,也需要能够执行此操作。)

I am using C# and IText 7. I am able to load and scan the existing PDF for these internal links. 我正在使用C#和IText7。我能够加载和扫描现有PDF的这些内部链接。 But what I can't seem to do is change the links' appearance. 但是我似乎无法做的是更改链接的外观。 After searching, I learned that the PdfAnnotation class is for creating new links and not for altering existing ones. 搜索之后,我了解到PdfAnnotation类用于创建新链接,而不是用于更改现有链接。 I'm told I need to use Put() to change existing ones. 有人告诉我我需要使用Put()来更改现有的。 I've tried a number of different approaches, but none of them seem to be working. 我尝试了许多不同的方法,但是似乎都没有用。

var pdfDoc = new PdfDocument(new PdfReader(txt_FileLoaded.Text), new PdfWriter(outfile));
for (int x = pgStart; x <= pgEnd; x++)
{
    PdfPage page = pdfDoc.GetPage(x);
    var annotations = page.GetAnnotations();
    foreach (var a in annotations)
    {
        if (a.GetSubtype() == PdfName.Link)
        {
            PdfLinkAnnotation link = (PdfLinkAnnotation)a;
            var action = link.GetAction();
            if (action != null)
            {
                if ( 
                    (action.Get(PdfName.S) == PdfName.URI) || 
                    (action.Get(PdfName.S) == PdfName.GoToR) )
                {
                    //Do something with external links if you want
                }
                else if ( 
                    (action.Get(PdfName.S) == PdfName.GoTo) ||
                    (action.Get(PdfName.S) == PdfName.GoToE))
                {
                    //Do something with internal links
                    link.Put(PdfName.C, new PdfArray(ColorConstants.BLUE.GetColorValue()));
                    link.Put(PdfName.Border, new PdfArray(new int[] {0,0,5}));
                }
            }
        }
    }
}
pdfDoc.Close();

The new file is correctly written when I call Close() , but no underlining is appearing. 当我调用Close() ,新文件已正确写入,但没有出现下划线。 Again, I've confirmed that it's indeed finding the links. 再次,我确认确实可以找到链接。 What specific changes do I need to make via Put() to add these underlines? 我需要通过Put()进行哪些具体更改才能添加这些下划线?

Thanks for your time!! 谢谢你的时间!!

To the best of my knowledge what you are trying to achieve cannot be achieved by purely modifying the annotation objects. 据我所知,您试图实现的目标无法仅通过修改注释对象来实现。 It might be possible to try playing with appearance streams but I'm not sure it will work and even if it will it can have some side effects. 也许可以尝试使用外观流,但是我不确定它是否会起作用,即使会带来一些副作用。

Annotations just encode the rectangular area which becomes clickable and the action (or destination) that will be triggered when that area is clicked. 批注仅对可单击的矩形区域和单击该区域时将触发的动作(或目标)进行编码。 It is also possible to configure the border of the annotation but PDF specification does not allow you to do fine-grained tuning and thus you won't be able to just set the bottom border to emulate the underlining. 也可以配置注释的边框,但是PDF规范不允许您进行细调,因此您将无法仅设置底部边框来模拟下划线。

What we will be doing instead is drawing a line directly in the contents of the page in the hope that the annotation position is accurate enough. 相反,我们要做的是直接在页面的内容中画一条线,希望注释位置足够准确。

We can get annotation's area with annotation.getRectangle() , and then use PdfCanvas to draw a line with matching coordinates (you could also shift it upwards a bit if needed). 我们可以使用annotation.getRectangle() PdfCanvas annotation.getRectangle()获得注解的区域,然后使用PdfCanvas绘制一条具有匹配坐标的线(如果需要,您也可以将其向上移动一点)。 The code is in Java, but you will find it very easy to convert to C# since only the method names would start with the capital letters. 该代码使用Java,但是您会发现转换为C#非常容易,因为只有方法名称以大写字母开头。

PdfPage page = pdfDocument.getPage(i);
// Create canvas where we would draw additional lines
PdfCanvas pageCanvas = new PdfCanvas(page);
for (PdfAnnotation annotation : page.getAnnotations()) {
    Rectangle annotationArea = annotation.getRectangle().toRectangle();
    // Draw a line at the bottom of the annotation area
    pageCanvas.setStrokeColor(ColorConstants.BLUE).
            moveTo(annotationArea.getLeft(), annotationArea.getBottom()).
            lineTo(annotationArea.getRight(), annotationArea.getBottom()).
            stroke();
}

This is how the initial PDF looks like: 初始PDF如下所示:

初始PDF

This is how the output PDF looks like 这是输出PDF的样子

结果PDF

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM