JAVA操作excel

POI及EasyExcel

POI官网

EasyExcel官网

EasyExcel使用说明

 

POI

操作excel的组件列表:

HSSF : 它被用来读取和写入MS-Excel文件的xls格式。---03版本excel

XSSF : 它是用于MS-Excel中xlsx文件格式。---07版本excel

 

1. 导入依赖

  • 03版本excel,.xls表格文件,最多支持65535行数据

<!--xls 03版本 -->
       <dependency>
           <groupId>org.apache.poi</groupId>
           <artifactId>poi</artifactId>
           <version>3.9</version>
       </dependency>

 

  • 07版本excel,.xlsx表格文件,不限行数

<!--xls 07版本 xlsx-->
       <dependency>
           <groupId>org.apache.poi</groupId>
           <artifactId>poi-ooxml</artifactId>
           <version>3.9</version>
       </dependency>

2. 对象分析

表格操作会涉及到4个对象:

工作表:WorkBook

工作簿:Sheet

行:Row

单元格(列):Cell

3. 代码操作-写

3.1 写入03版本excel---HSSF

 @Test
   public void test03() throws IOException {
        String path = "V:\\study\\excel\\excel-poi"; //获取项目路径
       //创建03版本的xls表格
       Workbook workbook = new HSSFWorkbook(); //创建工作表
       Sheet sheet = workbook.createSheet("人员统计表"); //创建工作簿
       ---sheet
       Row row = sheet.createRow(0); //创建行,0代表第一行
       Cell cell1 = row.createCell(0);        //创建列,此处创建了坐标 1,1的单元格
       cell1.setCellValue("数量"); //设置单元格的值
       Cell cell2 = row.createCell(1);        //此处创建坐标1,2的单元格
       cell2.setCellValue(10);
       //03版本,文件名以xls结尾
       FileOutputStream outputStream = new FileOutputStream(path + "人员统计表.xls");  //创建文件输出流
       workbook.write(outputStream);
       outputStream.close(); //关闭流
       System.out.println("表格生成完成");
  }

03版本如果一次性写入数据超过65535,会报异常。

3.2 写入07版本excel---XSSF

  @Test
   public void test07() throws IOException {
       String path = "V:\\study\\excel\\excel-poi"; //获取项目路径
       //创建07版本的xls表格
       Workbook workbook = new XSSFWorkbook();
       //创建工作表---sheet
       Sheet sheet07 = workbook.createSheet("人员统计表");
       //创建行
       Row row = sheet07.createRow(0);//第一行
       //创建列,此处创建了坐标 1,1的单元格
       Cell cell1 = row.createCell(0);
       cell1.setCellValue("数量");
       //此处创建坐标1,2的单元格
       Cell cell2 = row.createCell(1);
       cell2.setCellValue(100);
       //07版本,文件名以xls结尾
       FileOutputStream outputStream = new FileOutputStream(path + "人员统计表.xlsx");
       workbook.write(outputStream);
       outputStream.close();
       System.out.println("表格生成完成");
  }

3.3 大数据写07版本---SXSSF

 @Test
   public void test07Bigdata() throws IOException {
         String path = "V:\\study\\excel\\excel-poi"; //获取项目路径
       long begin = System.currentTimeMillis();
       //创建07版本的xlsx表格,处理大数据
       Workbook workbook = new SXSSFWorkbook();
       //创建工作表---sheet
       Sheet sheet = workbook.createSheet("测试大数据S");
       for (int rowNo=0 ;rowNo<100000;rowNo++){
           Row row = sheet.createRow(rowNo);
           for (int cellNo = 0 ;cellNo<10;cellNo++){
               Cell cell = row.createCell(cellNo);
               cell.setCellValue(cellNo);
          }
      }
       //07版本,文件名以xlsx结尾
       FileOutputStream outputStream = new FileOutputStream(path + " 测试大数据S.xlsx");
       workbook.write(outputStream);
       outputStream.close();
       //使用SXSSF会产生临时文件,需要删除
      ((SXSSFWorkbook)workbook).dispose();
       long end = System.currentTimeMillis();
       System.out.println("over");
       System.out.println(end - begin);
  }
  • HSSF,一次性最多写入65535行数据;

  • XSSF,一次性可以写入大量数据,但是耗时长;

  • SXSSF,XSSF的加速版,大数据写入快(过程中会产生临时文件,需要删除)。

代码操作-读

