使用ftl生成word

背景:根据word模板下载word。word里面需要填充数据,格式是固定的。首先在word中给数据起个变量名称
在这里插入图片描述需要更换的数据改成${变量名!},必须是英文的,加感叹号是为了防止null,如果数据是null,文档下载下来后会直接显示null,加上感叹号就不会,没数据就是空。也可以不加感叹号,在代码设置下属性即可,后面会说到。变量名结束后把word另存为xml
在这里插入图片描述
然后复制到项目中,我用的是idea,打开后会发现就几行,后面老长了
在这里插入图片描述
然后format下ctrl+alt+L(快捷键仅供参考,本人是这样的),就会
在这里插入图片描述

这些红色不影响,不用管它。在文件中搜索${,被搜到的都是起变量的地方,有的地方是会分离的
在这里插入图片描述
这就需要手动帮他们破镜重圆了,剪切下即可
在这里插入图片描述
这种应该比较多,手动改下就行。改完后保存,改为.ftl文件。下面是代码

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;import java.io.*;
import java.util.Map;public class ExportController {public void download(WeeklyTask weeklyTask, HttpServletResponse response) {try {//加入模板的数据Map<String, Object> data = new HashMap<>();data.put("key", value);String outFileName = "测试.docx";//模板相对路径String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();path = path + "templates/";//linuxif ("/".equals(File.separator)) {path = path.replaceAll("\\\\", "/");}File outFile = createDoc(data, outFileName, path, "模板.ftl");if (null != outFile) {response.reset();response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(outFile.getName(), "UTF-8"));//获取文件输入流InputStream in = new FileInputStream(outFile);byte[] buffer = new byte[1024];OutputStream out = response.getOutputStream();int len = 0;while ((len = in.read(buffer)) > 0) {//将缓冲区的数据输出到客户端浏览器out.write(buffer, 0, len);}in.close();out.close();}} catch (Exception e) {e.printStackTrace();}}public static File createDoc(Map<String, Object> dataMap, String outFileName, String templatePath, String templateFileName) throws IOException {//设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载,Configuration configuration = new Configuration();//设置null转为空串configuration.setClassicCompatible(true);configuration.setDefaultEncoding("UTF-8");configuration.setDirectoryForTemplateLoading(new File(templatePath));Template t = null;try {//test.ftl为要装载的模板t = configuration.getTemplate(templateFileName, "UTF-8");t.setOutputEncoding("UTF-8");} catch (IOException e) {e.printStackTrace();}//输出文档路径及名称File outFile = new File(outFileName);if (!outFile.exists()) {outFile.createNewFile();}Writer out = null;FileOutputStream fos = null;try {fos = new FileOutputStream(outFile);OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");//这个地方对流的编码不可或缺,使用main()单独调用时,应该可以,但是如果是web请求导出时导出后word文档就会打不开,并且包XML文件错误。主要是编码格式不正确,无法解析。// out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));out = new BufferedWriter(oWriter);} catch (FileNotFoundException e1) {e1.printStackTrace();}try {t.process(dataMap, out);out.close();fos.close();return outFile;} catch (TemplateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}
}

我的模板文件放在
在这里插入图片描述
下,我是springBoot,前后端分离的maven。获取模板路径视情况而定。

//设置null转为空串
configuration.setClassicCompatible(true);

这个设置下就可以不加感叹号了。然后模板获取数据是根据你起的变量名称和Map的key对应来获取值的,即使模板里面的变量名称加了感叹号,key也不用加感叹号。然后就可以下载了。如果下载后发现有错位现象,多了空格或者换行,比如这种
在这里插入图片描述
下载的文件前面肯定多了很多空格或者回车,把多余的删除即可
在这里插入图片描述
还有是循环,塞数据的map要put成
List<Map<String, String>> list = new ArrayList<>();
Map<String, String> m = new HashMap<>();
m.put(“anzlsz01”,value);
list .add(m);
data.put(“TABLE1”, list);模板要这样在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555117.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么叫做项目孵化_蓝莓孵化营12进5争夺战,项目人绽放自我不留遗憾

国内首档互联网职业竞技励志节目《蓝莓孵化营》&#xff0c;今晚22点在浙江卫视播出第十一期。本期节目中&#xff0c;第三事业群的12组项目人将为最终的5张终极考核入场券展开争夺。这一次&#xff0c;他们比拼的是以“2020”为主题的短视频&#xff0c;每一组项目人都拼尽了自…

一开机就提示脱机工作_「华为手机维修自学教程」华为手机的开机触发电路 华为维修技巧...

谈谈华为的开机触发电路华为这段时间的新闻不少&#xff0c;大家应该都有说了解。华为的强大意味着华为手机的维修市场越来越大。从事维修的朋友们你们准备好了吗&#xff1f;今天给大家说一说&#xff0c;华为手机的开机触发电路。修苹果手机的朋友大家都知道&#xff0c;电源…

SpringBoot 整合mybatis-plus 高级功能及用法详解

springboot 整合mybatis-plus 高级功能及用法详解 学习并使用mybatis-plus的一些高级功能的用法例如&#xff1a; AR模式、 乐观锁 、逻辑删除 、自动填充、数据保护等功能 为了方便演示&#xff0c;咱们还是新建一个全新的项目 引入mp依赖 <dependency><groupId>…

8除以2表示什么意思_八字中劫财,比肩分别表示什么意思

◆◆比劫与其他十神的生克关系◆◆食伤&#xff1a;比劫生食伤财星&#xff1a;比劫克财星官星&#xff1a;官星克比劫印星&#xff1a;印星生比劫◆◆比劫帮身◆◆八字术语&#xff0c;比肩劫财均可助日干之力&#xff0c;如甲见甲(比)、乙(劫)、寅(禄)、卯(刃)之类&#xff0…

MyBatis-plus 自动填充MetaObjectHandler不生效问题

背景 在项目中经常遇到一些数据需要自动填充&#xff0c;填充方法都是同一种规则&#xff0c;例如创建时间等。 1 自动填充方法配置 1.1 实体类添加注解 1.2 在handler包下实现元对象处理器接口 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import o…

博途变量类型_PLC数据类型(UDT)

UDT类型是一种由多个不同数据类型元素组成的数据结构&#xff0c;元素可以是基本数据类型&#xff0c;也可以是STRUCT、数组等复杂数据类型以及其它UDT等。UDT类型嵌套UDT类型的深度限制为 8 级。UDT类型可以在DB、OB/FC/FB接口区处使用。从TIA 博途 V13SP1 开始&#xff0c;S7…

Mybatis-Plus条件参数查询手册

【引言】 使用mybatis-plus框架的基础上&#xff0c;直接使用其中的条件参数进行查询还是很方便的。但每次使用到像大于、不等于这样一些不常用条件时&#xff0c;都需要现查&#xff0c;所以记录在这篇博客里&#xff0c;当作一个自己的查询手册。 【手册】 查询方式说明se…

java 最快平衡几个值_Java 集合框架面试问题集锦

Java集合框架(例如基本的数据结构)里包含了最常见的Java常见面试问题。很好地理解集合框架&#xff0c;可以帮助你理解和利用Java的一些高级特性。下面是面试Java核心技术的一些很实用的问题。Q&#xff1a;最常见的数据结构有哪些&#xff0c;在哪些场景下应用它们&#xff1f…

mybatis-plus 如何判断参数是否为空并作为查询条件

判断参数是否为空并作为查询条件 Overridepublic Page<DemandEntity> selectByDepartmentDisplay(DemandEntity demandEntity) {EntityWrapper<DemandEntity> wrapper new EntityWrapper<DemandEntity>();wrapper.eq(!StringUtils.isNullOrEmpty(demandEnt…

linux 总数 进程_Linux运用一些常用命令,优秀的PHPer都需掌握

作为一名优秀的phper&#xff0c;Linux是必备的一项技能&#xff0c;工作3-5年的基本能明白我讲的道理&#xff01;今天搜集整理了一些Linux服务器运维常用命令,希望对大家有帮助&#xff1a;1.删除0字节文件find -type f -size 0 -exec rm -rf {} 2.查看进程按内存从大到小排列…

c语言高低位拷贝_C语言指针详解

1为什么使用指针 假如我们定义了 char a’A’ &#xff0c;当需要使用 ‘A’ 时&#xff0c;除了直接调用变量 a &#xff0c;还可以定义 char *p&a &#xff0c;调用 a 的地址&#xff0c;即指向 a 的指针 p &#xff0c;变量 a&#xff08; char 类型&#xff09;只占了一…

MybatisPlus中@TableField注解的使用详解

MybatisPlus中TableField注解的使用详解 实现 官方文档说明&#xff1a; com.baomidou.mybatisplus.annotations.TableField TableField注解新增属性 update 预处理 set 字段自定义注入 (讲解&#xff1a;比如我们使用mybatisplus自带的insert()方法向数据库插入数据时&…

dataframe记录数_大数据系列之Spark SQL、DataFrame和RDD数据统计与可视化

Spark大数据分析中涉及到RDD、Data Frame和SparkSQL的操作&#xff0c;本文简要介绍三种方式在数据统计中的算子使用。1、在IPython Notebook运行Python Spark程序IPython Notebook具备交互式界面&#xff0c;可以在Web界面输入Python命令后立刻看到结果&#xff0c;还可将数据…

bug的生命周期、bug状态转换图

当我们发现一个bug的时候&#xff0c;应该怎么理清他们之间的关系呢&#xff1f;一个bug 从open到close的所有状态 都是我们测试人员需要注意的。 一、bug的状态 新建&#xff08;New&#xff09; 新发现的bug&#xff0c;未经评审决定是否指派给开发人员进行修改。 确认&…

wps居中对齐不在中间_WPS文字快捷键总结(Windows版本)--值得收藏

WPS Office是一款国产的办公软件套装&#xff0c;有WPS文字、WPS表格和WPS演示三个板块&#xff0c;可以实现办公软件最常见的文字、表格、演示等多种功能&#xff0c;支持阅读和输出PDF文件&#xff0c;全面兼容Microsoft Office97-2010格式。想要熟练地使用WPS办公软件&#…

bugzilla使用规范分享

bugzilla使用规范分享 1.new/confirmed 测试人员将Bug提交给任务分发人员&#xff08;研发模块负责人&#xff09;&#xff0c; 此时Bug状态为new/confirmed&#xff0c;开始Bug的生命周期&#xff0c;如果测试人员知道具体负责的研发人员&#xff0c;也可以直接指定&#x…

编程语言_如何正确地学习编程语言

首先&#xff0c;当前学生和职场人学习编程已经成为了一个大的趋势&#xff0c;掌握编程语言不仅能够提升自身获取信息的能力&#xff0c;同时也能够拓展自身的能力边界&#xff0c;这一点在工业互联网时代会有更加明显的体现。编程语言本身并不难&#xff0c;但是要想形成自己…

测试游戏帧率电脑温度的软件,游戏中显示帧数和温度方法_游戏画面中实时显示FPS帧数温度技巧...

相信很多游戏玩家平时都是在用电脑玩游戏&#xff0c;而且大家也喜欢看一看自己在在游戏画面中实时的FPS帧数和温度信息。但是很网友对这个游戏画面中如何实时显示FPS帧数、频率、硬件温度不太清楚&#xff0c;下面智能手机网分享一下具体的操作方法&#xff0c;以便大家在玩游…

12面魔方公式图解法_一位建筑工程师:多年渴望就是学会魔方还原,只按这七步就可以!...

本人性别男&#xff0c;年龄47岁&#xff0c;一位建筑工程师&#xff0c;性格开朗&#xff0c;喜欢学习&#xff0c;2013年在网上搜索记忆关键词&#xff0c;从此开始了学习超级记忆和思维导图之路&#xff01;也因此&#xff0c;接触了魔方&#xff01;初学魔方&#xff0c;我…

navicat运行db文件_使用 YAML 文件配置 Jenkins 流水线

本文转载自&#xff1a;Jenkins 中文社区这也是一种自定义流水线 DSL 的方法几年前&#xff0c;我们的 CTO 写了一篇关于 使用 Jenkins 和 Docker 为 Ruby On Rails 应用提供持续集成服务 的文章。这些年&#xff0c;我们一直使用这个 CI 流水线解决方案&#xff0c;直到我们最…