eventpoi java百万级以上excel导入导出

开源地址

GitHub - beijing-penguin/eventpoi: 事件流poi处理工具

<dependency>
    <groupId>io.github.beijing-penguin</groupId>
    <artifactId>eventpoi</artifactId>
    <version>0.0.8</version>
</dependency>

知乎文案链接

eventpoi java百万级以上excel导入导出 - 知乎

优点

  • 支持 【功能】 【读取excel/导入】excel文件高性能读取 并自动转java对象,只需一行代码
  • 支持 【功能】 支持导出表格形式的excel文件,和列表excel文件
  • 支持 【功能】 【图片导入】支持图片列和文本混合列形式的excel导入
  • 支持 【功能】 【行回调异步处理】边读边处理,无须等待excel全部解析。
  • 支持 【功能】 自动识别xls文件和xlsx文件格式
  • 支持 【功能】 自动识别date列时间格式,无需像别的工具那样,时间字段上设置yyyyMMdd格式
  • 支持 【功能】 复杂的表格导出,既包含【列表形式】的数据 也包含【表单形式】的数据导出(查看 "测试包含表格和列表数据的复杂导出.java" 文件)
  • 支持 【特性】 使用事件驱动方式读取excel,无行数和内存限制。
  • 支持 【特性】 高性能SXSSFWorkbook导出大文件,默认也是使用SXSSFWorkbook导出(导出20w行数据,仅需要3s)

对比阿里的EasyExcel,本开源工具具有如下优势(前两点是本开源的主要优势)

  • 支持复杂结构的、可带图片的excel文件导出
  • 支持复杂excel结构的图片导入
  • 支持较新的poi版本,目前支持到了4.1.2
  • 性能对比持平(100w导出,普通机器测试,耗时仅需十几秒。cpu好点的服务器,可能只有8~9秒)
  • 操作更加简单,无需build构造实体,仅需一行代码调用静态方法

使用案例均能在开源代码的src/test/java目录下,直接main方法运行,使用中,如果遇到模板文件读取不到的FileNotFoundException情况,可能是因为不同IDE编译器编译路径文件不同导致,请自行调整代码(使用绝对磁盘路径如E:\\xx\\xx\\xx\\template.xlsx),保证能正确读到template.xlsx文件即可。

使用方法

新建一个需要导出的模板文件,如下

preview

调用代码,使用一行代码读取excel(方法参数上需要传入上面定义好的模板文件),如下

package com.dc.eventpoi.test;

import java.util.List;

import com.alibaba.fastjson.JSON;
import com.dc.eventpoi.ExcelHelper;

public class 使用一行代码读取excel {
    public static void main(String[] args) throws Exception {
        List<Person> objList = ExcelHelper.parseExcelToObject(Test1.class.getResourceAsStream("demo1.xlsx"), Test1.class.getResourceAsStream("demo1Templete.xlsx"), Person.class);
        System.err.println(JSON.toJSONString(objList,true));
    }
}

同样的方式,传入模板文件以及自己的业务数据,使用一行代码导出excel,如下

package com.dc.eventpoi.test;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import com.dc.eventpoi.ExcelHelper;
import com.dc.eventpoi.core.PoiUtils;

public class 使用一行代码导出excel {
    public static void main(String[] args) throws Exception {
        List<Person> personList = new ArrayList<Person>();
        //构造导出时的数据
        for (int i = 0; i < 2000; i++) {
            
            Person p1 = new Person();
            p1.setNo("NO_"+i);
            p1.setAge(11);
            p1.setName("ssssss_"+i);
            p1.setRemark("测试测试啊remar_"+i);
            personList.add(p1);
        }
        
        //模拟一些需要删除某些列 的业务场景
        byte[] newTempFile = PoiUtils.deleteCol(Test1.class.getResourceAsStream("demo1Templete.xlsx"), "${salary}");
        long t1 = System.currentTimeMillis();
        byte[] exportByteData = ExcelHelper.exportExcel(newTempFile, personList,0);
        System.out.println("cost="+(System.currentTimeMillis()-t1));
        //支持设置单元格样式噢!!!^_^
        //        byte[] exportByteData = ExcelHelper.exportExcel(Test1.class.getResourceAsStream("demo1Templete.xlsx"), personList,new CallBackCellStyle() {
        //            @Override
        //            public void callBack(CellStyle cellStyle) {
        //              cellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        //              cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 上下居中
        //              cellStyle.setBorderTop(BorderStyle.THIN);
        //              cellStyle.setBorderBottom(BorderStyle.THIN);
        //              cellStyle.setBorderLeft(BorderStyle.THIN);
        //              cellStyle.setBorderRight(BorderStyle.THIN);
        //            }
        //        }, "${salary}");
        Files.write(Paths.get("./my_test_temp/测试导出指定对象并删除指定列.xlsx"), exportByteData);
    }
}

下面看下比较复杂的excel结构的导出

