当前位置: 首页 > news >正文

FreeMarker生成word文档,固定word模板

该方法也就是通过freemarker生成固定的word文档,动态的word模板布局不能用该方法。

也就是必须有一个固定的模板文档是.ftl类型

如果初始文件为

 需要手动改为:

 也就是所有需要替换的地方,都需要有${XX}替换。

 

主要步骤为:

  1. 将 word 中需要填充的数据用占位符${变量名}替换。
  2. 将该 word 另存为 .xml 的格式,并检查看格式是否有误(主要看占位符有没被分割开来)。
  3. 将后缀.xml改成.ftl后,再调用相关 API 即可生成 word 文档。

特别注意,一定是将word另存为xml格式,而不是在外面修改后缀,不然会乱码。

其次一定要在xml或者ftl格式下检查格式,查询${XX}是否正确,看是否有占位符被分隔开的情况,如果有,只需将中间多余的部分删除即可。

处理普通文本
处理文本比较简单,在原文件中直接用占位符 ${} 替换即可。

处理表格
处在生成 word 表格时,FreeMarker 是利用列表一行一行循环填充的,而表头只会生成一次,因此我们还需手动改动一下 .ftl 文件。

注意:<w:tbl> 表示一个表格 、<w: tr> 表示一行、<w: tc> 表示一列,我们先找到第一行填充数据的那行,在前后分别加上如下语句即可:
 

<#list itemList as item>
</#list>

在这里插入图片描述

 

另一种情况:还有一种情况,即需要进行单元格的合并操作,前面和上面都差不多,不过还要加上另一种标签:

<w:vmerge w:val='restart'/>
<w:vmerge/>

我们先用 ${item.startMerge}(开始合并)和 ${item.endMerge}(结束合并)分别替换上面2行。

我们可以看到第一列分组是有合并单元格存在的,因此,找到第一列的 <w: tc> 那,如下图所示:

在这里插入图片描述 

 

1.导入相关依赖

我们主要用到了 FreeMarker,在这里,只需要导入以下依赖即可:

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

2.生成 word 的工具类

此方法将生成的文档传到前端;


