我创建 pdf 并且我需要在工作流中进行后处理来更新内容,为此最好的查找方法是创建带有注释的 PdfFormField。
在创建带有注释的字段后,我可以通过 AcroField 对象搜索位置并获取页面和位置。
public static List<FieldPosition> getPositions(PdfReader pdfReader, String name) {
AcroFields acroFields = pdfReader.getAcroFields();
List<FieldPosition> fieldPositions = acroFields.getFieldPositions(name);
return fieldPositions;
}
您可以在如下位置绘制文本:
public static void writeString(PdfReader pdfReader, PdfStamper pdfStamper, String name, String valueStr, Font fontType, float leftDiff,
float bottomDiff) throws IOException, DocumentException {
Phrase pagePhrase = new Phrase(valueStr, fontType);
float left;
float bottom;
List<FieldPosition> fieldPositions = getPositions(pdfReader, name);
if (fieldPositions != null) {
for (FieldPosition fieldPos : fieldPositions) {
left = fieldPos.position.getLeft() + leftDiff;
bottom = fieldPos.position.getBottom() + bottomDiff;
PdfContentByte cover = pdfStamper.getOverContent(fieldPos.page);
ColumnText.showTextAligned(cover, Element.ALIGN_LEFT, pagePhrase, left, bottom, 0);
}
}
}
您可以在此处查看创建表单字段的示例http://itextpdf.com/examples/iia.php?id=157 上面的示例使用简单的 iText API 与表格和单元格(您可以看到单元格用于获取矩形对于领域)
我尝试以两种方式创建相同的字段。为单元格(td)或字段(输入或其他)创建处理器
TagProcessorFactory tagProcessorFactory = Tags.getHtmlTagProcessorFactory();
tagProcessorFactory.addProcessor(new XHTMLTableTagProcessor(), new String[] { "table" });
tagProcessorFactory.addProcessor(new XHTMLCellMarkTagProcessor(writer), new String[] { "td" });
tagProcessorFactory.addProcessor(new XHTMLInputMarkTagProcessor(writer), new String[] { "input" });
HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
htmlContext.setTagFactory(tagProcessorFactory);
细胞处理器
public class XHTMLCellMarkTagProcessor extends AbstractTagProcessor {
private PdfWriter writer;
public XHTMLCellMarkTagProcessor(PdfWriter writer) {
this.writer = writer;
}
@Override
public List<Element> end(WorkerContext ctx, Tag tag, List<Element> currentContent) {
String mark = "mark";
String strMark = tag.getAttributes().get(mark);
String strName = tag.getAttributes().get("name");
boolean isMark = StringUtils.isAlpha(strMark) && strMark.equalsIgnoreCase("true");
System.out.println(String.format(currentContent.size() + "<<< %s %s ", strName, strMark));
List<Element> retval = super.end(ctx, tag, currentContent);
if (isMark && StringUtils.isNotBlank(strName)) {
for (Element element : retval) {
if (element instanceof PdfPCell) {
final TextField nameField = new TextField(writer, new Rectangle(0, 0, 1, 5), strName);
try {
final PdfFormField formField = nameField.getTextField();
final int width = 1;
PdfPCellEvent cellEvent = new PdfPCellEvent() {
@Override
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
try {
formField.setWidget(new Rectangle(position.getLeft(), position.getBottom(), position.getLeft() + width,
position.getTop()), PdfAnnotation.HIGHLIGHT_NONE);
writer.addAnnotation(formField);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
((PdfPCell) element).setCellEvent(cellEvent);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
return retval;
}
}
无论是否调用父元素,元素始终为零,不存在表或 div 等单元格的默认处理器 获取错误:java.lang.IllegalArgumentException:PdfPTable 构造函数中的列数必须大于零。
输入处理器
public class XHTMLInputMarkTagProcessor extends AbstractTagProcessor {
private PdfWriter writer;
public XHTMLInputMarkTagProcessor(PdfWriter writer) {
this.writer = writer;
}
@Override
public List<Element> start(final WorkerContext ctx, final Tag tag) {
List<Element> elements = super.start(ctx, tag);
try {
String mark = "mark";
String strMark = tag.getAttributes().get(mark);
String strType = tag.getAttributes().get("type");
String strName = tag.getAttributes().get("name");
String strSize = tag.getAttributes().get("size");
String strValue = tag.getAttributes().get("value");
boolean isMark = StringUtils.isAlpha(strMark) && strMark.equalsIgnoreCase("true");
int size = StringUtils.isNumeric(strSize) ? new Integer(strSize.trim()) : 0;
System.out.println(String.format("<<< %s %s %s %s %s", strName, strType, strMark, strSize, size));
if (isMark && StringUtils.isNotBlank(strType) && strType.equals("text")) {
TextField nameField = new TextField(writer, new Rectangle(100, 100, 100, 50), strName);
nameField.setBackgroundColor(BaseColor.GREEN);
PdfFormField formField = nameField.getTextField();
formField.setValueAsString(strValue);
formField.setWidget(new Rectangle(100, 100, 100, 100), PdfAnnotation.HIGHLIGHT_PUSH);
writer.addAnnotation(formField);
//System.out.println("ADDDD");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return elements;
}
}
我在结果 PDF 中什么也看不到。 无法将 TextField 对象添加到元素列表,因为没有扩展 Element 接口