问题
工作中经常有这样的需求,将一些数据,导出为下图的PDF文件,那Java怎么做呢?今天手把手教你
准备模版
模版地址:https://download.csdn.net/download/ZHUSHANGLIN/91923381
修改模版使用AcrobatProPortable工具,在"编辑PDF"按钮修改模版样式,在"准备表单"按钮中修改模版中填充内容,需要工具的留言私发你
Java代码
首先添加依赖
xml
<!--PDF打印-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
<scope>compile</scope>
</dependency>
java
public R CreatePDF(Tbmmu301Entity tbmmu301Entity,List<Tbmmu301aEntity> list,String user){
String separator = File.separator;//Windows :"\" Linux : "/"
FileSystemView fsv = FileSystemView.getFileSystemView();
// 模板路径
String templatePath = "PDF/MMU791.pdf";
//第一次生成的新文件路径,文件名
String newPDFPath = fsv.getDefaultDirectory().toString()+separator+tbmmu301Entity.getIssueNo()+"_temp.pdf";
// 最终生成的新文件路径,文件名
String finalPDFPath = fsv.getDefaultDirectory().toString()+separator+"Proof of going out_"+tbmmu301Entity.getIssueNo()+".pdf";
logger.info("MMU791物资出门证明打印PDF路径",finalPDFPath);
//com.itextpdf.text.pdf
PdfReader reader;
FileOutputStream out;
ByteArrayOutputStream bos;
PdfStamper stamper;
R<String> result = new R<>();
try{
logger.info("开始", DateUtil.formatDateTime(new Date()));
out = new FileOutputStream(newPDFPath);// 输出流
reader = new PdfReader(templatePath);// 读取pdf模板
bos = new ByteArrayOutputStream();
stamper = new PdfStamper(reader, bos);
AcroFields form = stamper.getAcroFields();
Map<String, String> PDFData = new HashMap<>();//存放需要填充的模板数据
String isBack = "";
String issueType = iDictValue.getDictValue("leaveDoorType",tbmmu301Entity.getIssueType());
if(tbmmu301Entity.getIsBack().equals("Y")){
isBack = "是";
}else if(tbmmu301Entity.getIsBack().equals("N")){
isBack = "否";
}
Map tbmmi001Map=iDictValue.getTbmma001ByCodeAndKey("compid_sort",tbmmu301Entity.getCompanyId());//VALUE_B存公司简称
if(Func.isEmpty(tbmmi001Map)){
return R.fail("打印失败,获取TBMMA001表-compid_sort当前公司信息失败");
}
String compShort=tbmmi001Map.get("VALUE_B")==null?"":tbmmi001Map.get("VALUE_B").toString();
if(compShort.equals("")){
return R.fail("打印失败,获取当前公司:"+tbmmu301Entity.getCompanyId()+"简称失败,请联系系统管理员至采购业务字典compid_sort,设定当前公司参数2");
}
String approveNode = "";
approveNode=iGetApproveNodeClient.getApproveNode(tbmmu301Entity.getIssueNo());//45751 获取OA审批流程打印
PDFData.put("companyName",compShort+"出门证明");
PDFData.put("issueNo",tbmmu301Entity.getIssueNo());//申请单号
PDFData.put("issueType",issueType);//出门类型
PDFData.put("issueUser",tbmmu301Entity.getIssueUserId());//申请人
PDFData.put("issueDept",tbmmu301Entity.getIssueDeptName());//申请部门
PDFData.put("driverName",tbmmu301Entity.getDriverName());//司机姓名
PDFData.put("issueTel",tbmmu301Entity.getIssueTel());//司机电话
PDFData.put("carNo",tbmmu301Entity.getCarNo());//车牌
PDFData.put("isBack",isBack);//是否返厂
PDFData.put("memo",tbmmu301Entity.getMemo());//备注
PDFData.put("approveNode",approveNode);//审批流程
logger.info("PDFData",PDFData.toString());
// 设置字体,不设置很可能,中文无法显示。
//BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
// 检查文件是否存在
String fontPath = "/fonts/simsunb.ttf";
InputStream fontStream = getClass().getResourceAsStream(fontPath);
if (fontStream == null) {
throw new RuntimeException("字体文件未找到: " + fontPath);
}
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int nRead;
while ((nRead = fontStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
byte[] fontBytes = buffer.toByteArray();
BaseFont bf = BaseFont.createFont("simsunb.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, false, fontBytes, null);
form.addSubstitutionFont(bf);
// 数据查询后,值的植入 强烈推荐键值方式,其他方式很容易混
Set<String> keySet = PDFData.keySet();
for (String key : keySet) {//填充固定表单值
form.setField(key, PDFData.get(key)==null?" ":PDFData.get(key));
}
logger.info("模板填充完成",DateUtil.formatDateTime(new Date()));
stamper.setFormFlattening(true);// 如果为false那么生成的PDF文件还能编辑,一定要设为true
stamper.close();
Document doc = new Document();
PdfCopy copy = new PdfCopy(doc, out);
doc.open();
PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
copy.addPage(importPage);
doc.close();//第一次生成的pdf,生成模板数据
logger.info("模板PDF生成完成",DateUtil.formatDateTime(new Date()));
// 填充子档数据
generateFinalPdf(newPDFPath, finalPDFPath, list ,user);
logger.info("上传开始",DateUtil.formatDateTime(new Date()));
File pdfFile = new File(finalPDFPath);
MultipartFile MultipartFile = getMultipartFile(pdfFile);
Map<String,String> result1 = obsUtil.saveFile(MultipartFile.getOriginalFilename(),MultipartFile);
if("200".equals(result1.get("code"))){
String key = result1.get("key");;
String fileName = "";
fileName = MultipartFile.getOriginalFilename();
System.err.println(fileName);
if (fileName.contains("\\")) {//去掉反斜杠
fileName = fileName.split("\\\\")[1];
}
String url = obsUtil.generatePresignedUrl(key);
logger.info("PDF文件key",key);
logger.info("修改后PDF文件name",fileName);
result.setSuccess(true);
result.setData(url);
if (pdfFile.exists()) {
boolean isDelete2 = pdfFile.delete();
logger.info("第二个PDF是否删除:", String.valueOf(isDelete2));
}
logger.info("出门证明打印:",result.toString());
}
copy.close();
reader.close();
bos.close();
}catch (Exception e){
e.printStackTrace();
logger.info("MMU791物资出门证明打印PDF异常",e.getMessage());
}finally {
//删除本地文件
File pdfFile1 = new File(newPDFPath);
if (pdfFile1.exists()) {
boolean isDelete1 = pdfFile1.delete();
logger.info("第一个PDF是否删除:", String.valueOf(isDelete1));
}
}
return result;
}
private void generateFinalPdf(String newPath, String finalPath, List<Tbmmu301aEntity> list, String user) throws Exception{
FileOutputStream outputStream = new FileOutputStream(finalPath);
PdfReader reader = new PdfReader(newPath);// 读取pdf模板
Rectangle pageSize = reader.getPageSize(1);
Document document = new Document(pageSize);
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
PdfContentByte cbUnder = writer.getDirectContentUnder();
PdfImportedPage pageTemplate = writer.getImportedPage(reader, 1);
cbUnder.addTemplate(pageTemplate, 1, 1); //第一次生成的PDF填充到第二次生成的 位置
//document.newPage();//新创建一页来存放后面生成的表格
//package com.itextpdf.text;
Paragraph paragraph2 = new Paragraph(new Phrase(" ")); //创建一个空的段,用于调整第二个段的位置
Paragraph paragraph = generatePdfATATable(list,user);//此处为生成的表格及内容方法
paragraph.setSpacingBefore(115);//不同模板设置不同距离
//paragraph.setKeepTogether(false);//表示该段落必须放在一个页面上
//新建一行
//document.add(Chunk.NEWLINE);
document.add(paragraph2);//增加块到文档
document.add(paragraph);//增加块到文档
// document.setPageSize(new Rectangle(100, 100));
document.close();
reader.close();
writer.close();
}
public Paragraph generatePdfATATable(List<Tbmmu301aEntity> list,String user) throws Exception{
//BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
// 检查文件是否存在
String fontPath = "/fonts/simsunb.ttf";
InputStream fontStream = getClass().getResourceAsStream(fontPath);
if (fontStream == null) {
throw new RuntimeException("字体文件未找到: " + fontPath);
}
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int nRead;
while ((nRead = fontStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
byte[] fontBytes = buffer.toByteArray();
BaseFont bfChinese = BaseFont.createFont("/fonts/STSong-Light.ttf",BaseFont.IDENTITY_H , BaseFont.NOT_EMBEDDED);
Font fontChinese = new Font(bfChinese, 15F, Font.NORMAL);// 设置PDF字体 五号
//Paragraph ret = new Paragraph("附表1: 基线按ATA章节分类情况统计表", fontChinese); //表title
Paragraph ret = new Paragraph("",fontChinese); //表title
PdfPTable tableBox = new PdfPTable(11); //列数
tableBox.setWidths(new int[] {
10,17,17,17,17,17,17,17,17,17,17 //每个单元格占多宽
});
tableBox.setWidthPercentage(105f); //占PDF整个宽度的百分比
tableBox.setPaddingTop(500);
tableBox.setSplitRows(false);
//tableBox.addCell(getTableCell(new Phrase("标题", fontChinese), false, 3, 1));//colspan:跨横着的格数 rowspan:跨竖着的格数
tableBox.addCell(getTableCell(new Phrase("Serial Number", fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase("Types", fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase("Supplier Code", fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase("Supplier Name", fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase("Material Code", fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase("Material Name", fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase("Model", fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase("Procurement Unit", fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase("Stock Unit", fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase("Ex-factory quantity", fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase("Date of Departure", fontChinese), false, 1, 1));
String tbmmu301Id="";
for(int i=0;i<list.size();i++){
Tbmmu301aEntity s = list.get(i);
tableBox.addCell(getTableCell(new Phrase(String.valueOf(i+1), fontChinese), false, 1, 1));
String inventoryType = "";
if(Func.isNotEmpty(s.getInventoryType())){
inventoryType = iDictValue.getDictValue("ItemGrade",s.getInventoryType());
}
tableBox.addCell(getTableCell(new Phrase(inventoryType, fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase(s.getSupplierId(), fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase(s.getSupplierName(), fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase(s.getItemId(), fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase(s.getItemName(), fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase(s.getTypeSpec(), fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase(s.getItemUnit(), fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase(s.getInvUnit(), fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase(ZoaCommonUtil.parseNumber(s.getPlanQty(),ZoaCommonUtil.Decimal.THREE), fontChinese), false, 1, 1));
tableBox.addCell(getTableCell(new Phrase(s.getBroutDate(), fontChinese), false, 1, 1));
tbmmu301Id=s.getTbmmu301Id()==null?"":s.getTbmmu301Id();
}
Tbmmu301Entity tbmmu301Entity=baseMapper.selectOne(new QueryWrapper<Tbmmu301Entity>().lambda().eq(Tbmmu301Entity::getTbmmu301Id,tbmmu301Id).eq(Tbmmu301Entity::getIsDeleted,0));
//tableBox.addCell(getTableCell(new Phrase("testtest", fontChinese), false, 1, 1));
tableBox.addCell(getCell(new Phrase("Printed by:", fontChinese), true, 2, 1));
tableBox.addCell(getCell(new Phrase(user, fontChinese), false, 3, 1));
tableBox.addCell(getCell(new Phrase(iPrintNumFeign.printNum(tbmmu301Entity.getCompanyId(),tbmmu301Entity.getIssueNo(),"MMU791"), fontChinese), false, 2, 1));
tableBox.addCell(getCell(new Phrase("Printing time:", fontChinese), true, 2, 1));
tableBox.addCell(getCell(new Phrase(DateUtil.formatDateTime(new Date()), fontChinese), false, 3, 1));
ret.add(tableBox);
ret.setLeading(90f);// 主档和子档的上下距离
//ret.setPaddingTop(1000);
return ret;
}