POI使用

Apache POI 使用小记

最近通过项目学习了Apache POI操作Excel的方法,记录一下方便日后使用。

首先导入Excel,生成WorkBook实例,之后便可以通过workbook读取Excel文档中的数据

public void importWorkBook(String filename){

      WorkBook wb =null;
      wb = getWorkBook(filename);  //检查导入的文件是哪一个版本的excel 创建对应的工作簿
      if(wb == null) 
           return;
      int numbs = wb.getNumberOfSheets();  //获取工作簿中的工作表数目
      if(numbs > 0){
            for(int i=0;i<numbs;i++){   //遍历每个工作表,进行相应的处理,比如将表中数据存入数据库
                Sheet sheet = wb.getSheetAt(i);
                if(sheet!=null &&  sheetName.equals("工程造价指标(定额)")){
                    ...
                }else if(sheet!=null && sheetName.contains("工程造价指标(清单)")){
                    saveSheetToDb(sheet);
                }else{
                    continue;
                }
            }
        }

}

生成WorkBook实例

private Workbook getWorkbook (String filename) {
    Workbook wb = null;
    if (filename == null || !filename.matches("^.+\\.(?i)((xls)|(xlsx))$")) {
        return null;
    }
    boolean isExcel2003 = true;
    /** 对文件的合法性进行验证 */
    if (filename.matches("^.+\\.(?i)(xlsx)$")) {
        isExcel2003 = false;
    }
    /** 检查文件是否存在 */
    File file = new File(filename);
    if (file == null || !file.exists()) {
        return null;
    }
    /** 根据版本选择创建Workbook的方式 */
    try {
        wb = (Workbook) (isExcel2003 ? new HSSFWorkbook(new FileInputStream(file)) : new XSSFWorkbook(new FileInputStream(file)));
    } catch (FileNotFoundException e) {
        logger.error(e.getMessage(),e);
    } catch (IOException e) {
        logger.error(e.getMessage(),e);
    }
    return wb;
}

将每张工作表中的数据保存到数据库中

private void saveSheetToDb(Sheet sheet){
    Map<Integer, List<String>> rowMap = ExcelUtil.parseSheet(sheet); //导入的行集合
    Map<String, Object> resMap= ExcelUtil.resMap;
    Map<String, Object> modelMap = (Map<String, Object>) resMap.get("model");//行模型集合
    Map<String, Object> paramMap = (Map<String, Object>) resMap.get("param");//参数集合
    List<Entity> resList = new ArrayList<>();//将要插入数据库的实体集合

    //1 把行集合转化成一张或多张表格
    List<List<Integer>> tableList = ExcelUtil.convertToTableList(rowMap, (List<String>) modelMap.get("tableHeadModelRow"));

    for (List<Integer> table : tableList) {
           /*
                一张Sheet工作表中可能存在多张表格数据 
                根据定义的行模型集合modelMap和参数集合paramMap  
                找到需要的数据
                将其封装为实体类Entiy
           */
           Entity entity = new Entity(,,,,);
           resList.add(entity);
    }

    // 插入费用到数据库,如果实体数据条数大于200条,分批次插入
    if (!resList.isEmpty()){
        if (resList.size() > 200){
            int size = resList.size();
            int times = size % 200 == 0 ? size / 200 : size / 200 + 1;
            List<Entity> list = null;
            for (int i = 1; i <= times; i++){
                if (i == times){
                    list = resList.subList((i -1) * 200, size);
                }else {
                    list = resList.subList((i -1) * 200, i * 200);
                }
                zbFillDonorSpreadMapper.addBatchDonorSpread(list);
            }
        }else {
            zbFillDonorSpreadMapper.addBatchDonorSpread(resList);
        }
    }

}

ExcelUtil parseSheet 方法

/**
 * 把页签解析成行集合
 * @param sheet 页签
 * @return 行集合,key为行索引,value为单元格集合
 */
public static Map<Integer, List<String>> parseSheet(Sheet sheet){
   int rowNum = sheet.getLastRowNum() + 1;
   Map<Integer, List<String>> rowMap = new LinkedHashMap<>();
   for (int r = 0; r < rowNum; r++){
       Row row = sheet.getRow(r);
       List<String> cellList = new ArrayList<>();
       boolean isDataList = false;
       for (int c = 0; c < row.getLastCellNum(); c++){
           Cell cell = row.getCell(c);
           cell.setCellType(Cell.CELL_TYPE_STRING);
           String value = getCellValue(row, c);
           if (value == null){
               cellList.add("?");//占位符
           }else {
               if (Pattern.matches(IS_NUM_EXP, value)){
                   isDataList = true;
               }
               cellList.add(value.replaceAll("\\s", ""));
           }
       }
       if (isDataList){
           cellList.add("dataRowFlag");//增加标识,用于识别数据行
       }
       rowMap.put(r, cellList);
   }
    return rowMap;
}

ExcelUtil convertToTableList 方法

 /**
 * 把行集合按表头规则解析成多个表格
 * @param rowMap 行集合
 * @param tableHeadModelRow 表头模板
 * @return 一个或多个表格的集合,集合保存的是行号,并不是数据
 */
public static List<List<Integer>> convertToTableList(Map<Integer, List<String>> rowMap, List<String> tableHeadModelRow){
    List<List<Integer>> tableList = new ArrayList<>();
    for (Map.Entry<Integer, List<String>> entry : rowMap.entrySet()) {//遍历所有行
        List<String> row = entry.getValue();
        int rowIndex = entry.getKey();
        if (row.containsAll(tableHeadModelRow)){//如果行是表头,创建新的表
            tableList.add(new ArrayList<Integer>());
            tableList.get(tableList.size() - 1).add(rowIndex);
        }else if (tableList.size() > 0){//如果不是表头行,并且不为页签内第一个表头行上方的行
            tableList.get(tableList.size() - 1).add(rowIndex);
        }
    }
    return tableList;
}

下面列出resMap的数据 和 对应的一份excel文件截图

ExcelUtil.resMap = 
{
    model={
        normTitleModelRow=[
            管理费,
            利润,
            风险费用
        ],
        tableHeadModelRow=[
            项目编码,
            项目名称,
            计量单位,
            综合单价
        ],
        totalModelRow=[
            合计,
            —,
            —
        ],
        machineHeadModelRow=[
            3.机械
        ],
        labourHeadModelRow=[
            1.人工
        ],
        materialHeadModelRow=[
            2.材料
        ],
        dataModelRow=[
            dataRowFlag
        ],
        resTableHeadModelRow=[
            人工、材料及机械名称,
            单位,
            数量,
            基价单价,
            基价合价,
            市场单价,
            市场合价,
            备注
        ]
    },
    param={
        profitFee={
            name=利润,
            cellOffset=0,
            rowOffset=-185
        },
        managementFee={
            name=管理费,
            cellOffset=0,
            rowOffset=-185
        },
        unit={
            name=单位,
            cellOffset=-1,
            rowOffset=-1
        },
        riskFee={
            name=风险费用,
            cellOffset=0,
            rowOffset=-185
        },
        quatity={
            name=数量,
            cellOffset=-1,
            rowOffset=-1
        },
        unitPrice={
            name=市场单价,
            cellOffset=-1,
            rowOffset=-1
        },
        qdCode={
            name=项目编码,
            cellOffset=1,
            rowOffset=0
        },
        costName={
            name=人工、材料及机械名称,
            cellOffset=-1,
            rowOffset=-1
        }
    }
}
Excel文件截图 (1):

这里写图片描述

Excel文件截图 (2):

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值