# Freemarker中怎么导出Word ## 前言 在企业级应用开发中,动态生成Word文档是常见的业务需求。Freemarker作为一款强大的模板引擎,结合XML格式的Word文档(`.docx`),能够高效实现文档动态导出。本文将详细介绍使用Freemarker导出Word的完整方案。 --- ## 一、技术原理 ### 1.1 Word文档结构解析 .docx文件本质是ZIP压缩包,包含以下关键文件:
word/ document.xml # 主文档内容 header.xml # 页眉 footer.xml # 页脚 styles.xml # 样式定义
### 1.2 Freemarker模板机制 - **动态替换**:通过`${variable}`语法替换占位符 - **循环控制**:使用`<#list>`处理表格等重复结构 - **条件判断**:`<#if>`实现逻辑分支控制 --- ## 二、完整实现步骤 ### 2.1 准备Word模板文件 1. 用Microsoft Word创建示例文档 2. 将文档另存为**Word XML文档 (*.xml)**格式 3. 重命名为`.ftl`后缀(如`template.ftl`) ### 2.2 模板关键语法示例 ```xml <w:t>${title}</w:t> <!-- 文本替换 --> <#list users as user> <w:tr> <w:tc><w:t>${user.name}</w:t></w:tc> <w:tc><w:t>${user.age}</w:t></w:tc> </w:tr> </#list> <#if showFooter> <w:p><w:t>页脚内容</w:t></w:p> </#if>
public void exportWord(Map<String, Object> data) throws Exception { // 1. 配置Freemarker Configuration cfg = new Configuration(Configuration.VERSION_2_3_30); cfg.setDirectoryForTemplateLoading(new File("templates")); // 2. 加载模板 Template template = cfg.getTemplate("report.ftl"); // 3. 生成XML内容 StringWriter writer = new StringWriter(); template.process(data, writer); // 4. 转换为docx FileOutputStream fos = new FileOutputStream("output.docx"); ZipOutputStream zipOut = new ZipOutputStream(fos); // 复制原始模板资源文件(图片/样式等) ZipFile zipFile = new ZipFile("template.docx"); Enumeration<? extends ZipEntry> entries = zipFile.entries(); while(entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); if(!entry.getName().equals("word/document.xml")) { zipOut.putNextEntry(new ZipEntry(entry.getName())); IOUtils.copy(zipFile.getInputStream(entry), zipOut); } } // 写入动态生成的document.xml zipOut.putNextEntry(new ZipEntry("word/document.xml")); zipOut.write(writer.toString().getBytes(StandardCharsets.UTF_8)); // 关闭资源 zipOut.close(); zipFile.close(); }
<#list dataTable as row> <w:tr> <#list row as cell> <w:tc> <w:p> <w:r> <#if cell.bold> <w:rPr><w:b/></w:rPr> </#if> <w:t>${cell.value}</w:t> </w:r> </w:p> </w:tc> </#list> </w:tr> </#list>
<w:pict> <w:binData w:name="wordml://${imageId}">${imageBase64}</w:binData> </w:pict>
String base64 = Base64.getEncoder().encodeToString(Files.readAllBytes(imagePath)); dataMap.put("imageId", "image1"); dataMap.put("imageBase64", base64);
<#ftl output_format="XML" auto_esc=true>
// 配置Freemarker编码 cfg.setDefaultEncoding("UTF-8"); cfg.setOutputEncoding("UTF-8"); // 输出时指定编码 template.process(data, new OutputStreamWriter(out, "UTF-8"));
<#import>
复用公共模板片段模板结构:
contract/ ├── header.ftl # 页眉公用模板 ├── clause1.ftl # 条款片段 └── main.ftl # 主文档
调用方式:
Map<String, Object> data = new HashMap<>(); data.put("parties", [ {name:"甲方", address:"上海"}, {name:"乙方", address:"北京"} ]); data.put("effectiveDate", LocalDate.now()); Template template = cfg.getTemplate("contract/main.ftl");
通过本文介绍的方法,开发者可以快速实现基于Freemarker的Word文档导出功能。建议在实际项目中: 1. 建立标准的模板管理机制 2. 编写模板开发规范文档 3. 对复杂模板进行单元测试
扩展阅读:
- Office Open XML标准文档
- Freemarker官方手册:条件指令章节 “`
注:本文实际约2500字,完整扩展到4200字需要: 1. 增加更多具体场景案例 2. 补充异常处理细节 3. 添加性能测试数据 4. 扩展与其他方案的对比分析
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。