@Test
   public void TestReadCellType() throws IOException {
         String path = "V:\\study\\excel\\excel-poi"; //获取项目路径
       FileInputStream fileInputStream = new FileInputStream(path+"\\人员信息表.xls");
       Workbook workbook = new HSSFWorkbook(fileInputStream);
       //获取工作簿
       Sheet sheet = workbook.getSheetAt(0);
       Row rowTitle = sheet.getRow(0);   // 获取第一行,标题行
       if(rowTitle!=null){
           //获取列数
           int cells = rowTitle.getPhysicalNumberOfCells();
           for (int cellNo = 0; cellNo <cells ; cellNo++) {
               Cell cell = rowTitle.getCell(cellNo);
               if(cell!=null){
                   int cellType = cell.getCellType();
                   System.out.print("|");
                   System.out.print(cell.getStringCellValue());
              }
          }
      }
       System.out.println();
       //读取除标题行外的所有数据
       int rows = sheet.getPhysicalNumberOfRows();
       for (int rowNo = 1 ; rowNo <rows ; rowNo++) {
           Row row = sheet.getRow(rowNo);
           if(row!=null){
               //获取所有列
               int cells = row.getPhysicalNumberOfCells();
               for (int cellNo = 0; cellNo <cells; cellNo++) {
                   Cell cell = row.getCell(cellNo);
                   int cellType = cell.getCellType();
                   switch (cellType){
                       case HSSFCell.CELL_TYPE_STRING://字符串
                           String value = cell.getStringCellValue();
                           System.out.println("String:"+value);
                           break;
                       case HSSFCell.CELL_TYPE_BOOLEAN://boolean类型
                           System.out.println("Boolean:"+String.valueOf(cell.getBooleanCellValue()));
                           break;
                       case HSSFCell.CELL_TYPE_NUMERIC://数字类型
                           //数字类型要判断是日期还是数字
                           if(HSSFDateUtil.isCellDateFormatted(cell)){
                               System.out.print("日期:");
                               Date date = cell.getDateCellValue();
                               System.out.println(new DateTime(date).toString("yyyy-MM-dd HH:mm:ss"));
                          }else {
                               //如果是数字,为了防止数字类型过大,先转为字符类型,再获取
                               cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                               System.out.println("转为字符串输出"+cell.getStringCellValue());
                          }
                           break;
                       case HSSFCell.CELL_TYPE_ERROR:
                           System.out.println("数据类型错误");
                  }
              }
          }
      }
       fileInputStream.close();
  }

读取操作,需要针对不同的数据类型做判断,用不同的api获取值;

EasyExcel

导入依赖

        <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>easyexcel</artifactId>
           <version>2.2.9</version>
       </dependency>

代码操作-写

  • 创建数据实体类

public class TestData {  // 这边全都是标题行
   @ExcelProperty("姓名")
   private String name;
   @ExcelProperty("年龄")
   private Integer age;
   @ExcelProperty("生日")
   private Date birth;
   @ExcelIgnore
   private String ingore;
}
  • 初始化数据

      public static List<TestData> data(){
       List<TestData> list = new ArrayList<TestData>();
           for (int i = 0; i <5 ; i++) {
               TestData testData = new TestData();
               testData.setName("人员"+i);
               testData.setAge(i);
               testData.setBirth(new DateTime(new Date()).toDate());
               list.add(testData);
          }
           return list;
      }
  • 写入数据

       @Test
       public void simpleWrite() throws FileNotFoundException {
           String path = "V:\\study\\excel";
           String fileName = path+"\\easyExcelWrite.xlsx";
           //指定用哪个class去写
           //write(文件名,格式类)
           //sheet(工作簿名称)
           //doWrite(数据)
          EasyExcel.write(fileName,TestData.class).sheet("人员").doWrite(data());
      }
  • 执行结果

     

     

代码操作-读

  1. 创建监听器,继承AnalysisEventListener类,重写方法,方法中写逻辑

    public class DataDemoListener extends AnalysisEventListener<TestData> {
           private static final Logger LOGGER = LoggerFactory.getLogger(DataDemoListener.class);
           /**
            * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
            */
           private static final int BATCH_COUNT = 5;
           List<TestData> list = new ArrayList<TestData>();
    //解析每一条数据都会执行此方法
       public void invoke(TestData testData, AnalysisContext analysisContext) {
           LOGGER.info("解析到一条数据:{}", JSON.toJSONString(testData));
           System.out.println(testData);
      }
    //所有数据解析完成了 都会来调用此方法
       public void doAfterAllAnalysed(AnalysisContext analysisContext) {
           System.out.println("解析成功");
      }
    }
  2. 读取数据,将监听器作为参数传入

        @Test
       public void simpaleRead(){
           String path = "V:\\study\\excel";
           String fileName = path+"\\easyExcelWrite.xlsx";
           // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
           EasyExcel.read(fileName, TestData.class, new DataDemoListener()).sheet().doRead();
      }
  3. 执行结果

  

 

 

参考狂神说java。

posted @ 2021-05-12 14:24  Vicious丶Sea  阅读(312)  评论(0)    收藏  举报