【问题标题】:How to read cell value from formula cell using apache poi如何使用 apache poi 从公式单元格中读取单元格值
【发布时间】:2020-06-08 21:30:56
【问题描述】:

我正在尝试从 excel 文件中读取所有数据,该文件也有一些公式单元格, 但我不知道哪个单元格是公式单元格。无论单元格的类型如何,我如何从单元格中读取所有值。

我的代码是这样的

FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
while (rows.hasNext()) {
     row = (HSSFRow) rows.next();
     Iterator cells = row.cellIterator();
     while (cells.hasNext()) {
             cell = (HSSFCell) cells.next();
             if (cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
                  ar.add(cell.getStringCellValue());
             } else if (cell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
                 ar.add(cell.getNumericCellValue());
             }else if (cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
                 ar.add(evaluator.evaluateFormulaCell(cell));
             } else {
                 ar.add("");
             }
     }
}

我将公式单元格值设为 0

【问题讨论】:

    标签: java apache-poi


    【解决方案1】:

    您正在寻找的方法是 Cell.getCachedFormulaResultType - 用于告诉您公式结果类型的公式单元格

    你的代码可以是这样的:

    private void handleCell(int type, Cell cell) {
             if (type == HSSFCell.CELL_TYPE_STRING) {
                  ar.add(cell.getStringCellValue());
             } else if (type == HSSFCell.CELL_TYPE_NUMERIC) {
                 ar.add(cell.getNumericCellValue());
             } else if (type == HSSFCell.CELL_TYPE_BOOLEAN) {
                 ar.add(cell.getBooleanCellValue());
             } else if (type == HSSFCell.CELL_TYPE_FORMULA) {
                 // Re-run based on the formula type
                 handleCell(cell.getCachedFormulaResultType(), cell);
             } else {
                 ar.add("");
             }
    }
    
    public void handleSheet(Sheet sheet) {
        for (Row row : sheet) {
           for (Cell cell : row) {
               handleCell(cell.getCellType(), cell);
           }
        }
    }
    

    请注意,迭代器只给出文件中定义的单元格,因此如果单元格从未被使用过,就会有间隙。如果您需要获取每个单元格,包括丢失的单元格,请参阅Iterating vs Fetching docs

    【讨论】:

    • 嗨,Gagravarr,感谢您的回复。但是上面的代码给出了 javax.servlet.ServletException: java.lang.StackOverflowError ... 所以我又写了一个方法handelCell2() 并在公式条件中调用handelCell2()。现在我也不例外..但仍然没有得到公式单元格的值......
    • 0 表示它是数字。在这种情况下,只需调用 cell.getNumericCellValue()
    • @DipeshGupta 现在试试看,我忘记将使用类型的行更改为传入的行
    • 这很适合我。谢谢! @DipeshGupta getCachedFormulaResultType 根据给定的公式返回实际值。您确定您尝试处理的单元格包含公式吗?
    【解决方案2】:

    使用Cell.getCachedFormulaResultType,我们得到缓存的公式值;因此我们必须评估公式以获得新值

    public static void main(String args[]) {
        FileInputStream inp = null;
        try {            
            inp = new FileInputStream("E:\\Hasangi\\tets\\test\\book.xls");
    
            HSSFWorkbook workbook = new HSSFWorkbook(inp);
            FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
            HSSFSheet sheet = workbook.getSheetAt(0);
            Row row = sheet.getRow(2);
            Cell cell = row.getCell(0);
    
            cell.setCellValue(1235487845);
            handleSheet(sheet, evaluator);
            FileOutputStream fileOut = new FileOutputStream("E:\\Hasangi\\tets\\test\\book.xls");
            workbook.write(fileOut);
            fileOut.close();
        } catch (IOException ex) {
            Logger.getLogger(xlreader.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private static void handleCell(int type, Cell cell, FormulaEvaluator evaluator) {
        if (type == HSSFCell.CELL_TYPE_STRING) {
          System.out.println(cell.getStringCellValue());
        } else if (type == HSSFCell.CELL_TYPE_NUMERIC) {
           System.out.println(cell.getNumericCellValue());
        } else if (type == HSSFCell.CELL_TYPE_BOOLEAN) {
           System.out.println(cell.getBooleanCellValue());
        } else if (type == HSSFCell.CELL_TYPE_FORMULA) {
            // Re-run based on the formula type
            evaluator.evaluateFormulaCell(cell);
            handleCell(cell.getCachedFormulaResultType(), cell, evaluator);
        } else {
           System.out.println("");
        }
    }
    
    public static void handleSheet(Sheet sheet,FormulaEvaluator evaluator) {
        for (Row row : sheet) {
            for (Cell cell : row) {
                handleCell(cell.getCellType(), cell,evaluator);
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      这是我的功能:

      public void getValueOfFormulaCell() throws IOException
      {
          FileInputStream xlsfile = new FileInputStream(new File("D:\\Desktop\\Temp\\marks.xls"));
          HSSFWorkbook objWorkbook = new HSSFWorkbook(xlsfile);
          Sheet sheet = objWorkbook.getSheetAt(0);
          FormulaEvaluator evaluator = objWorkbook.getCreationHelper().createFormulaEvaluator();
      
          // suppose your formula is in B4
          CellReference cellReference = new CellReference("B4"); 
          Row row = sheet.getRow(cellReference.getRow());
          Cell cell = row.getCell(cellReference.getCol()); 
      
          CellValue cellValue = evaluator.evaluate(cell);
      
          switch (cellValue.getCellType()) {
              case Cell.CELL_TYPE_BOOLEAN:
                  System.out.println(cellValue.getBooleanValue());
                  break;
              case Cell.CELL_TYPE_NUMERIC:
                  System.out.println(cellValue.getNumberValue());
                  break;
              case Cell.CELL_TYPE_STRING:
                  System.out.println(cellValue.getStringValue());
                  break;
              case Cell.CELL_TYPE_BLANK:
                  break;
              case Cell.CELL_TYPE_ERROR:
                  break;
      
              // CELL_TYPE_FORMULA will never happen
              case Cell.CELL_TYPE_FORMULA: 
                  break;
          }               
          }
      

      【讨论】:

        【解决方案4】:

        上面的帖子有效,它帮助我编写了以下也有效的程序。 以下代码读取包含公式、错误、字符串、数字的 Excel 文件 (.xlsx)。 它读取 Excel 文件并将其转换为 PIPE 分隔的字符串以写入文本文件。

        public String readExcelFile(String filepathname)
        {
            String extractedText = null;
            try 
            {
        
                InputStream is = new FileInputStream(filepathname);
                XSSFWorkbook myExcelBook = new XSSFWorkbook(is);
                XSSFSheet myExcelSheet = myExcelBook.getSheet("VendorCentral");
        
                // Get iterator to all the rows in current sheet
        
                Iterator<Row> rowIterator = myExcelSheet.iterator();
        
                //Traversing through each row of xlsx file
        
                int rowNum=0;
                StringBuffer rowContents;
        
                StringBuffer sheetContents = new StringBuffer();
        
                XSSFFormulaEvaluator evaluator = myExcelBook.getCreationHelper().createFormulaEvaluator();
        
                while (rowIterator.hasNext())
                {
                    Row row = rowIterator.next();
                    rowNum++;
        
                    rowContents = new StringBuffer();
        
                    //For each row, iterate through each column
                    Iterator<Cell> cellIterator = row.cellIterator();
        
                    while (cellIterator.hasNext())
                    {
                        Cell cell = cellIterator.next();
        
                        switch (cell.getCellType())
                        {
                            case Cell.CELL_TYPE_STRING:
                                rowContents.append(cell.getStringCellValue() + DELIM_CHAR); 
                                break;
        
                            case Cell.CELL_TYPE_NUMERIC:
                                rowContents.append(cell.getNumericCellValue()  + DELIM_CHAR); 
                                break;
        
                            case Cell.CELL_TYPE_BOOLEAN:
                                rowContents.append(cell.getBooleanCellValue()  + DELIM_CHAR); 
                                break;
        
                            case Cell.CELL_TYPE_BLANK:
                                rowContents.append(""  + DELIM_CHAR); 
                                break;
        
                            case Cell.CELL_TYPE_ERROR:
                                rowContents.append("#Error"  + DELIM_CHAR); 
                                break;
        
                            case Cell.CELL_TYPE_FORMULA:
                                CellValue cellValue = evaluator.evaluate(cell );
                                System.out.println("cellValue.formatAsString: " + cellValue.formatAsString());
                                System.out.println("cellValue.getStringValue: " + cellValue.getStringValue()  );
        
                                rowContents.append(cellValue.formatAsString()  + DELIM_CHAR); 
                                break;
        
                            default:
                                rowContents.append(""  + DELIM_CHAR); 
        
                        }
        
                    }
        
                    if (rowContents.length() > 0)
                        rowContents.deleteCharAt(rowContents.length()-1);
        
                    System.out.println("Row " + rowNum + ": " + rowContents.toString() );
                    sheetContents.append("Row " + rowNum + ": " + rowContents.toString() + "\n" );
                }
        
        
                myExcelBook.close();
                if (sheetContents.length() > 0)
                    sheetContents.deleteCharAt(sheetContents.length()-1);
        
                extractedText = sheetContents.toString();
        
            } catch (Exception e) 
            {
                e.printStackTrace();
            }
            return extractedText;
        }
        

        【讨论】:

          猜你喜欢
          • 2019-06-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多