月眸


freemarker生成word文档

毛毛小妖 2019-06-19 344浏览 0条评论
首页/ 正文
分享到: / / / /

这段时间有个需求,需要将word模板部分文字变成不可编辑的,传给其他公司。由于现在的模板都是用书签形式进行替换的,并且是用pageoffice操作的,我们系统不允许设置任何格式。解决方案是:读取生成的文档的所有书签和内容,丢到map里面,然后制作freemarker模板,将数据填充到freemarker模板中,再保存成新的文档。这个过程如果人工来做的话,不仅工作量大,而且很容易出错,所以我写了些小程序来进行自动处理,好了,开始干活吧!下面是步骤。

一、将word模板设置限制编辑并保存为Word xml文档格式,如图所示为限制编辑操作步骤,这样子设置完,此文档就不允许编辑啦。注意,xml的名字尽可能用英文,大家都知道中文的名字在不同的环境中java处理起来会出现各种奇葩的问题。

二、将生成的xml文档放到eclipse或者其他工具中进行格式化,不要问我为什么要格式化,我也不知道,不格式化会报错的。

三、运行小程序,自动将书签解析并生成相应的freemarker能识别的变量

package com.sy.poi;

import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XmlTest1 {

	private final static String RPR = "w:rPr";

	private static List<String> elementList = Arrays.asList("w:b", "w:bCs");
	
    //不想设为可读的区域,将相应的书签名称放到这个list里
	private static final List<String> exceptBookmarks = Arrays.asList("xxx");
	
	public static void main(String[] args) throws Exception {
		String basePath = "D:/docTemplate/";
		String fileName = "yssccxpjs.xml";
		String filePath = basePath+fileName;
		String outPath = basePath+"replace_"+fileName;
		// 创建工厂documentBuilderFactory
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		// 创建一个documentBuilder
		DocumentBuilder db = dbf.newDocumentBuilder();
		// 指定要解析的xml文件
		Document document = db.parse(filePath);
		createNodeByTag(document);
		saveDocument(document,outPath);
	}

	/**
	 * 描述: 保存
	 * @author shengyu
	 * @param doc
	 * @param outPath 
	 * @throws Exception 
	 * @date:2019年6月18日 下午2:59:01
	 */
	public static void saveDocument(Document doc, String outPath) throws Exception {
		// 创建一个TransformerFactory实例
		TransformerFactory tff = TransformerFactory.newInstance();
		// 通过TransformerFactory 得到一个转换器
		Transformer tf = tff.newTransformer();
		// 将 XML Source 转换为 Result
		tf.transform(new DOMSource(doc), new StreamResult(outPath));
	}

	/**
	 * 描述: 处理xml文档,根据书签创建模板标签
	 * @author shengyu
	 * @param docu 
	 * @date:2019年6月18日 下午3:01:47
	 */
	public static void createNodeByTag(Document docu) {
		NodeList nodelist = docu.getElementsByTagName("w:bookmarkStart");
		for (int i = 0; i < nodelist.getLength(); i++) {
			Node rootNode = (Node) nodelist.item(i);
			NamedNodeMap attributes = rootNode.getAttributes();
			String textContent = attributes.item(1).getTextContent().toUpperCase();
			if (textContent.startsWith("PO_")) {
				System.err.println(textContent);
				// 先取紧随其后的非书签节点
				Node nextSibling = rootNode.getNextSibling().getNextSibling();
				String nextNodeName = null;
				if (nextSibling != null) {
					nextNodeName = nextSibling.getNodeName();
					if ("w:bookmarkEnd".equals(nextNodeName)) {
						nextSibling = nextSibling.getNextSibling().getNextSibling();
						if (nextSibling != null) {
							nextNodeName = nextSibling.getNodeName();
						} else {
							nextNodeName = null;
						}
					}
				}

				Node originNode = null;
				// 如果紧随其后的非书签节点为空,则取紧随其前的非书签节点
				if (nextNodeName == null) {
					originNode = rootNode.getPreviousSibling().getPreviousSibling();
					if (originNode != null) {
						String originNodeName = originNode.getNodeName();
						if ("w:bookmarkEnd".equals(originNodeName)) {
							originNode = originNode.getPreviousSibling().getPreviousSibling();
							originNodeName = originNode.getNodeName();
						}
						if ("w:bookmarkStart".equals(originNodeName)) {
							originNode = originNode.getPreviousSibling().getPreviousSibling();
						}
					}
				} else {
					originNode = nextSibling;
				}
				//需要限制编辑的区域
				Element permitStartElement = null;
				Element permitEndElement = null;
				if(!exceptBookmarks.contains(textContent)){
					permitStartElement = docu.createElement("w:permStart");
					String id = UUID.randomUUID().toString();
					permitStartElement.setAttribute("w:id", id);
					permitStartElement.setAttribute("w:edGrp", "everyone");
					permitEndElement = docu.createElement("w:permEnd");
					permitEndElement.setAttribute("w:id", id);
				}
				// 创建文本节点
				Element element = docu.createElement("w:r");

				// 创建文本属性属性
				CreateChildren(originNode, docu, element, null);

				// 创建文本域
				Element textElement = docu.createElement("w:t");
				textElement.setTextContent("${" + textContent + "}");
				element.appendChild(textElement);
				
				Node insertBefore = null;
				if(!exceptBookmarks.contains(textContent)){
					insertBefore = rootNode.getParentNode().insertBefore(permitEndElement, rootNode.getNextSibling());
				}
				Node insertBefore2 = rootNode.getParentNode().insertBefore(element, insertBefore);
				if(!exceptBookmarks.contains(textContent)){
					rootNode.getParentNode().insertBefore(permitStartElement, insertBefore2);
				}
			}
		}
	}

	public static void CreateChildren(Node currentNode, Document docu, Element element, Element rprElement) {
		if (currentNode != null) {
			NodeList childNodes = currentNode.getChildNodes();
			String nodeName = currentNode.getNodeName();
			NamedNodeMap attributes = currentNode.getAttributes();
			if (nodeName != null && !"#text".equals(nodeName)) {
				if (RPR.equals(nodeName)) {
					rprElement = docu.createElement(RPR);
					element.appendChild(rprElement);
				}
				String str = nodeName;
				int length = attributes.getLength();
				// 处理有属性的,或者包含加粗,斜体等的
				if (length > 0 || elementList.contains(currentNode.getNodeName())) {
					str += ":";
					Element attr = docu.createElement(currentNode.getNodeName());
					for (int i = 0; i < length; i++) {
						Node item = attributes.item(i);
						String name = item.getNodeName();
						String value = item.getTextContent();
						attr.setAttribute(name, value);
						str += item + " ";
					}
					if (rprElement != null) {
						rprElement.appendChild(attr);
					}
				}
				System.out.println(str);
				for (int j = 0; j < childNodes.getLength(); j++) {
					Node childNode = childNodes.item(j);
					String childName = childNode.getNodeName();
					if (childName != null && !"#text".equals(childName)) {
						CreateChildren(childNode, docu, element, rprElement);
					}
				}
			}
		}
	}
}

