背景:跟着我的步骤一步一步,最后一定会成功!!
首先生成pdf有很多种方式:
- iText,生成PDF文档,还支持将XML、Html文件转化为PDF文件;
- Apache PDFBox,生成、合并PDF文档;
- docx4j,生成docx、pptx、xlsx文档,支持转换为PDF格式。
比较:
- iText开源协议为AGPL,而其他两个框架协议均为Apache License v2.0。需要用画笔去花模板,很繁琐!
- Apache PDFBox,生成、合并PDF文档;
- docx4j,生成docx、pptx、xlsx文档,支持转换为PDF格式。
本文使用最后一种,思路如下图:
步骤
1.首先将你要生成的pdf,用worl画出来,比如你需要特定结构的pdf,你没办法做到,但是一个wold你可以通过编辑,得到你想要的模板 。如下:(你想要替换的内容换成${arg0!""},就是用将来你需要替换的数据暂时用变量表示出来,后续只要替换变量的值即可!而模板本身不变)
2.其次将word的字体换成宋体(通用),文件另存为xml格式文件如下:
3.将文件改名,以.ftl形式结尾(利用freemarker,所以改成freemarker文件形式)
4.读取ftl文件,将其转化成xml字符串。读取xml字符串,将其转换成word,读取word,利用dom4j将其转换成你想要的模式的pdf
@SuppressWarnings({ "unchecked", "rawtypes" })
private Map createPdf(List<Loan> loanList) {
Map fileMap = new HashMap();
for (Loan loan : loanList) {
// 创建数据
String bankParentName = "";
// List<SysOrg> orgByOrgId = service.getOrgByOrgId(loan.getBankId());
// if (orgByOrgId!=null && orgByOrgId.size()>0) {
// String orgPathname = orgByOrgId.get(0).getOrgPathname();
// if (orgPathname.indexOf("/", 1)==-1) {
// bankParentName = orgPathname.substring(1);
// }else {
// bankParentName = orgPathname.substring(1,orgPathname.indexOf("/", 1));
// }
// }
// 银行名称
String bankName = loan.getBankName();
// 企业名称
String enterpriseName = loan.getEnterpriseName();
// 贷款编号
// String loanNumber = loan.getLoanNumber();
String loanNumber = loan.getUpdator();
// 会议方案期数
Long meetingPlanNper = loan.getMeetingPlanNper();
// 会议方案金额
BigDecimal meetingPlanAmount = loan.getMeetingPlanAmount().multiply(new BigDecimal(10000));
//融资平台企业类别
String businessCategory = loan.getBusinessCategory();
//信用贷款
BigDecimal credit;
//索赔金额
BigDecimal claimAmount;
if ("第一类".equals(businessCategory)) {
credit = new BigDecimal(0);
claimAmount =new BigDecimal(0);
}else if ("第二类".equals(businessCategory)) {
credit = meetingPlanAmount.multiply(new BigDecimal(0.6667));
claimAmount = meetingPlanAmount.multiply(new BigDecimal(0.3333));
}else if ("第三类".equals(businessCategory)) {
credit = meetingPlanAmount.multiply(new BigDecimal(0.95));
claimAmount = meetingPlanAmount.multiply(new BigDecimal(0.005));
}else {
credit = new BigDecimal(0);
claimAmount =new BigDecimal(0);
}
Map dataMap = new HashMap();
dataMap.put("arg0", bankParentName);
dataMap.put("arg1", bankName);
dataMap.put("arg2", enterpriseName);
dataMap.put("arg3", loanNumber);
dataMap.put("arg4", ConvertNumberToUpper.toChinese(meetingPlanNper+""));
dataMap.put("arg5", ConvertNumberToUpper.digitUppercase(meetingPlanAmount.doubleValue()));
if (credit.intValue()==0) {
dataMap.put("arg6", "___________");
}else {
dataMap.put("arg6", ConvertNumberToUpper.digitUppercase(credit.doubleValue()));
}
if (claimAmount.intValue()==0) {
dataMap.put("arg7", "___________");
}else {
dataMap.put("arg7", ConvertNumberToUpper.digitUppercase(claimAmount.doubleValue()));
}
// Map dataMap = new HashMap();
// dataMap.put("bankName", loan.getBankName());
// dataMap.put("loanNumber", loan.getLoanNumber());
// dataMap.put("enterpriseName", loan.getEnterpriseName());
// dataMap.put("applicationSituationAmount", ConvertNumberToUpper.digitUppercase(loan.getApplicationSituationAmount()*10000));
// dataMap.put("meetingPlanAmount", ConvertNumberToUpper.digitUppercase(loan.getMeetingPlanAmount()*10000));
// dataMap.put("meetingPlanNper", ConvertNumberToUpper.toChinese(loan.getMeetingPlanNper()+""));
// 获取模板
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
configuration.setClassForTemplateLoading(this.getClass(), "/template/chj");
String name = "temp" + UUID.randomUUID() + ".doc";
File file = new File(name);
try {
Template template = configuration.getTemplate("testwold.ftl");
template.setEncoding("UTF-8");
/*Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(name), "UTF-8"));
template.process(dataMap, out);
out.close();*/
/**
* 这段是我为了测试pdf功能而增加上的-start
*/
//将数据和ftl文件组装为xml文本
StringWriter stringWriter = new StringWriter();
BufferedWriter writer = new BufferedWriter(stringWriter);
template.process(dataMap, writer);
String xmlStr = stringWriter.toString();
System.out.println("xmlStr:"+xmlStr);
writer.close();
//使用docx4j将xml文本加载为word文档对象
ByteArrayInputStream in = new ByteArrayInputStream(xmlStr.getBytes("utf-8"));
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(in);
Mapper nzt = wordMLPackage.getFontMapper();
Map<String, PhysicalFont> fontMappingssss = nzt.getFontMappings();
//使用docx4j将word文档转存为pdf文档
String outputfilepath = "D:\\late\\qyh\\caohejing\\finally\\test.pdf";
FileOutputStream os = new FileOutputStream(new File(outputfilepath));
FOSettings foSettings = Docx4J.createFOSettings();
Mapper fontMapper = new IdentityPlusMapper();
Map<String, PhysicalFont> physicalFonts = PhysicalFonts.getPhysicalFonts();
Set<String> keySet = physicalFonts.keySet();
//中文字体转换
fontMapper.getFontMappings().put("Calibri", physicalFonts.get("Calibri"));
fontMapper.getFontMappings().put("华文行楷", physicalFonts.get("STXingkai"));
fontMapper.getFontMappings().put("隶书", physicalFonts.get("LiSu"));
fontMapper.getFontMappings().put("宋体",physicalFonts.get("SimSun"));
fontMapper.getFontMappings().put("微软雅黑",physicalFonts.get("Microsoft Yahei"));
fontMapper.getFontMappings().put("黑体",physicalFonts.get("SimHei"));
fontMapper.getFontMappings().put("楷体",physicalFonts.get("KaiTi"));
fontMapper.getFontMappings().put("新宋体",physicalFonts.get("NSimSun"));
fontMapper.getFontMappings().put("华文行楷", physicalFonts.get("STXingkai"));
fontMapper.getFontMappings().put("华文仿宋", physicalFonts.get("STFangsong"));
fontMapper.getFontMappings().put("宋体扩展",physicalFonts.get("simsun-extB"));
fontMapper.getFontMappings().put("仿宋",physicalFonts.get("FangSong"));
fontMapper.getFontMappings().put("仿宋_GB2312",physicalFonts.get("FangSong_GB2312"));
fontMapper.getFontMappings().put("幼圆",physicalFonts.get("YouYuan"));
fontMapper.getFontMappings().put("华文宋体",physicalFonts.get("STSong"));
fontMapper.getFontMappings().put("华文中宋",physicalFonts.get("STZhongsong"));
try {
wordMLPackage.setFontMapper(fontMapper);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
foSettings.setWmlPackage(wordMLPackage);
Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);
// Docx4J.toPDF(wordMLPackage, new FileOutputStream(new File(outputfilepath)));
//Word转PDF
/*WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(new File("abc.docx"));
Mapper fontMapper = new IdentityPlusMapper();
// fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
mlPackage.setFontMapper(fontMapper);
OutputStream os = new java.io.FileOutputStream("abc.pdf");
FOSettings foSettings = Docx4J.createFOSettings();
foSettings.setWmlPackage(mlPackage);
Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL); */
/**
* 这段是我为了测试pdf功能而增加上的-end
*/
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
} catch (Docx4JException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//fileMap.put(loan.getEnterpriseName()+"_投放通知书_告知书.doc", file);
}
return fileMap;
}
5.项目所用jar包:
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-export-fo</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.18</version>
</dependency>
6.结果展示:
总结:生成pdf有很多种方式,但是本文所选可以实现复杂的数据替换,复杂的模板使用!思路清晰,容易上手!是不是很简单!嘻嘻!