1.使用Microsoft Office Word编辑word模板,把需要动态修改的内容替换成${xxxxxx},如果有图片,尽量选择较小的图片几十K左右,并调整好位置及大小
图1 模板示例
注意:
1.变量需要使用${},例如:${CORP_ADDR}
2.将word文件另存为Word 2003 XML文档格式
图2 另存为Word 2003 XML文档
注意:
1.另存为文件名要使用英文命名
2.请使用Microsoft Office Word打开word并且另存为,因为WPS没有Word 2003 XML选项,只要Word XML,可能会出现兼容问题,导致2003版本word无法打开,并且图片处理上要麻烦一点
3.如果保存为Word XML文档,那么需要修改的地方更多(具体请查下最下面的测试模板)
3.用Firstobject free XML editor格式化导出来的xml文件
图3 Firstobject free XML editor格式化XML
下载Firstobject free XML editor,然后打开刚导出的xml,然后按F8或者Shift+F8快捷键格式化,然后保存
由于word另存为xml格式文件时,xml代码是被压缩的,所以需要格式化一下,便于阅读与编辑
4.使用Notepad++或类似编辑工具打开xml,检查动态变量是否正确
由于word编辑过程中,设置字体等原因,可能会导致${xxxxx}会被分割开,所以要检查xml文件里面的所有变量命名是否正确;
修改后→
图4 此处为错误变量与修改后变量
5.图片处理
1)如果导出来的文档与模板上的图片数量相等,不会动态新增图片的
搜索<w:binData ,会看到被这个标签包含起来的base64形式的图片,将base64编码删除,然后换成变量名${XXXXX}
修改后→
图5 修改图片变量
2)如果图片是动态新增的,那么需要修改XML模板多处
1、搜索<w:binData ,会看到被这个标签包含起来的base64形式的图片,将base64编码删除,然后换成变量名${XXXXX}
2、修改<w:binData 的w:name属性 与 它匹配的<v:imagedata 标签的src属性,确保它们两个的命名一样,但是与其他图片命名不重复
注意:
1.“>${XXXXX}<”图片变量这尖括号中间不能加任何其他的诸如空格,tab,换行等符号。
6.处理List列表(待选)
使用<#list files as XXXX> </#list>遍历数据,其中XXXX为遍历后的对象,可以使用XXXX来取值,${XXXX_index}表示下标,${XXXX.NAME}为对象的值
图6 处理List
7. 标识替换完之后,模板就弄完了,另存为.ftl后缀文件即可
注意:
1.一定不要用word打开ftl模板文件,否则xml内容会发生变化,导致前面的工作白做了。
8.JAVA处理
1)引入freemarker
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.22</version> </dependency> |
2)加入Util工具类
package com.gzzn.gzajzhjgpt.util;import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;import cn.hutool.core.codec.Base64;
import freemarker.template.Configuration;
import freemarker.template.Template;/*** <b>利用FreeMarker,将ftl模板转为word;</b><br>* 1.将word另存为xml,修改后缀为ftl放入src/main/resources/templates中<br>* 2.WordUtil.createWord(dataMap, "check_report_temp.ftl", stream);调用* @ClassName: WordUtil* @author Jinlong Li* @Date: 2020年3月23日 下午3:04:50*/
public class WordUtil {/*** * @Title: createWord* @author Jinlong Li* @Date 2020年3月23日 上午11:24:27* @param dataMap word中需要展示的动态数据,用map集合来保存* @param templateName word模板名称,例如:teample.ftl* @param os 输出流* @return void 返回类型*/@SuppressWarnings("deprecation")public static void createWord(Map<String, Object> dataMap, String templateName, OutputStream os) {try {// 创建配置实例Configuration configuration = new Configuration();// 设置编码configuration.setDefaultEncoding("UTF-8");// ftl模板文件configuration.setClassForTemplateLoading(WordUtil.class, "/templates");// 获取模板Template template = configuration.getTemplate(templateName);// 将模板和数据模型合并生成文件Writer out = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));// 生成文件template.process(dataMap, out);// 关闭流out.flush();out.close();} catch (Exception e) {e.printStackTrace();}}/*** 将图片转换为BASE64为字符串* * @param filename* @return* @throws IOException*/public static String getImageString(String filename) throws IOException {InputStream in = null;byte[] data = null;try {in = new FileInputStream(filename);data = new byte[in.available()];in.read(data);in.close();} catch (IOException e) {throw e;} finally {if (in != null) {in.close();}}return data != null ? Base64.encode(data) : "";}/*** 将图片转换为BASE64为字符串* * @param filename* @return* @throws IOException*/public static String getImageString(File file) throws IOException {InputStream in = null;byte[] data = null;try {in = new FileInputStream(file);data = new byte[in.available()];in.read(data);in.close();} catch (IOException e) {throw e;} finally {if (in != null) {in.close();}}return data != null ? Base64.encode(data) : "";}/*** 将图片转换为BASE64为字符串* * @param filename* @return* @throws IOException*/public static String getImageString(InputStream is) throws IOException {byte[] data = null;try {data = new byte[is.available()];is.read(data);} catch (IOException e) {throw e;} finally {if (is != null) {is.close();}}return data != null ? Base64.encode(data) : "";}
}
注意:
1.根据存放模板目录不一样,请调整Util里面的模板文件存放根目录,默认是/templates,即src/main/resources下面的templates目录下面
图7 模板文件目录
3)调用生成文档
/** 生成word */ WordUtil.createWord(dataMap, "check_report_temp.ftl", stream); |
参数dataMap为Map<String, Object>结构的参数,key对应模板内的变量名,
参数check_report_temp.ftl,为模板文件名称
参数stream为输出流,如果想下载:
图8 下载word文档示例
如果想输出到本地:
图9 输出到本地示例
保存到本地测试代码:TestJava2Word.java
测试模板:check_report_temp.ftl
注意:测试模板导出的是Word XML文档,所以对图片处理上比Word 2003 XML文档上要多
Word 2003 XML测试模板:operinspectinfo.ftl
Word模板:OperInspectInfo.docx
效果图: