之前使用[XWPFDocument][]动态写入word,XWPFDocument不支持2003,word2003需要用HWPFDocument,HWPFDocument对于动态生成行效果不是很好,所以使用freemarker动态生成,生成的支持所有格式。
一、使用officeword建一个需要的表格,需要动态替换的可以先写上字母
![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70][]
二、另存为word2003xml格式
![20190507101739653.png][]
三、把后缀修改为ftl
![20190507101833803.png][]
四、把word xml格式化,可以使用notepad++的xml tool插件,或者使用在线格式化
格式化前
![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 1][]
格式化后
![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 2][]
五、把之前所有要替换的字母加$\{\}
![20190507102240262.png][]改为![20190507102258388.png][]
六、需要动态添加的找到
,在上加![20190507102336915.png][]
![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 3][]
循环里面的字母加上$\{postdutyNormObj.\}
![20190507103541717.png][]
七、合并单元格
例合并5行的第一列,第一行的第一列有值,增加;第二、三、四、五行的第一列没值把去掉,增加
第一行:
![20190507104953341.png][]
第二、三、四、五行:
![20190507104936551.png][]
动态判断如下:其中index是行号
![20190507105305977.png][]
![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 4][]
八、内容相同的上下行合并,其中preContent是上一行的值,可以在java里添加需要判断列的值
![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 5][]
![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 6][]
九、单元格内换行
![20190507105707524.png][]
在java里循环,trs就是替换的count
for (int i = 0; i < count; i++) {
VPersonalWorkDailyChild tr = list_p.get(i);
VPersonalWorkDaily parent = baseInfoService.getObjectById(VPersonalWorkDaily.class, tr.getId_personal_work_daily());
String data = i+1+". "+gfnull(tr.getTime())+" "+gfnull(parent.getName_place())+gfnull(tr.getPlace())+" "+gfnull(tr.getContent());
trs += "
"+
""+
""+
""+
""+
""+
""+
""+
""+
""+
""+
""+
""+data+""+
""+
"";
}
十、Controller代码,map是所有要替换的内容
/**
*
* @Date 2019年2月25日 下午17:30:23
* @Description 考核成绩汇总导出考核表具体条目
* @Fcunction exportWordForSpecific
* @param response
* @return ReturnDatas
*
*/
@ResponseBody
@SystemControllerLog(description="考核成绩汇总导出考核表具体条目")
@RequestMapping(value="exportWordForSpecific")
public ReturnDatas exportWordForSpecific(HttpServletResponse response, String id){
ReturnDatas returnDatas = ReturnDatas.getSuccessReturnDatas();
try {
Map map = assessGradeSumService.exportWordForSpecific(id);
String org_name = (String) map.get("org_name");
String user_name = (String) map.get("user_name");
String month_ = (String) map.get("month_");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/msexcle");
response.setHeader("content-disposition", "attachment;filename="+new String((org_name+"-"+user_name+month_+"履职考核表").getBytes("utf-8"),"ISO8859-1")+".doc");
OutputStream outputStream = response.getOutputStream();
WordGenerator.createDoc(map, "AssessMonthTable2.ftl", outputStream);
outputStream.flush();
outputStream.close();
returnDatas.setStatus(ReturnDatas.SUCCESS);
return returnDatas;
} catch (Exception e) {
e.printStackTrace();
LogUtil.error("考核成绩汇总导出考核表具体条目异常:"+e.getMessage(),e);
returnDatas.setStatus(ReturnDatas.ERROR);
returnDatas.setMessage("考核成绩汇总导出考核表具体条目异常。");
}
return returnDatas;
}
十一、WordGenerator 工具类
package com.enter.net.util;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
public class WordGenerator {
/**
* 生成doc文件
* @param dataMap word中需要展示的动态数据
* @param templateName word模板名称
* @param output 输出流
* @return
* @throws IOException
* @throws TemplateException
*/
public static void createDoc(Map, ?> dataMap,String templateName,OutputStream output) throws TemplateException, IOException {
//创建配置实例
Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
//设置编码
configuration.setDefaultEncoding("UTF-8");
//空值
configuration.setClassicCompatible(true);
//ftl模板文件统一放至 com.fh.template 包下面
configuration.setClassForTemplateLoading(WordGenerator.class,"/templates/");
//获取模板
Template template = configuration.getTemplate(templateName);
//将模板和数据模型合并生成文件
Writer out = new BufferedWriter(new OutputStreamWriter(output,"UTF-8"));
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
// Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
//生成文件
template.process(dataMap, out);
//关闭流
out.flush();
out.close();
}
}
十二、参考
注:若动态替换的内容里有特殊符号,如"<>",可以是用?html转义。在freemarker模板里把$\{content\}改成$\{content?html\}
标签相关
:每一行;:是每一列;
:里面添加合并;
:里面是内容样式及内容;
:里面是内容;
$\{assessAllObj.content?html\}:如果替换的内容里有<>会报错,可以加上?html进行转义
常用到的语句
#if>
#if>
[watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70]: /images/1599997842466.png
[20190507101739653.png]: /images/1599997819417.png
[20190507101833803.png]: /images/1599997797266.png
[watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 1]: /images/1599997763522.png
[watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 2]: /images/1599997740474.png
[20190507102240262.png]: /images/1599997715295.png
[20190507102258388.png]: /images/1599997685929.png
[20190507102336915.png]: /images/1599997657247.png
[watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 3]: /images/1599997627679.png
[20190507103541717.png]: /images/1599997602324.png
[20190507104953341.png]: /images/1599997578442.png
[20190507104936551.png]: /images/1599997549191.png
[20190507105305977.png]: /images/1599997523687.png
[watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 4]: /images/1599997495250.png
[watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 5]: /images/1599997463967.png
[watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MjYwMzE1_size_16_color_FFFFFF_t_70 6]: /images/1599997424074.png
[20190507105707524.png]: /images/1599997370369.png