用Freemarker后端导出Word表格
去年做了一个将word表格从后端导出的功能
在这里久远的记录一下...
文档准备
excel表格用编辑器打开后,可以发现它也是一个可编辑的标记性的格式,如同html页面里面的标签首尾相连。
为表格填充假数据
首先为需要导出的word表格填充假数据来占位。
方便之后动态填充数据找到对应的位置。
将word文档另存为xml格式文件
填充好数据后,我们将word文档保存为xml标记语言。
然后将其命名为.ftl后缀文件。
在IDEA里对其进行格式化,我们就能看到其像标签一样的标记语言。
后台操作
引入freemarker的依赖
首先要为我们的项目中引入freemarker的依赖。
<!--freemarker-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
### 使用到的工具类
在这里,我对项目word导出使用到一个工具类如下~
public class WordUtils {
private static Configuration contractConfiguration = null;
private static Configuration applicationConfiguration = null;
//这里注意的是利用WordUtils的类加载器动态获得模板文件的位置
//private static final String templateFolder = WordUtils.class.getClassLoader().getResource("").getPath();
private static String templateFolder = SystemUtil.getRootPath() + SystemUtil.DOCUMENT_FORM_PATH;//模板存放路径
static {
contractConfiguration = new Configuration(Configuration.VERSION_2_3_23);
contractConfiguration.setDefaultEncoding("utf-8");
try {
contractConfiguration.setDirectoryForTemplateLoading(new File(templateFolder + SystemUtil.SEPARATOR + "contract"));
} catch (IOException e) {
e.printStackTrace();
}
}
private WordUtils() {
throw new AssertionError();
}
//导出合同
public static void exportWord(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile) throws IOException {
Template freemarkerTemplate = contractConfiguration.getTemplate(ftlFile);
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
try {
// 调用工具类的createDoc方法生成Word文档
file = createDoc(map, freemarkerTemplate);
fin = new FileInputStream(file);
//String fileName = title + ".doc";
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
// 设置浏览器以下载的方式处理该文件名
String fileName = title + ".doc";
response.setHeader("Content-Disposition", "attachment;filename="
.concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
out = response.getOutputStream();
byte[] buffer = new byte[512]; // 缓冲区
int bytesToRead = -1;
// 通过循环将读入的Word文件的内容输出到浏览器中
while ((bytesToRead = fin.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
} finally {
if (fin != null) fin.close();
if (out != null) out.close();
if (file != null) file.delete(); // 删除临时文件
}
}
private static File createDoc(Map<?, ?> dataMap, Template template) {
String name = "sellPlan.doc";
File f = new File(name);
Template t = template;
try {
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
t.process(dataMap, w);
w.close();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
return f;
}
}
这里map是代表存放的数据,以键值对的形式存取。
title代表导出文件的名称。
ftlFile代表模板的名称。
调用工具类
调用工具类eg~
@RequestMapping(value = "/registerExport/{djbid}", method = RequestMethod.GET)
@ResponseBody
public JsonResult registerExport(@PathVariable String djbid, HttpServletRequest request, HttpServletResponse response) {
PrintRegisterVO djbData = getCbhtData(djbid);
String title = djbData.getCbfmc() + "-登记簿";
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("djb", djbData);
try {
WordUtils.exportContractWord(request, response, dataMap, title, "农村土地承包经营权证登记簿.ftl");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
ftl模板动态data替换
局部模板代码如下~~~
<#list djb.familyMember as f>
<w:tblPrEx>
<w:tblCellMar>
<w:top w:w="0" w:type="dxa"/>
<w:bottom w:w="0" w:type="dxa"/>
</w:tblCellMar>
</w:tblPrEx>
<w:trPr>
<w:gridAfter w:val="1"/>
<w:wAfter w:w="10" w:type="dxa"/>
<w:trHeight w:h-rule="exact" w:val="454"/>
<w:jc w:val="center"/>
</w:trPr>
<w:tc>
<w:tcPr>
<w:tcW w:w="1340" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="00A24009" wsp:rsidRPr="00487C70" wsp:rsidRDefault="00FE0AE2" wsp:rsidP="00210D10">
<w:pPr>
<w:spacing w:line="400" w:line-rule="exact"/>
<w:jc w:val="center"/>
<w:rPr>
<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
<wx:font wx:val="宋体"/>
<w:sz w:val="24"/>
<w:sz-cs w:val="24"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
<wx:font wx:val="宋体"/>
<w:sz w:val="24"/>
<w:sz-cs w:val="24"/>
</w:rPr>
<w:t></w:t>
</w:r>
<w:r>
<w:rPr>
<w:rFonts w:ascii="宋体" w:h-ansi="宋体"/>
<wx:font wx:val="宋体"/>
<w:sz w:val="24"/>
<w:sz-cs w:val="24"/>
</w:rPr>
<w:t>${f.cyxm!}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="845" w:type="dxa"/>
<w:gridSpan w:val="2"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="00A24009" wsp:rsidRPr="00487C70" wsp:rsidRDefault="00FE0AE2" wsp:rsidP="00210D10">
<w:pPr>
<w:spacing w:line="400" w:line-rule="exact"/>
<w:jc w:val="center"/>
<w:rPr>
<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
<wx:font wx:val="宋体"/>
<w:sz w:val="24"/>
<w:sz-cs w:val="24"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
<wx:font wx:val="宋体"/>
<w:sz w:val="24"/>
<w:sz-cs w:val="24"/>
</w:rPr>
<w:t></w:t>
</w:r>
<w:r>
<w:rPr>
<w:rFonts w:ascii="宋体" w:h-ansi="宋体"/>
<wx:font wx:val="宋体"/>
<w:sz w:val="24"/>
<w:sz-cs w:val="24"/>
</w:rPr>
<w:t>${f.cyxbmc!}</w:t>
</w:r>
</w:p>
</w:tc>
</#list>
End
关于freemarker导出word实现还有很多种方式~
此处有错误望指出~
关于freemarker语法我会单独开一篇blog~
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
Yida!
喜欢就支持一下吧