easyExcel实现分批导入,动态表头分批导出,以及导出表格样式设置

本文主要是介绍easyExcel实现分批导入,动态表头分批导出,以及导出表格样式设置,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.6</version></dependency>

一,分批导入

1.首先配置表格头映射类
@Getter
@Setter
@EqualsAndHashCode
public class IndexOrNameData {/*** 强制读取第三个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配*/@ExcelProperty(index = 2)private Double doubleData;/*** 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据*/@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;
}
2.编写excel数据读监听器
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener implements ReadListener<IndexOrNameData > {/*** 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 100;/*** 缓存的数据*/private List<IndexOrNameData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);/*** 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。*/private DemoDAO demoDAO;public DemoDataListener() {// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数demoDAO = new DemoDAO();}/*** 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来** @param demoDAO*/public DemoDataListener(DemoDAO demoDAO) {this.demoDAO = demoDAO;}/*** 这个每一条数据解析都会来调用** @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}* @param context*/@Overridepublic void invoke(IndexOrNameData  data, AnalysisContext context) {log.info("解析到一条数据:{}", JSON.toJSONString(data));cachedDataList.add(data);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (cachedDataList.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listcachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}/*** 所有数据解析完成了 都会来调用** @param context*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();log.info("所有数据解析完成!");}/*** 加上存储数据库*/private void saveData() {log.info("{}条数据,开始存储数据库!", cachedDataList.size());demoDAO.save(cachedDataList);log.info("存储数据库成功!");}
}

分批插入的实现是在invoke方法中,当读取缓存数达到我们预期的插入数量时就进行插入,然后重新更新list,原本的list就会被回收,达到方式内存溢出的效果,可以在这个方法中进行行参数校验,有异常抛出即可

3.编写读入方法
 // 写法1:fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭EasyExcel.read(fileName, IndexOrNameData.class, new DemoDataListener()).sheet().doRead();// 写法2fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";// 一个文件一个readertry (ExcelReader excelReader = EasyExcel.read(fileName, IndexOrNameData.class, new DemoDataListener()).build()) {// 构建一个sheet 这里可以指定名字或者noReadSheet readSheet = EasyExcel.readSheet(0).build();// 读取一个sheetexcelReader.read(readSheet);}

二,动态表头分批导出

