当前位置:   article > 正文

Alibaba的EasyExcel使用心得

easyexcel

目录

前言:

开发前准备:

1、导入依赖

2、导出实体类

1)常用注解

2)注意内容

3、监听器

ExcelMapper

Handler

4、模板文件

5、测试demo

1)调整单元格样式

2)插入图片

最终效果:

 项目实战:

1、读Excel

Controller

Service

ServiceImpl

2、写Excel

Controller

Service

ServiceImpl

前言:

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便。

官网:EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel (alibaba.com)

开发前准备:

1、导入依赖

  1. <dependency>
  2.   <groupId>com.alibaba</groupId>
  3.   <artifactId>easyexcel</artifactId>
  4.   <version>2.2.3</version>
  5. </dependency>

2、导出实体类

  1. import com.alibaba.excel.annotation.ExcelIgnore;
  2. import com.alibaba.excel.annotation.ExcelProperty;
  3. import com.baomidou.mybatisplus.annotation.TableName;
  4. import lombok.Data;
  5. import java.util.Date;
  6. @Data
  7. @TableName("user")
  8. public class ExcelUserEntityImport {
  9. private static final long serialVersionUID = 1L;
  10. @ExcelProperty(value = "用户名")
  11. private String username;
  12. @ExcelProperty(value = "密码")
  13. private String password;
  14. @ExcelProperty(value = "手机号")
  15. private String phone;
  16. @ExcelProperty("性别标签")
  17. private Integer sex;
  18. @ExcelProperty({"基础信息","年龄"})
  19. private Integer age;
  20. @ExcelProperty({"基础信息","性别"})
  21. private String gender;
  22. @ExcelProperty(value ={"基础信息","地址"})
  23. private String address;
  24. @ExcelIgnore
  25. //@ExcelProperty(converter = DateConverter.class,value = "生日")
  26. private Date birthday;
  27. //忽略导出字段
  28. @ExcelIgnore
  29. private Long id;
  30. @ExcelIgnore
  31. private String hobby;
  32. @ExcelIgnore
  33. private Date creatTime;
  34. @ExcelIgnore
  35. private Date updateTime;
  36. @ExcelIgnore
  37. private Integer isDeleted;
  38. }

1)常用注解

@ExcelProperty(value = "用户名",index=0)         ->导出属性名

@ExcelIgnore                                                       ->忽略导出的字段

2)注意内容

如果在@ExcelProperty中不指定index的值,index会默认从0开始排版,如果指定顺序,导出的表格则会按照index顺序进行排版。

3、监听器

  1. import com.alibaba.excel.context.AnalysisContext;
  2. import com.alibaba.excel.event.AnalysisEventListener;
  3. import com.alibaba.fastjson.JSON;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. // 有个很重要的点 UserDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
  10. @Slf4j
  11. public class UserDataListener extends AnalysisEventListener<ExcelUserEntityImport> {
  12. private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUserEntityImport.class);
  13. /**
  14. * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
  15. */
  16. private static final int BATCH_COUNT = 100;
  17. /**
  18. * 缓存的数据
  19. */
  20. private List<ExcelUserEntityImport> list = new ArrayList<>(BATCH_COUNT);
  21. @Override
  22. public void invoke(ExcelUserEntityImport data, AnalysisContext analysisContext) {
  23. LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
  24. String gender = data.getGender();
  25. Integer sex = getSexByGender(gender);
  26. data.setSex(sex);
  27. /**
  28. * 自己要完成的逻辑
  29. * 进行自己功能的实现
  30. */
  31. list.add(data);
  32. if (list.size() >= BATCH_COUNT) {
  33. // saveData();
  34. // 存储完成清理 list
  35. list = new ArrayList<>(BATCH_COUNT);
  36. }
  37. }
  38. public Integer getSexByGender(String gender) {
  39. switch (gender){
  40. case "男":
  41. return 1;
  42. case "女":
  43. return 2;
  44. case "未知":
  45. return 3;
  46. default:
  47. throw new RuntimeException("性别异常");
  48. }
  49. }
  50. @Override
  51. public void doAfterAllAnalysed(AnalysisContext analysisContext) {
  52. LOGGER.info("所有数据解析完成!");
  53. }
  54. /**
  55. * 自己要完成的逻辑
  56. * 进行自己功能的实现
  57. */
  58. public void doSome(){}
  59. }

