java导出2007版word(docx格式)freemarker + xml 实现
2016-10-17 17:11
851 查看
Freemarker+xml生成docx
原理概述:word从2003版就支持xml格式,而freemarker是java封装的模板工具,两者结合也就是在xml中需要动态生成的部分调用freemarker的指令(类似于EL表达式),来生成我们需要的数据,再用流输出文件,就达到了写word的效果。
生成word的基本流程图如下:
按照项目需要生成固定格式的docx格式的模板。
为方便测试做了个简单的例子,docx模板的内容如下图:
生成xml模板
从docx模板中取出word/document.xml,由于docx属于zip格式,可以用winrar打开,如图:
除word文件夹外其它文件为基本配置文件,取出word/document.xml(存放word文件的文本内容)如下图:
需要把document.xml解压出来,修改里面需要从数据库导出的数据用freemarker的指令代替,例如${test} 同时可以用遍历函数
替换完成后相当于生成了xml模板
生成的Xml模板:
这里把数据库中的数据放到map中,把map和xml模板交给freemarker来生成(填充完数据)的xml具体实现方法如下:
利用freemarker生成数据
调用freemarker中的process方法(上图中的方法)来填充数据。
例(用1中生成的xml为模板填充数据):
//xml的模板路径 template/test.xml
String xmlTemplate = "test.xml";
//填充完数据的临时xml
String xmlTemp = "d:\\temp.xml";
Writer w = new FileWriter(new File(xmlTemp));
//1.需要动态传入的数据
Map<String,Object> p = new HashMap<String,Object>();
List<String> students = new ArrayList<String>();
students.add("张三");
students.add("李四");
students.add("王二");
p.put("test", "测试一下是否成功");
p.put("students", students);
//2.把map中的数据动态由freemarker传给xml
XmlToExcel.process(xmlTemplate, p, w);
注:下文中会给出源码这里只是方便理解。
导出word文件
利用java的zipFile 和 ZipOutputStream 及zipFile.getInputStream() 来根据docx模板导出 (需要把word/document.xml文件替换成(填充完数据)的xml)具体操作流程如下:
这里输出的文件即为完整的docx格式的word文件
测试调用的代码:
调用成功后生成的test.docx如下图:
注:
测试项目的目录结构:
需要引入的包:
链接:http://pan.baidu.com/s/1eS7JHia 密码:tlec
原理概述:word从2003版就支持xml格式,而freemarker是java封装的模板工具,两者结合也就是在xml中需要动态生成的部分调用freemarker的指令(类似于EL表达式),来生成我们需要的数据,再用流输出文件,就达到了写word的效果。
生成word的基本流程图如下:
1. 生成docx模板和xml模板
生成docx模板按照项目需要生成固定格式的docx格式的模板。
为方便测试做了个简单的例子,docx模板的内容如下图:
生成xml模板
从docx模板中取出word/document.xml,由于docx属于zip格式,可以用winrar打开,如图:
除word文件夹外其它文件为基本配置文件,取出word/document.xml(存放word文件的文本内容)如下图:
需要把document.xml解压出来,修改里面需要从数据库导出的数据用freemarker的指令代替,例如${test} 同时可以用遍历函数
替换完成后相当于生成了xml模板
生成的Xml模板:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 wp14"> <w:body> <w:p w:rsidR="009175C2" w:rsidRDefault="005B5FB3" w:rsidP="005B5FB3"> <w:pPr> <w:pStyle w:val="1"/> <w:jc w:val="center"/> <w:rPr> <w:rFonts w:hint="eastAsia"/> </w:rPr> </w:pPr> <w:bookmarkStart w:id="0" w:name="_GoBack"/> <w:bookmarkEnd w:id="0"/> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> </w:rPr> <w:t> 这是一个测试Word</w:t> </w:r> </w:p> <w:p w:rsidR="005B5FB3" w:rsidRDefault="005B5FB3" w:rsidP="005B5FB3"> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> </w:rPr> </w:pPr> </w:p> <w:p w:rsidR="005B5FB3" w:rsidRDefault="005B5FB3" w:rsidP="005B5FB3"> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> </w:rPr> </w:pPr> </w:p> <w:p w:rsidR="005B5FB3" w:rsidRDefault="005B5FB3" w:rsidP="005B5FB3"> <w:pPr> <w:pStyle w:val="a3"/> <w:numPr> <w:ilvl w:val="0"/> <w:numId w:val="1"/> </w:numPr> <w:ind w:firstLineChars="0"/> <w:rPr> <w:rFonts w:hint="eastAsia"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> </w:rPr> <w:t> ${test}</w:t> </w:r> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> </w:rPr> <w:t xml:space="preserve"> </w:t> </w:r> </w:p> <#list students as s> <w:p w:rsidR="005B5FB3" w:rsidRDefault="005B5FB3" w:rsidP="005B5FB3"> <w:pPr> <w:pStyle w:val="a3"/> <w:numPr> <w:ilvl w:val="0"/> <w:numId w:val="1"/> </w:numPr> <w:ind w:firstLineChars="0"/> <w:rPr> <w:rFonts w:hint="eastAsia"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> </w:rPr> <w:t> ${s} </w:t> </w:r> </w:p> </#list> <w:sectPr w:rsidR="005B5FB3" w:rsidRPr="005B5FB3"> <w:pgSz w:w="11906" w:h="16838"/> <w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="851" w:footer="992" w:gutt 4000 er="0"/> <w:cols w:space="425"/> <w:docGrid w:type="lines" w:linePitch="312"/> </w:sectPr> </w:body> </w:document>
2. 利用freemarker填充数据并生成word文件
这里把数据库中的数据放到map中,把map和xml模板交给freemarker来生成(填充完数据)的xml具体实现方法如下:
package com.hannet.yigehui; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.HashMap; import java.util.Map; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; public class XmlToExcel { private static XmlToExcel tplm = null; private Configuration cfg = null; private XmlToExcel() { cfg = new Configuration(); try { //注册tmlplate的load路径 cfg.setClassForTemplateLoading(this.getClass(), "/template/"); } catch (Exception e) { } } private static Template getTemplate(String name) throws IOException { if(tplm == null) { tplm = new XmlToExcel(); } return tplm.cfg.getTemplate(name); } /** * * @param templatefile 模板文件 * @param param 需要填充的内容 * @param out 填充完成输出的文件 * @throws IOException * @throws TemplateException */ public static void process(String templatefile, Map param ,Writer out) throws IOException, TemplateException{ //获取模板 Template template=XmlToExcel.getTemplate(templatefile); template.setOutputEncoding("UTF-8"); //合并数据 template.process(param, out); if(out!=null){ out.close(); } } }
利用freemarker生成数据
调用freemarker中的process方法(上图中的方法)来填充数据。
例(用1中生成的xml为模板填充数据):
//xml的模板路径 template/test.xml
String xmlTemplate = "test.xml";
//填充完数据的临时xml
String xmlTemp = "d:\\temp.xml";
Writer w = new FileWriter(new File(xmlTemp));
//1.需要动态传入的数据
Map<String,Object> p = new HashMap<String,Object>();
List<String> students = new ArrayList<String>();
students.add("张三");
students.add("李四");
students.add("王二");
p.put("test", "测试一下是否成功");
p.put("students", students);
//2.把map中的数据动态由freemarker传给xml
XmlToExcel.process(xmlTemplate, p, w);
注:下文中会给出源码这里只是方便理解。
导出word文件
利用java的zipFile 和 ZipOutputStream 及zipFile.getInputStream() 来根据docx模板导出 (需要把word/document.xml文件替换成(填充完数据)的xml)具体操作流程如下:
package com.hannet.yigehui; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.Writer; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; import freemarker.template.TemplateException; /** * 其实docx属于zip的一种,这里只需要操作word/document.xml中的数据,其他的数据不用动 * @author yigehui * */ public class XmlToDocx { /** * * @param documentFile 动态生成数据的docunment.xml文件 * @param docxTemplate docx的模板 * @param toFileName 需要导出的文件路径 * @throws ZipException * @throws IOException */ public void outDocx(File documentFile,String docxTemplate,String toFilePath) throws ZipException, IOException { try { String fileName = XmlToDocx.class.getClassLoader().getResource("").toURI().getPath()+docxTemplate; File docxFile = new File(fileName); ZipFile zipFile = new ZipFile(docxFile); Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries(); ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(toFilePath)); int len=-1; byte[] buffer=new byte[1024]; while(zipEntrys.hasMoreElements()) { ZipEntry next = zipEntrys.nextElement(); InputStream is = zipFile.getInputStream(next); //把输入流的文件传到输出流中 如果是word/document.xml由我们输入 zipout.putNextEntry(new ZipEntry(next.toString())); if("word/document.xml".equals(next.toString())){ //InputStream in = new FileInputStream(new File(XmlToDocx.class.getClassLoader().getResource("").toURI().getPath()+"template/test.xml")); InputStream in = new FileInputStream(documentFile); while((len = in.read(buffer))!=-1){ zipout.write(buffer,0,len); } in.close(); }else { while((len = is.read(buffer))!=-1){ zipout.write(buffer,0,len); } is.close(); } } zipout.close(); } catch (URISyntaxException e) { e.printStackTrace(); }catch (FileNotFoundException e) { e.printStackTrace(); } } }
这里输出的文件即为完整的docx格式的word文件
测试调用的代码:
public static void main(String[] args) throws IOException, TemplateException { //xml的模板路径*/* String xmlTemplate = "test.xml"; //设置docx的模板路径 和文件名 String docxTemplate = "template/test.docx"; String toFilePath = "d:\\test.docx"; //填充完数据的临时xml String xmlTemp = "d:\\temp.xml"; Writer w = new FileWriter(new File(xmlTemp)); //1.需要动态传入的数据 Map<String,Object> p = new HashMap<String,Object>(); List<String> students = new ArrayList<String>(); students.add("张三"); students.add("李四"); students.add("王二"); p.put("test", "测试一下是否成功"); p.put("students", students); //2.把map中的数据动态由freemarker传给xml XmlToExcel.process(xmlTemplate, p, w); //3.把填充完成的xml写入到docx中 XmlToDocx xtd = new XmlToDocx(); xtd.outDocx(new File(xmlTemp), docxTemplate, toFilePath); }
调用成功后生成的test.docx如下图:
注:
测试项目的目录结构:
需要引入的包:
链接:http://pan.baidu.com/s/1eS7JHia 密码:tlec
相关文章推荐
- java导出2007版word(docx格式)freemarker + xml 实现
- java导出word(2003版doc格式) FreeMarker+XML实现
- java 导出word 利用freemarker指令更改xml 导出word docx文档 (3)
- java docx4j导出HTML为word(.docx)报错:org.docx4j.org.xhtmlrenderer.load INFO:: SAX XMLReader in use (parse
- java用freemarker实现导出word----包含图片
- asp.net导出excel-一行代码实现excel、xml、pdf、word、html、csv等7种格式文件导出功能而且美观-SNF快速开发平台
- Java Web项目中利用FreeMarker模板生成的word文档,其它格式文档同理,如pdf,txt,java,xml等等
- Java Web项目中利用FreeMarker模板生成的word文档,其它格式文档同理,如pdf,txt,java,xml等等
- Java利用freemaker和(excelXML表格或wordXML表格),导出自己任何想要格式的文档
- java 调用jacob和java2word导出word,并实现将带有格式的html文本和图片插入word
- java freemarker 实现word文件导出
- Java实现用Freemarker完美导出word文档(带图片)
- Java基于XML+FreeMarker导出Word
- java freemarker 通过ftl模板文件导出word文件发现在有中文地方出现在乱码,打开word文件提示xml错误解决办法
- java freemarker模板 实现word文件导出
- java使用Freemarker+xml导出word
- java基于freemarker导出指定word格式带多图片源码。
- Java大批量导出数据,格式可以为xml或excel
- PageOffice实现最简单的Java导出Word中的数据
- java实现word套打(关于Freemarker生成word的使用(java生成word))