# easyExcel **Repository Path**: leo_9527/easy-excel ## Basic Information - **Project Name**: easyExcel - **Description**: 阿里出品 easyExcel[基于poi] 入门小结及优化 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 6 - **Forks**: 1 - **Created**: 2022-03-25 - **Last Updated**: 2023-11-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # esayExcel 3.1x~3.2x ## 官方文档:https://easyexcel.opensource.alibaba.com ## 代码分享:https://gitee.com/leo_9527/easy-excel ### 一、简介(什么是easyExcel) > 快速的读取`excel`中的数据。 > > 映射`excel`和实体类,让代码变的更加简洁。 > > 在读写大文件的时候使用磁盘做缓存,更加的节约内存。 > > EasyExcle是阿里巴巴开源的excle处理框架,以使用简单、节省内存著称。 > > EasyExcel能大大减少占用内存的主要原因是再解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。 > > easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出; > > 03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便 > > 64M内存20秒读取75M(46W行25列)的Excel(3.0.2+版本) ### 二、功能(它能做什么) #### 1、读 #### 2、写 #### 3、填充 ### 三、常用 #### 1. 常用注解 ##### `ExcelProperty` 用于匹配excel和实体类的匹配,参数如下: | 名称 | 默认值 | 描述 | | --------- | ----------------- | ------------------------------------------------------------ | | value | 空 | 用于匹配excel中的头,必须全匹配,如果有多行头,会匹配最后一行头 | | order | Integer.MAX_VALUE | 优先级高于`value`,会根据`order`的顺序来匹配实体和excel中数据的顺序 | | index | -1 | 优先级高于`value`和`order`,会根据`index`直接指定到excel中具体的哪一列 | | converter | 自动选择 | 指定当前字段用什么转换器,默认会自动选择。读的情况下只要实现`com.alibaba.excel.converters.Converter#convertToJavaData(com.alibaba.excel.converters.ReadConverterContext)` 方法即可 | ``` # 官方建议: # 1、不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配 # 2、如果用名字去匹配,名字重复,会导致只有一个字段读取到数据 # 根据Excel 结构变化频率去选择 index/name。 ``` ##### `ExcelIgnore` 默认所有字段都会和excel去匹配,加了这个注解会忽略该字段 ##### `ExcelIgnoreUnannotated` 默认不加`ExcelProperty` 的注解的都会参与读写,加了不会参与 ##### `DateTimeFormat` 日期转换,用`String`去接收excel日期格式的数据会调用这个注解,参数如下: | 名称 | 默认值 | 描述 | | ---------------- | -------- | ------------------------------------------------------------ | | value | 空 | 参照`java.text.SimpleDateFormat`书写即可。例:yyyy-MM-dd HH:mm:ss | | use1904windowing | 自动选择 | excel中时间是存储1900年起的一个双精度浮点数,但是有时候默认开始日期是1904,所以设置这个值改成默认1904年开始 | ##### `NumberFormat` 数字转换,用`String`去接收excel数字格式的数据会调用这个注解。 | 名称 | 默认值 | 描述 | | ------------ | -------------------- | ------------------------------------- | | value | 空 | 参照`java.text.DecimalFormat`书写即可 | | roundingMode | RoundingMode.HALF_UP | 格式化的时候设置舍入模式 | ``` 参考: “0”——表示一位数值,如没有,显示0。如“0000.0000”,整数位或小数位>4,按实际输出,<4整数位前面补0小数位后面补0,凑足4位。 “#”:无小数,小数部分四舍五入。 “.#”:整数部分不变,一位小数,四舍五入。 “.##”:整数部分不变,二位小数,四舍五入。 “.”——表示小数点。 ``` #### 2. 常用对象及参数 ##### a. 写相关 ###### `WriteWorkbook` 对象 可以理解成一个excel ###### `WriteSheet` 对象 可以理解成一个excel里面的一个工作簿 ###### `WriteTable` 对象 一个表单里面如果有多个实际用的表格,则可以用 `WriteTable` ###### 参数使用代码参考如下: ~~~java EasyExcel.write(fileName, WriteExcelBasicEntity.class) // 在 write 方法之后, 在 sheet方法之前都是设置WriteWorkbook的参数 .sheet("模板") // 在 sheet 方法之后, 在 doWrite方法之前都是设置WriteSheet的参数 .table() // 在 table 方法之后, 在 doWrite方法之前都是设置WriteTable的参数 .doWrite(() -> { // 分页查询数据 return data(); }); ~~~ ###### `WriteWorkbook`,`WriteSheet` ,`WriteTable`都会有的参数,如果为空,默认使用上级。 | 名称 | 默认值 | 描述 | | ----------------------- | ------ | ------------------------------------------------------------ | | converter | 空 | 默认加载了很多转换器,这里可以加入不支持的字段 | | writeHandler | 空 | 写的处理器。可以实现`WorkbookWriteHandler`,`SheetWriteHandler`,`RowWriteHandler`,`CellWriteHandler`,在写入excel的不同阶段会调用 | | relativeHeadRowIndex | 0 | 写入到excel和上面空开几行 | | head | 空 | 与`clazz`二选一。读取文件头对应的列表,会根据列表匹配数据,建议使用class | | clazz | 空 | 与`head`二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据 | | autoTrim | true | 会对头、读取数据等进行自动trim | | use1904windowing | false | excel中时间是存储1900年起的一个双精度浮点数,但是有时候默认开始日期是1904,所以设置这个值改成默认1904年开始 | | useScientificFormat | false | 数字转文本的时候在较大的数值的是否是否采用科学计数法 | | needHead | true | 是否需要写入头到excel | | useDefaultStyle | true | 是否使用默认的样式 | | automaticMergeHead | true | 自动合并头,头中相同的字段上下左右都会去尝试匹配 | | excludeColumnIndexes | 空 | 需要排除对象中的index的数据 | | excludeColumnFieldNames | 空 | 需要排除对象中的字段的数据 | | includeColumnIndexes | 空 | 只要导出对象中的index的数据 | | includeColumnFieldNames | 空 | 只要导出对象中的字段的数据 | ###### `WriteWorkbook` 对象 独有参数如下: | 名称 | 默认值 | 描述 | | --------------------- | ---------------------- | ------------------------------------------------------------ | | excelType | 空 | 当前excel的类型,支持XLS、XLSX、CSV | | outputStream | 空 | 与`file`二选一。写入文件的流 | | file | 空 | 与`outputStream`二选一。写入的文件 | | templateInputStream | 空 | 模板的文件流 | | templateFile | 空 | 模板文件 | | charset | Charset#defaultCharset | 只有csv文件有用,写入文件的时候使用的编码 | | autoCloseStream | true | 自动关闭写入的流。 | | password | 空 | 读取文件的密码 | | inMemory | false | 是否在内存处理,默认会生成临时文件以节约内存。内存模式效率会更好,但是容易OOM | | writeExcelOnException | false | 写入过程中抛出异常了,是否尝试把数据写入到excel | ###### `WriteSheet` 对象 独有参数如下: | 名称 | 默认值 | 描述 | | --------- | ------ | ---------------------------------- | | sheetNo | 0 | 需要写入的编码 | | sheetName | 空 | 需要些的Sheet名称,默认同`sheetNo` | ###### `WriteTable` 对象 独有参数如下: | 名称 | 默认值 | 描述 | | ------- | ------ | -------------- | | tableNo | 0 | 需要写入的编码 | ##### b. 读相关 ###### `ReadWorkbook` 对象 可以理解成一个excel ###### `ReadSheet ` 对象 可以理解成一个excel里面的一个工作簿 ###### 参数使用代码参考如下: ~~~java EasyExcel.read(fileName, ReadExcelBasicEntity.class, new ReadExcelBasicListener()) // 在 read 方法之后, 在 sheet方法之前都是设置ReadWorkbook的参数 .sheet() // 在 sheet 方法之后, 在 doRead方法之前都是设置ReadSheet的参数 .doRead(); ~~~ ###### `ReadWorkbook` , `ReadSheet` 都会有的参数,如果为空,默认使用上级。 | 名称 | 默认值 | 描述 | | ------------------- | ------ | ------------------------------------------------------------ | | converter | 空 | 默认加载了很多转换器,这里可以加入不支持的字段 | | readListener | 空 | 可以注册多个监听器,读取excel的时候会不断的回调监听器中的方法 | | headRowNumber | 1 | excel中头的行数,默认1行 | | head | 空 | 与`clazz`二选一。读取文件头对应的列表,会根据列表匹配数据,建议使用class | | clazz | 空 | 与`head`二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据 | | autoTrim | true | 会对头、读取数据等进行自动trim | | use1904windowing | false | excel中时间是存储1900年起的一个双精度浮点数,但是有时候默认开始日期是1904,所以设置这个值改成默认1904年开始 | | useScientificFormat | false | 数字转文本的时候在较大的数值的是否是否采用科学计数法 | ###### `ReadWorkbook` 对象 独有参数 | 名称 | 默认值 | 描述 | | ------------------------ | ----------------------- | ------------------------------------------------------------ | | excelType | 空 | 当前excel的类型,支持XLS、XLSX、CSV | | inputStream | 空 | 与`file`二选一。读取文件的流,如果接收到的是流就只用,不用流建议使用`file`参数。因为使用了`inputStream` easyexcel会帮忙创建临时文件,最终还是`file` | | file | 空 | 与`inputStream`二选一。读取文件的文件。 | | mandatoryUseInputStream | false | 强制使用 `inputStream` 来创建对象,性能会变差,但是不会创建临文件。 | | charset | Charset#defaultCharset | 只有csv文件有用,读取文件的时候使用的编码 | | autoCloseStream | true | 自动关闭读取的流。 | | readCache | 空 | 默认小于5M用 内存,超过5M会使用 `EhCache`,这里不建议使用这个参数。 | | readCacheSelector | SimpleReadCacheSelector | 用于选择什么时候用内存去存储临时数据,什么时候用磁盘存储临时数据 | | ignoreEmptyRow | true | 忽略空的行 | | password | 空 | 读取文件的密码 | | xlsxSAXParserFactoryName | 空 | 指定sax读取使用的class的名称,例如:`com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl` | | useDefaultListener | true | `@since 2.1.4` 默认会加入`ModelBuildEventListener` 来帮忙转换成传入`class`的对象,设置成`false`后将不会协助转换对象,自定义的监听器会接收到`Map`对象,如果还想继续接听到`class`对象,请调用`readListener`方法,加入自定义的`beforeListener`、 `ModelBuildEventListener`、 自定义的`afterListener`即可。 | | extraReadSet | 空 | 额外需要读取内容的set,默认不读取这些数据 | | readDefaultReturn | STRING | `@since 3.2.0` STRING:会返回一个Map的数组,返回值就是你在excel里面不点击单元格看到的内容 ACTUAL_DATA:会返回一个Map的数组,返回实际上存储的数据,会帮自动转换类型,Object类型为`BigDecimal`、`Boolean`、`String`、`String`、null,中的一个, READ_CELL_DATA: 会返回一个Map>的数组,其中`?`类型参照ACTUAL_DATA的 | ###### `ReadSheet` 对象 独有参数 | 名称 | 默认值 | 描述 | | --------- | ------ | ---------------------------------------------------- | | sheetNo | 0 | 需要读取Sheet的编码,建议使用这个来指定读取哪个Sheet | | sheetName | 空 | 根据名字去匹配Sheet | ##### c. 填充相关(参考写相关) ### 四、其他相关 #### `@ColumnWidth` 用于设置列宽度的注解。 | 参数名称 | 描述 | | -------- | ------------------------------------------------------------ | | value | 字符长度,最大可以设置255个字符。因为一个excel单元格最大可以写入的字符个数就是255个字符。 | #### `@ContentRowHeight` 用于设置行高的注解。 | 参数名称 | 描述 | | -------- | -------------------- | | value | 行高,-1代表自动行高 | #### `@ContentLoopMerge` 用于设置合并单元格的注解。 | 参数名称 | 描述 | | ------------ | ------ | | eachRow | 合并行 | | columnExtend | 合并列 | #### `@HeadFontStyle` 用于定制标题字体格式的注解 | 参数名称 | 描述 | | ------------------ | -------------------------------------------------------- | | fontName | 字体名称 | | fontHeightInPoints | 字体高度 即 字体的大小 | | italic | 是否斜体 | | strikeout | 是否设置删除水平线 | | color | 字体颜色 参考:org.apache.poi.ss.usermodel.IndexedColors | | typeOffset | 偏移量 | | underline | 下划线 | | bold | 是否加粗 | | charset | 编码格式 | #### `@ContentStyle` 用于设置内容格式注解。 | 参数名称 | 描述 | | ------------------- | ------------------------------------------------------------ | | dataFormat | 日期格式 | | hidden | 设置单元格使用此样式隐藏 | | locked | 设置单元格使用此样式锁定 | | quotePrefix | 在单元格前面增加'`'符号,数字或公式将以字符串形式展示 | | horizontalAlignment | 设置是否水平居中 | | wrapped | 设置文本是否应换行。将此标志设置为true通过在多行上显示使单元格中的所有内容可见 | | verticalAlignment | 设置是否垂直居中 | | rotation | 设置单元格中文本旋转角度。03版本的Excel旋转角度区间为-90°\~90°,07版本的Excel旋转角度区间为0°\~180° | | indent | 设置单元格中缩进文本的空格数 | | borderLeft | 设置左边框的样式 | | borderRight | 设置右边框样式 | | borderTop | 设置上边框样式 | | borderBottom | 设置下边框样式 | | leftBorderColor | 设置左边框颜色 | | rightBorderColor | 设置右边框颜色 | | topBorderColor | 设置上边框颜色 | | bottomBorderColor | 设置下边框颜色 | | fillPatternType | 设置填充类型 | | fillBackgroundColor | 设置背景色 | | fillForegroundColor | 设置前景色 | | shrinkToFit | 设置自动单元格自动大小 | #### `@HeadRowHeight` 用于设置标题行行高的注解。 | 参数名称 | 描述 | | -------- | -------------------- | | value | 行高,-1代表自动行高 | #### `@HeadStyle` 用于设置标题样式的注解。 | 参数名称 | 描述 | | ------------------- | ------------------------------------------------------------ | | dataFormat | 日期格式 | | hidden | 设置单元格使用此样式隐藏 | | locked | 设置单元格使用此样式锁定 | | quotePrefix | 在单元格前面增加'`'符号,数字或公式将以字符串形式展示 | | horizontalAlignment | 设置是否水平居中 | | wrapped | 设置文本是否应换行。将此标志设置为true通过在多行上显示使单元格中的所有内容可见 | | verticalAlignment | 设置是否垂直居中 | | rotation | 设置单元格中文本旋转角度。03版本的Excel旋转角度区间为-90°\~90°,07版本的Excel旋转角度区间为0°\~180° | | indent | 设置单元格中缩进文本的空格数 | | borderLeft | 设置左边框的样式 | | borderRight | 设置右边框样式 | | borderTop | 设置上边框样式 | | borderBottom | 设置下边框样式 | | leftBorderColor | 设置左边框颜色 | | rightBorderColor | 设置右边框颜色 | | topBorderColor | 设置上边框颜色 | | bottomBorderColor | 设置下边框颜色 | | fillPatternType | 设置填充类型 | | fillBackgroundColor | 设置背景色 | | fillForegroundColor | 设置前景色 | | shrinkToFit | 设置自动单元格自动大小 | ### 五、写相关 拦截器 #### `CellWriteHandler` 导出单元格处理拦截器 | 方法名称 | 描述 | | ---------------------- | ------------------------------ | | beforeCellCreate | 在创建单元格之前调用 | | afterCellCreate | 在创建单元格之后调用 | | afterCellDataConverted | 在创建单元格之后 数据转换器 | | afterCellDispose | 在单元格上的所有操作完成后调用 | #### `SheetWriteHandler` 导出工作簿处理拦截器 | 方法名称 | 描述 | | ----------------- | -------------------- | | beforeSheetCreate | 在创建工作簿之前调用 | | afterSheetCreate | 在创建工作簿之后调用 | ### 六、读相关 监听器 > 官方强调注意:有个很重要的点 自定义监听器 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去 #### `ReadListener` 接口监听读取Excel结果 | 方法名称 | 描述 | | ------------------------------------------------------------ | ------------------------------------------------------------ | | `invoke` (T data, AnalysisContext context) | 数据解析时 一行 触发调用 | | `doAfterAllAnalysed` (AnalysisContext context) | 数据解析完成调用 | | `onException` (Exception exception, AnalysisContext context) throws Exception | 当任何一个侦听器执行错误报告时,所有侦听器都会收到此方法。如果这里抛出异常,则整个读取操作将终止。 | | `invokeHead` (Map> headMap, AnalysisContext context) | 数据解析时 一列 触发调用函数 | | `extra` (CellExtra extra, AnalysisContext context) | 返回额外信息(批注、超链接、合并单元格信息读取)时调用 | | `hasNext` (AnalysisContext context) | 验证是否有另一段数据。你可以通过返回false来停止读取 | ### 七、读相关 数据分析上下文 #### `AnalysisContext` 分析上下文 | 方法名称 | 描述 | | ----------------------------------------------- | --------------------------- | | `currentSheet` (ReadSheet readSheet) | 选择当前工作簿 | | readWorkbookHolder | 返回当前 `Excel对象` 持有者 | | readSheetHolder | 返回当前 `工作簿对象`持有者 | | readRowHolder | 返回当前 `行对象`持有者 | | `readRowHolder` (ReadRowHolder readRowHolder) | 返回当前 `行对象`持有者 | | currentReadHolder | 当前持有者 | | getCustom | 自定义属性 | | analysisEventProcessor | 事件处理器 | | readSheetList | 客户需要读取的数据 | | `readSheetList` (List readSheetList) | 客户需要读取的数据 | #### `readWorkbookHolder` Excel对象 持有者 | 属性名称 | 描述 | | ----------------------- | ------------------------------------------------------------ | | readWorkbook | `Excel对象` 持有者 | | inputStream | 输入流 如果“inputStream”和“file”都不为空,则先文件 | | file | 读文件 如果“inputStream”和“file”都不为空,则先文件 | | charset | 字符集,适用于CSV文件 | | mandatoryUseInputStream | 必选使用 输入流。默认为false | | autoCloseStream | 自动关闭流 默认为true | | readDefaultReturn | 读取默认返回值 【com.alibaba.excel.metadata.BasicParameter 基本参数】 | | excelType | excel 类型 | | customObject | 该对象可以在 监听器 中读取 | | ignoreEmptyRow | 忽略空行。默认为true。 | | readCache | 存储临时数据以节省内存的缓存。 | | readCacheSelector | 选择缓存 @link com.alibaba.excel.cache.selector.SimpleReadCacheSelector | | tempFile | 读取excel时的临时文件 | | password | 是否加密 | | extraReadSet | 阅读一些其他字段。默认不读取 | | actualSheetDataList | 实际工作簿数据 | | parameterSheetDataList | 参数工作簿数据 | | readAll | 读取所有 | | hasReadSheet | 防止重复工作簿 | #### `readSheetHolder` 工作簿对象 持有者 | 属性名称 | 描述 | | ------------------------- | --------------------------------------------- | | readSheet | 返回工作表中包含此单元格的行的行索引。从0开始 | | parentReadWorkbookHolder | 父类阅读工作簿持有者 | | sheetNo | 工作簿编号 | | sheetName | 工作簿名称 | | approximateTotalRowNumber | 获取总行数,数据可能不准确 | | cellMap | 当前单元格的数据存储 | | cellExtra | 当前额外单元格的数据存储 | | rowIndex | 当前行索引 | | tempCellData | 当前单元格数据 | | maxNotEmptyDataHeadSize | 读取页头数据中最大页头的大小 | #### `cellExtra` 额外单元格的数据存储 | 属性名称 | 描述 | | ----------------- | ----------------------------------------------------- | | CellExtraTypeEnum | 单元格额外信息类型 枚举类【批注、超链接、单元格合并】 | | text | 单元格额外信息 数据内容 | | firstRowIndex | 如果该对象是一个区间,则第一行索引 | | lastRowIndex | 如果该对象是一个区间,则为最后一行索引 | | firstColumnIndex | 如果该对象是一个区间,则为第一列索引 | | lastColumnIndex | 如果该对象是一个区间,则为最后一列索引 | #### `readRowHolder` 行对象 持有者 | 属性名称 | 描述 | | --------------------- | --------------------------------------------- | | rowIndex | 返回工作表中包含此单元格的行的行索引。从0开始 | | rowType | 行类型 | | cellMap | 单元格 集合 | | currentRowAnalysisRes | 当前侦听器的结果 | | globalConfiguration | 一些全局变量 | #### `readHolder` 获取相应持有者 | 方法名称 | 描述 | | --------------------- | ------------------------------------------------------------ | | readListenerList | 当前操作的单元格需要执行什么处理程序 【返回 接口监听 读取 结果】 | | excelReadHeadProperty | 返回 定义excel的header属性 | ### 八、读相关 转换器 #### `Converter` Java对象和excel对象之间的转换 | 方法名称 | 描述 | | ------------------------------------------------------------ | ------------------------- | | supportJavaTypeKey | 回到Java中的对象类型 | | supportExcelTypeKey | 返回excel中的对象enum | | `convertToJavaData` (ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception | 将excel对象转换为Java对象 | | `convertToJavaData` (ReadConverterContext context) throws Exception | 将excel对象转换为Java对象 | | `convertToExcelData` (T value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception | 将Java对象转换为excel对象 | | `convertToExcelData` (WriteConverterContext context) throws Exception | 将Java对象转换为excel对象 | ### 九、填充相关 #### `FillConfig` 填充配置 | 属性名称 | 描述 | | ----------- | ------------------------------------------------------------ | | direction | 书写方向枚举类 | | forceNewRow | 每次使用list参数时,重新创建一个新行。默认为create。警告:如果您使用forceNewRow设置为true,将不能使用异步写文件,简单的 说整个文件将存储在内存中。 | | autoStyle | 自动继承样式 默认true |