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数据效果如图

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

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

相关文章

西部市场的无限潜力与成都的崛起“2024成都电子信息展会”

随着科技的飞速发展&#xff0c;电子信息产业已成为全球经济增长的重要引擎。作为中国西部的重要城市&#xff0c;成都正迅速崛起为电子信息产业的聚集地。2024成都电子信息博览会将于7月份在成都世纪城新国际会展中心隆重召开&#xff0c;此次盛会将汇集来自世界各地的业界精英…

第三方软件测试公司有哪些服务形式?如何收费?

由于软件企业的增多&#xff0c;企业更加注重软件开发&#xff0c;因此会将软件测试工作交由第三方软件测试公司进行。第三方软件测试公司也就是专门做软件测评的外包公司&#xff0c;主要是发现软件漏洞和缺陷以便公正、客观评估软件质量&#xff0c;再出具一份软件测试报告。…

mac安装k8s环境

安装kubectl brew install kubectl 确认一下安装的版本 kubectl version --client 如果想在本地运行kubernetes 需要安装minikube brew install minikube 需要注意安装minikube需要本地的docker服务是启动的 启动 默认连接的是google的仓库 minikube start 指定阿…

Flink实时电商数仓之DWS层

需求分析 关键词 统计关键词出现的频率 IK分词 进行分词需要引入IK分词器&#xff0c;使用它时需要引入相关的依赖。它能够将搜索的关键字按照日常的使用习惯进行拆分。比如将苹果iphone 手机&#xff0c;拆分为苹果&#xff0c;iphone, 手机。 <dependency><grou…

MIT线性代数笔记-第31讲-线性变换及对应矩阵

目录 31.线性变换及对应矩阵打赏 31.线性变换及对应矩阵 线性变换相当于是矩阵的抽象表示&#xff0c;每个线性变换都对应着一个矩阵 例&#xff1a; 考虑一个变换 T T T&#xff0c;使得平面上的一个向量投影为平面上的另一个向量&#xff0c;即 T : R 2 → R 2 T:R^2 \to R…

用ChatGPT挑选钻石!著名珠宝商推出-珠宝GPT

根据Salesforce最新发布的第五版《互联网购物报告》显示&#xff0c;ChatGPT等生成式AI的出现、快速发展&#xff0c;对零售行业和购物者产生了较大影响。可有效简化业务流程实现降本增效&#xff0c;并改善购物体验。 著名珠宝商James Allen为了积极拥抱生成式AI全面提升销售…

软件测试/测试开发丨Python闭包函数和计时器学习笔记

闭包函数 闭包的内部函数中&#xff0c;对外部作用域的变量进行引用闭包无法修改外部函数的局部变量闭包可以保存当前的运行环境 # 普通方法实现 def output_student(name, gender, grade1):print(F"新学期开学啦&#xff0c;学生{name}是{gender}&#xff0c;他是{grad…

AI时代下,如何看待“算法利维坦”?

ChatGPT的浪潮从2022年袭来后&#xff0c;至今热度不减&#xff0c;呈现出蓬勃发展的趋势。AI家居、医疗、教育、金融、公益、农业、艺术......AI真的已经走进了生活的方方面面&#xff0c;我们仿佛已经进入了AI时代&#xff0c;势不可挡。人工智能水平如此之高&#xff0c;不禁…

OpenCV-Python(21):OpenCV中的轮廓性质

3.轮廓的性质 本文我们将主要学习基于轮廓来提取一些经常使用的对象特征。 3.1 长宽比 边界矩形的宽高比&#xff1a; x,y,w,h cv2.boundingRect(cnt) aspect_ratio float(w)/h 3.2 Extent 轮廓面积与边界矩形面积的比。 area cv2.contourArea(cnt) x,y,w,h cv2.bounding…

王道考研计算机网络——应用层

如何为用户提供服务&#xff1f; CS/P2P 提高域名解析的速度&#xff1a;local name server高速缓存&#xff1a;直接地址映射/低级的域名服务器的地址 本机也有告诉缓存&#xff1a;本机开机的时候从本地域名服务器当中下载域名和地址的对应数据库&#xff0c;放到本地的高…

