使用ftl生成word

x33g5p2x  于2022-05-24 转载在 其他  
字(3.6k)|赞(0)|评价(0)|浏览(448)

背景:根据word模板下载word。word里面需要填充数据,格式是固定的。首先在word中给数据起个变量名称


需要更换的数据改成${变量名!},必须是英文的,加感叹号是为了防止null,如果数据是null,文档下载下来后会直接显示null,加上感叹号就不会,没数据就是空。也可以不加感叹号,在代码设置下属性即可,后面会说到。变量名结束后把word另存为xml

然后复制到项目中,我用的是idea,打开后会发现就几行,后面老长了

然后format下ctrl+alt+L(快捷键仅供参考,本人是这样的),就会

这些红色不影响,不用管它。在文件中搜索${,被搜到的都是起变量的地方,有的地方是会分离的

这就需要手动帮他们破镜重圆了,剪切下即可

这种应该比较多,手动改下就行。改完后保存,改为.ftl文件。下面是代码

  1. import org.apache.poi.xwpf.usermodel.XWPFDocument;
  2. import org.apache.poi.xwpf.usermodel.XWPFTable;
  3. import org.apache.poi.xwpf.usermodel.XWPFTableCell;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.core.io.ClassPathResource;
  6. import org.springframework.web.bind.annotation.*;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.*;
  9. import java.net.URLEncoder;
  10. import java.text.SimpleDateFormat;
  11. import java.util.*;
  12. import freemarker.template.Configuration;
  13. import freemarker.template.Template;
  14. import freemarker.template.TemplateException;
  15. import java.io.*;
  16. import java.util.Map;
  17. public class ExportController {
  18. public void download(WeeklyTask weeklyTask, HttpServletResponse response) {
  19. try {
  20. //加入模板的数据
  21. Map<String, Object> data = new HashMap<>();
  22. data.put("key", value);
  23. String outFileName = "测试.docx";
  24. //模板相对路径
  25. String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
  26. path = path + "templates/";
  27. //linux
  28. if ("/".equals(File.separator)) {
  29. path = path.replaceAll("\\\\", "/");
  30. }
  31. File outFile = createDoc(data, outFileName, path, "模板.ftl");
  32. if (null != outFile) {
  33. response.reset();
  34. response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(outFile.getName(), "UTF-8"));
  35. //获取文件输入流
  36. InputStream in = new FileInputStream(outFile);
  37. byte[] buffer = new byte[1024];
  38. OutputStream out = response.getOutputStream();
  39. int len = 0;
  40. while ((len = in.read(buffer)) > 0) {
  41. //将缓冲区的数据输出到客户端浏览器
  42. out.write(buffer, 0, len);
  43. }
  44. in.close();
  45. out.close();
  46. }
  47. } catch (Exception e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. public static File createDoc(Map<String, Object> dataMap, String outFileName, String templatePath, String templateFileName) throws IOException {
  52. //设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载,
  53. Configuration configuration = new Configuration();
  54. //设置null转为空串
  55. configuration.setClassicCompatible(true);
  56. configuration.setDefaultEncoding("UTF-8");
  57. configuration.setDirectoryForTemplateLoading(new File(templatePath));
  58. Template t = null;
  59. try {
  60. //test.ftl为要装载的模板
  61. t = configuration.getTemplate(templateFileName, "UTF-8");
  62. t.setOutputEncoding("UTF-8");
  63. } catch (IOException e) {
  64. e.printStackTrace();
  65. }
  66. //输出文档路径及名称
  67. File outFile = new File(outFileName);
  68. if (!outFile.exists()) {
  69. outFile.createNewFile();
  70. }
  71. Writer out = null;
  72. FileOutputStream fos = null;
  73. try {
  74. fos = new FileOutputStream(outFile);
  75. OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
  76. //这个地方对流的编码不可或缺,使用main()单独调用时,应该可以,但是如果是web请求导出时导出后word文档就会打不开,并且包XML文件错误。主要是编码格式不正确,无法解析。
  77. // out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
  78. out = new BufferedWriter(oWriter);
  79. } catch (FileNotFoundException e1) {
  80. e1.printStackTrace();
  81. }
  82. try {
  83. t.process(dataMap, out);
  84. out.close();
  85. fos.close();
  86. return outFile;
  87. } catch (TemplateException e) {
  88. e.printStackTrace();
  89. } catch (IOException e) {
  90. e.printStackTrace();
  91. }
  92. return null;
  93. }
  94. }

我的模板文件放在

下,我是springBoot,前后端分离的maven。获取模板路径视情况而定。

  1. //设置null转为空串
  2. configuration.setClassicCompatible(true);

这个设置下就可以不加感叹号了。然后模板获取数据是根据你起的变量名称和Map的key对应来获取值的,即使模板里面的变量名称加了感叹号,key也不用加感叹号。然后就可以下载了。如果下载后发现有错位现象,多了空格或者换行,比如这种

下载的文件前面肯定多了很多空格或者回车,把多余的删除即可

还有是循环,塞数据的map要put成
List<Map<String, String>> list = new ArrayList<>();
Map<String, String> m = new HashMap<>();
m.put(“anzlsz01”,value);
list .add(m);
data.put(“TABLE1”, list);模板要这样

相关文章