freemarker 模板导出docx 及合并

//添加目录
	public static void generateTOC(XWPFDocument document)
			throws InvalidFormatException, FileNotFoundException, IOException {
		String findText = "toc";//word模板段落标识(在此标识处生成目录)
		String replaceText = "";
		for (XWPFParagraph p : document.getParagraphs()) {
			for (XWPFRun r : p.getRuns()) {
				int pos = r.getTextPosition();
				String text = r.getText(pos);
				System.out.println(text);
				if (text != null && text.contains(findText)) {
					text = text.replace(findText, replaceText);
					r.setText(text, 0);
					addField(p, "TOC \\o \"1-3\" \\h \\z \\u");
					// addField(p, "TOC \\h");
					break;
				}
			}
		}
	}

	private static void addField(XWPFParagraph paragraph, String fieldName) {
		CTSimpleField ctSimpleField = paragraph.getCTP().addNewFldSimple();
		ctSimpleField.setInstr(fieldName);
		ctSimpleField.setDirty(STOnOff.TRUE);
		ctSimpleField.addNewR().addNewT().setStringValue("<<fieldName>>");
	}

  

前提

word.docx 模板更改后缀为zip

打开zip 获取 word 文件夹种document.xml

在document.xml 种填充所需参数${}格式,循环添加<#list items as item></#list>

document.xml 放入项目templates 文件夹中

工具代码

public class FreeMarkUtils {
	private static Logger logger = LoggerFactory.getLogger(FreeMarkUtils.class);

	public static Configuration getConfiguration() {
		// 创建配置实例
		Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
		// 设置编码
		configuration.setDefaultEncoding("utf-8");
		configuration.setClassForTemplateLoading(FreeMarkUtils.class, "/templates");// 换成自己对应的目录
		return configuration;
	}

	/**
	 * 获取模板字符串输入流
	 * 
	 * @param dataMap
	 *            参数
	 * @param templateName
	 *            模板名称
	 * @return
	 */
	public static ByteArrayInputStream getFreemarkerContentInputStream(Map<String, Object> dataMap,
			String templateName) {
		ByteArrayInputStream in = null;
		try {
			// 获取模板
			Template template = getConfiguration().getTemplate(templateName);
			StringWriter swriter = new StringWriter();
			// 生成文件
			template.process(dataMap, swriter);

			in = new ByteArrayInputStream(swriter.toString().getBytes("utf-8"));// 这里一定要设置utf-8编码
																				// 否则导出的word中中文会是乱码
		} catch (Exception e) {
			logger.error("", e);
		}
		return in;
	}

	public static void createDocx(Map<String, Object> dataMap, OutputStream outputStream, String zipPath) {
		ZipOutputStream zipout = null;
		try {
			/*
			 * //图片配置文件模板 ByteArrayInputStream documentXmlRelsInput =
			 * FreeMarkUtils.getFreemarkerContentInputStream(dataMap,
			 * documentXmlRels);
			 */

			// 内容模板
			ByteArrayInputStream documentInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, "document.xml");
			// 最初设计的模板
			// File docxFile = new
			// File(WordUtils.class.getClassLoader().getResource(template).getPath());
			File docxFile = new File(zipPath);// 换成自己的zip路径
			if (!docxFile.exists()) {
				docxFile.createNewFile();
			}
			@SuppressWarnings("resource")
			ZipFile zipFile = new ZipFile(docxFile);
			Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
			zipout = new ZipOutputStream(outputStream);
			// 开始覆盖文档------------------
			int len = -1;
			byte[] buffer = new byte[1024];
			while (zipEntrys.hasMoreElements()) {
				ZipEntry next = zipEntrys.nextElement();
				InputStream is = zipFile.getInputStream(next);
				if (next.toString().indexOf("media") < 0) {
					zipout.putNextEntry(new ZipEntry(next.getName()));
					if ("word/document.xml".equals(next.getName())) {// 如果是word/document.xml由我们输入
						if (documentInput != null) {
							while ((len = documentInput.read(buffer)) != -1) {
								zipout.write(buffer, 0, len);
							}
							documentInput.close();
						}
					} else {
						while ((len = is.read(buffer)) != -1) {
							zipout.write(buffer, 0, len);
						}
						is.close();
					}
				}
			}

		} catch (Exception e) {
			System.out.println("word导出失败:" + e.getStackTrace());
			logger.error("TET", e);
		} finally {
			if (zipout != null) {
				try {
					zipout.close();
				} catch (IOException e) {
					System.out.println("io异常");

				}
			}
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					System.out.println("io异常");
				}
			}
		}
	}

	// 两个对象进行追加
	public static XWPFDocument mergeWord(XWPFDocument document, XWPFDocument doucDocument2) throws Exception {
		XWPFDocument src1Document = document;
		XWPFParagraph p = src1Document.createParagraph();
		// 设置分页符
		p.setPageBreak(true);
		CTBody src1Body = src1Document.getDocument().getBody();
		XWPFDocument src2Document = doucDocument2;
		CTBody src2Body = src2Document.getDocument().getBody();
		// XWPFParagraph p2 = src2Document.createParagraph();
		XmlOptions optionsOuter = new XmlOptions();
		optionsOuter.setSaveOuter();
		String appendString = src2Body.xmlText(optionsOuter);
		String srcString = src1Body.xmlText();
		String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
		String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
		String sufix = srcString.substring(srcString.lastIndexOf("<"));
		String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));
		CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
		src1Body.set(makeBody);
		return src1Document;
	}

}

  业务代码