ExcelMapper

  1. public interface ExcelMapper extends BaseMapper<ExcelUserEntityImport> {
  2. }

Handler

  1. import com.alibaba.excel.write.handler.SheetWriteHandler;
  2. import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
  3. import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
  4. import org.apache.poi.ss.usermodel.DataValidation;
  5. import org.apache.poi.ss.usermodel.DataValidationConstraint;
  6. import org.apache.poi.ss.usermodel.DataValidationHelper;
  7. import org.apache.poi.ss.usermodel.Sheet;
  8. import org.apache.poi.ss.util.CellRangeAddressList;
  9. import java.util.HashMap;
  10. import java.util.Map;
  11. //要在导出时添加到对应的handler中
  12. public class ExcelTemplateHandler implements SheetWriteHandler {
  13. @Override
  14. public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
  15. }
  16. @Override
  17. public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
  18. String[] sexTypes = new String[]{"男", "女", "未知"};
  19. Map<Integer, String[]> mapDropDown = new HashMap<>();
  20. // 3 为导出表格索引,索引冲0开始。 如不在excel导出实体类指定,则按照先后顺序
  21. mapDropDown.put(3, sexTypes);
  22. Sheet sheet = writeSheetHolder.getSheet();
  23. ///开始设置下拉框
  24. DataValidationHelper helper = sheet.getDataValidationHelper();//设置下拉框
  25. for (Map.Entry<Integer, String[]> entry : mapDropDown.entrySet()) {
  26. /***起始行、终止行、起始列、终止列**/
  27. CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, entry.getKey(), entry.getKey());
  28. /***设置下拉框数据**/
  29. DataValidationConstraint constraint = helper.createExplicitListConstraint(entry.getValue());
  30. DataValidation dataValidation = helper.createValidation(constraint, addressList);
  31. /*处理Excel兼容性问题
  32. if (dataValidation instanceof XSSFDataValidation) {
  33. dataValidation.setSuppressDropDownArrow(true);
  34. dataValidation.setShowErrorBox(true);
  35. } else {
  36. dataValidation.setSuppressDropDownArrow(false);
  37. }*/
  38. sheet.addValidationData(dataValidation);
  39. }
  40. }
  41. }

4、模板文件

5、测试demo

  1. @Test
  2. @SneakyThrows
  3. public void test() {
  4. /**
  5. * 1、进行模板填充
  6. */
  7. // 生成Excel路径
  8. String filePath = "a.xlsx";
  9. //模板路径
  10. String templatePath = "temp.xlsx";
  11. ExcelWriter excelWriter = EasyExcel.write(filePath).withTemplate(templatePath).build();
  12. WriteSheet writeSheet = EasyExcel.writerSheet().build();
  13. //代表表格每次都会重新生成新的一行,而不是使用下面的空行。
  14. FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
  15. // 填充数据
  16. ExcelTemplate template = new ExcelTemplate();
  17. template.setEaddress("河南省xxxx")
  18. .setEbegintime(new Date())
  19. .setEdesc("摸鱼ing")
  20. .setEendtime(new Date())
  21. .setEidcard("41xxxxxxxxxxx")
  22. .setEmajor("电子商务")
  23. .setEmarriage("未婚")
  24. .setEname("小张")
  25. .setEnation("汉")
  26. .setEbirthday(new Date())
  27. .setEpost("天才少女")
  28. .setEgradeationtime(new Date())
  29. .setEschool("xxxx")
  30. .setEsex("女")
  31. .setEworkcom("天庭六部")
  32. .setEsalary(10000000.0)
  33. .setEnative("未知");
  34. //进行字段的填充
  35. excelWriter.fill(template, writeSheet);
  36. //进行模板表格的填充 datal和模板相互对应
  37. //excelWriter.fill(new FillWrapper(template, template, fillConfig, writeSheet);
  38. // 别忘记关闭流
  39. excelWriter.finish();

进行测试后发现,单元格相关没有对应格式。

1)调整单元格样式

  1. /**
  2. * 2、进行单元格合并 样式调整
  3. */
  4. //注意:一定要先把文件创建完后再进行单元格样式设置
  5. FileInputStream inputStream = new FileInputStream(new File(filePath));
  6. XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
  7. XSSFSheet sheet = workbook.getSheetAt(0);
  8. // 合并列 列和行均为0开始
  9. sheet.addMergedRegion(new CellRangeAddress(16, 16, 1, 2));
  10. sheet.addMergedRegion(new CellRangeAddress(16, 16, 3, 4));
  11. sheet.addMergedRegion(new CellRangeAddress(16, 16, 5, 6));
  12. sheet.addMergedRegion(new CellRangeAddress(16, 16, 7, 8));
  13. sheet.addMergedRegion(new CellRangeAddress(16, 16, 9, 10));
  14. sheet.addMergedRegion(new CellRangeAddress(16, 16, 11, 13));
  15. //进行下边框的设置
  16. RegionUtil.setBorderBottom(BorderStyle.THIN,new CellRangeAddress(15, 15, 1, 13),sheet);

