大数据分页查询分页导出 - wujiuye/miniexcel GitHub Wiki

大数据分页查询分页导出

目的:实现边查询边写入,避免一次将所有数据查询出来而占用太大的内存。

ExcelWriterListener的几个方法

  • getDataObjectClass:获取记录的类型;
  • autoGenerateTitle:是否需要在创建Sheet时自动生成标题,一般情况下返回true就好了,除非导出的表格确实不需要标题;
  • getNetOutputDataRealSize:表示接下来要写入的数据的大小;
  • getOutputDataWithSheetNumber:与getNetOutputDataRealSize需要配合使用。返回接下来实际需要写入的数据;

实现分页查询分页导出依赖的正是getNetOutputDataRealSizegetOutputDataWithSheetNumber这两个方法。前者是表示接下来要写入的数据的大小,后者则需要返回接下来实际需要写入的数据。如果getNetOutputDataRealSize返回0则表示结束。

ExcelWriterListener的定义如下:

public interface ExcelWriterListener<T> {

    /**
     * 出异常时被调用
     */
    default void onError(Exception e) {
        e.printStackTrace();
    }

    /**
     * 获取输出的数据的类型
     *
     * @return
     */
    Class<T> getDataObjectClass();

    /**
     * 是否需要自动生成标题输出,使用反射获取范型T的字段名作为标题
     *
     * @return 标题会被连续的输出到第一行的连续列
     */
    boolean autoGenerateTitle();

    /**
     * 每次刷盘一次完成后,继续写入数据时先调用该方法获取下一次输出的数据真实的总数
     *
     * @param sn 第几个sheet
     * @return 返回0则结束导出
     */
    int getNetOutputDataRealSize(int sn);

    /**
     * 获取本次需要输出的数据
     *
     * @param sn         第几个sheet
     * @param limitStart 上次完成刷盘后的指针位置 (从0开始) (闭区间-包含)
     * @param limitEnd   limitStart + getOutputDataSizeWithSheetNumber返回的值 (开区间-不包含)
     * @return 不运行返回null,否则抛出异常
     */
    List<T> getOutputDataWithSheetNumber(int sn, int limitStart, int limitEnd);

}

getOutputDataWithSheetNumber方法的两个参数limitStartlimitEnd是借鉴了分页查询的思想,实现分页查询、写入。

demo如下:

 public class TestMain{
    /**
     * 测试导出
     */
    @Test
    public void testWrite() {
       
        AbstractExcelWriter excelWriter = AbstractExcelWriter.createExcelWriter("/tmp/miniexcel-test", ExcelFileType.XLSX);
        excelWriter.setSheetSize(1000)
                .setBrushPageSize(1000)
                .setSheetNameFromat("Sheet{sn}");
     
        writer.write(new ExcelWriterListener() {
            
              private Page<DateModel> data;

            @Override
            public Class<DateModel> getDataObjectClass() {
                return DateModel.class;
            }

            @Override
            public boolean autoGenerateTitle() {
                return true;
            }

            @Override
            public int getNetOutputDataRealSize(int sn) {
                data = 从数据库查询(); // data包含分页信息
                data.setPage(date.getPage()+1); // 设置下一页的页码
                return data.getRecords.size(); // 获取当前页的数据总数,返回0则结束
            }

            @Override
            public List<DateModel> getOutputDataWithSheetNumber(int sn, int limitStart, int limitEnd) {
                // limitStart和limitEnd在本例中没有用到;
                return data.getRecords();
            }
        });
    }
}
⚠️ **GitHub.com Fallback** ⚠️