四、利用freemarker生成最后的文档

package com.ai.trial;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Bookmark;
import org.apache.poi.hwpf.usermodel.Range;
import org.junit.Test;

import com.ai.trial.modules.trial.controller.TlTrialProcessController;

import freemarker.template.Configuration;
import freemarker.template.Template;

public class TestDoc {

	@Test
	public void test() {
		//从fastdfs取最新生成的文档
		String dataFilePath = "D:\\poitest\\data.doc";
		//freemarker模板
		String templateName = "template.ftl";
		//输出路径
		String outPath = "D:\\poitest\\template.doc";
		Map<String, String> dataMap = getDataMap(dataFilePath);
		processDoc(dataMap,templateName,outPath);
	}
	
	private void processDoc(Map<String, String> dataMap, String templateName, String outPath) {
		OutputStream os = null;
		try {
			//创建模板的临时文件
			String folder = System.getProperty("java.io.tmpdir");
			if(!folder.endsWith("/") && !folder.endsWith("\\")){
				folder = folder + "/";
			}
			Configuration config = new Configuration();
			config.setDefaultEncoding("utf-8");
			config.setClassForTemplateLoading(TlTrialProcessController.class, "/template/");
			Template fmTemplate = config.getTemplate(templateName);
			config.setDirectoryForTemplateLoading(new File(folder));
			StringWriter result = new StringWriter();
			fmTemplate.process(dataMap, result);
			byte[] b = result.toString().getBytes("utf-8");
			os = new FileOutputStream(outPath);
			os.write(b);
			os.flush();
			os.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(os!=null){
				try {
					os.close();
				} catch (Exception e2) {
					System.err.println(e2);
				}
			}
		}
	}
	
	public Map<String, String> getDataMap(String templatePath) {
		Map<String, String> dataMap = new HashMap<>();
		InputStream is;
		HWPFDocument doc = null;
		try {
			is = new FileInputStream(templatePath);
			doc = new HWPFDocument(is);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (doc != null) {
			for (int i = 0; i < doc.getBookmarks().getBookmarksCount(); i++) {
				final Bookmark bookmark = doc.getBookmarks().getBookmark(i);
				if (bookmark.getName() != null && bookmark.getName().startsWith("PO_")) {
					final Range range = new Range(bookmark.getStart(), bookmark.getEnd(), doc);
					String bookmarkName = bookmark.getName().trim().toUpperCase();
					dataMap.put(bookmarkName, range.text());
				}
			}
		}
		return dataMap;
	}

}

 

最后修改:2019-06-19 15:01:38 © 著作权归作者所有
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付

上一篇

发表评论

说点什么吧~

评论列表

还没有人评论哦~赶快抢占沙发吧~