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.rhkb.cn/news/226530.html

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

相关文章

Unity Shader-真实下雨路面

Unity Shader-真实下雨路面 简介素材1.准备插件Amplify Shader Editor&#xff08;这里我使用的是1.6.4最新版&#xff09;2.贴纸和切图d 一、创建一个Shader Surface&#xff0c;实现气泡播放效果二、叠加一次气泡播放效果&#xff0c;使其看起来更多&#xff0c;更无序三、小…

学生使用什么牌子的护眼灯好?五款优秀台灯分享

在近几年&#xff0c;儿童青少年近视率非常高。很多家长认为孩子近视的原因是没有养成正确的用眼习惯&#xff0c;例如经常趴桌子写作业、眯眼看书等&#xff0c;但实际上这些坏习惯是因为没有合适的光线而导致的。所以安排一盏合适的台灯给孩子学习是非常重要的。 很多家长会选…

GitHub教程-自定义个人页制作

GitHub是全球最大的代码托管平台&#xff0c;除了存放代码&#xff0c;它还允许用户个性化定制自己的主页&#xff0c;展示个人特色、技能和项目。本教程旨在向GitHub用户展示如何制作个性化主页&#xff0c;同时&#xff0c;介绍了GitHub Actions的应用&#xff0c;可以自动化…

Docker 使用详解看了挺开悟的

使用docker ps命令可以查看所有正在运行中的容器列表&#xff0c; 使用docker inspect命令我们可以查看更详细的关于某一个容器的信息。 $ docker inspect 容器id/image[{"Id": "b57ee6bbf1f4f62a5aba6a73acd53b0f9b8ec542e1f9fa9213159ffd3828c7b4",&q…

[Angular] 笔记 8:list/detail 页面以及@Input

1. list 页面 list/detail 是重要的 UI 设计模式。 vscode terminal 运行如下命令生成 detail 组件&#xff1a; PS D:\Angular\my-app> ng generate component pokemon-base/pokemon-detail --modulepokemon-base/pokemon-base.module.ts CREATE src/app/pokemon-base/p…

Mybatis行为配置之Ⅲ—其他行为配置项说明

专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL Mybatis配置入门 Mybatis行为配置之Ⅰ—缓存 Mybatis行为配置…

ChatGPT在地学、GIS、气象、农业、生态、环境等领域中的高级应用

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

华为云服务器yum无更新问题解决

买了一个华为云服务器&#xff0c;系统是银河麒麟v10&#xff0c;cpu选择的事华为的坤鹏。 买了一段时间后&#xff0c;使用yum更新&#xff0c;发现没有任何更新包。 又过了一段时间&#xff0c;还是没有更新包。 通过漏扫设备&#xff0c;发现系统内存在较多存在漏洞的软件…

tsconfig.app.json文件报红:Option ‘importsNotUsedAsValues‘ is deprecated...

在创建vue3 vite ts项目时的 tsconfig.json&#xff08;或者tsconfig.app.json&#xff09; 配置文件经常会报一个这样的错误&#xff1a; 爆红&#xff1a; Option ‘importsNotUsedAsValues’ is deprecated and will stop functioning in TypeScript 5.5. Specify compi…

gin框架使用系列之四——json和protobuf的渲染

系列目录 《gin框架使用系列之一——快速启动和url分组》《gin框架使用系列之二——uri占位符和占位符变量的获取》《gin框架使用系列之三——获取表单数据》 上篇我们介绍了如何获取数据&#xff0c;本篇我们介绍一下如何返回固定格式的数据。 一、返回JSON数据 在web开发中…

大创项目推荐 深度学习OCR中文识别 - opencv python

文章目录 0 前言1 课题背景2 实现效果3 文本区域检测网络-CTPN4 文本识别网络-CRNN5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习OCR中文识别系统 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;…

红队打靶练习:DIGITALWORLD.LOCAL: FALL

目录 信息收集 1、arp 2、netdiscover 3、nmap 4、nikto 5、whatweb 6、小结 目录探测 1、gobuster 2、dirsearch WEB 80端口 /test.php 文件包含漏洞 SSH登录 提权 get root and flag 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interfa…

Qt/C++音视频开发61-多屏渲染/一个解码渲染到多个窗口/画面实时同步

一、前言 多屏渲染就是一个解码线程对应多个渲染界面&#xff0c;通过addrender这种方式添加多个绘制窗体&#xff0c;我们经常可以在展会或者卖电视机的地方可以看到很多电视播放的同一个画面&#xff0c;原理应该类似&#xff0c;一个地方负责打开解码播放&#xff0c;将画面…

Android下载gradle失败解决方法

1、在gradle-wrapper.properties文件中查看自己需要下载gradle什么版本的包和zip路径&#xff08;wrapper/dists&#xff09;。 2、在setting中查看Gradle的保存路径&#xff0c;如下图&#xff1a;C:/Users/Administrator/.gradle&#xff0c;加上第一步的zip路径得到下载grad…

SQL Server 存储过程 触发器 事务处理

CSDN 成就一亿技术人&#xff01; 难度指数&#xff1a;* * CSDN 成就一亿技术人&#xff01; 目录 1. 存储过程的作用 创建存储过程 2. 触发器 触发器的种类 insert触发器 update触发器 delete触发器 测试 3. 事务 开始事务 提交事务 回滚事务 举个实例 在 SQ…

分享好用的chatgpt

1.在vscode中&#xff0c;点击这个&#xff1a; 2.搜索&#xff1a;ChatGPT - 中文版&#xff0c;个人觉得这个更好用&#xff1a; 3.下载完成之后&#xff0c;左侧会多出来这个&#xff1a; 点击这个图标就能进入chatgpt界面了 4.如果想使用tizi访问国外的chatgpt&#xf…

.Net FrameWork总结

.Net FrameWork总结 介绍.Net公共语言运行库CLI的组成.NET Framework的主要组成.NET Framework的优点CLR在运行期管理程序的执行&#xff0c;包括以下内容CLR提供的服务FCL的组成 或 服务&#xff08;这个其实就是我们编码时常用到的类库&#xff09;&#xff1a;&#xff08;下…

使用vue3实现echarts漏斗图表以及实现echarts全屏放大效果

1.首先安装echarts 安装命令&#xff1a;npm install echarts --save 2.页面引入 echarts import * as echarts from echarts; 3.代码 <template> <div id"main" :style"{ width: 400px, height: 500px }"></div> </template> …

认识数据的规范化

关系模型满足的确定约束条件称为范式&#xff0c;根据满足约束条件的级别不同&#xff0c;范式由低到高分为 1NF&#xff08;第一范式&#xff09;、2NF&#xff08;第二范式&#xff09;、3NF&#xff08;第三范式&#xff09;、BCNF&#xff08;BC 范式&#xff09;、4NF&…

Vue使用Element table表格格式化GMT时间为Shanghai时间

Vue使用Element表格格式化GMT时间为Shanghai时间 说明 阿里巴巴java开发规范规定&#xff0c;数据库必备gmt_create、gmt_modified字段&#xff0c;使用的是GMT时间&#xff0c;在中国使用必然要转换我中国时间。 在阿里巴巴的Java开发规范中&#xff0c;要求每个表都必备三…