之前使用XWPFDocument动态写入word,XWPFDocument不支持2003,word2003需要用HWPFDocument,HWPFDocument对于动态生成行效果不是很好,所以使用freemarker动态生成,生成的支持所有格式。
一、使用officeword建一个需要的表格,需要动态替换的可以先写上字母
二、另存为word2003xml格式
三、把后缀修改为ftl
四、把word xml格式化,可以使用notepad++的xml tool插件,或者使用在线格式化
格式化前
格式化后
五、把之前所有要替换的字母加${}
改为
六、需要动态添加的找到<w:tr>,在<w:tr>上加<#list postdutyNormList as postdutyNormObj>
循环里面的字母加上${postdutyNormObj.}
七、合并单元格
例合并5行的第一列,第一行的第一列有值,增加<w:vmerge w:val="restart"/>;第二、三、四、五行的第一列没值把<w:r></w:r>去掉,增加<w:vmerge/>
第一行:
第二、三、四、五行:
动态判断如下:其中index是行号
八、内容相同的上下行合并,其中preContent是上一行的值,可以在java里添加需要判断列的值
九、单元格内换行
在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 += "<w:p wsp:rsidR=\"00000000\" wsp:rsidRDefault=\"008F1A6A\">"+
"<w:pPr>"+
"<w:jc w:val=\"left\"/>"+
"<w:rPr>"+
"<w:sz w:val=\"20\"/>"+
"</w:rPr>"+
"</w:pPr>"+
"<w:r>"+
"<w:rPr>"+
"<w:rFonts w:hint=\"fareast\"/>"+
"<w:sz w:val=\"20\"/>"+
"</w:rPr>"+
"<w:t>"+data+"</w:t>"+
"</w:r>"+
"</w:p>";
}
十、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<String, Object> 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.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}
标签相关
<w:tr></w:tr>:每一行;
<w:tc></w:tc>:是每一列;
<w:p></w:p>:控制单元格内换行;
<w:tcPr></w:tcPr>:里面添加合并;
<w:r></w:r>:里面是内容样式及内容;
<w:t></w:t>:里面是内容;
${assessAllObj.content?html}:如果替换的内容里有<>会报错,可以加上?html进行转义
常用到的语句
<#list postdutyNormList as postdutyNormObj>
</#if>
<#if postdutyNormObj.index==1>
<w:vmerge w:val="restart"/>
<#else>
<w:vmerge/>
</#if>
更多推荐
java使用freemarker模板导出word,合并单元格,单元格内换行
发布评论