最近因为工作原因,要分析一个Excel文档的数据,结果发现获取到的数据里有很多时候是空的,经过实际分析发现是合并单元格导致的不能获取到值,于是对于POI处理合并单元格的一些获取方法进行了测试。
获取Excel单元的测试方法如下:
/**
* 获取合并单元格
*
* @param fileName 文件名称
* @param sheetName 工作簿名称
*/
public static void getHeBingDanYuanGe(String fileName, String sheetName) {
//判断文件名格式是否为excel
if (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx")) {
System.out.println("文件类型异常,不为excel文档");
return;
}
File file = new File(fileName);
//判断文件是否存在
if (!file.exists()) {
System.out.println("文件不存在,请检查文件路径");
return;
}
Workbook wb = null;
InputStream is = null;
try {
is = new FileInputStream(file);
if (fileName.endsWith(".xls")) {
wb = new HSSFWorkbook(is);
} else {
wb = new XSSFWorkbook(is);
}
Sheet sheet = wb.getSheet(sheetName);
int lastRowNum = sheet.getLastRowNum();//最后一行的行坐标
for (int i = 0; i <= lastRowNum; i++) {
Row row = sheet.getRow(i);
int firstCellNum = row.getFirstCellNum();//行开始的列坐标
int lastCellNum = row.getLastCellNum();//行结束的列坐标+1
}
/**
* 获取合并单元格,根据测试验证发现查找顺序:单行多列合并,单列多行合并,多行多列合并,从上往下,从左往右
* 合并单元格的值只能通过合并单元格的首行首列组成的坐标获取到,其他的行坐标列坐标都无法获取到具体的取值
*/
List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
System.out.println(mergedRegions.size());
for(CellRangeAddress mergeRegion : mergedRegions){
int firstRow = mergeRegion.getFirstRow();//获取合并单元格的起始行坐标
int lastRow = mergeRegion.getLastRow();//获取合并单元的结束行坐标
int firstColumn = mergeRegion.getFirstColumn();//获取合并单元格的起始列坐标
int lastColumn = mergeRegion.getLastColumn();//获取合并单元格的结束列坐标
System.out.println(firstRow + " " + lastRow + " " + firstColumn + " " + lastColumn);
for(int i=firstRow; i<=lastRow; i++){
Row row = sheet.getRow(i);
for(int j=firstColumn; j<=lastColumn; j++){
Cell cell = row.getCell(j);
System.out.println(getCellValueByCell(cell));
}
}
int numberOfCells = mergeRegion.getNumberOfCells();//获取合并单元格的原单元格个数
System.out.println("numberOfCells:"+numberOfCells);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("读取文件内容异常");
} finally {
try {
wb.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Excel文档截图如下:
运行结果如下:
7
2 2 2 3
3numberOfCells:2
2 2 5 7
7
numberOfCells:3
4 4 3 4
5numberOfCells:2
5 5 3 5
6
numberOfCells:3
3 4 2 2
4numberOfCells:2
0 2 0 1
1numberOfCells:6
0 1 2 3
2numberOfCells:4
根据测试结果,可以很明显的看出,对于合并单元格的基础单元格,除了位于该合并单元格首行首列的基础单元格能够获取到实际的取值外,其他的基础单元格均无法正常获取到值。如果需要获取值的话,需要先定位到该合并单元格的首行首列坐标,然后根据首行首列坐标获取到单元格的取值。
与此同时,可以看出,调用sheet.getMergedRegions()方法获取工作簿里的合并单元格集合时,是从左往右、从上往下进行检索的。检索过程中,优先检索当行多列合并的单元格,然后是多行单列合并的单元格,最后才是多行多列合并的单元格。这里也是需要在实际过程中注意的点,毕竟不少人的常识认为是根据合并后的单元格从左往右、从上往下检索就行,不会去考虑合并单元格的行数、列数对应的关系。