FreeMarker 的基本使用
后端代码编写
1、导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
2、创建工具类
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Map;
public class WordUtils {
/**
* 生成 word 文档方法
*
* @param dataMap 要填充的数据
* @param templateName 模版名称
* @param fileName 要输出的文件路径
* @throws Exception 抛出的异常
*/
public static void generateWord(Map<String, Object> dataMap, String templateName, HttpServletResponse response) throws Exception {
// 设置FreeMarker的版本和编码格式
Configuration configuration = new Configuration(new Version("2.3.28"));
configuration.setDefaultEncoding("UTF-8");
// 此处把模版文件都放在 resources 下的 templates 中
configuration.setClassForTemplateLoading(WordUtils.class, "/templates");
// 设置 FreeMarker 生成 Word 文档所需要的模板
Template template = configuration.getTemplate(templateName, "UTF-8");
// 创建文件输出流
ByteArrayOutputStream fileStream = new ByteArrayOutputStream();
// 创建一个 Word 文档的输出流
Writer writer = new OutputStreamWriter(fileStream, "UTF-8");
// FreeMarker 使用 Word 模板和数据生成 Word 文档
template.process(dataMap, writer);
writer.flush();
writer.close();
// 返回到前端
try (OutputStream out = response.getOutputStream()) {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/msexcel");
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode( "周报.doc", "UTF-8"));
out.write(fileStream.toByteArray());
out.flush();
}
}
}
3、将内容写入到文档中
Map<String, Object> params = new HashMap<>();
params.put("name", "xiaojiang");
// 生成 word 文档
WordUtils.generateWord(params, "user.ftl", response);
4、转为 pdf
<!-- word 转 pdf -->
<dependency>
<groupId>com.documents4j</groupId>
<artifactId>documents4j-local</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>com.documents4j</groupId>
<artifactId>documents4j-transformer-msoffice-word</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
public static void generateWord(Map<String, Object> dataMap, String templateName, HttpServletResponse response, String fileName) throws Exception {
// 生成 word 的代码
// 将 word 输出流转为输入流,转为pdf
InputStream in = new ByteArrayInputStream(fileStream.toByteArray());
documents4jWordToPdf(in, "D:/test.pdf");
}
public static void documents4jWordToPdf(InputStream docxInputStream, String targetPath) {
File outputFile = new File(targetPath);
try {
OutputStream outputStream = new FileOutputStream(outputFile);
IConverter converter = LocalConverter.builder().build();
converter.convert(docxInputStream)
.as(DocumentType.DOCX)
.to(outputStream)
.as(DocumentType.PDF).execute();
outputStream.close();
} catch (Exception e) {
}
}
文档模板的创建
1、创建 word 模板和表格
2、将 word 文件另存为 .xml 格式的文件,然后修改为 .ftl 后缀
3、在 IDEA 中打开该文件并格式化文件,会发现 word 其实就是通过 xml 标签进行设置的
4、找到需要替换的文字部分,可以直接搜索文字,使用 EL 表达式和变量进行替换
FreeMarker 常用标签
1、遍历列表,下标通过 k_index 获取
<#list list as k>
<w:r>
<w:rPr>
<w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体" w:cs="宋体"/>
<w:sz w:val="24"/>
<w:szCs w:val="24"/>
</w:rPr>
<w:t>${ k_index + 1} . ${ k.amount} </w:t>
</w:r>
</#list>
2、判断
<#if k.amount != 0>
<w:r>
<w:rPr>
<w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体" w:cs="宋体"/>
<w:sz w:val="24"/>
<w:szCs w:val="24"/>
</w:rPr>
<w:t>(${ k.amount} </w:t>
</w:r>
<#else>
<!-- 其他显示内容 -->
</#if>
3、合并上下单元格,一般写在单元格的列头 <w:tcPr> 中,有些版本使用的是 w:vmerge 标签
<!-- 合并单元格的开始 -->
<w:vMerge w:val="restart"/>
<!-- 被上一个单元格合并 -->
<w:vMerge w:val="continue"/>
4、定义变量
<!-- 定义变量 -->
<#assign pre = "">
<!-- 赋值给变量 -->
<#assign pre = "name">
5、合并内容相同的上下单元格
<#assign pre = "">
<#list tensList as t>
<w:tr w:rsidR="00B7397A">
<w:tc>
<w:tcPr>
<w:tcW w:w="787" w:type="dxa"/>
<w:vAlign w:val="center"/>
<#if t.deptName != pre>
<w:vMerge w:val="restart"/>
<#else>
<w:vMerge w:val="continue"/>
</#if>
<#assign pre = t.deptName>
</w:tcPr>
<w:p w:rsidR="00B7397A" w:rsidRDefault="0057625A">
<w:pPr>
<w:spacing w:line="560" w:lineRule="exact"/>
<w:rPr>
<w:rFonts w:ascii="黑体" w:eastAsia="黑体" w:hAnsi="黑体" w:cs="仿宋_GB2312"/>
<w:sz w:val="24"/>
<w:szCs w:val="24"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:ascii="黑体" w:eastAsia="黑体" w:hAnsi="黑体" w:cs="仿宋_GB2312"
w:hint="eastAsia"/>
<w:sz w:val="24"/>
<w:szCs w:val="24"/>
</w:rPr>
<w:t>${ t.deptName} </w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</#list>

6、调整导出 word 页面方向(横向或纵向)
搜索w:sectPr 标签,一般位于内容后面
用于设置以上页面的方向,纵向设置
<w:sectPr w:rsidR="00334CFE">
<w:pgSz w:w="11906" w:h="16838"/>
<w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="851"
w:footer="992" w:gutter="0"/>
<w:cols w:space="425"/>
<w:docGrid w:type="lines" w:linePitch="312"/>
</w:sectPr>
横向设置
<w:sectPr w:rsidR="00334CFE">
<w:pgSz w:w="16838" w:h="11906"/>
<w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="851"
w:footer="992" w:gutter="0"/>
<w:cols w:space="425"/>
<w:docGrid w:type="lines" w:linePitch="312"/>
</w:sectPr>
谢谢光临~
- 本文链接:https://lxjblog.gitee.io/2024/07/16/%E5%AF%BC%E5%87%BA%20Word%20%E6%96%87%E6%A1%A3/
- 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。