JAVA通过模板生成DOCX文档(2)

叁歲伎倆 2022-06-14 06:16 324阅读 0赞

第一篇链接

看第一篇文章会对原理更理解一些,但是比较繁琐,所以写了这一篇,怎么获取和修改xml在上一篇都有,不赘述了

  1. import freemarker.template.Configuration;
  2. import freemarker.template.Template;
  3. import java.io.*;
  4. import java.util.Enumeration;
  5. import java.util.HashMap;
  6. import java.util.Map;
  7. import java.util.zip.ZipEntry;
  8. import java.util.zip.ZipFile;
  9. import java.util.zip.ZipOutputStream;
  10. public class Main {
  11. public static void main(String[] args) {
  12. // 路径
  13. String templatepath = "D:\\Projects\\lib\\generateDocx";
  14. String docxname = "demo.docx";
  15. String xmlname = "demo.xml";
  16. String tmpxmlpath = "D:\\Projects\\lib\\generateDocx\\complete.xml";
  17. String targetpath = "D:\\Projects\\lib\\generateDocx\\complete.docx";
  18. // 数据
  19. Map<String,Object> data = new HashMap();
  20. data.put("words","这里是文字");
  21. // 生成文档
  22. try {
  23. generate(templatepath, docxname, xmlname, tmpxmlpath, targetpath, data);
  24. } catch (Exception e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. /**
  29. * @Description 根据参数生成docx合同文档
  30. * @author belle.wang
  31. * @param templatepath 模板所在文件夹
  32. * @param docxname docx格式模板文件名(不带路径)
  33. * @param xmlname xml格式模板,有freemaker标记(不带路径)
  34. * @param tmpxmlpath 临时xml文件路径
  35. * @param targetPath 目标路径
  36. * @param param 待填充数据
  37. * @return
  38. * @throws Exception
  39. */
  40. private static boolean generate(String templatepath, String docxname, String xmlname,
  41. String tmpxmlpath, String targetPath, Map<String, Object> param) throws Exception {
  42. Configuration cfg = new Configuration();
  43. cfg.setDirectoryForTemplateLoading(new File(templatepath));
  44. Template template = cfg.getTemplate(xmlname);
  45. template.setOutputEncoding("UTF-8");
  46. Writer out = new FileWriter(new File(tmpxmlpath));
  47. // 数据放到模板xml里面,生成带数据的xml
  48. template.process(param, out);
  49. if (out != null) {
  50. out.close();
  51. }
  52. // 带数据的xml生成docx
  53. File file = new File(tmpxmlpath);
  54. File docxFile = new File(templatepath + "/" + docxname);
  55. ZipFile zipFile = new ZipFile(docxFile);
  56. Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
  57. ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(targetPath));
  58. int len = -1;
  59. byte[] buffer = new byte[1024];
  60. while (zipEntrys.hasMoreElements()) {
  61. ZipEntry next = zipEntrys.nextElement();
  62. InputStream is = zipFile.getInputStream(next);
  63. // 把输入流的文件传到输出流中 如果是word/document.xml由我们输入
  64. zipout.putNextEntry(new ZipEntry(next.toString()));
  65. if ("word/document.xml".equals(next.toString())) {
  66. InputStream in = new FileInputStream(file);
  67. while ((len = in.read(buffer)) != -1) {
  68. zipout.write(buffer, 0, len);
  69. }
  70. in.close();
  71. } else {
  72. while ((len = is.read(buffer)) != -1) {
  73. zipout.write(buffer, 0, len);
  74. }
  75. is.close();
  76. }
  77. }
  78. zipout.close();
  79. return true;
  80. }
  81. }

很精简吧,模板文件是在这个目录下

![Image 1][]Center

关于生成图片

上一篇有一个评论是问生成图片的,研究了一下通过模板比较困难,如果是doc的话就很容易,因为图片转为base64,字符串插进去就可以了,跟文本差不多。但是docx本质是一个压缩文件

xml中也可发现图片的复杂程度不是文字可以比拟的

Center 1

而且图片的插入不是简简单单把图片转为字符串,而是一个引用,怎么引用的呢,看图

我们上传的图片到这里来了,word/media

![Image 1][]Center 2

word/_rels/document.xml.rels文件内容:

Center 3

这边就关联到图片了。id=“rId4”

所以要通过freemaker标记插入图片很困难,可以换一种思路,最终docx文件生成之后,用doc4j在指定位置插入图片。

后记:

使用docx4j插入图片我已实现,网上找的demo,代码虽短,找jar包找的欲仙欲死

使用docx4j插入图片

[Image 1]:

发表评论

表情:
评论列表 (有 0 条评论,324人围观)

还没有评论,来说两句吧...

相关阅读

    相关 合并DOCX文档

    找了好久好久的方法,结果无意间发现了,感激上苍啊 只能合并DOCX噢,不能合并DOC,强制修改文件名后缀也是不可以的哟,所以又花了好久找上一篇文章的方法。 废话不多说,上代