Excel-Boot 是一款 Excel 导入导出解决方案组成的轻量级开源组件.
如果喜欢或愿意使用, 请 star 本项目或者点击 donate 图标捐赠我们
如果是企业使用, 为了产品推广, 请通过评论, Issue,PullRequest README 的合作企业告诉我们企业名称
有任何问题可以通过 issue 或者评论或者添加 QQ 群 (716145748) 告知我们, 尽力第一时间解决您的问题
合作企业:
开源库(同步更新):
GitHub: https://github.com/programmeres/excel-boot
码云: https://gitee.com/nw1992/easy-poi
功能简介
浏览器导出 Excel 文件(支持单 / 多 sheet)
浏览器导出 Excel 模板文件
指定路径生成 Excel 文件(支持单 / 多 sheet)
返回 Excel 文件 (支持单 / 多 sheet) 的 OutputStream, 一般用于将 Excel 文件上传到远程, 例如 FTP
导入 Excel 文件(支持单 / 多 sheet)
功能强大
1. 解决导出大量数据造成的内存溢出问题(支持分页查询数据库, 采用 poi 官方推荐 API(SXSSFWorkbook), 实现指定行数刷新到磁盘)
2. 解决导入大量数据造成的内存溢出问题(支持分页插入数据库, 采用 poi 官方推荐 API(XSSF and SAX), 采用 SAX 模式一行行读取到内存当中去)
3. 解决含有占位符的空假行造成的读空值问题
4. 解决 Long 类型或者 BigDecimal 的精度不准问题
组件特色
1. 导入可以自定义解析成功或失败的处理逻辑
2. 导出支持分页查询, 全量查询, 自定义每条数据的处理逻辑
3. 内置缓存, 3 万条 11 列数据, 排除查询数据所用时间, 第一次导出 2.2s 左右, 第二次导出在 1.4s 左右; 第一次导入 3.5s 左右, 第二次导入 2.5s 左右
4. 注解操作, 轻量且便捷
5. 内置常用正则表达式类 RegexConst(身份证号, 手机号, 金额, 邮件)
6. 可配置是否适配单元格宽度, 默认开启(单元格内容超过 20 个汉字不再增加宽度, 3 万条 11 列数据, 耗时 50ms 左右, 用时与数据量成正比)
7. 假如出现异常, Sheet, 行, 列位置也都一并打印
8. 注解中的用户自定义字符串信息以及 Excel 信息已全部 trim, 不用担心存在前后空格的风险
9.Excel 样式简洁, 大方, 美观
10. 导出的单条数据假如全部属性都为 null 或 0 或 0.0 或 0.00 或空字符串者 null 字符串, 自动忽略, 此特性也可让用户自定义忽略规则
11. 除了直接返回 OutputStream 的方法以外的导出方法, 正常或异常情况都会自动关闭 OutputStrem,Workbook 流
组件需知
导入 & 导出
1. 导入和导出只支持尾缀为 xlsx 的 Excel 文件
2. 标注注解的属性顺序即 Excel 列的排列顺序
3. 时间转化格式 (dateFormat) 默认为 "yyyy-MM-dd HH:mm:ss"
导入
1. 当导入 Excel, 读取到空行, 则停止读取当前 Sheet 的后面数据行
2. 导入 Excel 文件, 单元格格式使用文本或者常规, 防止出现不可预测异常
3. 导入字段类型支持: Date,Short(short),Integer(int),Double(double),Long(long),Float(float),BigDecimal,String 类型
4. 导入 BigDecimal 字段精度默认为 2, roundingMode 默认为 BigDecimal.ROUND_HALF_EVEN, scale 设置为 - 1 则不进行格式化
5. 第一行有效单元格内必须包含内容并且以第一行为依据, 导入 Excel 文件列数必须等于标注注解的属性数量
6.Date 类型字段, Excel 与时间转化格式 (dateFormat) 相比, 格式要保持一致 (反例: 2018/12/31 和 "yyyy-MM-dd") 并且长度要一致或更长(反例:"2018-12-31" 和 yyyy-MM-dd HH:mm:ss"), 否则 SimpleDateFormat 将解析失败, 报"Unparseable date:"
导出
1. 导出 BigDecimal 字段默认不进行精度格式化
2. 分页查询默认从第一页开始, 每页 3000 条
3.Excel 每超过 2000 条数据, 将内存中的数据刷新到磁盘当中去
4. 使用分 Sheet 导出方法, 每 8 万行数据分 Sheet
5. 当使用 (exportResponse,exportStream,generateExcelStream) 方法时, 当单个 Sheet 超过 100 万条则会分 Sheet
6. 标注属性类型要与数据库类型保持一致
7. 如果想提高性能, 并且内存允许, 并发导出量不大, 可以根据实际场景适量改变分页条数和磁盘刷新量
扩展
1. 新建子类继承 ExcelBoot 类, 使用子类构造器覆盖以下默认参数, 作为通用配置
2. 直接调用以下两个构造器, 用于临时修改配置
- /**
- * HttpServletResponse 通用导出 Excel 构造器
- */
- ExportBuilder(HttpServletResponse response, String fileName, Class excelClass, Integer pageSize, Integer rowAccessWindowSize, Integer recordCountPerSheet, Boolean openAutoColumWidth)
- /**
- * OutputStream 通用导出 Excel 构造器
- */
- ExportBuilder(OutputStream outputStream, String fileName, Class excelClass, Integer pageSize, Integer rowAccessWindowSize, Integer recordCountPerSheet, Boolean openAutoColumWidth)
- /**
- * Excel 自动刷新到磁盘的数量
- */
- public static final int DEFAULT_ROW_ACCESS_WINDOW_SIZE = 2000;
- /**
- * 分页条数
- */
- public static final int DEFAULT_PAGE_SIZE = 3000;
- /**
- * 分 Sheet 条数
- */
- public static final int DEFAULT_RECORD_COUNT_PEER_SHEET = 80000;
- /**
- * 是否开启自动适配宽度
- */
- public static final boolean OPEN_AUTO_COLUM_WIDTH = true;
版本
当前为 2.0 版本, 新版本正在开发
使用手册
1. 引入 Maven 依赖
2. 将需要导出或者导入的实体属性上标注 @ExportField 或 @ImportField 注解
3. 直接调用导出或导入 API 即可
POM.xml
- <dependency>
- <groupId>io.GitHub.magic-core</groupId>
- <artifactId>Excel-boot</artifactId>
- <version>2.0</version>
- </dependency>
导出导入实体对象
- /**
- * 导出导入实体对象
- */
- public class UserEntity {
- /**
- * Integer 类型字段
- */
- @ExportField(columnName = "ID", defaultCellValue = "1")
- @ImportField(required = true)
- private Integer id;
- /**
- * String 类型字段
- */
- @ExportField(columnName = "姓名", defaultCellValue = "张三")
- @ImportField(regex = IDCARD_REGEX, regexMessage="身份证校验失败")
- private String name;
- /**
- * BigDecimal 类型字段
- */
- @ExportField(columnName = "收入金额", defaultCellValue = "100", scale = 2, roundingMode=BigDecimal.ROUND_HALF_EVEN)
- @ImportField(scale = 2, roundingMode=BigDecimal.ROUND_HALF_EVEN)
- private BigDecimal money;
- /**
- * Date 类型字段
- */
- @ExportField(columnName = "创建时间", dateFormat="yyyy-MM-dd", defaultCellValue = "2019-01-01")
- @ImportField(dateFormat="yyyy-MM-dd")
- private Date birthDayTime;
- }
导出 API-Demo
- /**
- * 导出 API-Demo
- *
- * UserEntity 是标注注解的类, Excel 映射的导出类
- * ParamEntity 是数据层查询的参数对象
- * ResultEntity 是数据层查询到的 List 内部元素
- * UserEntity 可以和 ResultEntity 使用同一个对象, 即直接在数据层查询的结果对象上标注注解(建议使用两个对象, 实现解耦)
- *
- * pageQuery 方法是用户自己实现, 根据查询条件和当前页数和每页条数进行数据层查询
- * convert 方法是用户自己实现, 参数就是您查询出来的 list 中的每个元素引用, 您可以对对象属性的转换或者对象的转换, 如果不进行转换, 直接返回参数对象即可
- */
- @Controller
- @RequestMapping("/export")
- public class TestController {
- /**
- * 浏览器导出 Excel
- *
- * @param httpServletResponse
- */
- @RequestMapping("/exportResponse")
- public void exportResponse(HttpServletResponse httpServletResponse) {
- ParamEntity queryQaram = new ParamEntity();
- ExcelBoot.ExportBuilder(httpServletResponse, "Excel 文件名", UserEntity.class).exportResponse(queryQaram,
- new ExportFunction<ParamEntity, ResultEntity>() {
- /**
- * @param queryQaram 查询条件对象
- * @param pageNum 当前页数, 从 1 开始
- * @param pageSize 每页条数, 默认 3000
- * @return
- */
- @Override
- public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) {
- // 分页查询操作
- return new ArrayList<ResultEntity>();
- }
- /**
- * 将查询出来的每条数据进行转换
- *
- * @param o
- */
- @Override
- public UserEntity convert(ResultEntity o) {
- // 转换操作
- }
- });
- }
- /**
- * 浏览器多 sheet 导出 Excel
- *
- * @param httpServletResponse
- */
- @RequestMapping("/exportMultiSheetResponse")
- public void exportMultiSheetResponse(HttpServletResponse httpServletResponse) {
- ParamEntity queryQaram = new ParamEntity();
- ExcelBoot.ExportBuilder(httpServletResponse, "Excel 文件名", UserEntity.class).exportMultiSheetStream(queryQaram,
- new ExportFunction<ParamEntity, ResultEntity>() {
- /**
- * @param queryQaram 查询条件对象
- * @param pageNum 当前页数, 从 1 开始
- * @param pageSize 每页条数, 默认 3000
- * @return
- */
- @Override
- public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) {
- // 分页查询操作
- return new ArrayList<ResultEntity>();
- }
- /**
- * 将查询出来的每条数据进行转换
- *
- * @param o
- */
- @Override
- public UserEntity convert(ResultEntity o) {
- // 转换操作
- }
- });
- }
- /**
- * 导出 Excel 到指定路径
- */
- @RequestMapping("/exportStream")
- public void exportStream() throws FileNotFoundException {
- ParamEntity queryQaram = new ParamEntity();
- ExcelBoot.ExportBuilder(new FileOutputStream(new File("C:\\Users\\Excel 文件. xlsx")), "Sheet 名", UserEntity.class)
- .exportStream(queryQaram, new ExportFunction<ParamEntity, ResultEntity>() {
- /**
- * @param queryQaram 查询条件对象
- * @param pageNum 当前页数, 从 1 开始
- * @param pageSize 每页条数, 默认 3000
- * @return
- */
- @Override
- public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) {
- // 分页查询操作
- return new ArrayList<ResultEntity>();
- }
- /**
- * 将查询出来的每条数据进行转换
- *
- * @param o
- */
- @Override
- public UserEntity convert(ResultEntity o) {
- // 转换操作
- }
- });
- }
- /**
- * 导出多 sheet Excel 到指定路径
- */
- @RequestMapping(value = "exportMultiSheetStream")
- public void exportMultiSheetStream() throws FileNotFoundException {
- ParamEntity queryQaram = new ParamEntity();
- ExcelBoot.ExportBuilder(new FileOutputStream(new File("C:\\Users\\Excel 文件. xlsx")), "Sheet 名", UserEntity.class)
- .exportMultiSheetStream(queryQaram, new ExportFunction<ParamEntity, ResultEntity>() {
- /**
- * @param queryQaram 查询条件对象
- * @param pageNum 当前页数, 从 1 开始
- * @param pageSize 每页条数, 默认 3000
- * @return
- */
- @Override
- public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) {
- // 分页查询操作
- return new ArrayList<ResultEntity>();
- }
- /**
- * 将查询出来的每条数据进行转换
- *
- * @param o
- */
- @Override
- public UserEntity convert(ResultEntity o) {
- // 转换操作
- }
- });
- }
- /**
- * 生成 Excel OutputStream 对象
- */
- @RequestMapping(generateStream)
- public void generateExcelStream() throws FileNotFoundException {
- ParamEntity queryQaram = new ParamEntity();
- OutputStream outputStream = ExcelBoot.ExportBuilder(new FileOutputStream(new File("C:\\Users\\Excel 文件. xlsx")), "Sheet 名", UserEntity.class)
- .generateExcelStream(queryQaram, new ExportFunction<ParamEntity, ResultEntity>() {
- /**
- * @param queryQaram 查询条件对象
- * @param pageNum 当前页数, 从 1 开始
- * @param pageSize 每页条数, 默认 3000
- * @return
- */
- @Override
- public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) {
- // 分页查询操作
- return new ArrayList<ResultEntity>();
- }
- /**
- * 将查询出来的每条数据进行转换
- *
- * @param o
- */
- @Override
- public UserEntity convert(ResultEntity o) {
- // 转换操作
- }
- });
- }
- /**
- * 生成多 Sheet Excel OutputStream 对象
- */
- @RequestMapping(generateMultiSheetStream)
- public void generateMultiSheetExcelStream() throws FileNotFoundException {
- ParamEntity queryQaram = new ParamEntity();
- OutputStream outputStream = ExcelBoot.ExportBuilder(new FileOutputStream(new File("C:\\Users\\Excel 文件. xlsx")), "Sheet 名", UserEntity.class)
- .generateMultiSheetExcelStream(queryQaram, new ExportFunction<ParamEntity, ResultEntity>() {
- /**
- * @param queryQaram 查询条件对象
- * @param pageNum 当前页数, 从 1 开始
- * @param pageSize 每页条数, 默认 3000
- * @return
- */
- @Override
- public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) {
- // 分页查询操作
- return new ArrayList<ResultEntity>();
- }
- /**
- * 将查询出来的每条数据进行转换
- *
- * @param o
- */
- @Override
- public UserEntity convert(ResultEntity o) {
- // 转换操作
- }
- });
- }
- /**
- * 导出 Excel 模板
- */
- @RequestMapping("/exportTemplate")
- public void exportTemplate(HttpServletResponse httpServletResponse) {
- ExcelBoot.ExportBuilder(httpServletResponse, "Excel 模板名称", UserEntity.class).exportTemplate();
- }
- }
导入 API-Demo
- /**
- * 导入 API-Demo
- *
- * UserEntity 是标注注解的类, Excel 映射的导入类, onProcess 的 userEntity 参数则是 Excel 每行数据的映射实体
- * ErrorEntity 是封装了每行 Excel 数据常规校验后的错误信息实体, 封装了 sheet 号, 行号, 列号, 单元格值, 所属列名, 错误信息
- *
- * onProcess 方法是用户自己实现, 当经过正则或者判空常规校验成功后执行的方法, 参数是每行数据映射的实体
- * convert 方法是用户自己实现, 当经过正则或者判空常规校验失败后执行的方法
- */
- @Controller
- @RequestMapping("/import")
- public class TestController {
- @RequestMapping("/importExcel")
- public void importExcel() throws IOException {
- ExcelBoot.ImportBuilder(new FileInputStream(new File("C:\\Users\\ 导入 Excel 文件. xlsx")), UserEntity.class)
- .importExcel(new ExcelImportFunction<UserEntity>() {
- /**
- * @param sheetIndex 当前执行的 Sheet 的索引, 从 1 开始
- * @param rowIndex 当前执行的行数, 从 1 开始
- * @param resultEntity Excel 行数据的实体
- */
- @Override
- public void onProcess(int sheetIndex, int rowIndex, UserEntity userEntity) {
- // 对每条数据自定义校验以及操作
- // 分页插入: 当读取行数到达用户自定义条数执行插入数据库操作
- }
- /**
- * @param errorEntity 错误信息实体
- */
- @Override
- public void onError(ErrorEntity errorEntity) {
- // 操作每条数据非空和正则校验后的错误信息
- }
- });
- }
- }
来源: http://www.tuicool.com/articles/yQbquiq