需求:pdf较为复杂部分利用模板生成,但是后续还需要补充动态数据表格
模板生成参考
注意
1、读取了模板写入数据之后再用document.add()方法添加代码生成的表格内容无法生效
2、如果先添加表格再写入模板数据的话,模板的form域会丢失无法再写入数据。
3、方案:先读取模板写入数据后生成一个临时pdf,然后再去读取这个pdf并向它添加表格生成最终的pdf。
效果如下
接上篇代码
1、动态表格生成 及模拟数据
private static void appendTableToDocument(Document document){
//定义 6列的表格
PdfPTable table = new PdfPTable(new float[] { 80, 80, 80, 80, 80, 80});
table.setTotalWidth(520);
table.setLockedWidth(true);
table.setHorizontalAlignment(Element.ALIGN_CENTER);//居中
try {
//定义数据的字体
BaseFont baseFont = BaseFont.createFont("Helvetica","UTF-8",BaseFont.NOT_EMBEDDED);
Font textFont = new Font(baseFont, 6, Font.NORMAL);
//表头模拟数据
for (int i = 0; i < 6; i++) {
PdfPCell heardCell = new PdfPCell();
heardCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
heardCell.setHorizontalAlignment(Element.ALIGN_CENTER);
heardCell.setPhrase(new Phrase("value", textFont));
table.addCell(heardCell);
}
//表格数据
DecimalFormat df = new DecimalFormat("0.00");
for (int i = 0; i < 1000; i++) {
PdfPCell value1 = new PdfPCell();
value1.setPhrase(new Phrase("2022"+i, textFont));
table.addCell(value1);
Double value = Math.random()*10;
PdfPCell value2 = new PdfPCell();
value2.setPhrase(new Phrase(df.format(value), textFont));
}
document.add(table);
} catch (Exception e) {
e.printStackTrace();
}
}
关键点:获取已经填充内容的pdf ,新建一页,保存表格
@GetMapping("/pdf")
public void downLoadPdf(HttpServletResponse response){
try{
//模板文件
String sourceFile = "D:\\PDF-TEST\\blog.pdf";
//下载后pdf名
String fileName = "pdf-test";
response.setHeader("content-disposition", "attachment;filename=" + fileName + ".pdf");
response.setContentType("application/octet-stream");
OutputStream out = response.getOutputStream();
//输出到本地
// FileOutputStream out = new FileOutputStream("D:\\test.pdf");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//读取模板
PdfReader reader = new PdfReader(sourceFile);
// PdfStamper pdfStamper = new PdfStamper(reader, out);
PdfStamper pdfStamper = new PdfStamper(reader, bos);// 后续读取已经填充过的pdf流
//设置字体格式
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontList = new ArrayList<>();
fontList.add(baseFont);
//获取模板文件中的表单域
AcroFields afs = pdfStamper.getAcroFields();
afs.setSubstitutionFonts(fontList);
//填充文本data
Map data = mockData().get("data");
for (Map.Entry<String, AcroFields.Item> entry : afs.getFields().entrySet()) {
if (!CollectionUtils.isEmpty(data) && data.get(entry.getKey()) != null) {
//Field , 这个是自己在pdf上定义的变量名称
afs.setField(entry.getKey(), data.get(entry.getKey()).toString(), true);
}
}
// 处理图片
Map imageMap = mockData().get("image");
for (Map.Entry<String, AcroFields.Item> entry : afs.getFields().entrySet()) {
if (!CollectionUtils.isEmpty(imageMap) && imageMap.get(entry.getKey()) != null) {
String key = entry.getKey();
String value = imageMap.get(entry.getKey()).toString();
int pageNo = afs.getFieldPositions(key).get(0).page;
Rectangle signRect = afs.getFieldPositions(key).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
//根据路径读取图片
Image image = Image.getInstance(value);
//获取图片页面
PdfContentByte under = pdfStamper.getOverContent(pageNo);
//图片大小自适应
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
//添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
}
}
pdfStamper.setFormFlattening(true);
pdfStamper.close();
/*********************************编辑填充后的pdf start ****************************/
reader = new PdfReader(bos.toByteArray());
Rectangle pageSize = reader.getPageSize(1);
Document document = new Document(pageSize);
PdfWriter writer = PdfWriter.getInstance(document, out);
document.open();
PdfContentByte cbUnder = writer.getDirectContentUnder();
PdfImportedPage pageTemplate = writer.getImportedPage(reader, 1);
cbUnder.addTemplate(pageTemplate, 0, 0);
//新创建一页来存放后面生成的表格
document.newPage();
//动态拼接表格
appendTableToDocument(document);
document.close();
/**********************************编辑填充后的pdf end******************************/
out.close();
}catch (Exception e){
e.printStackTrace();
}
}