使用poi包解析excel

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.16</version>
</dependency>

一个excel内容包括:sheet-->row-->cell (这时应该打开新建或打开一个excel看看)

  1. 先跑一个导入excel的小例子(先导入poi的包)
    目的:输出 shafish 到新建的excel中并命名该excel为student.xls

    //1. 创建工作簿(excel)
     HSSFWorkbook workbook = new HSSFWorkbook();
    //2. 创建sheet,命名为学生信息
     HSSFSheet hssfSheet = workbook.createSheet("学生信息");
    //3. 创建行
     HSSFRow hssfRow = hssfSheet.createRow(0);
    //4. 创建列
     HSSFCell hssfCell = hssfRow.createCell(0);
    //5. 填充数据(输出到excel的数据)
     hssfCell.setCellValue("shafish");
    //6. 创建excel输出流
     try {
         OutputStream out = new FileOutputStream("d://student.xls");
    //7. 使用workbook实现输出
         workbook.write(out);
    //8. 关闭输出流
         out.close();
     } catch (FileNotFoundException e) {
         e.printStackTrace();
     } catch (IOException e) {
         e.printStackTrace();
     }

    总结:1.首先创建一个excel对象
    2.生成sheet了解一个excel可以存多大数据
    3.生成一行,再指定一列--行列定位出一个单元格
    4.最后写入数据-->数据持久化(就是写进硬盘)

  2. 导出excel例子
    把上面保存在excel中的shafish导入程序中,应用场景:导入excel数据到数据库

    try {
    //1. 取得excel工作簿
     HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream("d://students.xls"));
    //2. 迭代每一个sheet(考虑某个sheet为空的情况)
     for(int i=0;i<workbook.getNumberOfSheets();i++) {
         HSSFSheet sheet = workbook.getSheetAt(i);
         if(sheet == null) {
             continue;
         }
    //3. 循环获取每一行
         for(int j=1;j<sheet.getLastRowNum();j++) {
             //得到当前行(也要考虑当前行是否为空的情况)
             HSSFRow row = sheet.getRow(j);
             if(row == null) {
                 continue;
             }
             System.our.println(row.getCell(0).getStringCellValue()));
         }
     }
    } catch (FileNotFoundException e) {
     e.printStackTrace();
    } catch (IOException e) {
     e.printStackTrace();
    }

    总结:
    先取得excel,一步步定位到保存数据的单元格,最后获取

  3. 将第一个把数据导入excel的例子封装成util方便使用
    需要先定义传入的参数(先看一遍有大概印象,不用太纠结,看完代码就会了解全部流程)

    data:一个List集合,包含T(泛型)类型的数据--比如下面用到的Student类
    out:一个文件输出流(FileOutputStream)--指定输出的路径和文件名
    fields:从Student中指定需要输出的东吸(Map<key,value>)--比如说Student类中有age,name,no三个属性。现在只需要把age和name保存在excel中。Map<类属性,在excel表头显示内容>--会使用到反射

    先定义Student类

    
    /**
  • @ClassName: Student

  • @Description: 学生实体类测试ExcelUtil导入

  • @author shafish

  • @date 2018年5月2日 下午1:40:16

  • */
    public class Student {
    private String name;
    private String no;
    private String sex;
    private int age;
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public String getNo() {
    return no;
    }
    public void setNo(String no) {
    this.no = no;
    }
    public String getSex() {
    return sex;
    }
    public void setSex(String sex) {
    this.sex = sex;
    }
    public int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    }

    
    `设置util工具类,处理传进的参数--data,out,fields`
    ```java
    /**
  • @ClassName: ExcelUtil

  • @Description: 封装一个传入数据生成excel表格的工具类

  • @author shafish

  • @date 2018年5月2日 下午12:34:27

  • */
    public class ExcelUtil {
    /**

    • @throws Exception

    • @Title: listToExcel

    • @Description: TODO(这里用一句话描述这个方法的作用)

    • @param @param data 要导出的数据

    • @param @param out 输出位置

    • @param @param fields 属性对应的表头

    • @return void 返回类型

    • @throws
      /
      public static void listToExcel(List data,OutputStream out,Map<String, String> fields) throws Exception {
      int sheetSize = 6000;//定义一个sheet最大的行数 03版的excel行数不能超过65536
      if(data==null||data.size()==0) {
      throw new Exception("传入数据源为空");
      }
      //1. 创建一个工作簿--sheet中的数据不能超过65536(需要做限制)
      HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
      //2. 计算一共可分多少个sheet--sheetNum
      int sheetNum = data.size()/sheetSize;
      if(data.size()%sheetSize!=0) {
      sheetNum += 1;
      }
      //3. 拿出实体中表头和对应数据 储存在数组中
      String[] fieldNames = new String[fields.size()];
      String[] chinaNames = new String[fields.size()];
      int count = 0;
      for(Entry<String, String> entry:fields.entrySet()) {
      String fieldName = entry.getKey();
      String chinaName = entry.getValue();
      fieldNames[count] = fieldName;
      chinaNames[count] = chinaName;
      count++;
      }
      //4. 在每一个sheet中填充内容--每个sheet都需要定义表头chinaName和它的数据fieldName
      for(int i=0;i<sheetNum;i++) {
      int rowCount = 0;
      HSSFSheet hssfSheet = hssfWorkbook.createSheet();
      int startIndex = i
      sheetSize;
      //数据的终结点需要跟data中数据size比较
      int endIndex = ((i+1)sheetSize>data.size())?data.size()-1:(i+1)sheetSize-1;
      //4.1 创建表头行
      HSSFRow hssfRow = hssfSheet.createRow(rowCount);
      //4.2 在表头填充完所有表头数据
      for(int j=0;j<chinaNames.length;j++) {
      HSSFCell hssfCell = hssfRow.createCell(j);
      hssfCell.setCellValue(chinaNames[j]);
      }
      rowCount++;
      //4.3 在表内容中填充对应数据(值)
      for(int index=startIndex;index<=endIndex;index++) {
      //4.3.1 先取得当前数据实体
      T item = data.get(index);
      //4.3.2 当前sheet在当前行显示数据
      hssfRow = hssfSheet.createRow(rowCount);
      //4.3.3 输出与表头对应的数据
      for(int j=0;j<chinaNames.length;j++) {
      //反射获取当前属性值
      Field field = item.getClass().getDeclaredField(fieldNames[j]);
      field.setAccessible(true);
      Object object =field.get(item);
      String value = object==null?"":object.toString();
      //设置单元格内容(某行某列确定一个单元格)
      HSSFCell hssfCell = hssfRow.createCell(j);
      hssfCell.setCellValue(value);
      }
      //循环构造下一行
      rowCount ++;
      }
      hssfWorkbook.write(out);
      }
      }
      }

      `写入数据,数据源可以从数据库中读`(先挖个坑)
      ```java
      public static void main(String[] args) {
        List<Student> data = new ArrayList<Student>();
        Student student = new Student();
        student.setAge(19);
        student.setName("fish");
        student.setNo("007");
        student.setSex("男");
        data.add(student);
      
        student = new Student();
        student.setAge(12);
        student.setName("as");
        student.setNo("008");
        student.setSex("男");
        data.add(student);
      
        student = new Student();
        student.setAge(20);
        student.setName("zx");
        student.setNo("009");
        student.setSex("男");
        data.add(student);
      
        student = new Student();
        student.setAge(21);
        student.setName("qw");
        student.setNo("010");
        student.setSex("女");
        data.add(student);
      
        student = new Student();
        student.setAge(22);
        student.setName("po");
        student.setNo("011");
        student.setSex("女");
        data.add(student);
      
        OutputStream out;
        try {
            out = new FileOutputStream("d://students.xls");
            Map<String,String> fields = new HashMap<String, String>();//new LinkedHashMap<String, String>();
            fields.put("age", "年龄");
            fields.put("no", "学号");
            fields.put("name", "姓名");
            fields.put("sex", "性别");
            ExcelUtil.listToExcel(data, out, fields);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
      }

      总结:
      1. 判断传入data有没有数据
      2. 创建一个工作簿
      3. 判断sheet
      4. 在sheet中填充数据
      4.1 每个sheet都需要填充表头(使用fields中的value)
      4.2 在表头的下一行开始填充对应的数据(根据fields中的key,使用反射获取data中当前对象的属性)
      重点
      5. 填充数据

      HSSFCell hssfCell = hssfRow.createCell(index);
      hssfCell.setCellValue(value);

      6. 其中需要用到的计算(计算一个sheet的起始和结束)

      //sheetSize是之前定义的sheet最大行数(03版sheet不能超过65536行)
      //0~5999、6000~1199、1200~1799、....
      int startIndex = i*sheetSize;
      int endIndex = ((i+1)*sheetSize>data.size())?data.size()-1:(i+1)*sheetSize-1;

result