单个word导出

@RequestMapping("/export")
	public void export(@RequestBody JSONObject json, HttpServletResponse res) throws Exception {
		JSONObject detail = taskService.detail(json);
		Map<String, Object> beanParams = new HashMap<>();
		beanParams.put("userTestName", detail.getString("user_test_name"));
		beanParams.put("postName", detail.getString("post_name"));
		beanParams.put("deptName", detail.getString("dept_name"));
		beanParams.put("testDate", DateUtils.formatDateDay(detail.getDate("test_date")));
		beanParams.put("testUserName", detail.getString("test_user_name"));
		beanParams.put("remarks",
				StringUtils.isEmpty(detail.getString("remarks_")) ? "" : detail.getString("remarks_"));
		beanParams.put("responsibilitys", detail.getJSONArray("responsibility_ids"));
		beanParams.put("zf", detail.getInteger("zf"));
		
         // 读到流中 File outFile = new File(ConfigUtils.getConfigValue("responsibility", "") + ".docx"); try { FreeMarkUtils.createDocx(beanParams, new FileOutputStream(outFile), ConfigUtils.getConfigValue("responsibility", "") + ".zip"); } catch (FileNotFoundException e) { e.printStackTrace(); } InputStream inStream = new FileInputStream(outFile);// 文件的存放路径 // 设置输出的格式 res.setContentType("application/octet-stream; charset=utf-8"); res.setHeader("Content-Disposition", "attachment; filename=" + Encodes.urlEncode("安全生产责任制.doc")); res.setCharacterEncoding("utf-8"); // 循环取出流中的数据 byte[] b = new byte[100]; int len; try { while ((len = inStream.read(b)) > 0) res.getOutputStream().write(b, 0, len); inStream.close(); } catch (IOException e) { e.printStackTrace(); } }

 合并多个word导出

@RequestMapping("/exports")
	public void exports(@RequestBody JSONObject json, HttpServletResponse res) throws Exception {
		json.put("enabled_state_id", "1");
		List<JSONObject> taskList = taskService.findAllList(json);
		if (taskList != null && taskList.size() > 0) {
			XWPFDocument docs = null;
			for (JSONObject task : taskList) {
				json.put("id_", task.getString("id_"));
				JSONObject detail = taskService.detail(json);
				Map<String, Object> beanParams = new HashMap<>();
				beanParams.put("userTestName", detail.getString("user_test_name"));
				beanParams.put("postName", detail.getString("post_name"));
				beanParams.put("deptName", detail.getString("dept_name"));
				beanParams.put("testDate", DateUtils.formatDateDay(detail.getDate("test_date")));
				beanParams.put("testUserName", detail.getString("test_user_name"));
				beanParams.put("remarks",
						StringUtils.isEmpty(detail.getString("remarks_")) ? "" : detail.getString("remarks_"));
				beanParams.put("responsibilitys", detail.getJSONArray("responsibility_ids"));
				beanParams.put("zf", detail.getInteger("zf"));
                   //导出指定文件 File outFile = new File("d:/test.docx");
                   //指定修改word后缀为zip路径 try { FreeMarkUtils.createDocx(beanParams, new FileOutputStream(outFile),"d:/test.zip"); } catch (FileNotFoundException e) { e.printStackTrace(); } if (taskList.indexOf(task) == 0) { docs = new XWPFDocument(new FileInputStream(outFile)); } if (taskList.indexOf(task) == 1) { docs = FreeMarkUtils.mergeWord(docs, new XWPFDocument(new FileInputStream(outFile))); } if (taskList.indexOf(task) > 1) { docs = FreeMarkUtils.mergeWord(docs, new XWPFDocument(new FileInputStream(outFile))); } } if (docs != null) { docs.write(res.getOutputStream()); docs.close(); } // 设置输出的格式 res.setContentType("application/octet-stream; charset=utf-8"); res.setHeader("Content-Disposition", "attachment; filename=" + Encodes.urlEncode("安全生产责任制.doc")); res.setCharacterEncoding("utf-8"); } else { } }

  

 

 

posted on 2020-06-29 15:16  江清澜静  阅读(1053)  评论(0编辑  收藏  举报

导航