poi 解析 excel 到对象

package com.adtec.moia.service.impl.yh.excel;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.BufferedWriter;  
import java.io.File;  
import java.io.FileInputStream;  
import java.io.FileWriter;  
import java.io.IOException;  
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;  
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;  
import org.apache.poi.ss.usermodel.Row;  
import org.apache.poi.ss.usermodel.Sheet;  
import org.apache.poi.ss.usermodel.Workbook;

import com.alibaba.fastjson.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell; 
import org.apache.poi.ss.usermodel.Row; 
public class EXLSReader {
  public static void main(String[] args) {
    // 设定Excel文件所在路径
    String excelFileName = "C:/Users/Administrator/Desktop/1630992431061.xls";
    // 读取Excel文件内容
    try {
      List<Map<String, Object>> readExcelData = readExcelData(excelFileName,"程序信息表",0,ExcelDataVO.class);
      System.out.println(readExcelData+"\n");
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    
   // for(int a=0;a<readResult.size();a++){
//      System.out.println(readResult.get(a).getName());
//      System.out.println(readResult.get(a).getJob());
//      System.out.println(readResult.get(a).getAge());
//      System.out.println(readResult.get(a).getLocation());
   //
   // }
    // todo 进行业务操作
    }
  
  
  //对象属性名集合
  static List<String> columnNameList = new ArrayList<>();

  //对象属性类型集合
  static List<String> columnTypeNameList = new ArrayList<>();
  /*
   * @author March
   * @Description  readExcelData:解析excel表格,并且封装进对象;一行就是一个map,map的key是对象的属性名;属性的数量和位置必须和表的列一一对应
   * @warning:Java对象的属性顺序还有数量必须和excel的列的顺序一一对应,否则数据不对应;Java属性的id可以忽略
   * @Date 1:36 下午 2020/5/19
   * @param url:excel文件地址
   * @param readSheetName :表名
   * @param ignoreRow:需要忽略的行数,如标题这种
   * @param titleRow:列名,作为对象的key
   * @return
   **/
  public static <T> List<Map<String, Object>> readExcelData(String url, String readSheetName, Integer ignoreRow, Class<T> clz) throws Exception {

      Optional.ofNullable(url).orElseThrow(() -> new RuntimeException("url文件路径不能为空"));
      Optional.ofNullable(readSheetName).orElseThrow(() -> new RuntimeException("readSheetName文件路径不能为空"));

      // 从XLSX/ xls文件创建的输入流
      try {
          FileInputStream fis = new FileInputStream(url);
          //封装单元格参数,map就是一行数据,key是
          List<Map<String, Object>> hospitalList = new ArrayList();

          // 创建工作薄Workbook
          Workbook workBook = null;

          // 读取2007版,以    .xlsx 结尾
//          if (url.toLowerCase().endsWith("xlsx")) {
//              try {
//                  workBook = new XSSFWorkbook(fis);
//              } catch (IOException e) {
//                  e.printStackTrace();
//              }
//          }
          // 读取2003版,以   .xls 结尾
          if (url.toLowerCase().endsWith("xls")) {
              try {
                  workBook = new HSSFWorkbook(fis);
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
          //获取总共的表格数量
          int numberOfSheets = workBook.getNumberOfSheets();

          // 循环 numberOfSheets
          for (int sheetNum = 0; sheetNum < numberOfSheets; sheetNum++) {

              // 得到 工作薄 的第 N个表
              Sheet sheet = workBook.getSheetAt(sheetNum);
              String sheetName = sheet.getSheetName();
              if (readSheetName.equals(sheetName)) {
                  //行
                  Row row;
                  // cell就是每个单元格的值
                  String cell;

                  //按顺序获取class的属性的类型的字符串
                  columnTypeNameList=EXLSReader.parseBeanPropertyTypeName(clz);
                  //按顺序获取class的属性名称
                  columnNameList=EXLSReader.paresBeanPropertyName(clz);

                  //数据封装
                  for (int i = sheet.getFirstRowNum(); i < sheet.getPhysicalNumberOfRows(); i++) {
                      //忽略的行数;
                      if (Integer.compare(i, ignoreRow - 1) != 1) {
                          continue;
                      }

                      // 循环行数
                      row = sheet.getRow(i);

                      //存储每行的参数
                      Map<String, Object> map = new HashMap<>();
                      for (int j = row.getFirstCellNum(); j < row.getPhysicalNumberOfCells(); j++) {

                          //遍历列名集合,
                          for (int k = 0; k < columnNameList.size(); k++) {
                              //当列名集合的下表和这行的下表相等时就放入map
                              if (k == j) {
                                  cell=Optional.ofNullable(row.getCell(j).toString()).orElse("");

                                  switch (columnTypeNameList.get(k)){
                                      case "java.lang.Int":
                                          map.put(columnNameList.get(k),Integer.valueOf(StringUtils.contains(cell,".")?cell.substring(0,cell.indexOf(".")):cell));
                                          break;
                                      case "java.lang.Long":
                                          map.put(columnNameList.get(k),Long.valueOf(cell));
                                          break;
                                      case "java.lang.Double":
                                          map.put(columnNameList.get(k),Double.valueOf(cell));
                                          break;
                                      case "java.lang.Float":
                                          map.put(columnNameList.get(k),Float.valueOf(cell));
                                          break;
                                      case "java.math.BigInteger":
                                          map.put(columnNameList.get(k), BigInteger.valueOf(Long.valueOf(cell)));
                                          break;
                                      case "java.math.BigDecimal":
                                          map.put(columnNameList.get(k),BigDecimal.valueOf(Double.valueOf(cell)));
                                          break;
//                                      case "java.util.Date":
//                                          map.put(columnNameList.get(k), DateUtils.parseDate(cell,"yyyy年MM月dd日","yyyy-MM-dd hh:mm:ss","yyyy-MM-dd HH:mm:ss"));
//                                          break;
                                      //默认返回字符串
                                      //如果有需要的拓展类型,在上面的case中增加类型的全类路径名
                                      default:
                                          map.put(columnNameList.get(k),cell);
                                          break;
                                  }
                              }
                          }
//                          System.out.print(cell+"\t");
                      }
                      hospitalList.add(map);
//                      System.out.println();
                  }
              }

          }
          return hospitalList;
      } catch (Exception e) {
          e.printStackTrace();
      }
      return null;
  }

  /*
   * @author March
   * @Description  parseMapListToObjectList:把excel的文件读出,先转为map集合,再转为对象集合
   * @Warning:对象的属性名的顺序数量必须和excel表格一一对应
   * @Date 1:33 下午 2020/5/21
       * @param url:excel文件路径
       * @param readSheetName:表名
       * @param ignoreRow:忽略的行数(只需要数据,不需要列的字段)
       * @param clz:需要转换的对象的class
   * @return
  **/
  public static <T> List<T> parseExcelToMapListToObjectList(String url, String readSheetName, Integer ignoreRow, Class<T> clz) throws IllegalAccessException, InstantiationException, IntrospectionException {
      List<T> listInfo = new ArrayList<>();
      List<Map<String, Object>> list = null;
      try {
          list = readExcelData(url, readSheetName, ignoreRow, clz);
      } catch (Exception e) {
          e.printStackTrace();
      }
      list.forEach(map -> {
          try {
              //map转为对象并且加入集合
              listInfo.add(EXLSReader.map2bean(map,clz));
          } catch (Exception e) {
              e.printStackTrace();
          }
      });
      return listInfo;
  }


  /*
   * @author March
   * @Description  map2bean:把map的值转为对象
   * @Warning:对象的属性名和map的key必须一致
   * @Date 1:35 下午 2020/5/21
   * @param map
       * @param clz
   * @return
  **/
  public static <T> T map2bean(Map<String, Object> map, Class<T> clz) throws Exception {
      if (null == map) {
          throw new RuntimeException();
      }
      try {
          //创建一个需要转换为的类型的对象
          T obj = clz.newInstance();
          //从Map中获取和属性名称一样的值,把值设置给对象(setter方法)

          //得到属性的描述器
          BeanInfo b = Introspector.getBeanInfo(clz, Object.class);
          PropertyDescriptor[] pds = b.getPropertyDescriptors();
          for (PropertyDescriptor pd : pds) {
              //得到属性的setter方法
              Method setter = pd.getWriteMethod();
              //得到key名字和属性名字相同的value设置给属性
              setter.invoke(obj, map.get(pd.getName()));
          }
          return obj;
      } catch (Exception e) {
          throw new RuntimeException();
      }
  }


  /*
   * @author March
   * @Description  paresBeanPropertyName:根据class依序获取对象属性的名字
   * @Date 11:13 上午 2020/5/21
   * @param clz
   * @return
  **/
  public static <T> List<String> paresBeanPropertyName(Class<T> clz) {
      //获取class的属性字段;
      Field[] fields = clz.getDeclaredFields();
      if (fields.length > 0) {
          List<String> beanPropertyNames=new ArrayList<>();
          try {
              //在使用java反射机制获取 JavaBean 的属性值时,如果该属性被声明为private 的,需要将setAccessible设置为true. 默认的值为false
              Field.setAccessible(fields, true);
              for (int i = 0; i < fields.length; i++) {
                  //忽略ID字段
                  if("id".equals(fields[i].getName())){
                      continue;
                  }
                  //获取属性的名字
                  beanPropertyNames.add(fields[i].getName());
              }
              return beanPropertyNames;
          }catch (Exception e){
              e.printStackTrace();
          }
      }
      return null;
  }



  /*
   * @author March
   * @Description  parseBeanPropertyType:根据class依序获取对象属性的数据类型
   * @Date 10:32 上午 2020/5/21
   * @param clz
   * @return
   **/
  public static  <T> List<String> parseBeanPropertyTypeName(Class<T> clz) {
      Field[] fields = clz.getDeclaredFields();
      if (fields.length > 0) {
          List<String> beanPropertyTypes=new ArrayList<>();
          try {
              //在使用java反射机制获取 JavaBean 的属性值时,如果该属性被声明为private 的,需要将setAccessible设置为true. 默认的值为false
              Field.setAccessible(fields, true);
              for (int i = 0; i < fields.length; i++) {
                  //获取属性的类型的名字
                  //忽略ID字段
                  if("id".equals(fields[i].getName())){
                      continue;
                  }
                  beanPropertyTypes.add(fields[i].getType().getName());
              }
              return beanPropertyTypes;
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
      return null;
  }

  public static boolean isNumeric(String str) {
      try {
          new BigDecimal(str);
      } catch (Exception e) {
          return false;
      }
      return true;
  }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值