java freemarker 动态生成excel文件
好久木有更新啦
抓住2023的小尾巴
浅浅更新一下吧~
最近做了一个动态生成excel的功能,这里记录下部分功能,主要用到的是freemarker框架,spring就有带,我起的demo载入了一下freemarker的jar包
一、创建模板
首先可以创建一个excel,编辑自己想要的模板,这里举个简单的例子
编写好后可以保存一下,然后再保存为.xml格式的文件,就能得到模板雏形
大概是长这样

然后根据ftl文件的语法,我们可以对模板进行改造,加入自己需要的字段
这里列举一些常见的方式
1、普通字段填充
<Cell ss:StyleID="s17"><Data ss:Type="String">姓名</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">${(name)!}</Data></Cell>
2、日期填充,java传入的参数类型为Date
<Cell ss:Index="2" ss:StyleID="s17"><Data ss:Type="String">出生年月</Data></Cell><Cell ss:StyleID="s17"><#if birth??><Data ss:Type="String">${birth?string("yyyy-MM-dd")}</Data></#if></Cell>
3、switch case选择用法
<Cell ss:StyleID="s17"><Data ss:Type="String">国籍</Data></Cell><Cell ss:StyleID="s17"><#if certType??><#switch certType> <#case "A"> <Data ss:Type="String">■身份证 □外籍护照 □港澳居民来往内地通行证</Data><#break> <#case "B"> <Data ss:Type="String">□身份证 ■外籍护照 □港澳居民来往内地通行证</Data><#break> <#case "C"> <Data ss:Type="String">□身份证 □外籍护照 ■港澳居民来往内地通行证</Data><#break> <#default> </#switch><#else><Data ss:Type="String">□身份证 □外籍护照 □港澳居民来往内地通行证</Data></#if></Cell>
4、数组对象展示
(这边我做的这个主要是因为有动态展示的需求,如果没有家属信息,就不展示家属单元格)
<#list spouseInfos as row><Row ss:AutoFitHeight="0"><Cell ss:MergeDown="2" ss:StyleID="s18"><Data ss:Type="String">家属信息</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">姓名</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">${(row.name)!}</Data></Cell></Row><Row><Cell ss:Index="2" ss:StyleID="s17"><Data ss:Type="String">关系</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">${(row.relation)!}</Data></Cell></Row><Row><Cell ss:Index="2" ss:StyleID="s17"><Data ss:Type="String">联系电话</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">${(row.tel)!}</Data></Cell></Row></#list>
这里需要注意如果使用了数组动态展示需要计算行数
可以把xml文件里的ExpandedRowCount参数进行修改,加入totalRowCount参数标记行数
在java程序中需要动态计算这个行数
<Table ss:ExpandedColumnCount="3" ss:ExpandedRowCount="${(totalRowCount)!}" x:FullColumns="1"x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="13.5">
模板制作好以后保存再修改文件格式名称为.ftl即可
主体部分为
<Table ss:ExpandedColumnCount="3" ss:ExpandedRowCount="${(totalRowCount)!}" x:FullColumns="1"x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="13.5"><Column ss:Index="3" ss:AutoFitWidth="0" ss:Width="310.5"/><Row><Cell ss:MergeDown="2" ss:StyleID="s18"><Data ss:Type="String">基本信息</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">姓名</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">${(name)!}</Data></Cell></Row><Row><Cell ss:Index="2" ss:StyleID="s17"><Data ss:Type="String">性别</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">${(sex)!}</Data></Cell></Row><Row><Cell ss:Index="2" ss:StyleID="s17"><Data ss:Type="String">出生年月</Data></Cell><Cell ss:StyleID="s17"><#if birth??><Data ss:Type="String">${birth?string("yyyy-MM-dd")}</Data></#if></Cell></Row><Row><Cell ss:MergeDown="2" ss:StyleID="s18"><Data ss:Type="String">其他信息</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">国籍</Data></Cell><Cell ss:StyleID="s17"><#if certType??><#switch certType> <#case "A"> <Data ss:Type="String">■身份证 □外籍护照 □港澳居民来往内地通行证</Data><#break> <#case "B"> <Data ss:Type="String">□身份证 ■外籍护照 □港澳居民来往内地通行证</Data><#break> <#case "C"> <Data ss:Type="String">□身份证 □外籍护照 ■港澳居民来往内地通行证</Data><#break> <#default> </#switch><#else><Data ss:Type="String">□身份证 □外籍护照 □港澳居民来往内地通行证</Data></#if></Cell></Row><Row><Cell ss:Index="2" ss:StyleID="s17"><Data ss:Type="String">居住地址</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">${(address)!}</Data></Cell></Row><Row><Cell ss:Index="2" ss:StyleID="s17"><Data ss:Type="String">联系电话</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">${(tel)!}</Data></Cell></Row><#list spouseInfos as row><Row ss:AutoFitHeight="0"><Cell ss:MergeDown="2" ss:StyleID="s18"><Data ss:Type="String">家属信息</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">姓名</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">${(row.name)!}</Data></Cell></Row><Row><Cell ss:Index="2" ss:StyleID="s17"><Data ss:Type="String">关系</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">${(row.relation)!}</Data></Cell></Row><Row><Cell ss:Index="2" ss:StyleID="s17"><Data ss:Type="String">联系电话</Data></Cell><Cell ss:StyleID="s17"><Data ss:Type="String">${(row.tel)!}</Data></Cell></Row></#list></Table>
二、生成文件
生成文件的主要java代码如下
import freemarker.template.Configuration;
import freemarker.template.Template;import java.io.*;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;public class ExcelUtil {/*** 根据模板生成文件* @param dataMap 写入数据* @param templateFilePath 模板文件路径* @param outFileName 输出文件路径*/public static void doGenerateFile(Map<String, Object> dataMap, String templateFilePath, String outFileName) {Writer out = null;FileOutputStream fileStream = null;//需要压缩的文件,大于1个才会压缩try {//生成合同文件Configuration configuration = new Configuration();configuration.setDefaultEncoding("UTF-8");Template t = configuration.getTemplate(templateFilePath); // 获取模板文件// 导出文件File outFile = new File(outFileName);//获取父目录File fileParent = outFile.getParentFile();//判断是否存在if (!fileParent.exists()) {//创建父目录文件fileParent.mkdirs();}OutputStreamWriter oWriter = null;fileStream = new FileOutputStream(outFile);oWriter = new OutputStreamWriter(fileStream, StandardCharsets.UTF_8);out = new BufferedWriter(oWriter);// 将填充数据填入模板文件并输出到目标文件t.process(dataMap, out);} catch (Exception e1) {if (fileStream != null && out != null) {close(fileStream, out);}System.out.println("生成文件出错," + e1.getMessage());} finally {if (fileStream != null && out != null) {close(fileStream, out);}}}private static void close(FileOutputStream fileStream, Writer out) {try {fileStream.flush();fileStream.close();out.flush();out.close();} catch (Exception e) {System.out.println("关闭流异常," + e.getMessage());}}public static Date str2Date(String dateString) {try {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");Date date = sdf.parse(dateString);return date;} catch (Exception e) {e.printStackTrace();}return null;}
}
写个简单的类测试一下
1、如果不需要展示List对象的数据,可以存一个空数组到Map,本文为例,家属信息为列表对象
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class TestMain {public static void main(String[] args) {//相对路径 模板文件、输出文件String templateFile = "file/temp.ftl";String outFileName = "file/test.xls";Map<String, Object> dataMap = test01();
// Map<String, Object> dataMap = test02();try {ExcelUtil.doGenerateFile(dataMap, templateFile, outFileName);} catch (Exception e) {System.out.println("处理异常," + e.getMessage());}}private static Map<String, Object> test01() {Map<String, Object> dataMap = new HashMap<>();BigDecimal baseRow = new BigDecimal(6);dataMap.put("name", "张三");dataMap.put("sex", "男");dataMap.put("birth", ExcelUtil.str2Date("1990-01-10"));dataMap.put("certType", "A");dataMap.put("address", "地址详情");dataMap.put("tel", "110110");
//放入一个空数组的参数避免合成的时候报错List<Map<String, Object>> list = new ArrayList<>();dataMap.put("spouseInfos", list);dataMap.put("totalRowCount", baseRow);return dataMap;}private static Map<String, Object> test02() {Map<String, Object> dataMap = new HashMap<>();BigDecimal baseRow = new BigDecimal(6);dataMap.put("name", "张三");dataMap.put("sex", "男");dataMap.put("birth", ExcelUtil.str2Date("1990-01-10"));dataMap.put("certType", "A");dataMap.put("address", "地址详情");dataMap.put("tel", "110110");List<Map<String, Object>> list = new ArrayList<>();Map<String, Object> s1 = new HashMap<>();s1.put("name", "李四");s1.put("relation", "夫妻");s1.put("tel", "112112");list.add(s1);dataMap.put("spouseInfos", list);//计算展示行数BigDecimal subtract = baseRow.add(new BigDecimal(3));dataMap.put("totalRowCount", subtract);return dataMap;}
}
使用test01数据效果如图

使用test02数据效果如图

相关文章:
java freemarker 动态生成excel文件
好久木有更新啦 抓住2023的小尾巴 浅浅更新一下吧~ 最近做了一个动态生成excel的功能,这里记录下部分功能,主要用到的是freemarker框架,spring就有带,我起的demo载入了一下freemarker的jar包 一、创建模板 首先可以创建一个e…...
第38节: Vue3 鼠标按钮修改器
在UniApp中使用Vue3框架时,你可以使用按键修饰符来更精确地处理键盘事件。以下是一个示例,演示了如何在UniApp中使用Vue3框架使用.left、.right和.middle按键修饰符: <template> <view> <input keydown"handleKeyDown&…...
redis cluster判断key属于那个分片。
一、判断阿里云 redis cluster,的key属于那个分片。 阿里云特有的命令info key 可以查看key属于那个slot,那个分片 命令行查看: xxxx:6379> info key xxxx_compressed_xxx slot:4941 node_index:9 xxxx:6379> cluster keyslot xxxx_…...
Centos7:Jenkins+gitlab+node项目启动(3)
Centos7:Jenkinsgitlabnode项目启动(1) Centos7:Jenkinsgitlabnode项目启动(1)-CSDN博客 Centos7:Jenkinsgitlabnode项目启动(2) Centos7:Jenkinsgitlabnode项目启动(2)-CSDN博客 Centos7:Jenkinsgitlabnode项目启…...
Linux安装GitLab教程
Linux安装GitLab教程 1、配置yum源 相当于新建一个文件,通过这个文件来安装gitlab vim /etc/yum.repos.d/gitlab-ce.repo 把这些配置粘进去 [gitlab-ce] nameGitlab CE Repository baseurlhttps://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el$releasever/ gp…...
react 之 美团案例
1.案例展示 2.环境搭建 克隆项目到本地(内置了基础静态组件和模版) git clone http://git.itcast.cn/heimaqianduan/redux-meituan.git 安装所有依赖 npm i 启动mock服务(内置了json-server) npm run serve 启动前端服务 npm…...
C基础使用
return 0; 语句用于表示退出程序。 一个程序有且只能有一个main函数的存在 安装编译环境: 安装vim: ubuntu里vim编辑器使用方法_ubuntu vim-CSDN博客 编译与运行: gcc hello.c //编译源文件 ./a.out //运行…...
Linux网络编程——Socket编程步骤及常用API
Sockt服务器和客户端的开发步骤 TCP connect()最好建立在listen()后,一旦监听到就建立连接。 UDP 常用API 包含头文件 #include<sys/types.h> #include<sys/socket.h>创建套接字(连接协议) 作用 用于根据指定的地址族、数据…...
数据挖掘 K-Means聚类
未格式化之前的代码: import pandas as pd#数据处理 from matplotlib import pyplot as plt#绘图 from sklearn.preprocessing import MinMaxScaler#归一化 from sklearn.cluster import KMeans#聚类 import os#处理文件os.environ["OMP_NUM_THREADS"] …...
医疗卫生行业网络安全需求发展
文章目录 一、行业安全建设需求分析1、等级保护2.0合规建设云计算技术大数据技术物联网技术移动互联网技术2、加强医疗数据安全保护加密存储与传输数据加强数据备份与恢复注重数据脱敏与分级保护3、强化网络安全制度管理完善应急预案与响应机制加强网络安全人员管理二、行业新技…...
【Unity热更新】学会AssetsBundle打包、加载、卸载
本教程详细讲解什么是AssetBundle压缩包机制!然后构建 AssetBundle、加载 AssetBundle 以及卸载 AssetBundle 的简要教程。这一个流程就是热更新! AssetBundles 简介 1.什么是AssetBundles? AssetBundles是Unity中一种用于打包和存储资源(如模型、纹理、声音等)的文件格…...
智能优化算法应用:基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.指数分布算法4.实验参数设定5.算法结果6.…...
vue 监听浏览器关闭或刷新事件
vue 监听浏览器关闭或刷新事件 需求 web项目中使用socket时,涉及到关闭刷新浏览器多次连接问题,其中一个解决方法是在关闭或刷新浏览器时,将连接断开。 代码 <script> export default {// 可以在created、beforeMount或mounted生命…...
VuePress-theme-hope 搭建个人博客 2【快速上手】 —— 安装、部署 防止踩坑篇
续👆VuePress、VuePress-theme-hope 搭建个人博客 1【快速上手】 项目常用命令 vuepress dev [dir] 会启动一个开发服务器,以便让你在本地开发你的 VuePress 站点。vuepress build [dir] 会将你的 VuePress 站点构建成静态文件,以便你进行后…...
ClickHouse基础知识(四):ClickHouse 引擎详解
1. 表引擎的使用 表引擎是 ClickHouse 的一大特色。可以说, 表引擎决定了如何存储表的数据。包括: ➢ 数据的存储方式和位置,写到哪里以及从哪里读取数据。 默认存放在/var/lib/clickhouse/data ➢ 支持哪些查询以及如何支持。 ➢ 并发数…...
关于设计模式、Java基础面试题
前言 之前为了准备面试,收集整理了一些面试题。 本篇文章更新时间2023年12月27日。 最新的内容可以看我的原文:https://www.yuque.com/wfzx/ninzck/cbf0cxkrr6s1kniv 设计模式 单例共有几种写法? 细分起来就有9种:懒汉&#x…...
Python爱心光波完整代码
文章目录 环境需求完整代码详细分析环境需求 python3.11.4PyCharm Community Edition 2023.2.5pyinstaller6.2.0(可选,这个库用于打包,使程序没有python环境也可以运行,如果想发给好朋友的话需要这个库哦~)【注】 python环境搭建请见:https://want595.blog.csdn.net/arti…...
PowerShell Instal 一键部署gitea
gitea 前言 Gitea 是一个轻量级的 DevOps 平台软件。从开发计划到产品成型的整个软件生命周期,他都能够高效而轻松的帮助团队和开发者。包括 Git 托管、代码审查、团队协作、软件包注册和 CI/CD。它与 GitHub、Bitbucket 和 GitLab 等比较类似。 Gitea 最初是从 Gogs 分支而来…...
C语言——指针题目“指针探测器“
如果你觉得你指针学的自我感觉良好,甚至已经到达了炉火纯青的地步,不妨来试试这道题目? #include<stdio.h> int main() {char* c[] { "ENTER","NEW","POINT","FIRST" };char** cp[] { c 3…...
Hive讲课笔记:内部表与外部表
文章目录 一、导言二、内部表1.1 什么是内部表1.1.1 内部表的定义1.1.2 内部表的关键特性 1.2 创建与操作内部表1.2.1 创建并查看数据库1.2.2 在park数据库里创建student表1.2.3 在student表插入一条记录1.2.4 通过HDFS WebUI查看数据库与表 三、外部表2.1 什么是外部表2.2 创建…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
