版权声明:本文为haiyuking原创文章,转载请注明出处!
这个方案只能在java中运行,无法在android项目中运行。所以此方案是:app将表单数据发送给后台,后台通过freemarker将表单数据根据模板ftl文件生成word文件,然后返回给app,由app进行展现。
官网下载地址:
后续将freemarker.jar文件添加到项目中。
注意:
例子:
对于word2016,另存为后会自动打开xml文件,所以需要先关闭xml文件,然后再使用firstobject xml editor软件打开xml文件!
下载firstobject xml editor软件(免安装版):下载地址:
官网下载的软件打开文件的时候可能会出现崩溃的问题。建议使用foxe_chs.exe软件进行编辑。下载地址见项目demo下载地址。
首先进行“缩进排版”
查找真实数据,替换成freemarker标记,其实就是map<string, object>中key,如${writedate},对应map的key值就是writedate。
替换成:
对于文本按照上面的方式进行替换,而对于图片需要这样替换:
图片是以base64编码存在的,且这些编码放在<w:bindata>标签之中。将这些base64编码使用占位符代替,然后java代码中将图片生成base64编码,传入值就能正常显示了。
替换成
注意:一定不要用word打开ftl模板文件查看,否则xml内容会发生变化,导致前面的工作白做了;可以使用editplus打开查看。
package com.why.main; import java.io.bufferedwriter; 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.outputstreamwriter; import java.io.unsupportedencodingexception; import java.io.writer; import java.util.hashmap; import java.util.map; import freemarker.template.configuration; import freemarker.template.template; import freemarker.template.templateexception; import sun.misc.base64encoder; /** * 生成doc文档 */ public class documenthandler { //测试 public static void main(string[] args) { documenthandler documenthandler = new documenthandler(); documenthandler.createdoc(); } // 配置实例:只需要一个实例(单例模式) private configuration configuration = null; private string tempdirpath = "d:/temp"; public documenthandler() { // 通过freemaker的configuration读取相应的ftl configuration = new configuration(configuration.version_2_3_28); configuration.setdefaultencoding("utf-8");// 设置默认编码方式 } /** * 生成doc文档 */ public void createdoc() { // 要填入模本的数据文件 map<string,object> datamap = new hashmap<string,object>(); getdata(datamap); // 设置模本装置方法和路径,freemarker支持多种模板装载方法。可以重servlet,classpath,数据库装载, // 如果模板是放在程序代码的包下面 //configuration.setclassfortemplateloading(this.getclass(),"../"); //如果放到服务器目录中,则使用下面的代码 try { configuration.setdirectoryfortemplateloading(new file(tempdirpath)); } catch (ioexception e2) { e2.printstacktrace(); } //这里要设置取消使用local语言环境 configuration.setlocalizedlookup(false); template template = null; try { // leavetemplet.ftl为要装载的模板 template = configuration.gettemplate("leavetemplet.ftl","utf-8"); } catch (ioexception e) { e.printstacktrace(); } // 输出文档路径及名称 file dir = new file(tempdirpath); file outfile = new file(tempdirpath + "/请假条.doc"); if (!dir.isdirectory()) { dir.mkdir(); if (!outfile.exists()) { try { outfile.createnewfile(); } catch (ioexception e) { system.out.println("创建文件失败"); e.printstacktrace(); } } } writer out = null; try { try { out = new bufferedwriter(new outputstreamwriter(new fileoutputstream(outfile), "utf-8")); } catch (unsupportedencodingexception e) { e.printstacktrace(); } } catch (filenotfoundexception e1) { system.out.println("输出文件失败"); e1.printstacktrace(); } try { template.process(datamap, out); system.out.println("it's success!"); } catch (templateexception e) { system.out.println("生成失败"); e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } } /** * 注意datamap里存放的数据key值要与模板中的参数相对应 */ private void getdata(map<string,object> datamap) { string imgbase64str = getimagestr(tempdirpath + "/leaderopinion_img.png"); // 使用string的有参构造方法 datamap.put("writedate","2018年10月13日");//填写日期 datamap.put("name","haiyuking");//姓名 datamap.put("dept","移动组");//部门 datamap.put("leavetype","☑倒休 √年假 ✔事假 ☐病假 ☐婚假 ☐产假 ☐其他");//请假类型 datamap.put("leavereason","倒休休息两天");//请假理由 datamap.put("leavestartdate","2018年10月13日上午");//请假开始日期 datamap.put("leaveenddate","2018年10月14日下午");//请假结束日期 datamap.put("leaveday","2");//请假天数 datamap.put("leaveleader","同意");//直属领导意见 datamap.put("leavedeptleaderimg",imgbase64str);//部门领导意见 } /** * 获取图片的base64值*/ private string getimagestr(string imgfile) { inputstream in = null; byte[] data = null; try { in = new fileinputstream(imgfile); data = new byte[in.available()]; in.read(data); in.close(); } catch (ioexception e) { e.printstacktrace(); } base64encoder encoder = new base64encoder(); return encoder.encode(data); } }
注意:map数据中的key值,对应ftl文件中的${xxxx}这里面的xxxx值。
1、不要使用英文;
2、如果想要保证一个整体,不要将中文、数字、标点符号一起使用(这里指占位区域);
3、日期想要作为一个整体,不要数字+中文输入,而是通过enter键输入;
下面记录的是不同输入的效果(使用firstobject xml editor软件打开xml文件)
使用英文:
使用数字:
使用中文:
日期采用数字+中文:
日期采用enter键输入:
中文+标点符号:
沫沫金:使用java模版引擎freemarker生成复杂的word文档
freemaker解析word模板(含图片)生成word文档
链接:https://pan.baidu.com/s/19apniywxt5gmn_kdqjfcra 提取码:eo0n