翻了好久都没找到java 实现easyExcel动态创建sheet,那写一个。

        要知道以 .xlsx结尾的excel文件每个sheet 只能写104万左右的数据量,

        如果想要写入500W条数据到excel,要么分到多个sheet中,每个sheet存100w左右数据,5个sheet存储完;

        要么写到五个xlsx文件中,这可能不是想要的。所以写入到同一个表格文件不同的sheet中去。

        封装的easyexcel只用于写数据,只要内存和硬盘足够大,亿万条数据也不在话下,但是无实际意义吧。

        另外我测试创建500个sheet 都去写数据,发现也是可以的。


目录

1.添加easyexcel依赖

2.封装easyExcel处理工具类

3.使用工具类

4.结果展示

 


1.添加easyexcel依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>easyexcel</artifactId>
      <version>2.0.5</version>
    </dependency>

    <!--配合插件lombok 使用-->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.2</version>
      <scope>provided</scope>
    </dependency>

2.封装easyExcel处理工具类

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 通用 excel 写操作模板
 */
public class ExcelHandler {

    private List<WriteSheet> sheets;    //excel的sheet集合
    private String dirName;             //excel存放的文件夹 默认文件夹my_excel
    private static final int DEFAULT_PER_SHEET_NUM = 1000000;//默认每个sheet存储的行数

    /**
     * 对象创建,生成excel时,文件默认存放的文件夹"my_excel"
     */
    public ExcelHandler() {
    }

    /**
     * 对象创建,生成excel时,excel文件指定存放的文件夹,文件夹可以多级 folderName:"aa/bb/cc"
     *
     * @param folderName
     */
    public ExcelHandler(String folderName) {
        dirName = folderName;
    }

    /**
     * 创建excel和sheet,创建时可以指定sheet 数量
     *
     * @param excelName
     * @param clazz
     * @param numSheet
     * @return
     * @throws Exception
     */
    public ExcelWriter create(String excelName, Class clazz, int numSheet) throws Exception {

        ExcelWriter excelWriter = EasyExcel.write(route(excelName), clazz.asSubclass(clazz)).build();
        createSheets(numSheet);
        return excelWriter;
    }

    /**
     * 创建excel和sheet,sheet 数量默认 5, 最高可存放500W 行左右的数据,受每个sheet存放数据的限制
     *
     * @param excelName
     * @param clazz
     * @return
     * @throws Exception
     */
    public ExcelWriter create(String excelName, Class clazz) throws Exception {

        ExcelWriter excelWriter = EasyExcel.write(route(excelName), clazz.asSubclass(clazz)).build();
        createSheets(5);
        return excelWriter;
    }

    /**
     * 写数据到excel,仅使用一个sheet,不可用于百万以上数据
     *
     * @param excelWriter
     * @param list
     */
    public void write(ExcelWriter excelWriter, List list) throws Exception {
        excelWriter.write(list, sheets.get(0));
    }

    /**
     * 写数据到excel
     *
     * @param excelWriter
     * @param list        每一次的数据
     * @param resize      动态调整大小
     */
    public void write(ExcelWriter excelWriter, List list, int resize) throws Exception {
        int index = resize / (DEFAULT_PER_SHEET_NUM + 1);
        excelWriter.write(list, sheets.get(index));
    }

    /**
     * 写完数据关闭(finish 有关流操作),必须的操作
     *
     * @param excelWriter
     */
    public void finish(ExcelWriter excelWriter) {
        excelWriter.finish();
    }

    /**
     * 创建指定数量的sheet
     *
     * @param num sheet的数量
     */
    private void createSheets(int num) {
        sheets = new ArrayList<>();
        for (int i = 1; i <= num; i++) {
            WriteSheet sheet = EasyExcel.writerSheet(i, "sheet" + i).build();
            sheets.add(sheet);
        }
    }

    /**
     * 表格存放路径
     *
     * @param excelName
     * @return
     */
    private String route(String excelName) {
        if (null == dirName) {
            dirName = "my_excel";
        }
        String filePath = dirName + "/";
        File fp = new File(filePath);
        if (!fp.exists()) {// 目录的创建
            fp.mkdirs();
        }
        return filePath + excelName + ".xlsx";
    }
}

3.使用工具类

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 用户实体类
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ContentRowHeight(15)
@HeadRowHeight(20)
@ColumnWidth(25)
public class Data1 {

    @ExcelProperty("账号")
    private String account;
    @ExcelProperty("密码")
    private String password;

}

import com.alibaba.excel.ExcelWriter;

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {

        Test t = new Test();
        t.test00();
        t.test01();
    }

    /**
     * 模拟百万以下数据导入到excel
     */
    private void test00() {

        int num = 0;
        ExcelHandler handler = null;
        ExcelWriter excelWriter = null;
        try {
            //创建handler对象--参数文件夹名
            handler = new ExcelHandler("test_00");
            excelWriter = handler.create("记录", Data1.class);

            List<Data1> list = new ArrayList<>(1024);

            //方式一:一次性导出
         /*   for (int i = 0; i < 1000000; i++) {//总数据 100W条
                num++;
                list.add(new Data1("张三" + num, "123abc" + num));
            }
            handler.write(excelWriter, list);
            */

            //方式二:分多次导出     为了降低导出过程中的内存资源,也可以这样
            for (int a = 0; a < 100; a++) {//模拟拿100 次数据
                for (int i = 0; i < 10000; i++) {//模拟一次拿的数据
                    num++;
                    list.add(new Data1("张三" + num, "123abc" + num));
                }
                handler.write(excelWriter, list);
                list.clear();//必须clear,否则数据会重复
            }


        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (null != excelWriter) {
                handler.finish(excelWriter);
            }
        }
    }

    /**
     * 模拟百万以上数据导入到excel
     */
    private void test01() {

        int count = 0;
        int num = 0;
        ExcelHandler handler = null;
        ExcelWriter excelWriter = null;
        try {
            //创建handler对象--参数:文件夹名
            handler = new ExcelHandler("test_001");
            excelWriter = handler.create("记录", Data1.class, 10);

            List<Data1> list = new ArrayList<>(1024);

            //此处依旧可以模仿test00()去优化

            for (int t = 0; t < 10; t++) {//模拟分页页数 每页50W数据

                for (int i = 0; i < 500000; i++) {//模拟每次数据量
                    num++;
                    list.add(new Data1("张三" + num, "123abc" + num));
                }
                //count 将控制插入哪一个sheet
                count += list.size();
                handler.write(excelWriter, list, count);
                list.clear();//必须clear,否则数据会重复
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (null != excelWriter) {
                handler.finish(excelWriter);
            }
        }
    }
}

4.结果展示

百万级数据导入导出java 千万级数据导出_List


备注:1.工具适用于数据导出,百万以下数据 看test00()方法的测试,百万,千万,亿万使用 test01()方法的测试。

           当然也可以修改工具类达到自己的要求。

2.如果不使用lombok插件,记得写相关的get,set,构造等方法。