word模板生成实现方案
word模板生成实现方案
传统word模板生成引擎主要采用FrameMark或Jasper构建模板文件并渲染生成;
存在问题
- 模板文件可读性差;
- 模板文件不可维护,开发人员模板修改及验证时间长;
优化方案:
替换采用poi-tlWord模板引擎,使用docx文件作为模板附件进行渲染及导出;降低模板文件维护难度,提高模板可读性;
poi-tl 基于Apache POI的Word模板引擎,项目免费开源,可商用;原生支持文本、图片、表格、列表、批注、EL表达式等;
poi-tl官网地址:https://deepoove.com/poi-tl/
使用实例
核心依赖
poi低版本可使用低版本poi-tl,具体版本依赖关系可参考官网说明
maven依赖
代码窗口 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.3</version></dependency><dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.12.2</version></dependency>创建及编辑模板template.docx
代码窗口 这是个word模板 参数name: {{name}}模板渲染及生成
代码窗口 String templatePath = "C:\\Users\\Hidewnd\\Desktop\\template.docx";Map<String, Object> data = new HashMap<>();data.put("name", "Sayi");data.put("start_time", "2019-08-04");XWPFTemplate template = XWPFTemplate.compile(templatePath).render(data);String targetPath = "C:\\Users\\Hidewnd\\Desktop\\outputDocx.docx";template.writeAndClose(new FileOutputStream(targetPath));
图片、表格、列表循环等可通过配置类Configure使用插件进行声明以实现不同效果
工具类封装
import cn.hutool.core.io.FileUtil;import cn.hutool.core.util.StrUtil;import com.deepoove.poi.XWPFTemplate;import com.deepoove.poi.config.Configure;import com.deepoove.poi.config.ConfigureBuilder;
import java.io.File;import java.io.FileNotFoundException;import java.io.InputStream;import java.io.OutputStream;import java.util.Map;
/** * word模板生成工具类 * <p> * 基于Poi-tl封装 官方文档:<a href="https://deepoove.com/poi-tl/">https://deepoove.com/poi-tl/</a> * </p> * * @author hidewnd */public class WordExportUtils {
/** * 根据模板文件导出文件 * * @param templateFile 模板附件 * @param targetName 目标文件名称 * @param data 数据Map,包含模板中需要替换的数据 * @return 生成文件对象 * @throws Exception 可能抛出的异常 */ public static File exportByFile(File templateFile, String targetName, Map<String, Object> data) throws Exception { ConfigureBuilder builder = Configure.builder(); return exportByFile(templateFile, targetName, data, builder.build()); }
/** * 根据模板文件导出文件 * * @param templateFile 模板附件 * @param targetName 目标文件名称 * @param data 数据Map,包含模板中需要替换的数据 * @param configure 配置参数项 * @return 生成文件对象 * @throws Exception 可能抛出的异常 */ public static File exportByFile(File templateFile, String targetName, Map<String, Object> data, Configure configure) throws Exception { checkTemplateFile(templateFile); File targetFile; try (XWPFTemplate template = XWPFTemplate.compile(templateFile, configure)) { template.render(data); String targetPath = formatTargetPath(templateFile.getParentFile().getAbsolutePath(), targetName); template.writeToFile(targetPath); targetFile = new File(targetPath); } return targetFile; }
private static void checkTemplateFile(File templateFile) throws Exception { if (templateFile == null || !templateFile.exists() || !templateFile.isFile()) { throw new FileNotFoundException("template File not found."); } if (!FileUtil.getSuffix(templateFile).equals("docx")) { throw new RuntimeException("template file type must be docx."); } }
private static String formatTargetPath(String targetParentPath, String targetName) { String fileName = StrUtil.emptyToDefault(targetName, "targetFile.docx"); if (StrUtil.endWith(fileName, ".docx")) { fileName = StrUtil.replaceLast(fileName, ".doc", ".docx"); } if (!fileName.contains(".docx")) { fileName += ".docx"; } return targetParentPath + File.separator + fileName; }
public static void exportByStream(InputStream templateStream, OutputStream outputStream, Map<String, Object> data) throws Exception { ConfigureBuilder builder = Configure.builder(); exportByStream(templateStream, outputStream, data, builder.build()); }
public static void exportByStream(InputStream templateStream, OutputStream outputStream, Map<String, Object> data, Configure configure) throws Exception { try (XWPFTemplate template = XWPFTemplate.compile(templateStream, configure)) { template.render(data); template.write(outputStream); } }
}