SpingBoot整合jxls2.0-excel导出—— 列表循环,自定义方法,超链接等
Java中实现excel导出数据的方法有很多,一般简单的可以通过操作POI进行,但是复杂的excel格式导出如果用POI就显得非常麻烦,本文介绍的jxls2.0完全依据模板进行导出,只需要进行简单的配置加数据,即可导出人工处理级别的复杂excel格式,因此写下几个系列教程供大家参考。
普通循环列表导出是一个非常简单的需求,实现它的方式有两种Api
方式一:jxls-core依赖(功能较弱,不推荐)
<dependency>
<groupId>net.sf.jxls</groupId>
<artifactId>jxls-core</artifactId>
<version>1.0.5</version>
</dependency>
另外需要注意一点:很多同学在做模板类型数据导出的时候,频繁遇到导出后文件格式打不开的情况,这个时候最有可能导致的错误不是代码有问题,而是因为模板文件被编译成了二进制文件,因此对于这一点需要特别处理,现在大多都是用Maven作为管理工具,对于Maven需要特别的配置如下:
<build>
<plugins>
<!-- 对xls模板打包但不编译 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>xls</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
</plugins>
</build>
是否是这个错误也很好检查,办法如下:
手动打开target包下对应的模板文件,看是否会报格式错误,自然就会明白问题到底出在哪一步了
具体实现代码非常简单,就直接贴出来了:
/***
* 数据导出
* @param request
* @param model
* @return
*/
@RequestMapping(value = "/monitoring/exportExcel")
public void exportExcel(HttpServletRequest request, HttpServletResponse response, HttpSession session, Model model) throws Exception {
// List集合 此处省略
List<Test> test = new ArrayList<>();
// 加入到模板集合中
Map<String, Object> datamap = new HashMap<>();
datamap.put("test", test);
try {
// 获取模板绝对路径
String path = session.getServletContext().getRealPath("");
// 模板文件路径
String srcPath = path + "/" + Config.MONITOR_EXPORT_TEMPLATE;
// 设置jxls内置
Configuration config = new Configuration();
config.setMetaInfoToken("\\\\");
XLSTransformer transformer = new XLSTransformer(config);
// 取得文件名。
String fileName = DateUtils.getTime3(endtime) + ".xls";
response.reset();
response.setHeader("Accept-Ranges", "bytes");
/* 解决各浏览器的中文乱码问题 */
String userAgent = request.getHeader("User-Agent");
// fileName.getBytes("UTF-8")处理safari的乱码问题
byte[] bytes = userAgent.contains("MSIE") ? fileName.getBytes() : fileName.getBytes("UTF-8");
// 各浏览器基本都支持ISO编码
fileName = new String(bytes, "ISO-8859-1");
response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName));
response.setContentType("application/octet-stream;charset=UTF-8");
// 利用poi完善excel中未填充的数据
HSSFWorkbook workBook = null;
InputStream ins = null;
OutputStream out = null;
try {
ins = new BufferedInputStream(new FileInputStream(srcPath));
workBook = (HSSFWorkbook) transformer.transformXLS(ins, datamap);
out = response.getOutputStream();
// 将内容写入输出流并把缓存的内容全部发出去
workBook.write(out);
out.flush();
} catch (Exception e) { } finally {
try {
if (ins != null) {
ins.close();
}
if (out != null) {
out.close();
}
} catch (Exception e) {}
}
} catch(Exception e) {}
}
对应的模板如下:
注意:代码中集合避免暴露过多信息因此是随意写的,读者真正使用时注意替换参数即可,模板语法类似jstl
方式二:jxls,jxls-poi依赖
同样需要注意模板文件地址被编译成二进制的问题,此方案就是我应用于SpringBoot的方案,且此方案的拓展性非常强
核心依赖:
<!-- 用以下版本jxls-api 功能更加强大,解决超链接等特殊需求 -->
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-poi</artifactId>
<version>1.0.15</version>
<exclusions><!-- 去掉默认日志打印 -->
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls</artifactId>
<version>2.4.6</version>
<exclusions><!-- 去掉默认日志打印 -->
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
</exclusions>
</dependency>
注意由于该api自身有日志输出相关的依赖,和我项目本身冲突了,所以我禁用了其日志相关的配置,如果和读者不冲突的话,可以开启,这个点影响不大
核心方法如下:
此处我采用的功能有:循环列表,自定义方法(数值转换),超链接等等
package cn.testin.monitorproxy.util;
import cn.testin.common.util.log.Logit;
import cn.testin.monitorproxy.pojo.enums.AlarmStatusEnum;
import cn.testin.monitorproxy.pojo.enums.MonitorTypeEnum;
import org.jxls.area.Area;
import org.jxls.builder.AreaBuilder;
import org.jxls.builder.xls.XlsCommentAreaBuilder;
import org.jxls.common.CellRef;
import org.jxls.common.Context;
import org.jxls.expression.JexlExpressionEvaluator;
import org.jxls.transform.Transformer;
import org.jxls.transform.poi.WritableCellValue;
import org.jxls.transform.poi.WritableHyperlink;
import org.jxls.util.TransformerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* ******************************
* Author: 柯贤铭
* CreateTime: 2019/2/15 14:52
* Description: excel导出工具类
* Version: V1.0
* ******************************
*/
public class ExcelUtils {
/***
* excel导出公共方法
* @param fileName 导出文件名
* @param templateFile 模板文件地址
* @param list 数据集合
* @param response response
* @param request request
*/
public static void exportExcel(String fileName, InputStream templateFile, List<?> list,
HttpServletResponse response, HttpServletRequest request) {
response.reset();
response.setHeader("Accept-Ranges", "bytes");
OutputStream os = null;
try {
// 解决各浏览器的中文乱码问题
String userAgent = request.getHeader("User-Agent");
// fileName.getBytes("UTF-8")处理safari的乱码问题
byte[] bytes = userAgent.contains("MSIE") ? fileName.getBytes() : fileName.getBytes("UTF-8");
// 各浏览器基本都支持ISO编码
fileName = new String(bytes, "ISO-8859-1");
response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName));
response.setContentType("application/octet-stream;charset=UTF-8");
Context context = new Context();
//设置参数变量
context.putVar("list", list);
Map<String , Object> myFunction = new HashMap<>();
myFunction.put("my", new ExcelUtils());
os = response.getOutputStream();
// 启动新的jxls-api 加载自定义方法
Transformer trans = TransformerFactory.createTransformer(templateFile, os);
JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) trans.getTransformationConfig().getExpressionEvaluator();
evaluator.getJexlEngine().setFunctions(myFunction);
// 载入模板、处理导出
AreaBuilder areaBuilder = new XlsCommentAreaBuilder(trans);
List<Area> areaList = areaBuilder.build();
areaList.get(0).applyAt(new CellRef("Hello!A1"), context);
trans.write();
} catch (Exception e) {
Logit.errorLog(e.getMessage(), new Throwable(e));
} finally {
try {
if (os != null) {
os.flush();
os.close();
}
if (templateFile != null) {
templateFile.close();
}
} catch (Exception e) {
Logit.errorLog(e.getMessage(), new Throwable(e));
}
}
}
// 格式化时间
public Object formatDate(Long time){
if(time != null){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = sdf.format(time);
return dateStr;
}
return "--";
}
// 时延-处理执行时间 ms -> s 且保留两位
public Object timeChange(Long time){
if(time != null){
DecimalFormat df = new DecimalFormat("0.00");
String result = df.format((double)time / 1000);
return result.equals("0.00") ? "--" : result + "s";
}
return "--";
}
// 超链接方法
public WritableCellValue myLink(String address, String title) {
return new WritableHyperlink(address, title);
}
// 告警类型转换 -> MonitorTypeEnum枚举类
public Object alarmType(Integer type){
if(type != null){
return MonitorTypeEnum.valueOf(type).getLabel();
}
return "--";
}
// 告警状态转换 -> AlarmStatusEnum枚举类
public Object statusType(Integer type){
if(type != null){
return AlarmStatusEnum.valueOf(type).getLabel();
}
return "--";
}
}
模板详情如下:
最终效果:
希望大家可以从我的博客里找到一点关于Excel导出的办法吧~
SpingBoot整合jxls2.0-excel导出—— 列表循环,自定义方法,超链接等的更多相关文章
- js导入excel&导出excel
Excel导入 html代码 <button style={{ color: '#1890ff', fontSize: '14px', cursor: 'pointer' }} onClick= ...
- 并发编程概述 委托(delegate) 事件(event) .net core 2.0 event bus 一个简单的基于内存事件总线实现 .net core 基于NPOI 的excel导出类,支持自定义导出哪些字段 基于Ace Admin 的菜单栏实现 第五节:SignalR大杂烩(与MVC融合、全局的几个配置、跨域的应用、C/S程序充当Client和Server)
并发编程概述 前言 说实话,在我软件开发的头两年几乎不考虑并发编程,请求与响应把业务逻辑尽快完成一个星期的任务能两天完成绝不拖三天(剩下时间各种浪),根本不会考虑性能问题(能接受范围内).但随着工 ...
- TP5.0源生Excel导出
PHPExcel类在TP5里边并不能很好的兼容,使用起来很麻烦. 不像是tp3.2那样直接import()加进来就能new,因为它里边的命名空间找不到.总是说undefined class. 如果是使 ...
- SpringBoot整合easyexcel实现Excel的导入与导出
导出 在一般不管大的或者小的系统中,各家的产品都一样,闲的无聊的时候都喜欢让我们这些程序员导出一些数据出来供他观赏,非说这是必须需求,非做不可,那么我们就只能苦逼的哼哧哼哧的写bug喽. 之前使用PO ...
- C# Excel导出超出65536行报错 Invalid row number (65536) outside allowable range (0..65535)
C# Excel导出超出65536行报错 Invalid row number (65536) outside allowable range (0..65535) 一:报错 Invalid row ...
- excel导出功能优化
先说说优化前,怎么做EXCEL导出功能的: 1. 先定义一个VO类,类中的字段按照EXCEL的顺序定义,并且该类只能用于EXCEL导出使用,不能随便修改. 2. 将查询到的结果集循环写入到这个VO类中 ...
- 记一次针对excel导出的优化
最近发现我们系统导出excel文件时由于是导出百万级数据导出,速度过慢并且内存占用多,故进行了下面的一次优化. 我们使用apache的poi进行excel文件操作 主要耗时: 1.从数据库得到需要导出 ...
- [moka同学笔记]PHPexcel之excel导出和导入
原案例来自http://www.sucaihuo.com/有修改 1.目录结构(文件不用解释,应该都可以看得懂,直接看代码)
- 偷懒小工具 - Excel导出公共类
说明 最近接了一个任务,就是做一个列表的Excel导出功能.并且有很多页面都会使用这个功能. 导出的Excel大体格式如图 很简单的列表,标题加背景色,然后不同类型,显示方式不一样.对齐方式不一样.不 ...
随机推荐
- 使用LaTeX输入矩阵
当前各种文本编辑器支持的LaTeX数学公式库大多基于KaTeX,或者在Web中用MathJax的比较多,下面给出一种在Web中输入矩阵的例子 $$\left[ \begin{array}{cccc}a ...
- WPF入门(1)
开始对WPF动手,从0开始一步一步深入学习 1)参考文档:msdn.<WPF编程宝典:使用C#2012和NET 4.5 第4版> 2)开发工具:Microsoft Visual Studi ...
- 百度文本编辑器的toolbars属性值描述
toolbars: [ [ 'anchor', //锚点 'undo', //撤销 'redo', //重做 'bold', //加粗 ...
- 资料共享-源代码-视频教程-PLC-OpenCV-C++-MFC
资料共享-源代码-视频教程-PLC-OpenCV-C++-MFC 资料共享-源代码-视频教程 资料共享-源代码-视频教程-PLC-OpenCV-C++-MFC
- Azure AD B2C(二)使用Azure AD B2C为ASP.NET Core 应用设置社交帐户(邮箱)登录/注册
一,引言 上次关于Azure AD B2C 讲到一些概念,有介绍到,Azure AD B2C 也是一种身份验证的解决方案,但是它运行客户使用其首选的社交,企业或者本地账户标识对应用程序和API进行单一 ...
- gitbub.com设置协作者提交代码步骤
1. 邀请协作者 点击settings 2. 等待协作者接受邀请 关注注册邮箱 3. 协作者生成公钥 一路回车即可 ssh-keygen -t rsa -b 4096 -C "公众号:九点半 ...
- typora中的图片处理20200622
typora中的图片处理20200622 食用建议 typora作为markdown的书写神器,一般习惯的流程是在typora中写完,然后复制粘贴到博客园中,然而,markdown中图片采用的是本地连 ...
- SSH网上商城一
Java高级项目之SSH网上商城项目实战: 1.采用目前最主流的三大框架开发即Struts2+Spring+Hibernate框架整合开发.2.通过AJAX技术提供良好的用户体验.3.提供了邮箱激活的 ...
- APP测试经验总结
app测试哪几项: 每一款APP上线之前都需要经过严格的测试,测试周期可按项目开发周期来确定测试时间,一般测试时间为两三周(15个工作日),不过这个根据项目实际情况,可能推迟或提前的. ...
- vueX基础知识点笔记
vuex是专门用来管理vue.js应用程序中状态的一个插件.他的作用是将应用中的所有状态都放在一起, 集中式来管理.需要声明的是,这里所说的状态指的是vue组件中data里面的属性.简单的来说, 它就 ...