POI進行單行單行地導入的數據在網上有許多的文章,但是要導入一個具有合並單元格的excel貌似比較難找。剛好最近完成了這樣的一個需求,要求導入具有合並單元格的excel:
1 /** 2 * 讀取excel數據,調用這方法開始 3 * @param is 4 * @param indexNum 至少需要多少列數據 5 */ 6 public static List<Object[]> readExcelToObj(InputStream is,int indexNum) { 7 8 Workbook wb = null; 9 List<Object[]> objArrList = null; 10 try { 11 objArrList = new ArrayList<>(); 12 wb = WorkbookFactory.create(is); 13 readExcel(wb, 0, 0, 0,objArrList,indexNum); 14 } catch (InvalidFormatException e) { 15 e.printStackTrace(); 16 } catch (IOException e) { 17 e.printStackTrace(); 18 } 19 return objArrList; 20 }
1 /** 2 * 讀取excel文件 3 * @param wb 4 * @param sheetIndex sheet頁下標:從0開始 5 * @param startReadLine 開始讀取的行:從0開始 6 * @param tailLine 去除最后讀取的行 7 */ 8 public static void readExcel(Workbook wb,int sheetIndex, int startReadLine, int tailLine, List<Object[]> objArrList, int indexNum) { 9 Sheet sheet = wb.getSheetAt(sheetIndex); 10 Row row = null; 11 12 for(int i=startReadLine; i<sheet.getLastRowNum()-tailLine+1; i++) { 13 row = sheet.getRow(i); 14 List<Object> objList = new ArrayList<>(); 15 for(int j = 0 ; j<row.getLastCellNum();j++) { 16 //for(Cell c : row) { 17 Cell c = row.getCell(j); 18 if(c==null){ 19 objList.add(""); 20 continue; 21 } 22 boolean isMerge = isMergedRegion(sheet, i, c.getColumnIndex()); 23 //判斷是否具有合並單元格 24 if(isMerge) { 25 String rs = getMergedRegionValue(sheet, row.getRowNum(), c.getColumnIndex()); 26 objList.add(rs); 27 }else { 28 objList.add(getCellValue(c)); 29 } 30 31 } 32 while(objList.size()<indexNum){ 33 objList.add(""); 34 } 35 objArrList.add(objList.toArray()); 36 } 37 }
1 /** 2 * 獲取合並單元格的值 3 * @param sheet 4 * @param row 5 * @param column 6 * @return 7 */ 8 public static String getMergedRegionValue(Sheet sheet ,int row , int column){ 9 int sheetMergeCount = sheet.getNumMergedRegions(); 10 11 for(int i = 0 ; i < sheetMergeCount ; i++){ 12 CellRangeAddress ca = sheet.getMergedRegion(i); 13 int firstColumn = ca.getFirstColumn(); 14 int lastColumn = ca.getLastColumn(); 15 int firstRow = ca.getFirstRow(); 16 int lastRow = ca.getLastRow(); 17 18 if(row >= firstRow && row <= lastRow){ 19 20 if(column >= firstColumn && column <= lastColumn){ 21 Row fRow = sheet.getRow(firstRow); 22 Cell fCell = fRow.getCell(firstColumn); 23 return getCellValue(fCell) ; 24 } 25 } 26 } 27 28 return null ; 29 }
1 /** 2 * 判斷指定的單元格是否是合並單元格 3 * @param sheet 4 * @param row 行下標 5 * @param column 列下標 6 * @return 7 */ 8 public static boolean isMergedRegion(Sheet sheet,int row ,int column) { 9 int sheetMergeCount = sheet.getNumMergedRegions(); 10 for (int i = 0; i < sheetMergeCount; i++) { 11 CellRangeAddress range = sheet.getMergedRegion(i); 12 int firstColumn = range.getFirstColumn(); 13 int lastColumn = range.getLastColumn(); 14 int firstRow = range.getFirstRow(); 15 int lastRow = range.getLastRow(); 16 if(row >= firstRow && row <= lastRow){ 17 if(column >= firstColumn && column <= lastColumn){ 18 return true; 19 } 20 } 21 } 22 return false; 23 }
1 /** 2 * 獲取單元格的值 3 * @param cell 4 * @return 5 */ 6 public static String getCellValue(Cell cell){ 7 8 if(cell == null) return ""; 9 10 if(cell.getCellType() == Cell.CELL_TYPE_STRING){ 11 12 return cell.getStringCellValue(); 13 14 }else if(cell.getCellType() == Cell.CELL_TYPE_BOOLEAN){ 15 16 return String.valueOf(cell.getBooleanCellValue()); 17 18 }else if(cell.getCellType() == Cell.CELL_TYPE_FORMULA){ 19 20 return cell.getCellFormula() ; 21 22 }else if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){ 23 24 return String.valueOf(cell.getNumericCellValue()); 25 26 } 27 return ""; 28 }
注意:這導入功能也適用於單行讀取,直接調用 readExcelToObj() 方法即可;參數1:傳入excel文件的輸入流;參數2:指定你希望至少要讀入多少列數據(比如傳入個0,就代表:如果你有的行只有3列數據的話,那么獲得的數組長度就只有3;如果你傳入了10,那些只有3列的數據會自動填充空字符串給數組,使每個數組最小長度為10);