Java解析复杂表格excel
解析复杂表格
在实际开发中,上传⽂件是⼗分常见的问题,⼀般情况下,解析的思路⽆⾮1. 固定表头进⾏解析;2. 每⼀⾏进⾏解析。但是偶尔会碰⼀下⼀些格式⽐较复杂的表格,⽤以上⽅式解析就 得不到我们想要的结果了。
例如以下这张表,乍⼀看是不是有种⼼态崩溃的感觉,
⾯对这种复杂表格,就需要采取特殊的⽅式了,⾸先,还是将思路,实现放到最后再说;1.按照每⼀⾏去解析,但是在解析时,需要判断是否为单元格;2. 得到数据后,还需要根据⾏号进⾏过滤,然后对每⼀⾏单元格数据进⾏合并操作;3. 得到数据后,最后需要根据列号进⾏过滤,对每⼀列单元格进⾏合并操作。
实现
话不多说,上代码:
1. 判断是否为单元格:
2. 解析代码:/**  *  *  * @param sheet  *            表单  * @param cellRow  *            被判断的单元格的⾏号  * @param cellCol  *            被判断的单元格的列号  * @return row: ⾏数;col 列数  * @throws IOException  * @Author zhangxinmin  */ private  static  Map <String , Integer > getMergerCellRegionRow (Sheet sheet , int  cellRow ,            int  cellCol ) {  Map <String , Integer > map = new  HashMap <>();  int  retVal = 0, retCol = 0 ;  int  sheetMergerCount = sheet .getNumMergedRegions ();  for  (int  i = 0; i < sheetMergerCount ; i ++) {  CellRangeAddress cra = (CellRangeAddress ) sheet .getMergedRegion (i );  int  firstRow = cra .getFirstRow (); // 合并单元格CELL 起始⾏  int  firstCol = cra .getFirstColumn (); // 合并单元格CELL 起始列  int  lastRow = cra .getLastRow (); // 合并单元格CELL 结束⾏  int  lastCol = cra .getLastColumn (); // 合并单元格CELL 结束列  if  (cellRow >= firstRow && cellRow <= lastRow ) { // 判断该单元格是否是在合并单元格中    if  (cellCol >= firstCol && cellCol <= lastCol ) {    retVal = lastRow - firstRow + 1; // 得到合并的⾏数    retCol = lastCol - firstCol + 1; // 得到合并的列数    break ;    }  }  }  map .put ("row", retVal );  map .put ("col", retCol );  return  map ; }private  static  Integer isMergedRegion (Sheet sheet ,int  row ,int  column ) {  int  sheetMergeCount = sheet .getNumMergedRegions ();  for  (int  i = 0; i < sheetMergeCount ; i ++) {  CellRangeAddress range = sheet .getMergedRegion (i );  int  firstColumn
= range .getFirstColumn ();  int  lastColumn = range .getLastColumn ();  int  firstRow = range .getFirstRow ();  int  lastRow = range .getLastRow ();  if (row >= firstRow && row <= lastRow ){    if (column >= firstColumn && column <= lastColumn ){    return  i ;    }  }  }  return  -1; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21java stream
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53public  static  List <CellRowAndColDTO > readDiffDataBySheet (Sheet sheet , int  startRows ){  Li
st <CellRowAndColDTO > result = new  ArrayList <>();  for  (int  rowIndex = startRows , z = sheet .getLastRowNum (); rowIndex <= z ; rowIndex ++) {  Row row = sheet .getRow (rowIndex );  if  (row == null ) {    continue ;  }
1
2
3
4
5
6
7
8
int  rowSize = row .getLastCellNum ();  for  (int  columnIndex = 0; columnIndex < rowSize ; columnIn
dex ++) {    CellRowAndColDTO dto = new  CellRowAndColDTO ();    Cell cell = row .getCell (columnIndex );    if  (cell != null ){    // 读取单元格数据格式(标记为字符串)    cell .setCellType (CellType .STRING );    String value = cell .getStringCellValue ();    if (0 != isMergedRegion (sheet , rowIndex ,columnIndex )){//判断是否合并格      // 处理有值的cell //      if (StringUtils.isEmpty(value)) {//      continue;//      }      dto .setRow (rowIndex );      dto .setCol (columnIndex );      Map <String , Integer > map = getMergerCellRegionRow (sheet , rowIndex , columnIndex );//获取合并的⾏列      dto .setCellCol (map .get ("col") == 0? 1:map .get ("col"));      dto .setCellRow (map .get ("row") == 0? 1:map .get ("row"));      dto .setCellValue (value );      result .add (dto );    }else {      dto .setRow (rowIndex );      dto .setCol (columnIndex );      Map <String , Integer > map = getMergerCellRegionRow (sheet , rowIndex , columnIndex );//获取合并的⾏列      dto .setCellCol (1);      dto .setCellRow (1);      dto .setCellValue (value );      result .add (dto );    }    }  }  }  List <CellRowAndColDTO > dtos = new  ArrayList <>();  Map <Integer , List <CellRowAndColDTO >> map = result .stream ().collect (Collectors .groupingBy (CellRowAndColDTO ::getRow ));//根据⾏进⾏分组  map .forEach ((k ,v ) -> {  for (int  i =0;i <v .size ();i ++){    if (i !=0){    Integer col = dtos .get (dtos .size ()-1).getCol ()+dtos .get (dtos .size ()-1).getCellCol ();    if (v .get (i ).getCol () == col ){      dtos .add (v .get (i ));      continue ;    }    }else {    dtos .add (v .get (i ));    }  }  });  List <CellRowAndColDTO > dtos2 = new  ArrayList <>();  Map <Integer , List <CellRowAndColDTO >> m
ap2 = dtos .stream ().collect (Collectors .groupingBy (CellRowAndColDTO ::getCol ));//根据列分组  map2.forEach ((k ,v ) -> {  for (int  i =0;i <v .size ();i ++){    if (i !=0){    if (v .get (i ).getCellRow () != 1){      if (v .get (i ).getCellCol () == v .get (i -1).getCellCol () && v .get (i ).getCellRow () == v .get (i -1).getCellRow ()){      if (v .get (i ).getCellRow () == 1 && v .get (i ).getCellCol () == 1){        dtos2.add (v .get (i ));        continue ;      }else {        if (StringUtils .isBlank ((v .get (i ).getCellValue ()))){        continue ;        }
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
说明⼀下: ⾸先我先获取每⼀⾏,然后对该⾏的每⼀个单元格cell对象进⾏判断处理,判断时候为单元格,如果是,则将⾏号,列号,合并⾏数,合并列数,数值进⾏存储,存储到List集合;然后,对该集合进⾏过滤操作,通过java8 stream流的⽅式先根据⾏号进⾏分组,然后获取下⼀个格的位置col ,然后进⾏判断,如果是下⼀个格则进⾏存储;如果是该单元格内的空格,则跳出循环。然后再根据列进⾏分组,根据⾏号列号进⾏对合并格其他空格单元格进⾏过滤,最后完成数据库存储,完成解析操作。
普通表格按⾏解析        }      }      }    }    }    dtos2.add (v .get (i ));  }  });  return  dtos2; }
73
74
75
76
77
78
79
80
81
82
83public  static  List <String []> readData (String fileType , int  startRows , boolean  ignoreRowBlank , InputStream is ) throws  IOException {  List <String []> result = new  ArrayList <>();  Workbook wb = readWorkBook (fileType , is );  for  (int  sheetIndex = 0; sheetIndex < wb .getNumberOfSheets (); sheetIndex ++) {  Sheet sheet = wb .getSheetAt (sheetIndex );  for  (int  rowIndex = startRows , z = s
heet .getLastRowNum (); rowIndex <= z ; rowIndex ++) {    Row row = sheet .getRow (rowIndex );    if  (row == null ) {    continue ;    }    int  rowSize = row .getLastCellNum ();    String [] values = new  String [rowSize ];    boolean  hasValue = false ;    for  (int  columnIndex = 0; columnIndex < rowSize ; columnIndex ++) {    String value = "";    Cell cell = row .getCell (columnIndex );    if  (cell != null ) {      // 注意:⼀定要设成这个,否则可能会出现乱码,后⾯版本默认设置      switch  (cell .getCellType ()) {      case  HSSFCell .CELL_TYPE_STRING :        value = cell .getStringCellValue ();        break ;      case  HSSFCell .CELL_TYPE_NUMERIC :        if  (HSSFDateUtil .isCellDateFormatted (cell )) {        Date date = cell .getDateCellValue ();        if  (date != null ) {          value = new  SimpleDateFormat ("yyyy-MM-dd")            .format (date );        } else  {          value = "";        }        } else  {        //value = new DecimalFormat("0").NumericCellValue());        if  (HSSFDateUtil .isCellDateFormatted (cell )) {          value = String .valueOf (cell .getDateCellValue ());        } else  {          cell .setCellType (Cell .CELL_TYPE_STRING );          String temp = cell .getStringCellValue ();          // 判断是否包含⼩数点,如果不含⼩数点,则以字符串读取,如果含⼩数点,则转换为Double 类型的字符串          if  (temp .indexOf (".") > -1) {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
这⾥我就不过多叙述这个按⾏解析了,代码思路⽐较简单⼀看就能懂。
总结
该⽂章为我总结平时开发过程中解决的难题的经验和思路;如果有更好的解决办法希望能不吝赐教。
⼤家携⼿在开发的道路上越⾛越远。不喜勿喷。          if  (temp .indexOf (".") > -1) {          value = String .valueOf (new  Double (temp )).trim ();          } else  {          value = temp .trim ();          }        }        }        break ;      case  HSSFCell .CELL_TYPE_FORMULA :        // 导⼊时如果为公式⽣成的数据则⽆值        if  (!cell .getStringCellValue ().equals ("")) {        value = cell .getStringCellValue ();        } else  {        value = cell .getNumericCellValue () + "";        }        break ;      case  HSSFCell .CELL_TYPE_BLANK :        break ;      case  HSSFCell .CELL_TYPE_ERROR :        value = "";        break ;      case  HSSFCell .CELL_TYPE_BOOLEAN :        value = (cell .getBooleanCellValue () == true  ? "Y"          : "N");        break ;      default :        value = "";      }    }    values [columnIndex ] = value ;    if  (!value .isEmpty ()) {      hasValue = true ;    }    }    if  (!ignoreRowBlank || hasValue ) {//不为忽略空⾏模式或不为空⾏    result .add (values );    }  }  }  return  result ; }
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。