java生成pdf(利用dom4j、freemarker生成固定模板格式的pdf文件)

背景:跟着我的步驟一步一步,最後一定會成功!!

首先生成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有很多種方式,但是本文所選可以實現複雜的數據替換,複雜的模板使用!思路清晰,容易上手!是不是很簡單!嘻嘻!

參考:https://www.jb51.net/article/160109.htm

發佈了17 篇原創文章 · 獲贊 2 · 訪問量 2314
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章