1.构建表头和数据
//获取表头    
private static List<String> makeHeads() {List<String> heads = new ArrayList<>(); //表头信息heads.add("唯一标识");heads.add("名称");heads.add("类型");return heads;}//获取数据private static List<Map<String, Object>> makeData() {List<Map<String, Object>> list = new ArrayList<>();//Map<String,Object> test1 = new LinkedHashMap<>(); //手动添加测试数据(可根据需要从数据库查询)test1.put("id", 1);test1.put("name", 2);test1.put("str", 3);list.add(test1);//Map<String,Object> test2 = new LinkedHashMap<>();test2.put("id", 11);test2.put("name", 22);test2.put("str", 33);list.add(test2);return list;}
2.写出代码
    public void exportExcel(HttpServletResponse httpServletResponse,@RequestParam(required = false) String fileName,@RequestParam(required = false) List<String> heads, @RequestParam(required = false) List<Map<String, Object>> list) throws IOException {if (StringUtils.isEmpty(fileName)){ //文件名称也可以动态获取fileName = System.currentTimeMillis() + ".xlsx";} else {fileName = fileName + ".xlsx";}if(heads == null || heads.size() == 0){heads = makeHeads();}if(list == null || list.size() == 0){list = makeData();}OutputStream os= responseInfo(httpServletResponse, fileName); // 调用responseInfo方法List<List<String>> hs = new ArrayList<>();for (String s : heads) {hs.add(Arrays.asList(s));}List<List<Object>> list2 = new ArrayList<>();for (int i = 0; i < list.size(); i++) {List<Object> objects = new ArrayList<>();Collection<Object> values = list.get(i).values();for (Object value : values) {objects.add(value.toString());}list2.add(objects);}// 头的策略WriteCellStyle headWriteCellStyle = new WriteCellStyle();// 背景设置为红色headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());WriteFont headWriteFont = new WriteFont();headWriteFont.setFontHeightInPoints((short)20);headWriteCellStyle.setWriteFont(headWriteFont);// 内容的策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);// 背景绿色contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());WriteFont contentWriteFont = new WriteFont();// 字体大小contentWriteFont.setFontHeightInPoints((short)20);contentWriteCellStyle.setWriteFont(contentWriteFont);// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现HorizontalCellStyleStrategy horizontalCellStyleStrategy =new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);//创建一个行高设置处理器,我这里直接用匿名内部类类了AbstractRowHeightStyleStrategy abstractRowHeightStyleStrategy = new AbstractRowHeightStyleStrategy() {@Overrideprotected void setHeadColumnHeight(Row row, int relativeRowIndex) {if (relativeRowIndex==0){row.setHeightInPoints(50);}else {row.setHeightInPoints(10);}}@Overrideprotected void setContentColumnHeight(Row row, int relativeRowIndex) {//默认主体的高度row.setHeightInPoints(10);}};//创建列宽设置处理器AbstractHeadColumnWidthStyleStrategy abstractHeadColumnWidthStyleStrategy = new AbstractHeadColumnWidthStyleStrategy() {@Overrideprotected Integer columnWidth(Head head, Integer columnIndex) {switch (columnIndex) {case 0:return 6;case 1:return 20;case 2:return 20;default:return 13;}}};WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();//开始写出ExcelWriter build = EasyExcel.write(os).head(hs)//注册内容以及表头处理器.registerWriteHandler(new HorizontalCellStyleStrategy(headWriteCellStyle ,contentWriteCellStyle))//注册行高处理器.registerWriteHandler(abstractRowHeightStyleStrategy)//注册列宽处理器.registerWriteHandler(abstractHeadColumnWidthStyleStrategy).build();//然后就可以用上边的buid对象往指定的sheet中写入数据了,当数据量大的时候,我们就可以分批写入,伪代码如下for(a a:list){build.write(list2,writeSheet);}}/*** 功能:公用方法,写回浏览器* [response, fileName]* @return {@link OutputStream}* @throws*/public static OutputStream responseInfo(HttpServletResponse response, String fileName) throws IOException {// 这里注意有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postmanresponse.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment; filename*=utf-8''" + fileName);OutputStream os=response.getOutputStream();return os;}/*** 如果要兼容swagger用这个,上面的注释掉* 功能:公用方法* 参数:fileName 文件名称, 如:123.xlsxpublic static OutputStream responseInfo(HttpServletResponse response, String fileName) throws IOException {response.setCharacterEncoding("utf-8");response.setContentType("APPLICATION/OCTET-STREAM");response.addHeader("Content-Disposition", "attachment;filename=" + fileName);OutputStream os=response.getOutputStream();return os;}*/

这篇关于easyExcel实现分批导入,动态表头分批导出,以及导出表格样式设置的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/403764

相关文章

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx

Vue ElementUI中Upload组件批量上传的实现代码

《VueElementUI中Upload组件批量上传的实现代码》ElementUI中Upload组件批量上传通过获取upload组件的DOM、文件、上传地址和数据,封装uploadFiles方法,使... ElementUI中Upload组件如何批量上传首先就是upload组件 <el-upl

Docker部署Jenkins持续集成(CI)工具的实现

《Docker部署Jenkins持续集成(CI)工具的实现》Jenkins是一个流行的开源自动化工具,广泛应用于持续集成(CI)和持续交付(CD)的环境中,本文介绍了使用Docker部署Jenkins... 目录前言一、准备工作二、设置变量和目录结构三、配置 docker 权限和网络四、启动 Jenkins

Python3脚本实现Excel与TXT的智能转换

《Python3脚本实现Excel与TXT的智能转换》在数据处理的日常工作中,我们经常需要将Excel中的结构化数据转换为其他格式,本文将使用Python3实现Excel与TXT的智能转换,需要的可以... 目录场景应用:为什么需要这种转换技术解析:代码实现详解核心代码展示改进点说明实战演练:从Excel到

如何使用CSS3实现波浪式图片墙

《如何使用CSS3实现波浪式图片墙》:本文主要介绍了如何使用CSS3的transform属性和动画技巧实现波浪式图片墙,通过设置图片的垂直偏移量,并使用动画使其周期性地改变位置,可以创建出动态且具有波浪效果的图片墙,同时,还强调了响应式设计的重要性,以确保图片墙在不同设备上都能良好显示,详细内容请阅读本文,希望能对你有所帮助...

HTML5中下拉框<select>标签的属性和样式详解

《HTML5中下拉框<select>标签的属性和样式详解》在HTML5中,下拉框(select标签)作为表单的重要组成部分,为用户提供了一个从预定义选项中选择值的方式,本文将深入探讨select标签的... 在html5中,下拉框(<select>标签)作为表单的重要组成部分,为用户提供了一个从预定义选项中

C# string转unicode字符的实现

《C#string转unicode字符的实现》本文主要介绍了C#string转unicode字符的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录1. 获取字符串中每个字符的 Unicode 值示例代码:输出:2. 将 Unicode 值格式化

python安装whl包并解决依赖关系的实现

《python安装whl包并解决依赖关系的实现》本文主要介绍了python安装whl包并解决依赖关系的实现,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录一、什么是whl文件?二、我们为什么需要使用whl文件来安装python库?三、我们应该去哪儿下

Python脚本实现图片文件批量命名

《Python脚本实现图片文件批量命名》这篇文章主要为大家详细介绍了一个用python第三方库pillow写的批量处理图片命名的脚本,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言源码批量处理图片尺寸脚本源码GUI界面源码打包成.exe可执行文件前言本文介绍一个用python第三方库pi

前端 CSS 动态设置样式::class、:style 等技巧(推荐)

《前端CSS动态设置样式::class、:style等技巧(推荐)》:本文主要介绍了Vue.js中动态绑定类名和内联样式的两种方法:对象语法和数组语法,通过对象语法,可以根据条件动态切换类名或样式;通过数组语法,可以同时绑定多个类名或样式,此外,还可以结合计算属性来生成复杂的类名或样式对象,详细内容请阅读本文,希望能对你有所帮助...