本篇文章主要讲解的是如何采用itext7进行模板填充。
- 创建PdfReader PdfWriter,构造函数支持路径已经流的形式。
- 创建PDFDocument
- 创建并设置中文字体
- 获取文本域的信息
- 判断文本框长度是否够单行显示
- 填充信息
- 设置模板不可编辑
private static void fillParam(PdfReader pdfReader, PdfWriter pdfWriter,
Map<String, Object> map, List<PdfPositon> pdfPositons) throws MalformedURLException {
//1、创建pdf文件
PdfDocument pdf = new PdfDocument(pdfReader, pdfWriter);
//2、创建中文字体
PdfFont f2 = null;
try {
f2 = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", true);
} catch (IOException e) {
logger.error("create Font Error");
}
pdf.addFont(f2);
//3、获取pdf模板中的域值信息
PdfAcroForm form = PdfAcroForm.getAcroForm(pdf, true);
Map<String, PdfFormField> fieldMap = form.getFormFields();
Iterator<String> paramIterator = map.keySet().iterator();
while (paramIterator.hasNext()) {
String key = paramIterator.next();
String value = map.get(key).toString();
PdfFormField formField = fieldMap.get(key);
if (formField == null) {
continue;
}
//4、判断文本域是否超出宽度 且文本域是单行
if (!compareWidth(f2, formField, value) && !formField.isMultiline()) {
logger.error("value width was out of text width fieldName:{}", key);
}
//5、填充信息
formField.setValue(value);
}
//6、设置文本不可编辑
form.flattenFields();
pdf.close();
}
注意点:
- 需要设置中文字体否则填充中文信息时可能无法显示
- 需要对单行的文本域进行宽度判断,目前代码中是打印了异常日志
- 如果未设置文本不可编辑的话,会出现生成的文件仍然可以修改的情况
下面来梳理一下如何判断文本值超出文本框的最大长度(Adobe 默认是不展示的,而实际使用过程中肯定是要提示一下用户的)
实际比较对象是文本值的宽度和文本域的宽度,但是计算文本值的宽度是需要知道字体以及字体大小。
/**
* 1、获取文本框的宽度 注意要减去左右的padding值 值为:PdfFormField.X_OFFSET 2、获取字符串宽度注意字体 需使用中文字体
*
* @param pdfFont 字体
* @param formField 文本域
* @param value 文本值
* @return textWidth >= valueWidth return true else false
*/
public static boolean compareWidth(PdfFont pdfFont, PdfFormField formField, String value) {
//获取当前文本字体大小
float fontSize = getFontSize(formField);
PdfArray position = formField.getWidgets().get(0).getRectangle();
float width = (float) (position.getAsNumber(2).getValue() - position.getAsNumber(0).getValue())
- PdfFormField.X_OFFSET * 2;
//获取当前文本值的宽度
float strWidth = pdfFont.getWidth(value, fontSize);
return width >= strWidth;
}
/**
* 获取adobe中设置的字体大小
* @param formField
* @return
*/
private static float getFontSize(PdfFormField formField) {
String defaultAppearance = formField.getDefaultAppearance().toString();
String[] daTable = defaultAppearance.split(" ");
return Float.valueOf(daTable[PdfFormField.DA_SIZE]);
}
注意:实际文本域的边框和字之间还是存在间隙了,类似于html中的padding,所以文本框的实际宽度还要减去两边的padding值