添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

使用easyExcel,多线程,导出excel,多个sheet页,excel数据和查询时数据顺序一致

阿里easyexcel 插件
easyexcel 项目git地址为:
https://github.com/alibaba/easyexcel
官网地址:https://alibaba-easyexcel.github.io
web下载demo参见: https://blog.csdn.net/weixin_43614067/article/details/116262853

pom.xml

 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>easyexcel</artifactId>
     <version>2.1.6</version>
 </dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.1</version>
</dependency>
<dependency>
    <groupId>org.apache.xmlbeans</groupId>
    <artifactId>xmlbeans</artifactId>
    <version>2.6.0</version>
</dependency>
 <dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi-ooxml</artifactId>
     <version>3.17</version>
 </dependency>
 <dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi-ooxml-schemas</artifactId>
     <version>3.17</version>
 </dependency>
 <dependency>
     <groupId>org.apche.poi</groupId>
     <artifactId>poi</artifactId>
     <version>3.17</version>
 </dependency>
    @Test
    public void simpleWrite() {
        String fileName = "C:\\Users\\Think\\Desktop\\" + "write" + System.currentTimeMillis() + ".xlsx";
        //EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
        ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
        for (int i = 0; i < 10; i++) {
            WriteSheet writeSheet = EasyExcel.writerSheet(i, "PS模板" + (i + 1)).build();
            excelWriter.write(data(), writeSheet);
        excelWriter.finish();
    private List<DemoData> data() {
        List<DemoData> list = new ArrayList<DemoData>();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setString("字符串" + i);
            data.setDate(new Date());
            data.setDoubleData(0.56);
            list.add(data);
        return list;
public class DemoData {
    /**@ColumnWidth 字段宽度,@ExcelProperty表头名 @ExcelIgnore不导出的字段*/
    @ColumnWidth(15)
    @ExcelProperty("字符串")
    private String string;
    @ColumnWidth(15)
    @ExcelProperty("日期")
    private Date date;
    @ColumnWidth(15)
    @ExcelProperty("数据")
    private Double doubleData;
    @ExcelIgnore
    private String name;
    //get,set方法省略

easyExcel的使用可以查看官网,官网有详细demo,这里是主要代码
写excel类

public class WriteExcel {
    public static void writeExcel(ExportExcelService exportExcelservice, QueryCondition queryCondition, int exifInfoCount, String finalXlsxPath) {
        //每个sheet保存的数据量
        int num = 600;
        ExcelWriter excelWriter = null;
        int corePoolSize=10;
        int maximumPoolSize=20;
        //用线程池管理多线程
        ThreadPoolExecutor exector = (ThreadPoolExecutor) Executors.newFixedThreadPool(corePoolSize);
        exector.setCorePoolSize(corePoolSize);
        exector.setMaximumPoolSize(maximumPoolSize);
        List<ReadExifInfoThread> tasks = new ArrayList<ReadExifInfoThread>();
        excelWriter = EasyExcel.write(finalXlsxPath, ExifInfo.class).build();
        //exifInfoCount 写入excel数据总量
        //pageCount 要写入sheet页数量。同分页
        int pageCount = exifInfoCount % num == 0 ? (exifInfoCount / num) : (exifInfoCount / num + 1);
        for (int i = 0; i < pageCount; i++) {
            ReadExifInfoThread readExifInfoThread = new ReadExifInfoThread(queryCondition, exportExcelservice, i, num);
            tasks.add(readExifInfoThread);
        try {
        	//用invokeAll方法提交任务,返回数据的顺序和tasks中的任务顺序一致,如果第一个线程查0-10000行数据,第二个线程查10000-10001行数据,
        	//第二个线程大概率比第一个线程先执行完,但是futures中第一位数据是0-10000的数据。
        	//[demo见:](https://blog.csdn.net/weixin_43614067/article/details/104983719)
            List<Future<List<ExifInfo>>> futures = exector.invokeAll(tasks);
            for (int i = 0; i < pageCount; i++) {
                List<ExifInfo> exifInfoList = futures.get(i).get();
                WriteSheet writeSheet = EasyExcel.writerSheet(i, "xxxx信息表" + (i + 1)).build();
                excelWriter.write(exifInfoList, writeSheet);
         } catch (Exception e) {
            Constant.bLog.error("写入excel数据失败",e);
        exector.shutdown();
        excelWriter.finish();

线程:从数据库读取数据

public class ReadExifInfoThread implements Callable<List<ExifInfo>> {
    private QueryCondition queryCondition;
    private ExportExcelService exportExcelservice;
    private  int i;
    private  int num;
    public ReadExifInfoThread(QueryCondition queryCondition, ExportExcelService exportExcelservice, int i, int num) {
        this.queryCondition = queryCondition;
        this.exportExcelservice = exportExcelservice;
        this.i = i;
        this.num = num;
    @Override
    public List<ExifInfo> call(){
        queryCondition.setBeginRow(String.valueOf(i*num));
        queryCondition.setEndRow(String.valueOf((i+1)*num));
        long startTime = System.currentTimeMillis();
        List<ExifInfo> exifInfoList = null;
        try {
        	//从数据库查询要写入excle的数据
            exifInfoList = exportExcelservice.getExifInfoByPage(queryCondition);
            long endTime=System.currentTimeMillis();
            long spendTime=endTime-startTime;
            Constant.bLog.info(Thread.currentThread().getName()+"查询耗时:"+spendTime);
        } catch (Exception e) {
            Constant.bLog.error("查询数据失败",e);
        return exifInfoList;

注:这里只用了多线程查询数据,写数据只是单线程。试过多线程写excel,一个线程写一个sheet页,但写入excel的数据会损坏,导致excel打开失败。

用easyExcel,多线程,生产者-消费者模式写入excel阿里easyexcel 插件easyexcel 项目git地址为: https://github.com/alibaba/easyexcel官网地址:https://alibaba-easyexcel.github.io写excel类public class WriteExcel { public static voi... int ndrcNum = SyuserSyroleMapper.countUserIsNDRC(dto.getSyuserId()); Query sql= getMatchFieldsByQuery(dto, bo,ndrcNum);
基于EasyExcel多线程分页导出excelMaven依赖线程池配置导出代码 第七更,基于EasyExcel 多线程分页导出excel 在项目中,BA要求全量导出表中数据,估计有十几万条,同事使用的是EasyPoi导致内存泄漏,我帮他优化,使用阿里的EasyExcel,解决了内存泄漏问题,但是导出17万数据仍需要84秒(本地测试),于是想到了多线程优化,最终测试时间为40秒,服务器上速度会更快,代码如下 Maven依赖 <dependencies> <dependen
@Override public Map<String, Object> exportBmInformationMainModelList(Map<String, Object> queryParams) { List<List<Object>> data...