import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;public class WordUtils {/*** 生成 word 文档方法** @param dataMap      要填充的数据* @param templateName 模版名称* @param fileName     要输出的文件路径* @throws Exception 抛出的异常*/public static void generateWord(HttpServletResponse response,Map<String, Object> dataMap, String templateName, String fileName) throws Exception {// 设置FreeMarker的版本和编码格式Configuration configuration = new Configuration(new Version("2.3.28"));configuration.setDefaultEncoding("UTF-8");// 设置FreeMarker生成Word文档所需要的模板的路径// configuration.setDirectoryForTemplateLoading(new File("/Users/xxx/Desktop/"));// 此处把模版文件都放在 resources 下的 templates 中configuration.setClassForTemplateLoading(WordUtils.class, "/templates");// 设置FreeMarker生成Word文档所需要的模板Template tem = configuration.getTemplate(templateName, "UTF-8");// 创建一个Word文档的输出流
//        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(fileName)), StandardCharsets.UTF_8));
//         FreeMarker使用Word模板和数据生成Word文档
//        response.setCharacterEncoding("UTF-8");response.setContentType("multipart/form-data");
//        response.setHeader("content-type", "application/octet-stream");
//        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));response.setCharacterEncoding("utf-8");response.setContentType("applicaiton/msword");
//        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx");response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));PrintWriter writer = response.getWriter();//tem.process(dataMap,new FileWriter("C:\\Users\\14017\\Desktop\\word.docx"));tem.process(dataMap, writer);writer.close();//tem.process(dataMap,response.getWriter());
//        writer.flush();
//        writer.close();
//        tem.process(dataMap,out);
//        out.flush();
//        out.close();}
}

此方法是将生成的文档存储到固定位置--目前在桌面

package com.iwiti.qcc.manage;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;public class WordUtils {/*** 生成 word 文档方法** @param dataMap      要填充的数据* @param templateName 模版名称* @param fileName     要输出的文件路径* @throws Exception 抛出的异常*/public static void generateWord(HttpServletResponse response,Map<String, Object> dataMap, String templateName, String fileName) throws Exception {// 设置FreeMarker的版本和编码格式Configuration configuration = new Configuration(new Version("2.3.28"));configuration.setDefaultEncoding("UTF-8");// 设置FreeMarker生成Word文档所需要的模板的路径// configuration.setDirectoryForTemplateLoading(new File("/Users/xxx/Desktop/"));// 此处把模版文件都放在 resources 下的 templates 中configuration.setClassForTemplateLoading(WordUtils.class, "/templates");// 设置FreeMarker生成Word文档所需要的模板Template tem = configuration.getTemplate(templateName, "UTF-8");// 创建一个Word文档的输出流
//        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(fileName)), StandardCharsets.UTF_8));
//         FreeMarker使用Word模板和数据生成Word文档
//        response.setCharacterEncoding("UTF-8");response.setContentType("multipart/form-data");
//        response.setHeader("content-type", "application/octet-stream");
//        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));//        response.setCharacterEncoding("utf-8");
//        response.setContentType("applicaiton/msword");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx");
//        response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
//        PrintWriter writer = response.getWriter();tem.process(dataMap,new FileWriter("C:\\Users\\14017\\Desktop\\word.docx"));
//        tem.process(dataMap, writer);
//        writer.close();//tem.process(dataMap,response.getWriter());
//        writer.flush();
//        writer.close();
//        tem.process(dataMap,out);
//        out.flush();
//        out.close();}
}

3.准备填充所需的数据

一般来说,我们的数据可能是从数据库中查询出来的各种对象,这里为了方便,就直接利用 HashMap 存储数据了。

 public static Map<String,Object> initData(){// 对应单元格的合并final String startMerge = "<w:vmerge w:val='restart'/>";final String endMerge = "<w:vmerge/>";final LocalDate nowDate = LocalDate.now();Map<String, Object> data = new HashMap<>();data.put("name", "张三");data.put("dept", "办公室");data.put("time", nowDate);List<Item> itemList = new ArrayList<>();Item item1 = new Item();item1.setProject("分组A").setProjectDetail.setTime("2-13").setProjectDetail.setPeople("小米")..setProjectDetail.setAddress("北京").setStartMerge(startMerge);itemList.add(item1);Item item2 = new Item();item2.setProject("分组A").setProjectDetail.setTime("2-13").setProjectDetail.setPeople("小米")..setProjectDetail.setAddress("北京").setEndMerge(endMerge);itemList.add(item2);ProjectItem item3 = new Item();item3.setProject("分组B").setProjectDetail.setTime("2-13").setProjectDetail.setPeople("小米")..setProjectDetail.setAddress("北京")itemList.add(item3);data.put("itemList", itemList);return data;}

注意的是表格的map的value是实体类,且这个实体类还有一个实体类嵌套,其次在修改模板是,将itemList  as item, 所以占位符就是${item.project}与${item.projectDetail.time}

4.生成 word 文档

 

         String templateName = QCC_TEMPLATE_WORD;String fileName = DateUtil.format(new Date(), "yyyyMMddHH") + QCC__WORD ;WordUtils.generateWord(response,data, templateName, fileName);//Qcc模板文件public static final String QCC_TEMPLATE_WORD = "QccTemplate.ftl";//Qcc生成文件名public static final String QCC__WORD = "QCC_REPORT.docx";

相关文章:

FreeMarker生成word文档,固定word模板

该方法也就是通过freemarker生成固定的word文档&#xff0c;动态的word模板布局不能用该方法。 也就是必须有一个固定的模板文档是.ftl类型 如果初始文件为 需要手动改为&#xff1a; 也就是所有需要替换的地方&#xff0c;都需要有${XX}替换。 主要步骤为&#xff1a; 将 w…...

前端必学的CSS制作Switch动画开关按钮演示

目录 前言 CSS 制作的 Switch 动画开关按钮 1.Html构建 2.CSS编写 3.完整代码 index.html文件 style.css文件 总结 前言 随着前端技术的不断发展与进步&#xff0c;界面交互的样式要求和美感也越来越高&#xff0c;很多网页的交互都加上了css动画,这里作者给大家分享一…...

C语言运算符(左值右值,基本运算符)

一.数据对象&#xff0c;左值&#xff0c;右值&#xff0c;运算符 数据对象&#xff1a;用于存储值的数据存储区域统称&#xff0c;而使用变量名是标识对象的一种方法&#xff08;还有指针&#xff0c;后面会教的&#xff09; 左值&#xff1a;用于标识特定数据对象的名称或表…...

【自学Python】一文读懂Python字符串是否是数字

Python字符串是否是数字 Python字符串是否是数字教程 在开发过程中&#xff0c;有时候我们需要判断一个 字符串 是否是 数字 形式&#xff0c;在 Python 中&#xff0c;判断字符串是否只由数字组成的函数为 isnumeric() 。 isnumeric() 函数只能判断 unicode 字符串&#xf…...

【PTA Advanced】1146 Topological Order(C++)

目录 题目 Input Specification: Output Specification: Sample Input: Sample Output: 思路 C 知识UP 代码 题目 This is a problem given in the Graduate Entrance Exam in 2018: Which of the following is NOT a topological order obtained from the given dire…...

基于stm32mp157的嵌入式linux+qt项目实战物联网毕业设计选题之智慧医疗项目

stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器&#xff0c;集成2个Cortex-A7核和1个Cortex-M4 核&#xff0c;A7核上可以跑Linux操作系统&#xff0c;M4核上可以跑FreeRT…...

Java实现邮件发送功能

确定发件人邮箱和密码某些邮箱服务器为了增加邮箱本身密码的安全性,给 SMTP 客户端设置了独立密码(有的邮箱称为“授权码”) 对于开启了独立密码的邮箱, 这里的邮箱密码必需使用这个独立密码(授权码) 确认发件人邮箱的 SMTP 服务器地址发件人邮箱的 SMTP 服务器地址, 必须…...

springboot+vue简单对接支付宝完整流程

源码 前端 vue-demo https://www.aliyundrive.com/s/dmnY8G6N6RM 点击链接保存&#xff0c;或者复制本段内容&#xff0c;打开「阿里云盘」APP &#xff0c;无需下载极速在线查看&#xff0c;视频原画倍速播放。 后端 aliPay https://www.aliyundrive.com/s/H2JFBjGWuf2 …...

Map 查找表

Map体现的结构是一个多行两列的表格,其中左列称为key,右列称为value.Map总是成对保存数据,并且总是根据key获取对应的value.因此我们可以将查询的条件作为key查询对应的结果作为value保存到Map中.Map有一个要求:key不允许重复(equals比较的结果)java.util.Map接口,是所有Map的顶…...

python--石头剪刀布游戏(列表)

本使用了下面几篇文章的知识&#xff1a; python(8)--列表初阶使用_码银的博客-CSDN博客 python(7)--if语句_码银的博客-CSDN博客 一、学习目标 利用列表实现石头剪刀布游戏 二、实验环境 Pycharm社区版、win11 三、代码 先贴代码&#xff0c;有需要的直接拿&#xff0c;想要进…...

Project Caliper:目标是打造最佳VR手柄

一提到Valve Index&#xff0c;人们很快联想到它的五指追踪VR手柄&#xff0c;这款支持手势追踪和体感反馈的高端VR手柄&#xff0c;是市面上最强大的C端VR手柄之一。尽管如此&#xff0c;它依然存在许多缺陷&#xff0c;比如配备的小型摇杆质量不佳、集成式设计不利于维修、人…...

自动驾驶:BEV开山之作LSS(lift,splat,shoot)原理代码串讲

自动驾驶&#xff1a;BEV开山之作LSS&#xff08;lift,splat,shoot&#xff09;原理代码串讲前言Lift参数创建视锥CamEncodeSplat转换视锥坐标系Voxel Pooling总结前言 目前在自动驾驶领域&#xff0c;比较火的一类研究方向是基于采集到的环视图像信息&#xff0c;去构建BEV视角…...

C# 如何实现对“属性”的扩展

目录一、为什么要扩展属性二、如何做&#xff1f;一、为什么要扩展属性 属性是一个类的特征&#xff0c;随着开发的不断升级&#xff0c;这种特征可能在一直变化&#xff0c;有时候为了向下兼容&#xff0c;一般属性的数量都是直接递增的。 例如&#xff1a;一个Person类&…...

EBS 物料属性 先后台对应关系 MTL_SYSTEM_ITEMS_B

Introductionweb The basic table mtl_system_items_b is the basic table of item in ERP system and there are a lot of columns,but I don’t know used of each column,particularly the column like %_flag. The reason of general exception may be because the ‘%_fl…...

MYSQL数据库-主从复制(原理及搭建)

文章目录1 概述2 原理3 搭建3.1 主库配置3.2 从库配置1 概述 主从复制是指将主数据库的DDL和 DML操作通过二进制日志传到从库服务器中&#xff0c;然后在从库上对这些日志重新执行(也叫重做)&#xff0c;从而使得从库和主库的数据保持同步。 MySQL支持一台主库同时向多台从库进…...

3GPP-NR Band25标准定义频点和信道(3GPP V17.7.0 (2022-12))

Reference test frequencies for NR operating band n25 Table 4.3.1.1.1.25-1: Test frequencies for NRoperating band n25 and SCS 15 kHz CBW [MHz]carrierBandwidth...

微信小程序 之 原生开发

目录 一、前期预备 1. 预备知识 ​2. 注册账号 - 申请AppID 3. 下载小程序开发工具 4. 小程序项目结构 ​5. 小程序的MVVM架构 二、创建小程序项目 1. 查看注册的appId ​2. 创建项目 ​3. 新建页面 01 - 创建text页面文件夹 ​02 - 新建text的page ​03 - 在app.json中配置 ​…...

常用vim命令和vim基本使用及Linux用户的管理,用户和组相关文件

常用vim命令和vim基本使用及Linux用户的管理&#xff0c;用户和组相关文件1. vim 的基本介绍和使用1.1 vim的三种模式1.2 常用vim命令【小白】1.3 Vim键盘图&#xff1a;2. Linux用户管理2.1 添加用户2.2 删除用户2.3 修改账号3. Linux系统用户组的管理4. 用户和组相关文件4.1 …...

阿里云服务器部署前后端分离项目

阿里云服务器部署 【若依】 前后端分离项目 文章目录一、域名解析二、服务器操作系统置空三、部署方式四、需安装环境配置五、Linux服务器安装相应内容&#xff08;具体安装步骤&#xff09;&#xff08;一&#xff09;安装JDK&#xff08;3种方式&#xff09;使用Yum安装&…...

内核经典数据结构list 剖析

前言&#xff1a;linux内核中有很多经典的数据结构&#xff0c;list(也称list_head)为其中之一&#xff0c;这些数据结构都是使用C语言实&#xff0c;并且定义和实现都在单独的头文件list.h中。可以随时拿出来使用。list.h的定义不同linux发行版本路径不同,我们可以在/usr/incl…...

华为OD机试 - 考优选核酸检测点(Python)| 真题+思路+考点+代码+岗位

优选核酸检测点 题目 张三要去外地出差,需要做核酸,需要在指定时间点前做完核酸, 请帮他找到满足条件的核酸检测点。 给出一组核酸检测点的距离和每个核酸检测点当前的人数给出张三要去做核酸的出发时间 出发时间是 10 分钟的倍数 同时给出张三做核酸的最晚结束时间题目中…...

在魔改PLUS-F5280开发板上使用合封qsp iflash

文章目录引言硬件调整软件调整总结引言 由于目前灵动官网暂未发布正式版的PLUS-F5280开发板&#xff0c;可以使用现有的PLUS-F5270 v1.2开发板&#xff08;下文简称PLUS-F5270开发版&#xff09;替换为MM32F5280微控制器芯片&#xff0c;改装为PLUS-F5280开发板。本文记录了使…...

uni-app 瀑布流

效果图 一、组件 components/u-myWaterfall.vue <template><view class"u-waterfall"><view id"u-left-column" class"u-column"><slot name"left" :leftList"leftList"></slot></view&…...

华为OD机试 - 去除多余空格(Python)| 真题+思路+考点+代码+岗位

去除多余空格 题目 去除文本多余空格,但不去除配对单引号之间的多余空格。给出关键词的起始和结束下标,去除多余空格后刷新关键词的起始和结束下标。 条件约束: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oQABYuJD-1676475739950)(https://…...

MyBatis 二级缓存简单使用步骤

1、二级缓存使用 在 MyBatis 中默认二级缓存是不开启的&#xff0c;如果要使用需手动开启。在 mybatis-config.xml 配置文件中设置 cacheEnabled true &#xff0c;配置如下&#xff1a; <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE c…...

kubeadmin kube-apiserver Exited 始终起不来查因记录

kubeadmin kube-apiserver Exited 始终起不来查因记录 [rootk8s-master01 log]# crictl ps -a CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD b7af23a98302e …...

论文投稿指南——中文核心期刊推荐(工程材料学)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…...

【动态规划】背包问题题型及方法归纳

背包问题的种类 背包问题是在规定背包容量为j的前提下&#xff0c;每个物品对应的体积为v[i]&#xff0c;价值为w[i]&#xff0c;从物品0到物品i中选择物品放入背包中&#xff0c;找出符合某种要求的价值。 &#xff08;1&#xff09;背包问题种类 01背包&#xff1a;每种物…...

全球十大资质正规外汇期货平台排行榜(最新版汇总)

外汇期货简称为FxFut&#xff0c;是“Forex Futures”的缩写&#xff0c;是在集中形式的期货交易所内&#xff0c;交易双方通过公开叫价&#xff0c;以某种非本国货币买进或卖出另一种非本国货币&#xff0c;并签订一个在未来的某一日期根据协议价格交割标准数量外汇的合约。 …...

使用Paramiko时遇到的一些问题

目录 1.背景 2.问题合集 1&#xff09;“bash: command not found” 2&#xff09;Paramiko中正常的输入&#xff0c;却到了stderr&#xff0c;而stdout是空 3&#xff09;命令实际是alias 1.背景 在自动化脚本中&#xff0c;使用了库Paramiko&#xff0c;远程SSH到后台服…...

教育咨询网站模板/优化网站seo方案

本文实例讲述了Python实现将16进制字符串转化为ascii字符的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a; 字符串456e633064316e675f31735f66336e&#xff0c;通过Python&#xff0c;按照两个字符&#xff0c;例如45,6e,63形式变成ascii码格式&#xff0c;输出a…...

建设银行招聘网站甘肃分行/信息流优化师证书

管理 Linux 系统中的文件和目录&#xff0c;除了可以设定普通权限和特殊权限外&#xff0c;还可以利用文件和目录具有的一些隐藏属性。chattr 命令&#xff0c;专门用来修改文件或目录的隐藏属性&#xff0c;只有 root 用户可以使用。该命令的基本格式为&#xff1a;[rootlocal…...

苏州新区网站制作/seo和sem的关系

### MVC![](http://p0zfk1qh0.bkt.clouddn.com/markdownmvc.png) 视图&#xff08;View&#xff09;&#xff1a;用户界面。 控制器&#xff08;Controller&#xff09;&#xff1a;业务逻辑 模型&#xff08;Model&#xff09;&#xff1a;数据保存 ** View 传送指令到 Contro…...

wordpress亲子模板下载/免费b站在线观看人数在哪里找到

在c言语中pow()函数是用来求x的y次幂。x、y及函数值都是double型 &#xff0c;其语法为“double pow(double x, double y)”&#xff1b;个中参数“double x”示意底数&#xff1b;参数“double y”示意指数。pow()函数用来求x的y次幂&#xff0c;x、y及函数值都是double型 &am…...

房产如何做网站/企业宣传推广方案

天朗气清的日子里&#xff0c;总想寻着一处花香缭绕之地&#xff0c;三两亲友&#xff0c;谈笑风生&#xff1b;阴雨绵绵的时候&#xff0c;亦想觅一方静谧清新之所&#xff0c;来一壶茶捧一本书&#xff0c;听雨打叶梢……没有大户型&#xff0c;没有庭院&#xff0c;即使是一…...

怎么做淘宝客导购网站/渠道推广策略

最近的工程需要搞一下并行&#xff0c;打算用一下cuda。开这个系列希望能够把这个过程中学到的有关并行的知识以及一些问题。 这一次主要介绍下如何在cuda并行中使用vector&#xff0c;包括空间分配与使用。 vector其实是可以被看做一个动态数组的&#xff0c;其存储的分配也…...