2)插入图片

  1. /**
  2. * 3、插入图片
  3. */
  4. // 转换成流
  5. ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
  6. BufferedImage bufferImg = ImageIO.read(new File("note.jpg"));
  7. ImageIO.write(bufferImg, "jpg", byteArrayOut);
  8. XSSFDrawing patriarch = sheet.createDrawingPatriarch();
  9. /**
  10. * new XSSFClientAnchor(0, 0, 0, 0, (short) 11, 2, (short) 12, 6);
  11. *4个参数是偏移量,设置为0即可 row1为起始行 row2结束行 前到后不到 (short) 11为起始列 (short) 12 为结束列
  12. * 设置好这些参数就能在指定位置插入图片
  13. */
  14. XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) 11, 3, (short) 14, 14);
  15. anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
  16. patriarch.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
  17. String mergeExcelPath="merge.xlsx";
  18. FileOutputStream outputStream = new FileOutputStream(mergeExcelPath);
  19. workbook.write(outputStream);
  20. outputStream.flush();

最终效果:

 项目实战:

1、读Excel

Controller

  1. @GetMapping("/exportExcel")
  2. @ApiOperation(value = "批量导出基础字段文件", notes = "导出file")
  3. public void exportExcel(HttpServletResponse response, @RequestParam String ids) throws IOException {
  4. List<Long> list = Func.toLongList(ids);
  5. userService.exportExcel(response, list);
  6. }

Service

void exportExcel(HttpServletResponse response, List<Long> list);

ServiceImpl

  1. @SneakyThrows
  2. @Override
  3. public void exportExcel(HttpServletResponse response, List<Long> list) {
  4. //导出所需数据(自己要的数据)
  5. List<User> userList = baseMapper.selectBatchIds(list);
  6. response.setContentType("application/vnd.ms-excel");
  7. response.setCharacterEncoding("utf-8");
  8. String fileName = URLEncoder.encode("用户数据", "UTF-8");
  9. response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
  10. EasyExcel.write(response.getOutputStream(), ExcelUserEntityImport.class)
  11. .registerConverter(new LongStringConverter())
  12. //样式的处理类 需要就注册进来.registerWriteHandler(new ExcelTemplateHandler())
  13. .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
  14. .sheet("数据导出").doWrite(userList);
  15. }

2、写Excel

Controller

  1. /**
  2. * 上传文件
  3. * @param file 文件
  4. */
  5. @PostMapping("/uploadFile")
  6. @ApiOperation(value = "上传文件", notes = "传入file")
  7. public R uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
  8. return userService.uploadFile(file);
  9. }

Service

R uploadFile(MultipartFile file);

ServiceImpl

  1. @Override
  2. public R uploadFile(MultipartFile file) {
  3. List<ExcelUserEntityImport> excelList=null;
  4. try {
  5. excelList = read(file.getInputStream(), ExcelUserEntityImport.class, new UserDataListener()).sheet().doReadSync();
  6. } catch (IOException e) {
  7. e.printStackTrace();
  8. }
  9. excelService.saveBatch(excelList);
  10. return R.ok();
  11. }

这样下来就大功告成了!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/程序性能提升者/article/detail/61134
推荐阅读
相关标签
  

闽ICP备14008679号