public class ListSheet<T> extends Sheet implements IPushModelSheet<T>
List<T>做数据源,所以它是应用最广泛的一种工作表。
ListSheet默认支持数据切片,少量数据可以在实例化时一次性传入,数据量较大时建议切片获取数据
new Workbook("11月待拜访客户")
.addSheet(new ListSheet<Customer>() {
@Override
protected List<Customer> more() {
// 分页查询数据
List<Customer> list = customerService.list(queryVo);
// 页码 + 1
queryVo.setPageNum(queryVo.getPageNum() + 1);
return list;
}
}).writeTo(response.getOutputStream());
如上示例覆写more()方法获取切片数据,直到返回空数据或null为止,这样不至少将大量数据堆积到内存,
输出协议使用RowBlock进行装填数据并落盘。more方法在ListSheet工作表是一定会被
调用的即使初始化工作表传入了数据,工作表判断无需导出的情况除外,比如未指定表头且Bean对象无任何@ExcelColumn注释,
则会导出空工作表
ListSheet使用getTClass()方法获取泛型的实际类型,内部优先使用Class.getGenericSuperclass()方法获取,
如果有子类指定T类型则可以获取到T的类型,否则将使用数组中第一条数据做为泛型的具体类型,
如果希望无数据时依然导出表头就必须让ListSheet获取泛型T的实际类型,当无数据且无子类指定T时可以使用
setClass(java.lang.Class<?>)方法设置泛型的类型
大多数使用ListSheet工作表导数据时都会使用注解,ListSheet支持自定义注解以延申功能,
你甚至可以不使用任何的内置注释全部使用自定义注解来实现导入导出,使用自定义注解时需要搭配自定义ListSheet解析注解,
其中最重要的两个方法ignoreColumn(AccessibleObject)和createColumn(AccessibleObject)就是读取
方法或字段上的注解来创建Column对象,AccessibleObject可能是一个Method或者一个Field
对象取值会优先调用get方法获取,如果未发现get方法则直接从field取值。导出数据并不仅限于get方法,
你可以在任何无参且仅有一个返回值的方法上添加@ExcelColumn注解进行导出,你还可以在子类定义相同的方法来替换父类上的@ExcelColumn注解,
解析注解时会从子类往上逐级解析至到父级为Object为止
除子类覆写more()方法外还可以通过setData(BiFunction)设置一个数据生产者,它可以减化数据分片的代码。
dataSupplier被定义为BiFunction<Integer, T, List<T>>,其中第一个入参Integer表示已拉取数据的记录数
(并非已写入数据),第二个入参T表示上一批数据中最后一个对象,业务端可以通过这两个参数来计算下一批数据应该从哪个节点开始拉取,
通常你可以使用第一个参数除以每批拉取的数据大小来确定当前页码,如果数据已排序则可以使用T对象的排序字段来计算下一批数据的游标从而跳过
limit ... offset ... 分页查询从而极大提升取数性能
new Workbook()
.addSheet(new ListSheet<Customer>()
// 分页查询,每页查询100条数据,可以通过已拉取记录数计算当前页面
.setData((i, lastOne) -> customerService.pagingQuery(i/100, 100))
).writeTo(Paths.get("f://abc.xlsx"));
参考文档:
ListMapSheet,
SimpleSheet| 限定符和类型 | 类和说明 |
|---|---|
static class |
ListSheet.EntryColumn
|
| 限定符和类型 | 字段和说明 |
|---|---|
protected List<T> |
data
临时存放数据
|
protected BiFunction<Integer,T,List<T>> |
dataSupplier
数据产生者,简化分片查询
|
protected int |
end
控制读取开始和结束下标
|
protected boolean |
eof
结束标记
EOF |
protected int |
forceExport
强制导出,忽略安全限制全字段导出,确认需求后谨慎使用
|
protected int |
start
控制读取开始和结束下标
|
protected StyleProcessor<T> |
styleProcessor
行级动态样式处理器
|
protected Class<?> |
tClazz
泛型<T>的实际类型
|
autoSize, cellValueAndStyle, columns, comments, copyCount, copySheet, extProp, extPropMark, headerReady, headerRowHeight, headStyle, headStyleIndex, hidden, id, LOGGER, name, nonHeader, progressConsumer, relManager, rowBlock, rowHeight, rows, sheetWriter, shouldClose, showGridLines, startCoordinate, watermark, width, workbook, zebraFill, zebraFillStyle| 构造器和说明 |
|---|
ListSheet()
实例化工作表,未指定工作表名称时默认以
'Sheet'+id命名 |
ListSheet(Column... columns)
实例化工作表并指定表头信息
|
ListSheet(List<T> data)
实例化工作表并指定初始数据
|
ListSheet(List<T> data,
Column... columns)
实例化工作表并指定初始数据和表头
|
ListSheet(String name)
实例化工作表并指定工作表名称
|
ListSheet(String name,
Column... columns)
实例化工作表并指定工作表名称和表头信息
|
ListSheet(String name,
List<T> data)
实例化工作表并指定工作表名称和初始数据
|
ListSheet(String name,
List<T> data,
Column... columns)
实例化工作表并指定工作表名称、初始数据和表头
|
| 限定符和类型 | 方法和说明 |
|---|---|
protected void |
append()
|
protected void |
attachFreezePanes(Class<?> clazz)
添加“冻结”窗格,默认解析
FreezePanes注解,支持自定义注解,
只需包含冻结的行列信息即可 |
protected List<Column> |
attachOtherColumn(Map<String,Method> existsMethodMapper,
Class<?> clazz)
收集可导出的
Method并创建Column对象 |
protected void |
buildHeaderComment(AccessibleObject main,
AccessibleObject sub,
Column column)
构建“批注”,默认解析
HeaderComment注解,支持自定义注解
优选从方法上获取注解,如果没有则从field中获取 |
protected void |
buildHeaderStyle(AccessibleObject main,
AccessibleObject sub,
Column column)
构建样式,默认解析
HeaderStyle注解
优选从方法上获取注解,如果没有则从field中获取 |
Sheet |
cancelForceExport()
取消强制导出,可以取消在工作表
Workbook上设置的全局强制导出标记 |
void |
close()
Release resources
|
protected ListSheet.EntryColumn |
createColumn(AccessibleObject ao)
创建列信息,默认解析@Comment注解,支持自定义注解
|
protected ListSheet.EntryColumn |
createColumnByAnnotation(ExcelColumn ec)
解析@ExcelColumn注解并创建表头
|
int |
dataSize()
获取当前数组中有多少数据,数组中的数据是动态变化的,所以这是一个瞬时值
|
protected RowBlock |
fillRowBlock(List<T> data)
将外部数据转为标准的行块
|
protected Method[] |
filterOthersMethodsCanExport(Map<String,Method> existsMethodMapper,
Class<?> clazz)
查找其它可导出的
Method方法,此方法将扩大查找范围,
包含无参且仅有一个返回值的方法也做为查找对象,如果该方法标记有@ExcelColumn
注解且无@IgnoreExport注解则添加到导出数组 |
Sheet |
forceExport()
强制导出
为了保证数据安全默认情况下Java Bean只导出标记有@ExcelColumn的字段和方法,
但某些情况不方便修改实体此时可以使用强制导出功能将Bean中的全字段导出(标记有@IgnoreExport注解除外),
此方法可能会造成数据泄漏风险,可参考
ExcelColumn注解说明 |
protected StyleProcessor<?> |
getDesignStyle(AccessibleObject ao)
读取单个字段或者方法上的样式处理器注解,默认解析
StyleDesign注解,支持自定义注解 |
protected StyleProcessor<?> |
getDesignStyle(Class<?> clazz)
读取类上的样式处理器注解,默认解析
StyleDesign注解,支持自定义注解 |
protected StyleProcessor<?> |
getDesignStyle(StyleDesign styleDesign)
读取样式处理器
|
protected int |
getEndIndex()
计算需要读取的尾下标,相对于当前数组的尾下标
|
protected T |
getFirst()
获取队列中第一个非
null对象用于解析 |
int |
getForceExport()
返回“强制导出”标识
|
protected Column[] |
getHeaderColumns()
获取表头信息,未实例化表头时会执行初始化方法实例化表头
|
StyleProcessor<T> |
getStyleProcessor()
获取当前工作表的行级动态样式处理器,如果未设置则从扩展参数中查找
|
protected Class<?> |
getTClass()
获取泛型T的实际类型,优先使用
Class.getGenericSuperclass()方法获取,如果有子类指定T类型则可以获取,
否则将使用数组中第一条数据做为泛型的具体类型 |
protected boolean |
ignoreColumn(AccessibleObject ao)
导出时忽略某些字段或方法,默认解析
IgnoreExport注解,支持自定义注解 |
protected int |
init()
初始化表头信息,如果未指定
Columns则默认反射T及其父类的所有字段,
并采集所有标记有ExcelColumn注解的字段和方法(这里限制无参数且仅有一个返回值的方法),
Column顺序由colIndex决定,如果没有colIndex则按字段和方法在
Java Bean中的定义顺序而定。 |
protected int |
left()
数组中剩余多少数据
|
protected void |
mergeGlobalSetting(Class<?> clazz)
设置全局设置
|
protected List<T> |
more()
除了实例化
ListSheet工作表指定的数据外,导出过程中会使用more方法获取更多数据,
直到返回null或空为止。 |
protected void |
paging()
分页处理,如果达到分页条件时会复制一个新的工作表插入到当前位置之后
|
protected void |
resetBlockData()
重置
RowBlock行块数据 |
protected void |
resetCellValueAndStyle(Row row,
Cell cell,
T rowData,
Object cellData,
Column column)
重置单元格数据和样式
|
protected void |
resetRowBlock(List<T> data,
int fromIndex,
int toIndex)
将外部数据转为标准的行块
|
protected void |
resetRowData(Row row,
T rowData)
重置单行数据
|
Sheet |
setClass(Class<?> tClazz)
指定泛型
T的实际类型,不指定时默认由反射或数组中第一个对象类型而定 |
ListSheet<T> |
setData(BiFunction<Integer,T,List<T>> dataSupplier)
设置数据生产者,如果设置了此值
more()方法将从此生产者中获取数据 |
ListSheet<T> |
setData(List<T> data)
设置初始数据,导出的时候依然会调用
more() 方法以获取更多数据 |
Sheet |
setStyleProcessor(StyleProcessor<T> styleProcessor)
设置行级动态样式处理器,作用于整行优先级高于单元格动态样式处理器
|
int |
writeData(List<T> data)
|
addRel, afterSheetAccess, afterSheetDataWriter, autoSize, buildHeadStyle, calculateRealColIndex, cancelZebraLine, checkColumnLimit, clone, createComments, defaultHeadStyle, defaultHeadStyleIndex, defaultZebraLine, findRel, fixedSize, fixedSize, forWrite, getAndSortHeaderColumns, getAutoSize, getCellValueAndStyle, getColumns, getComments, getCopySheetName, getDefaultWidth, getExtPropAsMap, getExtPropValue, getFileName, getHeaderRowHeight, getHeadStyle, getHeadStyleIndex, getId, getName, getNonHeader, getProgressConsumer, getRelManager, getRowBlockSize, getRowHeight, getRowLimit, getSheetWriter, getStartColNum, getStartRowNum, getWatermark, getWorkbook, getZebraFill, getZebraFillStyle, hasHeaderColumns, hidden, hideGridLines, ignoreHeader, insert, int2Col, isAutoSize, isHidden, isScrollToVisibleArea, isShowGridLines, markExtProp, mergeHeaderCellsIfEquals, nextBlock, onProgress, putAllExtProp, putExtProp, putExtPropIfAbsent, resetCommonProperties, reverseHeadColumn, search, setCellValueAndStyle, setColumns, setColumns, setHeaderRowHeight, setHeadStyle, setHeadStyleIndex, setId, setName, setRowHeight, setSheetWriter, setStartCoordinate, setStartCoordinate, setStartCoordinate, setStartCoordinate, setStartCoordinate, setStartCoordinate, setWatermark, setWorkbook, setZebraLine, showGridLines, size, sortColumns, toCoordinate, writeToprotected int start
protected int end
protected boolean eof
EOFprotected Class<?> tClazz
protected StyleProcessor<T> styleProcessor
protected int forceExport
protected BiFunction<Integer,T,List<T>> dataSupplier
public ListSheet()
'Sheet'+id命名public ListSheet(String name)
name - 工作表名称public ListSheet(Column... columns)
columns - 表头信息public ListSheet(String name, Column... columns)
name - 工作表名称columns - 表头信息public ListSheet(String name, List<T> data)
name - 工作表名称data - 初始数据public ListSheet(List<T> data, Column... columns)
data - 初始数据columns - 表头信息public Sheet setStyleProcessor(StyleProcessor<T> styleProcessor)
styleProcessor - 行级动态样式处理器public StyleProcessor<T> getStyleProcessor()
public Sheet setClass(Class<?> tClazz)
T的实际类型,不指定时默认由反射或数组中第一个对象类型而定tClazz - 泛型T的实际类型public ListSheet<T> setData(List<T> data)
more() 方法以获取更多数据data - 初始数据public ListSheet<T> setData(BiFunction<Integer,T,List<T>> dataSupplier)
more()方法将从此生产者中获取数据dataSupplier - 数据生产者其中Integer为已拉取数据的记录数,T为上一批数据中最后一个对象protected T getFirst()
null对象用于解析null对象public void close()
throws IOException
close 在类中 SheetIOException - if I/O error occurprotected void resetBlockData()
RowBlock行块数据resetBlockData 在类中 Sheetprotected void append()
protected Class<?> getTClass()
Class.getGenericSuperclass()方法获取,如果有子类指定T类型则可以获取,
否则将使用数组中第一条数据做为泛型的具体类型nullprotected int init()
Columns则默认反射T及其父类的所有字段,
并采集所有标记有ExcelColumn注解的字段和方法(这里限制无参数且仅有一个返回值的方法),
Column顺序由colIndex决定,如果没有colIndex则按字段和方法在
Java Bean中的定义顺序而定。
如果有指定Columns则忽略排序仅将Column.key与字段和方法进行绑定方便后续取值
protected ListSheet.EntryColumn createColumn(AccessibleObject ao)
ao - AccessibleObject 实体中的属性或方法protected ListSheet.EntryColumn createColumnByAnnotation(ExcelColumn ec)
ec - ExcelColumn注解protected void buildHeaderStyle(AccessibleObject main, AccessibleObject sub, Column column)
HeaderStyle注解
优选从方法上获取注解,如果没有则从field中获取
main - Methodsub - Fieldcolumn - 需要添加样式的表头protected void buildHeaderComment(AccessibleObject main, AccessibleObject sub, Column column)
HeaderComment注解,支持自定义注解
优选从方法上获取注解,如果没有则从field中获取
main - Methodsub - Fieldcolumn - 需要添加批注的表头protected void mergeGlobalSetting(Class<?> clazz)
clazz - Class of <T>protected StyleProcessor<?> getDesignStyle(Class<?> clazz)
StyleDesign注解,支持自定义注解clazz - Class of <T>nullprotected StyleProcessor<?> getDesignStyle(AccessibleObject ao)
StyleDesign注解,支持自定义注解ao - 字段Field或方法Methodnullprotected StyleProcessor<?> getDesignStyle(StyleDesign styleDesign)
styleDesign - 默认StyleDesignprotected boolean ignoreColumn(AccessibleObject ao)
IgnoreExport注解,支持自定义注解ao - Method or Fieldprotected List<Column> attachOtherColumn(Map<String,Method> existsMethodMapper, Class<?> clazz)
Method并创建Column对象existsMethodMapper - 已有的可导出Method映射,key为方法名clazz - Class of <T>Column数组protected Column[] getHeaderColumns()
getHeaderColumns 在类中 Sheetprotected int getEndIndex()
protected int left()
public int dataSize()
protected List<T> more()
ListSheet工作表指定的数据外,导出过程中会使用more方法获取更多数据,
直到返回null或空为止。这是一个独立于数据源的方法,它可以从任何数据源获取数据。
由于此方法是无状态的,所以需要在自定义工作表中维护分页、请求参数和上下文信息。
每次获得的数据越多写入速度就越快, 更多的数据可以减少数据库查询或网络请求次数,
但过多的数据会占用更多的内存,开发过程中需要在速度和内存消耗之间做权衡。
建议批量不要太大,整个过程最大的压力在写磁盘操作上,所以批量太大对性能改善甚微,
但最小批量最好要超过Sheet.getRowBlockSize()设置的大小也就是最小32
null和空数组表示结束protected void attachFreezePanes(Class<?> clazz)
FreezePanes注解,支持自定义注解,
只需包含冻结的行列信息即可clazz - Class of <T>protected Method[] filterOthersMethodsCanExport(Map<String,Method> existsMethodMapper, Class<?> clazz)
Method方法,此方法将扩大查找范围,
包含无参且仅有一个返回值的方法也做为查找对象,如果该方法标记有@ExcelColumn
注解且无@IgnoreExport注解则添加到导出数组existsMethodMapper - 已有的可导出Method映射,key为方法名clazz - Class of <T>Method数组public Sheet forceExport()
为了保证数据安全默认情况下Java Bean只导出标记有@ExcelColumn的字段和方法,
但某些情况不方便修改实体此时可以使用强制导出功能将Bean中的全字段导出(标记有@IgnoreExport注解除外),
此方法可能会造成数据泄漏风险,可参考ExcelColumn注解说明
public int getForceExport()
getForceExport 在类中 Sheetpublic int writeData(List<T> data) throws IOException
PUSH模式下使用
注意:由于外部拿不到自动分页创建的新工作表,所以PUSH模式将不支持自动分页,
超出数据上限将直接抛IndexOutOfBoundsException异常
writeData 在接口中 IPushModelSheet<T>data - 行数据IOException - if I/O error occur.protected void resetRowBlock(List<T> data, int fromIndex, int toIndex)
data - 外部数据fromIndex - 读取数据的起始下标(包含)toIndex - 读取数据的结束下标(不包含)Copyright © 2025. All rights reserved.