技术标签: spring java 流处理 Excel文件导出 后端
新人博主,随笔记录。主要还是通过自己日常工作积累,系统整理一些技术。希望能够节省更多人的时间,走出自己的路。
看了自己发的文章,可以帮助一些小伙伴很开心!!
上一篇文章主要用我个人觉得,效果很好的方法做excel的导出。但是那只是符合正常,简单的excel导出。可能很多小伙伴,会遇到一些复杂的样式的excel的导出。这一篇同样是用EasyExcel,主要是做一些数据格式复杂的excel,当然这一篇文章不包含复杂表头的excel导出
这一篇的环境和上一篇我们共用一个。因为都是用EasyExcel这个包中的API,所以没必要换一个工程。还不明白的小伙伴可以去瞟一眼我的上一篇文章Java从零开始实现导出excel(一)
这里同样用的是上一篇的实体。不过有点改变,我将性别这一列放开了。
这里有个需要注意的地方,因为EasyExcel是通过实体中@ExcelProperty注解中的index去匹配excel中的列,所以当我们不使用模板时,index一定要是连续且有效的,否则我们生成的excel中会出现空白表头列的情况
例如:下面这图是我没有放开性别那个字段时导出的excel表头
导出方法:
/**
* 使用EasyExcel导出excel
* @param response
* @throws Exception
*/
@GetMapping(value = "/exportExcel")
public void exportExcel(HttpServletResponse response) throws Exception {
response.setContentType("multipart/form-data");
response.setCharacterEncoding("utf-8");
response.setContentType("application/octet-stream;charset=utf-8");
LocalDate time = LocalDate.now();
String fileName = URLDecoder.decode("easyExcel导出_" + time, "UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("gb2312"), "ISO8859-1") + ".xls" + "\"");
OutputStream out = response.getOutputStream();
List<Student> data = getData();
Map<Integer,String[]> map = new HashMap<>();
map.put(2,new String[]{
"男","女"});//下拉导出
ExcelUtil.exportBySelect(out,data,map);
out.close();
}
//封装导出数据
private List<Student> getData() {
List<Student> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Student student = new Student();
student.setName("测试学生姓名-" + i);
student.setAge(i);
student.setSex(i % 2 == 1 ? "男" : "女");
student.setNum(111111L);
student.setAddress("追晨始梦程序员宅基地");
list.add(student);
}
return list;
}
工具类:
ExcelUtil
/**
* 功能描述: 导出数据到Excel
* <p>
* 使用阿里easyPoi 自定义导出excel携带下拉框
*
* @param out 输出
* @param list 需写入的数据
* @param mapDropDown 下拉框数据
*/
public static void exportBySelect(OutputStream out, List<? extends BaseRowModel> list, Map<Integer, String[]> mapDropDown) {
EasyExcelFactory.write(out, list.get(0).getClass()).registerWriteHandler(new EasyExcelSheetSelectUtils(mapDropDown)).sheet().doWrite(list);
}
这个公共方法中,我们需要去调用registerWriteHandler方法:将我们创建的自定义拦截器放入其中。
这个拦截器是我们这篇文章的重点——直接代码看
EasyExcelSheetSelectUtils
package com.example.demo;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import java.util.Map;
/**
* 自定义设置excel样式
*/
public class EasyExcelSheetSelectUtils implements SheetWriteHandler {
//第0列开始 设置某列的下拉内容
private Map<Integer,String[]> mapDropDown;
public EasyExcelSheetSelectUtils(Map<Integer, String[]> mapDropDown) {
this.mapDropDown = mapDropDown;
}
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
/**
* 自定义设置excel样式
* @param writeWorkbookHolder
* @param writeSheetHolder
*/
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
//获取sheet页
Sheet sheet = writeSheetHolder.getSheet();
///开始设置下拉框 //设置下拉框
DataValidationHelper helper = sheet.getDataValidationHelper();
for (Map.Entry<Integer, String[]> entry : mapDropDown.entrySet()) {
/***起始行、终止行、起始列、终止列**/
CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, entry.getKey(), entry.getKey());
/***设置下拉框数据**/
DataValidationConstraint constraint = helper.createExplicitListConstraint(entry.getValue());
DataValidation dataValidation = helper.createValidation(constraint, addressList);
/***处理Excel兼容性问题**/
if (dataValidation instanceof XSSFDataValidation) {
dataValidation.setSuppressDropDownArrow(true);
dataValidation.setShowErrorBox(true);
} else {
dataValidation.setSuppressDropDownArrow(false);
}
sheet.addValidationData(dataValidation);
}
//合并单元格
sheet.addMergedRegion(new CellRangeAddress(1, 2, 0, 0));
}
}
这个里面我写了两个常见的案例:
当然了,可能小伙伴们在实际工作中可能有很多不一样的需求,看完我的两个案例的实现,相信你所需要的样式,都可以自己实现。
这个功能可能模板导出时候,会更加方便一点。这里我觉得主要是一个思想
首先我们看实现的过程
我们自定义的拦截器一定要继承SheetWriteHandler这个接口
这个接口中有两个虚函数:
我们这里一般会用到下面那个函数 :afterSheetCreate
我们在自定义的拦截器中定义了一个私有属性mapDropDown,用来装下拉框的参数。用一个有参构造将我们需要的数据传进来
key: 表示第几列需要加入下拉框
value: 表示加入下拉框的值
这里我是只做了个案例,将excel表格中的第一列的第一行和第二行进行合并
有了这个sheet页的对象,那其他自定义功能的效果,小伙伴们可以发挥自己的技术,根据自己的需求完成excel导出!
这篇文章写完,突然想到,其实我们自定义拦截器在模板导出的方法中也是可以用的。我测试了一下。只需要改动调用方法即可:
效果:
原文链接:https://blog.csdn.net/liangzuojiayi/article/details/78183783%matplotlib inline是魔法函数官方给出的定义是:IPython有一组预先定义好的所谓的魔法函数(Magic Functions),你可以通过命令行的语法形式来访问它们。可见“%matplotlib inline”就是模仿命令行来访问magic函数..._matplotlib-inline是单独包吗
创建数组访问数组和数组的长度数组的相关方法创建数组<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>创建数组</title></head><body&..._js创建一个数组,并返回该数组的长度
WordPress 添加title中的logo<!--网页标题左侧显示--><link rel="icon" href="/favicon.png" type="image/x-icon"><!--收藏夹显示图标--><link rel="shortcut icon" href="/favicon.png" t..._wordpress 标题logo
为什么80%的码农都做不了架构师?>>> ...
最常见的就是下载:office deployment tool来解决,这也是官方的办法。_visio we can't install this product can't be installed on the selected updat
(给算法爱好者加星标,修炼编程内功)作者:HankingHuhttps://blog.csdn.net/u013309870/article/details/68941284全排列:从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。例如:1 、2 、3 三个元素的全排列为:{1,2,3},{1,3..._c++全排列 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个
今天坐了一天,把以前的东西整理了一通,简单“装饰”一下,放到网上给大家看:Cross-Browser Rich Text Editor 一个兼容多种浏览器(IE5.5+, Mozilla1.3+)的编辑器 dotnetBB 论坛上使用的编辑器 使用的是 DIV 而非 IFRAME 动网 HTML 编辑器 很老的一个,好像是动网新闻上的? 一个叫 M
一般从医学角度说,阳性(positive),代表有病或者有病毒,阴性(negative),代表正常。假阳性(false positive)是指因为种种原因把不具备阳性症状的人检测出阳性的结果。其实就是将没病的检查成有病的,假阳性检测结果易造成误诊,假阴性(false negative)就是将有病的检查为没病,假阴性结果导致漏诊。 敏感度(sensitivity):又称真阳性率,即患..._真阳性假阳性四格表计算
时间:2019-05-15 03:31:36 作者:adminALU设计 module ALU(ALU_OP,AB_SW,F_LED_SW,LED); input[2:0] ALU_OP,AB_SW,F_LED_SW; output[7:0] LED; reg[7:0] LED; reg[31:0] A,B,F; reg OF,ZF; always@(*) begin时间:2019-05-..._计算机组成原理cpth实验报告
翻译过来是:编译失败,出现2个错误These dependencies were not found没有找到这些依赖项根据下方提示重新下载cli
结构体初始化1、结构体的构造函数中初始化在C++中,结构体与类在使用上已没有本质上的区别了,所以可以使用构造函数来初始化。如下代码所示:struct Stu{int nNum;bool bSex;char szName[20];char szEmail[100];//构造函数初始化Stu(){nNum = 0;bSex = false;memset(szName,0,sizeof(szName))..._c语言结构体初始化赋值
HTTP 客户端是使用get方式提交http请求,来获取数据。该步骤有“一般”、“字段”两个标签页。“一般”标签页配置信息如图1所示。 图1 “一般”标签页配置信息下文详细解释各控件的含义:1、步骤名称:步骤的名称,在单一转换中,名称必须唯一。2、URL:指定请求地址。3、从字段中获取URL:勾选后,第四个控件“URL字...