一、动态模板处理
使用jar包以及工具,freemark.jar notepad++
1.在word中需要动态填充的地方写上变量名(填充的数据为map,写的变量为map的key),例如动态生成简历模板中在对应的姓名列中写入name,涉及到循环的地方只需要写一行,涉及到图片,先随便找一张图片放在需要动态显示的地方。这里的name在后续需要改成${name},有些资料提到可以在这一步骤的时候就写成${name},但是在使用过程中发现${name}会在另存为xml格式文件的时候会分开,反而增加工作量,因此建议使用name,而不是${name}
2.将word另存为xml
3.在安装notepad++插件用于后续替换处理:使用Notepad++的XML Tools插件格式化XML文件_notepad++ xml-优快云博客
4.在notepad++中打开xml
5.如果有图片处理,搜索<pkg:binaryData>、</pkg:binaryData>并将其中间内容替换为<pkg:binaryData>${img}</pkg:binaryData>,其中img为map中存储图片数据的key,图片的数据处理后续会提到。
6.选择 插件 - XML Tools - Pretty print(XML only - with line breaks)格式化xml文件
7.将模板中需要动态填充的数据用${key}替换,例如,name用${name}替换,如果有循环的地方,找到需要循环填充数据的地方在<w:tr w:rsidR="00642C40" w:rsidRPr="00667E05" w:rsidTr="00EB5C66">上写<#list workList2 as worklist>
用${worklist.workName}替换需要遍历的变量,在标记的结尾添加</#list>
8.替换完成后点击另存为.ftl格式的文件,保存可能报错“XML Parsing error at line 707:Extra content at the end of the document”,忽略。
这个时候动态模板就创建好了,下面是动态数据的处理
二、填充数据处理
数据存储在Map<String, Object>中,主要说下图片数据的处理,list数据存储在List<Object>中,其中Object为实体类。
图片处理
package cn.com.xyl;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import sun.misc.BASE64Encoder;
/**
* 填充动态word的图片数据处理示例
* @author xuyl 2018-3-20 下午3:47:33
*
*/
public class ImageHandle {
public static void main(String[] args) {
File file = new File("C:\\Users\\xuyl\\Desktop\\===temp===\\Hydrangeas.jpg");
InputStream is = null;
ByteArrayOutputStream out = null;
String rst = "";
try {
is = new FileInputStream(file);
out = new ByteArrayOutputStream();
//将图片写入out中
byte[] b = new byte[1024];
int i = 0;
while((i = is.read(b)) != -1){
out.write(b, 0, i);
}
//对out流做base64处理
BASE64Encoder encoder = new BASE64Encoder();
rst = encoder.encode(out.toByteArray());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(rst);
}
}
三、根据模板和数据生成动态模板
package cn.com.xy.servlet;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.com.jnpc.utils.CommonUtils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
public class CreateDynamicWord extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
try {
//1.创建word获取填充信息
createDoc("/cn/com/xyl/signTableTemp", "signTable.ftl", new HashMap<String, Object>(), "tempSignTable", request);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 根据Doc模板生成word文件
* @param templatePath ftl放的路径 放在包resumeTemplate下,为包的全路径/cn/com/xyl/signTableTemp
* @param fileName flt模板名称包含扩展名 signTable.ftl
* @param tempData 需要填入模板的数据
* @param savePath 生成的word保存的文件夹 可以放在盘符中例如D:\\leaderResume\
* 可以放在项目文件中
* WebRoot/leaderResume/eachLeaderResume 要在eachLeaderResume文件夹下新建一个空的文件,否则会报错
*/
public void createDoc(String templatePath, String fileName, Map<String,Object> tempData, String savePath, HttpServletRequest request) throws Exception{
//模板配置
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
//模板对象
Template template = null;
//加载模板文件
configuration.setClassForTemplateLoading(this.getClass(), templatePath);
//设置异常处理器
configuration.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
//定义Template对象,注意模板类型名字与fileName要一致
template = configuration.getTemplate(fileName);
String realFileName = tempData.get("meetingName") + getCurrentTime() + ".doc";
System.out.println("========realFileName===========" + realFileName);
request.setAttribute("FILE_NAME", realFileName);
String tempSavePath = CommonUtils.getWebInfFilePath(savePath) + realFileName;
File outFile = new File(tempSavePath);
Writer out = null;
out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));
template.process(tempData, out);
out.close();
}
public static String getCurrentTime(){
String str = "";
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
str = sdf.format(date);
return str;
}
}
至此就在生成了动态word,可以将路径返回到前台,然后下载或其他处理
================================
2019-04-11补充
再word使用变量填充模板时,可以直接加上${},如姓名一列${name},这里需要注意,如果直接写在word中,在转化为xml文件时$,{,}可能会分开,这样反而会更麻烦。可以这样处理,可以先写在notepad++中,然后直接拷贝过去即可。