项目中,遇到这么一个需求:根据单个模板批量导出pdf,批量导出的pdf要合并成一个pdf进行打印。两个问题点:1、根据模板生成pdf。2、pdf合并
这个问题可以使用itextpdf和Adobe Acrobat 来实现。
1、根据提供的word生成的pdf的模板样式
2、将其转出为pdf,wps就可以操作
3、用Adobe Acrobat打开该pdf
4、选择工具打开表单
5、自动检测到一些域但是不全,我们可以自己添加并且编辑相关的属性
1.1项目依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
1.2将准备好的模板pdf放入到项目中
1.3相关代码
1、读取模板以及设置字体
File schoolRollQRCode = QrCodeUtil.generate(studentPdfVo.getSchoolRoll(), 300, 300, FileUtil.file("/qrcode" + imageNumber + ".jpg"));
map.put("schoolRollQRCode", schoolRollQRCode.getPath());
org.springframework.core.io.Resource resource = new ClassPathResource("pdf_template/student.pdf");
PdfReader reader = new PdfReader(resource.getInputStream());
BaseFont bf = BaseFont.createFont();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(reader, bos);
AcroFields form = stamper.getAcroFields();
form.addSubstitutionFont(bf);
float bigFontSize = 10;
// false可编辑
stamper.setFormFlattening(true);
2、普通数据的录入,即模板中文本域对应单字段的录入:
Map<String, String> map1 = new HashMap<>(32);
imageNumber++;
File schoolRollQRCode = QrCodeUtil.generate(studentPdfVo.getSchoolRoll(), 300, 300, FileUtil.file("/qrcode" + imageNumber + ".jpg"));
map.put("schoolRollQRCode", schoolRollQRCode.getPath());
map.put("schoolRoll", studentPdfVo.getSchoolRoll());
map.put("name", studentPdfVo.getName());
map.put("gradeName", studentPdfVo.getGradeName());
map.forEach((key, value) -> {
try {
if ("schoolRollQRCode".equals(key)) {
int pageNo = stamper.getAcroFields().getFieldPositions(key).get(0).page;
Rectangle signRect = stamper.getAcroFields().getFieldPositions(key).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
// 读图片
Image image = Image.getInstance(map.get(key));
// 获取操作的页面
PdfContentByte under = stamper.getOverContent(pageNo);
// 根据域的大小缩放图片
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
// 添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
} else {
//设置这个表单域的字体
form.setFieldProperty(key, "textfont", bfChinese, null);
//设置这个表单域的字体大小
form.setFieldProperty(key, "textsize", bigFontSize, null);
form.setField(key, value);
}
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
});
3、二维码图片的录入
int pageNo = stamper.getAcroFields().getFieldPositions(key).get(0).page;
Rectangle signRect = stamper.getAcroFields().getFieldPositions(key).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
// 读图片
Image image = Image.getInstance(map.get(key));
// 获取操作的页面
PdfContentByte under = stamper.getOverContent(pageNo);
// 根据域的大小缩放图片
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
// 添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
4、集合的录入
Map<String, List<String>> listMap = new HashMap<>(4);
if (CollectionUtil.isNotEmpty(nameList)) {
listMap.put("Box1", nameList);
}
listMap.forEach((key, value) -> {
if (CollectionUtil.isNotEmpty(value)) {
int pageNo = form.getFieldPositions(key).get(0).page;
PdfContentByte pcb = stamper.getOverContent(pageNo);
Rectangle signRect = form.getFieldPositions(key).get(0).position;
//表格位置
int column = 2;
int row = value.size();
PdfPTable table = new PdfPTable(column);
float totalWidth = signRect.getRight() - signRect.getLeft();
float[] width = new float[2];
width[0] = (totalWidth / 9) * 2;
width[1] = (totalWidth / 9) * 7;
try {
table.setTotalWidth(width);
} catch (DocumentException e) {
e.printStackTrace();
}
table.setLockedWidth(true);
table.setKeepTogether(true);
table.setSplitLate(false);
table.setSplitRows(true);
Font fontProve = new Font(bfChinese, 13, 0);
//表格数据填写
for (int i = 0; i < row; i++) {
// 第一列
String name = value.get(i);
Phrase phrase;
if ("体检项目".equals(name)) {
phrase = new Phrase(name, new Font(bfChinese, 17, 0));
} else {
phrase = new Phrase(name, fontProve);
}
PdfPCell cell = new PdfPCell(phrase);
cell.setBorderWidth(1);
cell.setBorderWidthRight(0);
cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
cell.setVerticalAlignment(Element.ALIGN_CENTER);
cell.setLeading((float) 3.0, (float) 1.0);
cell.setMinimumHeight(30f);
table.addCell(cell);
// 第二列
Phrase phrase2 = new Phrase(null, fontProve);
PdfPCell cell2 = new PdfPCell(phrase2);
cell2.setBorderWidth(1);
cell2.setBorderWidthLeft(0);
cell2.setHorizontalAlignment(Element.ALIGN_CENTER);
cell2.setVerticalAlignment(Element.ALIGN_CENTER);
cell2.setLeading((float) 3.0, (float) 1.0);
cell2.setMinimumHeight(30f);
table.addCell(cell2);
}
table.writeSelectedRows(0, value.size(), signRect.getLeft(), signRect.getTop(), pcb);
}
});
2.1项目依赖
<dependency>
<groupId>com.luhuiguo</groupId>
<artifactId>aspose-pdf</artifactId>
<version>23.1</version>
</dependency>
2.2相关代码
OutputStream out = response.getOutputStream();
InputStream[] inputStreams = new InputStream[outputStreams.size()];
int i = 0;
for (ByteArrayOutputStream byteArrayOutputStream : outputStreams) {
// 将输出流转化成输入流
ByteArrayInputStream swapStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
inputStreams[i] = swapStream;
i++;
}
// 合并pdf
PdfFileEditor pdfFileEditor = new PdfFileEditor();
pdfFileEditor.concatenate(inputStreams, out);