更新:2021-01-15 - 增加了赏金
我正在尝试更改编校注释以更改在应用编校时刻录到 PDF 中的基础文本。在 Acrobat 中,您可以设置“编校代码”的集合,这些代码可用于确定您将某些内容标记为已编校的原因。我的目标是用系统定义的值覆盖用户选择的内容。代码将在应用编辑之前运行。
在我的尝试中,我发现将光标悬停在编辑框上时 Acrobat 产品中可用的“预览”是 Acrobat 独有的,大多数其他查看器不会显示预览。似乎预览与应用的实际编辑分开维护。我不需要更改预览中显示的文本,只需更改应用密文后显示的内容即可。
我已经增加了 150 声望的赏金,因为我认为我自己无法找到解决方案。我最初的问题指定了 iText7,因为这是在我自己的尝试中让我最接近的库。虽然我更喜欢使用 iText7,但我也会考虑使用我可以合理访问的其他库的解决方案(如果需要,我确实有少量预算可以用来购买另一个库)。
我保留了我最初的问题以及我在下面亲自尝试过的后续内容。我感谢提供的任何帮助。
如果您需要一个样本进行测试,这个 DropBox文件夹有一个名为的文件01 - Original.pdf
,您可以将其用作源文档。期望的结果是能够更改在将“原始覆盖文本”的编辑应用到任何其他值(例如“新文本”)时出现的文本。
原始问题:
我正在尝试更改 PDF 中每个修订注释中包含的文本,使用iText7
. 该PdfRedactAnnotation
对象有一个名为的方法SetOverlayText()
,看起来它应该做我想做的事。因此,我编写了一个打开 PDF 的方法,循环浏览页面,然后循环浏览每个页面上的注释,并检查注释是否为PdfRedactAnnotation
. 如果是,它会调用SetOverlayText()
.
在调试和查看注释属性时,我可以看到OverlayText
肯定发生了变化。但是,当我打开文件并通过将光标悬停在编辑标记上来检查覆盖文本时,原始覆盖文本仍然存在。
此外,如果我应用了编辑,原始的覆盖文本就是被烧入页面的内容。
但是,当我右键单击注释时(在应用编辑之前),覆盖文本会立即更新为新文本:
在这一点上,当我应用编辑时,将新文本刻录到 PDF 中。
有什么方法可以以编程方式触发修订注释更新,而无需打开并右键单击每个注释?我在下面包含了我的代码。感谢您提供任何人可以提供的任何建议。
PdfDocument pdfDoc = new PdfDocument(new PdfReader(@"C:\temp\Test - Original.pdf"), new PdfWriter(@"C:\temp\Test - Output.pdf"));
Document doc = new Document(pdfDoc);
int pageCount = pdfDoc.GetNumberOfPages();
for (int i = 1; i <= pageCount; i++)
{
var annotations = pdfDoc.GetPage(i).GetAnnotations();
foreach(var annotation in annotations)
{
if (annotation is PdfRedactAnnotation)
{
PdfRedactAnnotation redact = (PdfRedactAnnotation)annotation;
redact.SetOverlayText(new PdfString("New Text"));
}
}
}
doc.Close();
更新:截至 2021 年 1 月 7 日的调查结果
正如@mkl 的回答所指出的那样,PDF Redact Annotation Specification 阐明了底层的 redact annotation DOM 条目。OverlayText只是等式的一部分。如果您使用OverlayText,则必须定义一个DA元素(DA 是一个为 OverlayText 提供格式信息的字符串)。最后,如果定义了RO,它将取代几乎所有其他独立的显示条目。
我的测试文档是使用 Acrobat DC Pro 制作的,通过在 Acrobat 中手动添加编辑。这样做会产生一个带有所有上述条目的编辑注释。我的测试文档的副本可以在这个 DropBox文件夹中找到。
(旁注:在我最初的问题中,我提到将鼠标悬停在编辑的红色矩形上以预览应用的编辑将是什么样子......在多个浏览器和其他 PDF 查看器(如 Foxit Reader)中进行测试后,它看起来像功能“预览”仅在 Acrobat 产品中支持通过将鼠标悬停在红色轮廓上应用编辑时的外观。所有其他测试的查看器将仅显示红色边框,当您将光标悬停在它上面时不会发生任何事情。黑色上面显示的矩形只能在应用编辑后在其他程序中查看。
附加测试表明,悬停预览与编辑详细信息本身是分开维护的,Acrobat 会尝试使悬停详细信息与基础注释保持同步。测试时最好忽略悬停预览,并在应用编辑后参考结果。)
@mkl 建议删除 RO 条目以尝试让 OverlayText 优先考虑是一个好主意,但不幸的是它没有奏效。与我原来的结果没有显着差异。
在 iText7 的 PdfRedactAnnotation 中四处寻找之后,我发现以下方法都会导致对 Redact 对象的 RO 条目的引用:
PdfRedactAnnotation redact = (PdfRedactAnnotation)annotation;
redact.GetRolloverAppearanceObject();
redact.GetRedactionRolloverAppearance();
redact.GetPdfObject().Get(PdfName.RO);
redact.GetAppearanceDictionary().Get(PdfName.R);
(我通过检查相等比较器确认它们实际上是完全相同的引用。作为引用类型,它们true
在使用 测试时都返回==
)。
在进一步的测试中,我得出的结论是 RO 属性必须具有内部存储的相同 OverlayText 的副本。如果您有两个具有不同原始值的编校,您可以将 RO 元素从一个编校“复制”到另一个编校:
PdfObject ro = firstRedact.GetPdfObject().Get(PdfName.RO);
secondRedact.GetPdfObject().Put(PdfName.RO, ro);
如果您这样做并应用编辑,第一个编辑中的“覆盖文本”将替换第二个中的“覆盖文本”。其他 RO 元素值也被复制(例如 BBox,它定义了黑色矩形的尺寸)......但至少可以调整这些元素。
问题仍然是 RO 的 iText7 PdfObject 有 7 个子元素,并且它们或它们的后代元素似乎都没有暴露我试图更改的文本。
我的最后一个测试是我是否可以将 RO 元素从一个 PDF 复制到另一个(以便我可以使用第二个源 PDF 和已配置所需 RO“覆盖文本”的注释),但看起来间接对象不喜欢将 .Put() 放入其他文档中。
所以现在,我只能尝试找到一种方法来访问/更改存储在 RO 中的文本,或者从另一个文档中克隆预配置的 RO。