xinxihua

java使用POI进行Excel操作

Java花式处理EXCEL

2019.07.04 10:04:07字数 902阅读 2,407

批量处理1——文件的上传(bootstrap+Ajax+SSM)
批量处理2——Java花式处理EXCEL
批量处理3——Excel文件导出
批量处理4——java处理压缩文件

Java知多少——相对路径和绝对路径
HTTP知多少——Content-disposition(文件下载)

java批量处理专题——用户将Excel上传到服务器,服务器如何解析Excel并将其解析为java对象?

推荐阅读:解析EXCEL的API方法

 
image

1. 简单API介绍

1.1 workbook工作空间

由于Excel存在xls以及xlsx两种格式,所以创建方式也有所不同。

  • 对于xls格式,需要使用HSSFWorkbook来创建对象;
  • 对于xlsx格式,需要使用XSSFWorkbook来创建工作薄;

需要注意HSSFWorkBook与XSSSFWorkbook两个类都是Workbook接口的实现类。

        String extString = filePath.substring(filePath.lastIndexOf("."));
        InputStream is = null;
        try {
            is = new FileInputStream(filePath);
            if (".xls".equals(extString)) {
                wb = new HSSFWorkbook(is);
            } else if (".xlsx".equals(extString)) {
                wb = new XSSFWorkbook(is);
            } else {
                throw new BusinessException("文件格式错误");
            }

首先,我们获取到文件后缀名,然后创建FileInputStream文件输入流。然后,根据文件格式的不同,选择不同的workbook

1.2 Sheet

看到Excel模型中的sheet1(页面)了吗。其实就是定位到当前sheet进行处理的。

 
image

同样的创建Sheet的时候,也存在HSSFSheet和XSSFSheet这两种类型。所有我们使用其父类Sheet去处理对应的子类实现。

获取第一个sheet空间:

sheet = wb.getSheetAt(0);  

1.3 Row

作用是定位到特定的行。

getPhysicalNumberOfRows和getLastRowNum的区别这两个方法都是判断sheet是否有数据。
区别:

  • sheet.getPhysicalNumberOfRows():返回物理定义的行数(不是工作表中的行数)
  • sheet.getLastRowNum():返回此sheet中最后一行的数字编号,默认是从0开始。
  sheet = wb.getSheetAt(0);
  //获取sheet中,有数据的行数
  int rownum = sheet.getPhysicalNumberOfRows();
  //因为模板是在第四行开始读取,那么我们的直接定位到第四行
  for (int i = 4; i < rownum; i++) {
    //获取当前行
    Row row = sheet.getRow(i);
    if (row != null) {
      //开始对cell进行处理。
    }
  }

1.4 Cell

定位到特定的表格

获取到cell上的数据,进行“业务处理”,当然不同的业务逻辑不同,这里写几个特殊的处理方法。

1. 获取cell上的值,下标从0开始

Cell  cell= row.getCell(int index);

2. 判断Cell的单元格格式

 
image

单元格格式的枚举类型

public interface Cell {

    public final static int CELL_TYPE_NUMERIC = 0;

    public final static int CELL_TYPE_STRING = 1;

    public final static int CELL_TYPE_FORMULA = 2;

     public final static int CELL_TYPE_BLANK = 3;

    public final static int CELL_TYPE_BOOLEAN = 4;

    public final static int CELL_TYPE_ERROR = 5;
}

获取单元格的类型

int type1 = cell.getCellType();
if(type1==Cell.CELL_TYPE_STRING){
         //TODO                 
}

判断单元格是否为空

if (cell == null || org.apache.commons.lang3.StringUtils.isBlank(cell.getStringCellValue())) {
        failMap.put(i, "xx为空");
        break;
}

设置单元格格式

 cell.setCellType(Cell.CELL_TYPE_STRING);

若是文本格式,获取单元格里面的值

在批量上传的时候,推荐模板的单元格格式为文本模式。

cell.getStringCellValue();

如此一来,我们可以将Excel表格里面的数据全部解析出来。

2. 实战中的使用

当然,简单的API可以完成解析的,但是如何在项目中使用呢?

需求:对Excel处理完毕之后,需要记录成功多少笔,失败多少笔。

1. 用户点击上传成功之后,点击前端进行验证:
(1)创建List对象,将解析成功的Excel数据组装成对象保存在集合中;
(2)创建Map对象,保存解析失败的原因和row位置;

    

解析原文件

调用filePaserExcel(解析成功的对象,目标文件,解析成功Map,解析失败的Map)方法,解析Excel对象。

public int fileParseExcel(List<CliBatchWithdraw> successUser, File file,Map<Integer, String> rowSucMap, Map<Integer, String> failMap){
        String filePath = file.getAbsolutePath();
        if (filePath == null) {
            throw new BusinessException("文件路径为空");
        }
        String extString = filePath.substring(filePath.lastIndexOf("."));
        InputStream is = null;
        int count = 0;
        try {
            //获取WorkBook对象
            is = new FileInputStream(filePath);
            if (".xls".equals(extString)) {
                wb = new HSSFWorkbook(is);
            } else if (".xlsx".equals(extString)) {
                wb = new XSSFWorkbook(is);
            } else {
                throw new BusinessException("文件格式错误");
            }
            int count = 0;
        if (wb != null) {
            //获取sheet对象
            sheet = wb.getSheetAt(0);
            //获取Sheet中的实际行
            int rownum = sheet.getPhysicalNumberOfRows();
            String type = "";
            //在第四行进行解析
            for (int i = 4; i < rownum; i++) {
                Row row = sheet.getRow(i);
                if (row != null) {
                    User user= new User();
                    //获取第一个单元格
                    Cell userId= row.getCell(0);
                    //默认模板已经是文本格式的
                    if (userId== null || org.apache.commons.lang3.StringUtils.isBlank(userId.getStringCellValue())) {
                        //因为sheet可能存在空白行,所以判断第一列为空则代表Excel遍历完毕
                        failMap.put(i, "用户为空");
                        break;
                    }
                    userId.setCellType(Cell.CELL_TYPE_STRING);
                     //每遍历完一行,count++
                    count++;

                    Cell age = row.getCell(1);
                    if (age == null || org.apache.commons.lang3.StringUtils.isBlank(age .getStringCellValue())) {
                        failMap.put(i, "年龄为空");
                        continue;
                    }
                    age 

分类:

技术点:

相关文章: