• POI 和 EasyExcel


    POI 和 EasyExcel

    常用信息

    1、将用户信息导出为 excel 表格(导出数据....)

    2、将 Excel 表中的信息录入到网站数据库(习题上传....)大大减轻网站录入量!

    开发中经常会设计到 excel 的处理,如导出 Excel,导入 Excel 到数据库中!

    操作 Excel 目前比较流行的就是 Apache POI 和阿里巴巴的 easyExcel!

    Apache POI

    Apache POI 官网:Apache POI - the Java API for Microsoft Documents

     easyExcel

    easyExcel官网地址:https://github.com/alibaba/easyexcel

    EasyExcel 是阿里巴巴开源的一个 excel 处理框架以使用简单、节省内存著称

    EasyExcel 能大大减少占用内存的主要原因是在解析 Excel 时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。

    内存问题:POI = 100w 先加载到内存 OOM。。在写文件 es=1

    下图是 EasyExcel 和 POI 在解析 Excel时的对比图。

    官方文档:EasyExcel(文档已经迁移) · 语雀 

    POI-Excel写

    创建项目

    1、建立一个空项目,创建普通 Maven 的 Moudle kuang-poi

    2、引入 pom 依赖

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.apache.poigroupId>
    4. <artifactId>poiartifactId>
    5. <version>3.9version>
    6. dependency>
    7. <dependency>
    8. <groupId>org.apache.poigroupId>
    9. <artifactId>poi-ooxmlartifactId>
    10. <version>3.9version>
    11. dependency>
    12. <dependency>
    13. <groupId>joda-timegroupId>
    14. <artifactId>joda-timeartifactId>
    15. <version>2.10.1version>
    16. dependency>
    17. <dependency>
    18. <groupId>junitgroupId>
    19. <artifactId>junitartifactId>
    20. <version>4.12version>
    21. dependency>
    22. dependencies>

    03|07 版本的写,就是对象不同,方法一样的!

    需要注意:2003 版本和 2007 版本存在兼容性的问题!03 最多只有 65535 行!

    1、工作簿: 2、工作表: 3、行: 4、列:

    03 版本:

    1. String PATH = "/Users/zhang/Desktop/gitee/excel/zhang-poi";
    2. @Test
    3. public void testWirate03() throws IOException {
    4. // 1、创建一个工作簿 03
    5. Workbook workbook = new HSSFWorkbook();
    6. // 2、创建一个工作表
    7. Sheet sheet = workbook.createSheet("狂神观众统计表");
    8. // 3、创建一个行 0 代表第一行 (1,1)
    9. Row row1 = sheet.createRow(0);
    10. // 4、创建一个单元格 0 代表第一个单元格
    11. Cell cell11 = row1.createCell(0);
    12. // 去格子里边写入一个数据 第一行的第一列 (1,1)
    13. cell11.setCellValue("今日新增观众");
    14. // 5、创建第二个单元格 1 代表第二个单元格
    15. Cell cell12 = row1.createCell(1);
    16. // 去格子里边写入一个数据 第一行的第二列 (1,2)
    17. cell12.setCellValue(666);
    18. // 第二行
    19. Row row2 = sheet.createRow(1);
    20. // 第二行的第一列 (2,1)
    21. Cell cell21 = row2.createCell(0);
    22. cell21.setCellValue("统计时间");
    23. // 第二行的第二列 (2,2)
    24. Cell cell22 = row2.createCell(1);
    25. String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
    26. cell22.setCellValue(time);
    27. // 生成一张表(IO 流) 03 版本就是使用 xls 结尾!
    28. FileOutputStream fileOutputStream = new FileOutputStream(PATH + "狂神观众统计表03.xls");
    29. // 输出
    30. workbook.write(fileOutputStream);
    31. // 关闭流
    32. fileOutputStream.close();
    33. System.out.println("狂神观众统计表03 生成完毕!");
    34. }

    07 版本:

    1. String PATH = "/Users/zhang/Desktop/gitee/excel/zhang-poi";
    2. @Test
    3. public void testWirate07() throws IOException {
    4. // 1、创建一个工作簿 07
    5. Workbook workbook = new XSSFWorkbook();
    6. // 2、创建一个工作表
    7. Sheet sheet = workbook.createSheet("狂神观众统计表");
    8. // 3、创建一个行 0 代表第一行 (1,1)
    9. Row row1 = sheet.createRow(0);
    10. // 4、创建一个单元格 0 代表第一个单元格
    11. Cell cell11 = row1.createCell(0);
    12. // 去格子里边写入一个数据 第一行的第一列 (1,1)
    13. cell11.setCellValue("今日新增观众");
    14. // 5、创建第二个单元格 1 代表第二个单元格
    15. Cell cell12 = row1.createCell(1);
    16. // 去格子里边写入一个数据 第一行的第二列 (1,2)
    17. cell12.setCellValue(777);
    18. // 第二行
    19. Row row2 = sheet.createRow(1);
    20. // 第二行的第一列 (2,1)
    21. Cell cell21 = row2.createCell(0);
    22. cell21.setCellValue("统计时间");
    23. // 第二行的第二列 (2,2)
    24. Cell cell22 = row2.createCell(1);
    25. String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
    26. cell22.setCellValue(time);
    27. // 生成一张表(IO 流) 07 版本就是使用 xlsx 结尾!
    28. FileOutputStream fileOutputStream = new FileOutputStream(PATH + "狂神观众统计表07.xlsx");
    29. // 输出
    30. workbook.write(fileOutputStream);
    31. // 关闭流
    32. fileOutputStream.close();
    33. System.out.println("狂神观众统计表07 生成完毕!");
    34. }

    注意对象的一个区别,文件后缀

    大文件写 HSSF

    缺点:最多只能处理 65536 行,否则会抛出异常

    java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)

    优点:过程写入缓存,不操作磁盘,最后一次性写入磁盘,速度快

    1. String PATH = "/Users/zhang/Desktop/gitee/excel/zhang-poi";
    2. @Test
    3. public void testWirate03BigData() throws IOException {
    4. // 获取当前时间
    5. long begin = System.currentTimeMillis();
    6. // 创建工作簿
    7. Workbook workook = new HSSFWorkbook();
    8. // 创建工作表
    9. Sheet sheet = workook.createSheet();
    10. // 写入数据 超过 65536 行就会报错 java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)
    11. for (int rowNum = 0; rowNum < 65536; rowNum++) {
    12. // 创建行
    13. Row row = sheet.createRow(rowNum);
    14. for (int cellNum = 0; cellNum < 10; cellNum++) {
    15. // 创建列
    16. Cell cell = row.createCell(cellNum);
    17. cell.setCellValue(cellNum);
    18. }
    19. }
    20. System.out.println("over");
    21. // 生成一张表(io 流) 03 版本就是使用 xls 结尾!
    22. FileOutputStream fileOutputStream = new FileOutputStream(PATH + "testWirate03BigData.xls");
    23. // 输出
    24. workook.write(fileOutputStream);
    25. // 关闭流
    26. fileOutputStream.close();
    27. long end = System.currentTimeMillis();
    28. double time = (double) (end - begin) / 1000;
    29. System.out.println("时间差为:" + time);
    30. }

    大文件写 XSSF

    缺点:写数据时速度非常慢,非常耗内存,也会发生内存溢出,如 100 万条

    优点:可以写较大的数据量,如 20 万条

    1. String PATH = "/Users/zhang/Desktop/gitee/excel/zhang-poi";
    2. // 耗时较长! 优化,缓存
    3. @Test
    4. public void testWirate07BigData() throws IOException {
    5. // 获取当前时间
    6. long begin = System.currentTimeMillis();
    7. // 创建工作簿
    8. Workbook workook = new XSSFWorkbook();
    9. // 创建工作表
    10. Sheet sheet = workook.createSheet();
    11. // 写入数据
    12. for (int rowNum = 0; rowNum < 100000; rowNum++) {
    13. // 创建行
    14. Row row = sheet.createRow(rowNum);
    15. for (int cellNum = 0; cellNum < 10; cellNum++) {
    16. // 创建列
    17. Cell cell = row.createCell(cellNum);
    18. cell.setCellValue(cellNum);
    19. }
    20. }
    21. System.out.println("over");
    22. // 生成一张表(io 流) 07 版本就是使用 xlsx 结尾!
    23. FileOutputStream fileOutputStream = new FileOutputStream(PATH + "testWirate07BigData2.xlsx");
    24. // 输出
    25. workook.write(fileOutputStream);
    26. // 关闭流
    27. fileOutputStream.close();
    28. long end = System.currentTimeMillis();
    29. double time = (double) (end - begin) / 1000;
    30. System.out.println("时间差为:" + time);
    31. }

    大文件写 SXSSF

    优点:可以写非常大的数据量,如 100 万条甚至更多条,写数据速度更快,占用更少内存

    注意:

    过程中会产生临时文件,需要清理临时文件

    默认由 100 条记录被保存在内存中,如果超过这数量,则最前面的数据被写入临时文件

    如果想自定义内存中的数量,可以使用 new SXSSFWorkbook(数量)

    1. String PATH = "/Users/zhang/Desktop/gitee/excel/zhang-poi";
    2. @Test
    3. public void testWirate07BigDataS() throws IOException {
    4. // 获取当前时间
    5. long begin = System.currentTimeMillis();
    6. // 创建工作簿
    7. Workbook workbook = new SXSSFWorkbook();
    8. // 创建工作表
    9. Sheet sheet = workbook.createSheet();
    10. // 写入数据
    11. for (int rowNum = 0; rowNum < 1000000; rowNum++) {
    12. // 创建行
    13. Row row = sheet.createRow(rowNum);
    14. for (int cellNum = 0; cellNum < 10; cellNum++) {
    15. // 创建列
    16. Cell cell = row.createCell(cellNum);
    17. cell.setCellValue(cellNum);
    18. }
    19. }
    20. System.out.println("over");
    21. // 生成一张表(io 流) 07 版本就是使用 xlsx 结尾!
    22. FileOutputStream fileOutputStream = new FileOutputStream(PATH + "testWirate07BigDataS2.xlsx");
    23. // 输出
    24. workbook.write(fileOutputStream);
    25. // 关闭流
    26. fileOutputStream.close();
    27. // 清除临时文件!
    28. ((SXSSFWorkbook) workbook).dispose();
    29. long end = System.currentTimeMillis();
    30. double time = (double) (end - begin) / 1000;
    31. System.out.println("时间差为:" + time);
    32. }

    SXSSFWorkbook 来自官方的解释:实现"BigGridDemo"策略的流式 XSSFWorkbook 版本。这允许写入非常大的文件而不会耗尽内存,因为任何时候只有可配置的行部分被保存在内存中。

    请注意:仍然可能会消耗大量内存,这些内存基于您正在使用的功能,例如合并区域,注释......仍然只存储在内存中,因此如果广泛使用,可能需要大量内存。

    再使用 POI 的时候!内存问题 Jprofile

    POI-Excel读

    03|07

    03 版本

    1. String PATH = "/Users/zhang/Desktop/gitee/excel/"; // zhang-poi
    2. @Test
    3. public void testRead03() throws IOException {
    4. // 获取文件流
    5. FileInputStream fileInputStream = new FileInputStream(PATH + "zhang-poi狂神观众统计表03.xls");
    6. // 1、 创建一个工作簿 将文件流放到工作簿里 使用 excel 能操作的这边也都可以操作
    7. Workbook workbook = new HSSFWorkbook(fileInputStream);
    8. // 2、得到表 获取第 1 个表
    9. Sheet sheetAt = workbook.getSheetAt(0);
    10. // 3、得到行 获取第 1 行
    11. Row row = sheetAt.getRow(0);
    12. // 4、得到列 获取第一个单元格里边的数据
    13. Cell cell = row.getCell(1);
    14. // 读取值的时候一定要注意类型,否则就会失败
    15. // 取出 cell 的值 getStringCellValue() 获取字符串类型
    16. // System.out.println("cell.getStringCellValue() = " + cell.getStringCellValue());
    17. System.out.println("cell.getNumericCellValue() = " + cell.getNumericCellValue());
    18. fileInputStream.close();
    19. }

    07 版本

    1. String PATH = "/Users/zhang/Desktop/gitee/excel/"; // zhang-poi
    2. @Test
    3. public void testRead07() throws IOException {
    4. // 获取文件流
    5. FileInputStream fileInputStream = new FileInputStream(PATH + "zhang-poi狂神观众统计表07.xlsx");
    6. // 1、 创建一个工作簿 将文件流放到工作簿里 使用 excel 能操作的这边也都可以操作
    7. Workbook workbook = new XSSFWorkbook(fileInputStream);
    8. // 2、得到表 获取第 1 个表
    9. Sheet sheetAt = workbook.getSheetAt(0);
    10. // 3、得到行 获取第 1 行
    11. Row row = sheetAt.getRow(0);
    12. // 4、得到列 获取第一个单元格里边的数据
    13. Cell cell = row.getCell(1);
    14. // 读取值的时候一定要注意类型,否则就会失败
    15. // 取出 cell 的值 getStringCellValue() 获取字符串类型
    16. // System.out.println("cell.getStringCellValue() = " + cell.getStringCellValue());
    17. System.out.println("cell.getNumericCellValue() = " + cell.getNumericCellValue());
    18. fileInputStream.close();
    19. }

    注意获取值得类型即可

    读不同的数据类型(最麻烦的就是这里)

    1. String PATH = "/Users/zhang/Desktop/gitee/excel/"; // zhang-poi
    2. @Test
    3. public void testCellType() throws IOException {
    4. // 获取文件流
    5. FileInputStream fileInputStream = new FileInputStream(PATH + "明细表.xls");
    6. // 1、 创建一个工作簿 将文件流放到工作簿里 使用 excel 能操作的这边也都可以操作
    7. Workbook workbook = new HSSFWorkbook(fileInputStream);
    8. // 2、得到表 获取第 1 个表
    9. Sheet sheetAt = workbook.getSheetAt(0);
    10. // 获取标题内容
    11. Row rowTitle = sheetAt.getRow(0);
    12. if (rowTitle != null) {
    13. // 读取行的列 数量
    14. int cellCount = rowTitle.getPhysicalNumberOfCells();
    15. for (int cellNum = 0; cellNum < cellCount; cellNum++) {
    16. // 获取单元格里边的数据 根据传入的第几列
    17. Cell cell = rowTitle.getCell(cellNum);
    18. if (cell != null) {
    19. int cellType = cell.getCellType();
    20. // 根据单元格里边的数据类型,把具体的值给读取出来
    21. String cellValue = cell.getStringCellValue();
    22. System.out.print(cellValue + "|");
    23. }
    24. }
    25. System.out.println();
    26. }
    27. // 获取表中的内容 获取表中的所有行 ?
    28. int rowCount = sheetAt.getPhysicalNumberOfRows();
    29. for (int rowNum = 1; rowNum < rowCount; rowNum++) {
    30. // 获取行里边的内容
    31. Row rowData = sheetAt.getRow(rowNum);
    32. if (rowData != null) {
    33. // 读取行中的列
    34. int cellCount = rowTitle.getPhysicalNumberOfCells();
    35. for (int cellNum = 0; cellNum < cellCount; cellNum++) {
    36. System.out.print("[" + (rowNum+1) + "-" +(cellNum+1) + "]");
    37. // 获取单元格里边的数据 根据每列
    38. Cell cell = rowData.getCell(cellNum);
    39. // 匹配列的数据类型
    40. if (cell != null) {
    41. int cellType = cell.getCellType();
    42. String cellValue = "";
    43. switch (cellType){
    44. case Cell.CELL_TYPE_STRING: // 字符串
    45. System.out.print("【String】");
    46. cellValue = cell.getStringCellValue();
    47. break;
    48. case Cell.CELL_TYPE_BOOLEAN: // 布尔类型
    49. System.out.print("【Boolean】");
    50. cellValue = String.valueOf(cell.getBooleanCellValue());
    51. break;
    52. case Cell.CELL_TYPE_BLANK: // 为空
    53. System.out.print("【Blank】");
    54. break;
    55. case Cell.CELL_TYPE_NUMERIC: // 数字(日期、普通数字)类型
    56. System.out.print("【Numeric】");
    57. // 判断当前列是不是时间日期
    58. if (HSSFDateUtil.isCellDateFormatted(cell)) {
    59. System.out.print("【日期】");
    60. Date date = cell.getDateCellValue();
    61. cellValue = new DateTime(date).toString("yyyy-MM-dd");
    62. }else {
    63. // 不是日期格式,防止数字过长
    64. System.out.print("【转换为字符串输出】");
    65. cell.setCellType(Cell.CELL_TYPE_STRING);
    66. cellValue = cell.toString();
    67. }
    68. break;
    69. case Cell.CELL_TYPE_ERROR: // 布尔类型
    70. System.out.print("【数据类型错误】");
    71. cellValue = String.valueOf(cell.getErrorCellValue());
    72. break;
    73. case Cell.CELL_TYPE_FORMULA: // 公式类型,代表这个cell存的是一个公式
    74. System.out.print("【公式】");
    75. // 6、获取计算公式
    76. FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
    77. // 8、得到第 5 行第 1 列 计算公式的内容
    78. String formula = cell.getCellFormula();
    79. // formula = SUM(A2:A4)
    80. System.out.println("formula = " + formula);
    81. // 9、计算得到值 把获取到第 5 行,第 1 列的内容放入到
    82. CellValue evaluate = formulaEvaluator.evaluate(cell);
    83. // 10、将的到的内容转化为字符串
    84. cellValue = evaluate.formatAsString();
    85. // cellValue = 600.0
    86. // System.out.println("cellValue = " + cellValue);
    87. break;
    88. }
    89. System.out.println(cellValue);
    90. }
    91. }
    92. }
    93. }
    94. fileInputStream.close();
    95. }

    计算公式(了解即可)

    1. // 计算公式
    2. @Test
    3. public void testFormula() throws IOException {
    4. // 1、获取文件流 通过文件路径 加 文件名
    5. FileInputStream fileInputStream = new FileInputStream( PATH + "公式表.xls" );
    6. // 2、创建一个工作簿,并把文件流放入工作簿当中
    7. Workbook workbook = new HSSFWorkbook(fileInputStream);
    8. // 3、得到表 获取第一个表
    9. Sheet sheetAt = workbook.getSheetAt(0);
    10. // 4、获取到第 5 行的内容
    11. Row row = sheetAt.getRow(4);
    12. // 5、获取第 5 行,第 1 列的内容
    13. Cell cell = row.getCell(0);
    14. // 6、获取计算公式
    15. FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
    16. // 7、匹配列的数据类型 输出单元格的内容
    17. int cellType = cell.getCellType();
    18. switch (cellType){
    19. case Cell.CELL_TYPE_FORMULA: // 公式
    20. // 8、得到第 5 行第 1 列 计算公式的内容
    21. String formula = cell.getCellFormula();
    22. // formula = SUM(A2:A4)
    23. System.out.println("formula = " + formula);
    24. // 9、计算得到值 把获取到第 5 行,第 1 列的内容放入到
    25. CellValue evaluate = formulaEvaluator.evaluate(cell);
    26. // 10、将的到的内容转化为字符串
    27. String cellValue = evaluate.formatAsString();
    28. // cellValue = 600.0
    29. System.out.println("cellValue = " + cellValue);
    30. break;
    31. }
    32. }

    EasyExcel操作

    导入依赖

    1. <dependency>
    2. <groupId>com.alibabagroupId>
    3. <artifactId>easyexcelartifactId>
    4. <version>3.1.1version>
    5. dependency>
    6. <dependency>
    7. <groupId>com.alibabagroupId>
    8. <artifactId>fastjsonartifactId>
    9. <version>1.2.79version>
    10. dependency>

    写入测试

    1、DemoData.java

    1. package com.zhang.easyexcelpojo;
    2. import com.alibaba.excel.annotation.ExcelIgnore;
    3. import com.alibaba.excel.annotation.ExcelProperty;
    4. import lombok.Data;
    5. import java.util.Date;
    6. @Data
    7. public class DemoData {
    8. @ExcelProperty("字符串标题")
    9. private String string;
    10. @ExcelProperty("日期标题")
    11. private Date date;
    12. @ExcelProperty("数字标题")
    13. private Double doubleData;
    14. /**
    15. * 忽略这个字段
    16. */
    17. @ExcelIgnore
    18. private String ignore;
    19. }

    2、测试写入数据:

    1. String PATH = "/Users/zhang/Desktop/gitee/excel/";
    2. private List data() {
    3. List list = new ArrayList();
    4. for (int i = 0; i < 10; i++) {
    5. DemoData data = new DemoData();
    6. data.setString("字符串" + i);
    7. data.setDate(new Date());
    8. data.setDoubleData(0.56);
    9. list.add(data);
    10. }
    11. return list;
    12. }
    13. // 根据 list 写入 excel
    14. @Test
    15. public void simplewrite(){
    16. String fileName = PATH + "EasyTest.xlsx";
    17. //这里需要指定写用哪个 class去写,然后写到第一个 sheet,名字为模板然后文件流会自动关闭
    18. // 如果这里想使用03 则 传入excelType参数即可
    19. //write(fileName,格式类)
    20. //sheet(表名)
    21. //doWrite(数据),真实的就是从数据库中读取的或前端传过来的
    22. EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
    23. }

    3、最终的结果:

    读取测试

    测试读取:

    1、创建类 DemoDataListener 监听器:

    1. package com.zhang.easyexcelpojo;
    2. import com.alibaba.excel.context.AnalysisContext;
    3. import com.alibaba.excel.event.AnalysisEventListener;
    4. import com.alibaba.fastjson.JSON;
    5. import org.slf4j.Logger;
    6. import org.slf4j.LoggerFactory;
    7. import java.util.ArrayList;
    8. import java.util.List;
    9. // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
    10. public class DemoDataListener extends AnalysisEventListener {
    11. private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);
    12. /**
    13. * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
    14. */
    15. private static final int BATCH_COUNT = 5;
    16. List list = new ArrayList();
    17. private DemoDAO demoDAO;
    18. public DemoDataListener() {
    19. demoDAO = new DemoDAO();
    20. }
    21. public DemoDataListener(DemoDAO demoDAO) {
    22. this.demoDAO = demoDAO;
    23. }
    24. // 读取数据 会执行 invoke 方法 这个每一条数据解析都会来调用
    25. // DemoData 类型
    26. // AnalysisContext 分析上下文
    27. @Override
    28. public void invoke(DemoData data, AnalysisContext context) {
    29. System.out.println(JSON.toJSONString(data));
    30. list.add(data);
    31. System.out.println(list);
    32. // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
    33. if (list.size() >= BATCH_COUNT) {
    34. saveData(); //
    35. // 存储完成清理 list
    36. list.clear();
    37. }
    38. }
    39. // 所有数据解析完成了 都会来调用
    40. @Override
    41. public void doAfterAllAnalysed(AnalysisContext context) {
    42. // 这里也要保存数据,确保最后遗留的数据也存储到数据库
    43. saveData();
    44. LOGGER.info("所有数据解析完成!");
    45. }
    46. // 加上存储数据库
    47. private void saveData() {
    48. demoDAO.save(list);
    49. }
    50. }

    具体操作:

    2、持久层DemoDAO:

    1. package com.zhang.easyexcelpojo;
    2. import java.util.List;
    3. /**
    4. * 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。
    5. **/
    6. public class DemoDAO {
    7. public void save(List list) {
    8. // 持久化操作
    9. // 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入
    10. }
    11. }

     3、测试:

    1. // 最简单的读
    2. @Test
    3. public void simpleRead() {
    4. String fileName = PATH + "EasyTest.xlsx";
    5. // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
    6. EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
    7. }

    4、结果: 

    固定套路:

    1、写入、固定类格式进行写入

    2、读取、根据监听器设置的规则进行读取!

    学习方式

    了解,面向对象的思想,学会面向接口编程!

    理解使用测试 API!

    可以把EasyExcel的所有 api 测试一下(2-3小时!)

  • 相关阅读:
    Java文件前后端上传下载工具类
    DEJA_VU3D - Cesium功能集 之 068-空间坐标系之箭头
    机器学习之梯度下降Gradient Descent(李宏毅机器学习)
    一款优秀的盲盒APP源码成品需要具备什么条件
    SpringBoot 的 MVC
    竞赛 基于深度学习的人脸表情识别
    ES6 Promise的使用详解
    MyBatis实现动态SQL更新
    Jenkins+Gitlab自动部署Vue项目到远程服务器
    为什么void CreateListR(LinkNode*&S,String a[],int n)这里有问题
  • 原文地址:https://blog.csdn.net/m0_57508774/article/details/126028848