模板文件,分2个区域,一个是列表数据区域,一个是表格数据区域,如下

preview

下面的代码中,OrderInfo代表了占位符的表格数据区域,而List<ProductInfo>则代表了excel中列表形式的数据区域,那么代码如下:

package com.dc.eventpoi.test;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import com.dc.eventpoi.ExcelHelper;

public class 测试包含表格和列表数据的复杂导出 {
    public static void main(String[] args) throws Exception {
    	//列表或 表格的数据的集合
        List<Object>  excelDataList = new ArrayList<Object>();
        
    	//构造表格形式的数据
    	OrderInfo orderInfo = new OrderInfo();
    	orderInfo.setKehu("ddddcccc");
    	orderInfo.setOrderName("进口海鲜");
    	orderInfo.setTotalMoney("15.66");
    	orderInfo.setBuyer("张三");
    	orderInfo.setSaller("李四");
    	//添加表格数据 到大集合当中
    	excelDataList.add(orderInfo);
    	
    	
        List<ProductInfo> productList = new ArrayList<ProductInfo>();
        //构造导出时的数据
        for (int i = 0; i < 20; i++) {
            
        	ProductInfo p1 = new ProductInfo();
            p1.setNo("NO_"+i);
            p1.setName("ssssss_"+i);
            String img_file_path = new File(Test1.class.getResource("unnamed.jpg").getPath()).getAbsolutePath();
            p1.setHeadImage(Files.readAllBytes(Paths.get(img_file_path)));
            p1.setCaigouNum(i+10);
            productList.add(p1);
        }
        //添加列表数据到大集合当中
        excelDataList.add(productList);

        //第三个参数表示,导出时,删除那些列(按模板文件中的key删除,可不传)
        byte[] exportByteData = ExcelHelper.exportExcel(Test1.class.getResourceAsStream("订单_templete.xlsx"), excelDataList,0);
        Files.write(Paths.get("./my_test_temp/测试包含表格和列表数据的复杂导出.xlsx"), exportByteData);
    }
}

更复杂excel导出,如下面,需要动态合并单元格

package com.dc.eventpoi.test;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFSheet;

import com.dc.eventpoi.ExcelHelper;
import com.dc.eventpoi.core.inter.CellStyleCallBack;
import com.dc.eventpoi.core.inter.SheetCallBack;

public class 测试包含表格和列表数据的复杂导出2 {
    public static void main(String[] args) throws Exception {
    	//构造表格形式的数据
    	OrderInfo orderInfo = new OrderInfo();
    	orderInfo.setKehu("ddddcccc");
    	orderInfo.setOrderName("进口海鲜");
    	orderInfo.setTotalMoney("15.66");
    	orderInfo.setBuyer("张三");
    	orderInfo.setSaller("李四");
    	
    	//构造列表形式的数据
        List<Object>  excelDataList = new ArrayList<Object>();
        List<ProductInfo> productList = new ArrayList<ProductInfo>();
        ProductInfo p1 = new ProductInfo();
        p1.setNo("NO_1");
        p1.setName("ssssss111");
        //这是图片项
        String img_file_path = new File(Test1.class.getResource("unnamed.jpg").getPath()).getAbsolutePath();
        p1.setHeadImage(Files.readAllBytes(Paths.get(img_file_path)));
        
        ProductInfo p2 = new ProductInfo();
        p2.setNo("NO_2");
        p2.setName("ssssss222");
        
        ProductInfo p3 = new ProductInfo();
        p3.setNo("NO_3");
        p3.setName("ssssss333");
        
        productList.add(p1);
        productList.add(p2);
        productList.add(p3);
        
        excelDataList.add(productList);
        excelDataList.add(orderInfo);

        //导出
        byte[] exportByteData = ExcelHelper.exportExcel(Test1.class.getResourceAsStream("订单_templete.xlsx"), excelDataList,new SheetCallBack() {
            
            @Override
            public void callBack(SXSSFSheet sxssSheet) {
                CellRangeAddress mergedRegionAt = new CellRangeAddress(7, 8, 0, 0);
                sxssSheet.addMergedRegionUnsafe(mergedRegionAt);
            }
        },new CellStyleCallBack() {

            @Override
            public void callBack(SXSSFSheet sxssSheet, SXSSFCell curCell, CellStyle curCellStyle) {
                System.err.println(curCell.getRowIndex());
                if(curCell.getRowIndex()%2==0) {
                    curCellStyle.setFillForegroundColor(IndexedColors.AQUA.getIndex());
                    curCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                }else {
                    curCellStyle.setFillForegroundColor(IndexedColors.DARK_YELLOW.getIndex());
                    curCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                }
            }
            
        });
        Files.write(Paths.get("./my_test_temp/测试包含表格和列表数据的复杂导出2.xlsx"), exportByteData);
    }
}

导出效果图如下(第8行和第9行的第一列已经合并,也设置上了背景颜色)

preview

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值