C语言实现RSA算法加解密

使用c语言实现了RSA加解密算法&#xff0c;可以加解密文件和字符串。 rsa算法原理 选择两个大素数p和q&#xff1b;计算n p * q;计算φ(n)(p-1)(q-1)&#xff1b;选择与φ(n)互素的整数d&#xff1b;由de1 mod φ(n)计算得到e&#xff1b;公钥是(e, n), 私钥是(d, n);假设明…

Microsoft .NET Framework 4.5.1 离线安装包

Microsoft .NET Framework 4.5.1 安装包&#xff1a; 一、离线安装包&#xff1a; 百度网盘 链接: https://pan.baidu.com/s/1IGEYT1vyruY6KFu6XEmerA 提取码: m6ix 离线安装包官方地址&#xff1a; https://www.microsoft.com/zh-cn/download/details.aspx?id40779 二、在…

如何在VSCode搭建ESP-IDF开发ESP32

文章目录 概要安装VScode安装ESP-IDF插件使用官方例程小结 概要 ESP-IDF(Espressif IoT Development Framework) 即乐鑫物联网开发框架&#xff0c;它基于 C/C 语言提供了一个自给自足的 SDK&#xff0c;可为在 Windows、Linux 和 macOS 系统平台上开发 ESP32 应用程序提供工具…

跳跃表原理及实现

一、跳表数据结构 跳表是有序表的一种&#xff0c;其底层是通过链表实现的。链表的特点是插入删除效率高&#xff0c;但是查找节点效率很低&#xff0c;最坏的时间复杂度是O(N)&#xff0c;那么跳表就是解决这一痛点而生的。 为了提高查询效率&#xff0c;我们可以给链表加上索…

天翼云云间高速实现租户跨地域内网互通

一、业务需求 用户业务在襄阳、武汉两个云池部署&#xff0c;希望通过云间高速产品将两个资源池云内资源通过云内专网实现内网互通。要求内网双向互通。 二、测试环境配置 云池vpc名称vpc网段子网内网ip/gweip主机名互联网带宽襄阳ceshi192.168.0.0/16192.168.1.0/24192.168.…

unity学习笔记----游戏练习02

一、阳光值的展示和消耗 1.创建一个文本组件用于显示阳光的数值&#xff0c;然后在脚本中得到这个UI。 在SunManger中得到这个组件的引用 public TextMeshProUGUI sunPointText; 写一个用于更新显示的方法 public void UpdataSunPointText() { sunPointText.tex…

FileZilla的使用主动模式与被动模式

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《产品经理如何画泳道图&流程图》 ⛺️ 越努力 &#xff0c;越幸运 目录 一、FileZilla简介 1、FileZilla是什么&#xff1f; 2、FileZilla的应用场景 二、FileZilla的安装 1、下…

JVM篇:JVM内存结构

程序计数器 程序计数器英文名叫&#xff1a;Program Counter Register 作用&#xff1a;用来记录下一条jvm指令的地址行号。 先来查看一段jvm指令&#xff0c;这些指令对应的java代码就是输出1-5 操作系统运行该Java程序时具体流程如下 语言解释&#xff1a;源文件通过编译转…

光伏逆变器MPPT的作用、原理及算法

MPPT是逆变器非常核心的技术&#xff0c;MPPT电压在进行光伏电站设计时一项非常关键的参数。 一、什么是MPPT&#xff1f; &#xff08;单块光伏组件的I-V、P-V曲线&#xff09; 上图中&#xff0c;光伏组件的输出电压和电流遵循I-V曲线(绿色)、P-V曲线(蓝色)&#xff0c;如果…

NVMe over Fabrics:概念、应用和实现

对于大部分人来说&#xff0c;NVMe over Fabrics&#xff08;简称NVMf&#xff09;还是个新东西&#xff0c;因为其第一个正式版本的协议在今年6月份才发布。但是这并不影响人们对NVMf的关注&#xff0c;因为这项依托于NVMe的技术很可能继续改变存储市场格局。 NVMf的贡献在于…