问题
工作中经常有这样的需求,将一些数据,导出为下图的PDF文件,那Java怎么做呢?今天手把手教你
准备模版
模版地址:https://download.csdn.net/download/ZHUSHANGLIN/91923381
修改模版使用AcrobatProPortable工具,在"编辑PDF"按钮修改模版样式,在“准备表单”按钮中修改模版中填充内容,需要工具的留言私发你
Java代码
首先添加依赖
<!--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>
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.pdfPdfReader 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文件还能编辑,一定要设为truestamper.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); //表titleParagraph ret = new Paragraph("",fontChinese); //表titlePdfPTable 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;}