版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fenfenguai/article/details/78731331
之前写过一篇利用Freemarker模板生成doc的博客,不过那个博客有点缺陷,不支持生成docx格式的文档。所以,这里补充一篇,生成docx或doc格式的文档以具体的docx模板或者doc模板为主。这里以docx为例。
具体思路:
把docx文档修改为ZIP格式(修改.docx后缀名为.zip)
获取zip里的document.xml文档以及_rels文件夹下的document.xml.rels文档
把内容填充到document.xml里,以及图片配置信息填充至document.xml.rels文档里
在输入docx文档的时候把填充过内容的的 document.xml、document.xml.rels用流的方式写入zip(详见下面代码)。
把图片写入zip文件下word/media文件夹中
输出docx文档
docx模板修改成zip格式后的信息如下(因为word文档本身就是ZIP格式实现的)
这里写图片描述
这里写图片描述
document.xml里存放主要数据
media存放图片信息
_rels里存放配置信息
注意:如果docx模板里的图片带有具体路径的话,则图片的格式不受限制。
这里写图片描述
如果docx模板里里图片信息不带路径,则模板仅支持和模板图片类型一致的图片。
这里写图片描述
交代了这么多,下面就可以干货。
准备好docx模板
这里写图片描述
这里写图片描述
把docx文档修改为ZIP格式(修改.docx后缀名为.zip)
获取zip文件里的word文件夹下的document.xml以及_rels文件夹里的document.xml.rels文件作为模板。
这里写图片描述
这里写图片描述
这里写图片描述
注意:这里图片配置信息是根据 rId来获取的。docx模板总的${img_warn}就是rId的具体值。
为了避免重复,我的图片rId从17开始(在我没有修改之前,里面最大的rId是rId17)。
填充模板信息、写入图片信息。
String temp_path = File.separator+"template"+File.separator+"test"; // HttpServletRequest request = new MockHttpServletRequest(); // String base_path = request.getSession().getServletContext().getRealPath(File.separator)+temp_path+File.separator; // System.out.println(base_path); Map<String,Object> data_map = new HashMap<>(); // 1) 总体环比分析 List<String> res = new ArrayList<>(); res.add("本周报警总数环比上周上升5.62%,上周报警数20882,本周报警数22055。"); data_map.put("data_all_summary_title",res); res = new ArrayList<>(); res.add("本周高架总数环比上周上升16.55%,上周报警数2405,本周报警数2803。"); data_map.put("data_all_content_title",res); res = new ArrayList<>(); res.add("\uF06C\t本周断面环比上周上升12.8%,上周报警数547,本周报警数617。"); res.add("\uF06C\t本周上匝道环比上周上升17.5%,上周报警数1834,本周报警数2155。"); res.add("\uF06C\t本周下匝道环比上周上升29.17%,上周报警数24,本周报警数31。"); data_map.put("data_all_content",res); res = new ArrayList<>(); res.add("本周路口环比上周上升4.19%,上周报警数18477,本周报警数19252。"); data_map.put("data_all_end",res); String output_path = "D:/export/"; String output_file_name = System.currentTimeMillis()+"_freemarker_word.docx"; // FreemarkerWordUtils.createDocx(data_map,file_name,"document.xml",output_path, output_path+file_name); /** * * @param dataMap 参数数据 * @param docxTemplate docx模板名称 * @param xmltemplateName xml模板名称 * @param xmltConfigemplateName xml配置主模板名称 一般用来配置图片、样式信息 * @param temp_path 模板存放路径 * @param output_path 产出路径 * @param template_rir 模板文件下的子文件夹 * @param output_file_name 产出文件名称 */ List<String> picNameList = new ArrayList<>(); picNameList.add("pic1.png"); Map<String,String> picFiles = new HashMap<>(); picFiles.put("pic1.png","D:\\export\\png\\pic1.png"); picNameList.add("pic2.png"); picFiles.put("pic2.png","D:\\export\\png\\pic2.png"); picNameList.add("pic3.png"); picFiles.put("pic3.png","D:\\export\\png\\pic3.png"); picNameList.add("pic4.png"); picFiles.put("pic4.png","D:\\export\\png\\pic4.png"); picNameList.add("pic5.png"); picFiles.put("pic5.png","D:\\export\\png\\pic5.png"); picNameList.add("pic6.png"); picFiles.put("pic6.png","D:\\export\\png\\pic6.png"); picNameList.add("summary_pic7.png"); picFiles.put("summary_pic7.png","D:\\export\\png\\summary_pic7.png"); picNameList.add("summary_pic8.png"); picFiles.put("summary_pic8.png","D:\\export\\png\\summary_pic8.png"); picNameList.add("summary_pic9.png"); picFiles.put("summary_pic9.png","D:\\export\\png\\summary_pic9.png"); data_map.put("picNameList",picNameList); data_map.put("picFiles",picFiles); String base_path = "D:\\idea_workspace\\alarm\\alarm\\src\\main\\resources\\template\\test\\"; FreemarkerWordUtils.createDocx(data_map, "ptbjjcxbg.doc", "document.xml","document.xml.rels", temp_path,base_path, output_path, output_file_name);
/** * 生成主数据模板xml * @param dataMap 数据参数 * @param templateName 模板名称 * @param pathPrefix 模板路径 * @param filePath 生成路径 */ public static void createTemplateXml(Map dataMap, String templateName, String pathPrefix ,String filePath){ try { //创建配置实例 Configuration configuration = new Configuration(); //设置编码 configuration.setDefaultEncoding("UTF-8"); //ftl模板文件统一放至 com.lun.template 包下面 // configuration.setDirectoryForTemplateLoading(new File("D:/idea_workspace/alarm/alarm/src/main/resources/template/")); // configuration.setClassForTemplateLoading(FreemarkerWordUtils.class,"/template/doc"); configuration.setClassForTemplateLoading(FreemarkerWordUtils.class,pathPrefix); //获取模板 Template template = configuration.getTemplate(templateName); //输出文件 File outFile = new File(filePath); //如果输出目标文件夹不存在,则创建 if (!outFile.getParentFile().exists()){ outFile.getParentFile().mkdirs(); } //将模板和数据模型合并生成文件 Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8")); //生成文件 template.process(dataMap, out); //关闭流 out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } }
/** * * @param dataMap 参数数据 * @param docxTemplate docx模主板名称 * @param xmltemplateName xml主模板名称 * @param xmltConfigemplateName xml配置主模板名称 一般用来配置图片、样式信息 * @param temp_path 模板存放路径 * @param base_path 模板实际路径 * @param output_path 产出路径 * @param output_file_name 产出文件名称 */ public static void createDocx(Map dataMap,String docxTemplate, String xmltemplateName,String xmltConfigemplateName,String temp_path,String base_path,String output_path,String output_file_name){ try { try { //================================拼装生成xml配置文档================================ String xml_config_output_path = output_path+System.currentTimeMillis()+".xml.rels"; createTemplateXml(dataMap,xmltConfigemplateName,temp_path,xml_config_output_path); File xmlConfigFile = new File(xml_config_output_path); //读取 xmlConfigFile 文件 并获取rId 与 图片的关系 String xmlConfigFile_content = getFreemarkerContent(dataMap,xmltConfigemplateName,temp_path); System.out.println("===========================xmlConfigFile_content================================"); System.out.println(xmlConfigFile_content); System.out.println("===========================xmlConfigFile_content================================"); Document document = DocumentHelper.parseText(xmlConfigFile_content); Element rootElt = document.getRootElement(); // 获取根节点 Iterator iter = rootElt.elementIterator() ;// 获取根节点下的子节点head List<String> warn_img_list = new ArrayList<>(); List<String> warn_summary_img_list = new ArrayList<>(); // 遍历Relationships节点 while (iter.hasNext()) { Element recordEle = (Element) iter.next(); String id = recordEle.attribute("Id").getData().toString(); String target = recordEle.attribute("Target").getData().toString(); if(target.indexOf("media")==0){ // System.out.println("id>>>"+id+" >>>"+target); // id>>>rId18 >>>media/pic1 if(target.indexOf("summary")>0){ warn_summary_img_list.add(id); }else{ warn_img_list.add(id); } } } dataMap.put("warn_img_list",warn_img_list); if(!warn_summary_img_list.isEmpty()){ dataMap.put("img_sum_warn_o",warn_summary_img_list.get(0)); dataMap.put("img_sum_warn_t",warn_summary_img_list.get(1)); dataMap.put("img_sum_warn_tt",warn_summary_img_list.get(2)); } // dataMap.put("",""); //================================拼装生成xml配置文档================================ //================================拼装生成主模板xml文档================================ String xml_output_path = output_path+System.currentTimeMillis()+".xml"; createTemplateXml(dataMap,xmltemplateName,temp_path,xml_output_path); File xmlFile = new File(xml_output_path); //================================拼装生成主模板xml文档================================ File docxFile = new File(base_path+docxTemplate); if(!docxFile.exists()){ docxFile.createNewFile(); } ZipFile zipFile = new ZipFile(docxFile); Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries(); ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(output_path+output_file_name)); int len = -1; byte[] buffer = new byte[1024]; //------------------追加新图片------------------ // List<String> picList = new ArrayList<>(); Map<String,String> picFiles = (Map<String, String>) dataMap.get("picFiles"); if(picFiles!=null && !picFiles.isEmpty()){ for(String fileName :picFiles.keySet()){ ZipEntry next = new ZipEntry("word"+File.separator+"media"+File.separator+fileName); zipout.putNextEntry(new ZipEntry(next.toString())); InputStream in = new FileInputStream(picFiles.get(fileName)); while ((len = in.read(buffer)) != -1) { zipout.write(buffer, 0, len); } in.close(); } } //------------------追加新图片------------------ len = -1; while (zipEntrys.hasMoreElements()) { ZipEntry next = zipEntrys.nextElement(); InputStream is = zipFile.getInputStream(next); // 把输入流的文件传到输出流中 如果是word/document.xml由我们输入 zipout.putNextEntry(new ZipEntry(next.toString())); System.out.println(">>>>>>>>>"+next.isDirectory()); System.out.println(">>>>>>>>>>>>>>>>>"+next.toString()); System.out.println(">>>>>>>>>>>>>>>>>"+next.isDirectory()); if ("word/document.xml".equals(next.toString())) { InputStream in = new FileInputStream(xmlFile); while ((len = in.read(buffer)) != -1) { zipout.write(buffer, 0, len); } in.close(); } else if(next.toString().indexOf("document.xml.rels")>0){ InputStream in = new FileInputStream(xmlConfigFile); while ((len = in.read(buffer)) != -1) { zipout.write(buffer, 0, len); } in.close(); }else{ while ((len = is.read(buffer)) != -1) { zipout.write(buffer, 0, len); } is.close(); } } zipout.close(); } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } } public static String getFreemarkerContent(Map dataMap, String templateName,String temp_path){ String ret_str = ""; try { //创建配置实例 Configuration configuration = new Configuration(); //设置编码 configuration.setDefaultEncoding("UTF-8"); //ftl模板文件统一放至 com.lun.template 包下面 // configuration.setDirectoryForTemplateLoading(new File("D:/idea_workspace/alarm/alarm/src/main/resources/template/")); configuration.setClassForTemplateLoading(FreemarkerWordUtils.class,temp_path); //获取模板 Template template = configuration.getTemplate(templateName); //输出文件 //File outFile = new File(filePath); //如果输出目标文件夹不存在,则创建 // if (!outFile.getParentFile().exists()){ // outFile.getParentFile().mkdirs(); // } //将模板和数据模型合并生成文件 // Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8")); StringWriter swriter = new StringWriter(); //生成文件 template.process(dataMap, swriter); ret_str = swriter.toString(); } catch (Exception e) { e.printStackTrace(); } return ret_str; } /** * 删除文件 * @param listFiles */ public static void delFiles(List<String> listFiles){ if(listFiles!=null && !listFiles.isEmpty()){ for(String file_temp_path:listFiles){ File file_temp = new File(file_temp_path); if(file_temp.exists()){ file_temp.delete(); } } } }
- 输出具体的docx文档。
相关推荐
总的来说,“freemarker导出doc及docx”涉及到了Freemarker模板引擎的使用、SpringBoot的集成、以及利用Apache POI等库处理Word文档的技巧。实际操作时,你需要根据项目需求定制模板,设置数据模型,最后通过编程...
利用Freemarker模板生成doc或者docx文档(转载整理)-附件资源
总结来说,Java FreeMarker模板生成Word动态表格是通过结合FreeMarker模板引擎的灵活性和Apache POI的强大功能,来高效地创建和更新包含动态数据的Word文档,尤其适用于需要大量定制和自动化生成的场景。通过理解并...
总结来说,通过Java-Freemarker生成Word文档的关键步骤包括:创建Word模板、转换为XML、编辑XML模板,以及使用Freemarker的模板引擎将数据注入XML模板生成最终的Word文档。这个过程大大简化了动态生成Word文档的复杂...
Java 使用 FreeMarker 模板技术导出 Word 是一种常见的数据动态生成文档的方法,它结合了 Java 的编程能力和 FreeMarker 模板引擎的强大功能,能够帮助开发者高效地生成结构化的 Word 文档。FreeMarker 是一个开源的...
在Java开发中,有时我们需要将数据以Word文档的形式导出...虽然这个示例只支持.doc格式,但通过扩展可以支持.docx或者其他格式。要了解更多细节,可以查阅FreeMarker和Apache POI的官方文档,以及相关的Java代码示例。
这个过程涉及到对Freemarker模板的理解,Java对象数据的准备,以及利用Apache POI来处理Word文档结构。在实际应用中,这种能力对于自动化报告生成、合同定制或者其他需要动态创建Word文档的场景非常有用。
2、由上述生成的html模板通过java代码生成pdf; 3、示例有本地模板和远程模板之分,可杜绝pdf标题丢失的问题; 4、资源概要:先阅读README.md文档,然后根据文档中的资源示例运行代码,有postman和内部调用两种方式; 5...
本示例主要展示了如何使用Freemarker根据XML模板生成Word文档。以下是对这一技术的详细解释: 1. **Freemarker简介**: Freemarker是一个开源的Java库,它能够将数据模型与HTML、XML或其他文本格式的模板结合,...
下面我们将深入探讨如何使用Java根据模板生成带有图片的Word文档。 首先,我们要理解“将doc模版另存为xml格式”的步骤。Microsoft Word的.doc文件实际上是一种二进制格式,但可以通过“另存为”XML文档,将内容...
**FreeMarker + POI:模板生成Word并导入图片** 结合FreeMarker和Apache POI,我们可以创建一个模板Word文档,其中包含占位符,然后使用POI读取和填充这个模板,同时插入图片,生成最终的动态Word文档。以下是这个...
通过Freemarker生成docx文档时,需要将Word文档的后缀名改为.zip格式,然后解压zip文件,主要维护的是解压目录下的.rels文件(它用来绑定图片)和word目录下的document.ftl模板(用来输出内容和样式)。在这一过程中...
在Java应用中,使用FreeMarker导出Word文档可以提供灵活的文本和数据结合的方式,尤其适用于生成报告、合同等复杂格式的文档。本篇将详细介绍如何使用FreeMarker与Java结合来导出包含多张图片的Word文档。 1. **...
通过三种不同的方式(freemarker+jfreechart、xDoc、POI),根据模板创建Word文件。可以动态修改Word中表格(table)、图表(chart)等数据。导入工程后,可直接运行xxxDemo文件,查看文档生成效果。详见压缩包中的...
总的来说,使用Freemarker结合Apache POI生成docx文档是一项技术性较强的工作,涉及到XML处理、模板引擎的使用以及对Word文档结构的理解。在实际应用中,开发者需要对这些工具和库有深入的了解,以便更好地控制生成...
Java中的Freemarker是一个强大的模板引擎,常用于生成动态HTML、XML或文本文件,而这里我们讨论的是如何利用Freemarker生成复杂的Word文档。在Java应用中,有时我们需要生成结构化且内容丰富的Word文档,例如报告、...
Java利用FreeMarker导出Word是一项常见的技术需求,尤其在企业级应用中,常常需要将动态数据生成为Word文档,例如报告、合同等。FreeMarker是一个模板引擎,它能将Java对象的数据绑定到模板上,生成HTML、XML或者如...
2. **Apache POI和FreeMarker**:Apache POI是Java处理Microsoft Office格式文档的库,配合FreeMarker模板引擎,能够生成复杂的Word文档。但这种方式需要进行Word到XML、XML到FTL的转换,对于内容频繁变动的文档,...
3. **模板格式化工具**:为了将生成的FreeMarker模板转换为Word文档,我们通常会使用一些库,如Apache POI或docx4j。这些库提供了处理Microsoft Office文档格式的功能。例如,使用Apache POI,我们可以将HTML转换为...
值得注意的是,Freemarker生成的Word文档实际上是基于Open XML格式(.docx),而非传统的二进制Word格式(.doc)。但为了兼容性,我们通常将生成的文件扩展名设为`.doc`。 在实际应用中,你可能需要处理更复杂的...