zoukankan      html  css  js  c++  java
  • 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 { } }

      

     

  • 相关阅读:
    vue项目中引用spreadjs方法
    使用Element的table合并单元格的问题(合并行)
    卸载mysql
    mac 下安装mySQL
    react中界面跳转 A界面跳B界面,返回A界面,A界面状态保持不变 localStorage方法
    react点击弹出带出值和点击跳转页面带出值
    ajax优缺点
    vue项目console.log报错
    性能优化
    对象生命周期
  • 原文地址:https://www.cnblogs.com/wjlwo2ni/p/13208128.html
Copyright © 2011-2022 走看看