需求:pdf模板生成的复杂部分,但动态数据表需要补充
参考模板生成
itextpdf 使用模板生成pdf 下载_音乐土豆博客-CSDN博客
注意
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();
}
}