如何使用Apache POI读取已格式化但为空的Excel单元格?

4
我有一种使用Apache POI读取Excel单元格的方法,它运行良好。嗯...几乎良好。
public static ArrayList readXLsXFile() throws FileNotFoundException, IOException {

        ArrayList outListaExcel = new ArrayList();

        FileInputStream fis;
        ptxf= new FileInputStream(pathToExcelFile);
        XSSFWorkbook workbook = new XSSFWorkbook(ptxf);
        XSSFSheet sheetAr = workbook.getSheetAt(0);
        Iterator rowsAr = sheetAr.rowIterator();
        while (rowsAr.hasNext()) {
            XSSFRow row1 = (XSSFRow) rowsAr.next();
            Iterator cellsAr = row1.cellIterator();
            ArrayList<String> arr;
            arr = new ArrayList();
            while (cellsAr.hasNext()) {
                XSSFCell cell1 = (XSSFCell) cellsAr.next();
                arr.add(String.valueOf(cell1));
            }
            outListaExcel.add(arr);
        }
        return outListaExcel;
    }

如果单元格被格式化了,例如整个A列有边框,则它将继续读取空单元格并给出空字符串。如何忽略这些空(已格式化)单元格?
因此,readXLsXFile将为我提供一个ArryList,其中包含
[0] -> [1][2]
[1] -> [3][4] 

但因为A列有边框格式,它还将提供十个更多的空字符串节点。
编辑后Gagravarr的回答。
我可以避免检查是否为空,然后不将其添加到主列表中。但对于一些非常大的.xls文件,如果这些文件很多,这将需要太长时间,而且通常我认为这不是一个好的做法。
我的问题是,是否存在像单元格一样的“行”对象,我是否忽略了它们。
 ArrayList<ArrayList<String>>mainLista = new ArrayList<ArrayList<String>>();
for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
        Row r = sheet.getRow(rowNum);
        int lastColumn = r.getLastCellNum();
        ArrayList<String> subList = new ArrayList<String>();
        for (int cn = 0; cn < lastColumn; cn++) {
            Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL);

            if (c != null) {
                subList.add(c.getStringCellValue());
            } else {
            }
        }
        if (!subList.isEmpty() ){  // I think it is not good way
        mainLista.add(subList);}   // to do this, because it still reads 
    }                              // an empty rows  

2
当文本(或其他基于类型的值)为空时,您可以使用 continue。不确定您的确切意思是什么。 - Gábor Bakos
@GáborBakos,我已经编辑了我的问题,希望现在我表达得更清楚了。谢谢! - 1392023093user
2个回答

2
如同Apache POI文档中关于迭代行和单元格的解释所述,迭代器只会返回已定义并且有/曾经有内容的行和单元格。
如果你想要完全控制空白或空单元格来获取单元格,则需要使用类似以下的方式:
// Decide which rows to process
int rowStart = Math.min(15, sheet.getFirstRowNum());
int rowEnd = Math.max(1400, sheet.getLastRowNum());

for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
   Row r = sheet.getRow(rowNum);

   int lastColumn = Math.max(r.getLastCellNum(), MY_MINIMUM_COLUMN_COUNT);

   for (int cn = 0; cn < lastColumn; cn++) {
      Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL);
      if (c == null) {
         // The spreadsheet is empty in this cell
      } else {
         // Do something useful with the cell's contents
      }
   }
}

如果您想提取空单元格(通常是具有样式但没有值的单元格),可以尝试使用其他缺失单元格策略,例如RETURN_NULL_AND_BLANK


我能做到,但我认为这不是一个好的做法。因为在非常大的文件的情况下,如果它们太多了,缓冲每个空单元格是个不错的想法。顺便说一句,我没找到一种方法来检查行是否没有内容,而不必检查每个单元格。在 Apache POI 文档上,我只看到了你已经发布的内容。 - 1392023093user
你一次只缓冲一行。如果它是空的,就扔掉它。如果它有内容,就像正常处理一样? - Gagravarr
这完全取决于你如何定义空! - Gagravarr
1
好的,我已经告诉过你了。在这种情况下,空单元格意味着它们没有内容,但它们被格式化为具有边框或其他方式。我已经发布了一张图片,以使自己更清晰。 - 1392023093user
那么按照我已经建议的做法,正常获取它们,如果行中的所有单元格都为空(不是 null 且不持有数据),则丢弃该行的数据并不保存。 - Gagravarr
显示剩余3条评论

0

设置列B的边框,在我的情况下,它对我有帮助


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接