java - 尝试使用 Apache POI 从 Excel 工作簿获取公式时出错

标签 java excel apache-poi

我正在使用 Apache POI 更改 Excel 文档中的某些值,然后从不同的单元格读取结果。一切都很顺利,直到我收到客户的测试文件。经过测试,我发现有两个问题:

1) 当我尝试从具有公式的单元格获取值但返回格式为货币且以 € 符号作为前缀的结果时,出现错误。

2) 当我尝试从引用另一个公式单元格的单元格获取值时(例如:工作表 3 中的单元格 B20 的值为“=工作表 2!A20”,其中工作表 2 中的 A20 是SUM() 公式。),我收到错误。

错误是:线程“main”java.lang.IllegalStateException中出现异常:无法从错误公式单元格获取数值

文档名称、输入列(值被更改的位置)和输出列(从中读取值的位置)取自命令行。

您可以在下面找到我的代码:

package poitest;

import java.util.List;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.usermodel.*;

public class ReadExcel {
    public static void main(String[] args) throws FileNotFoundException, IOException {
        // Will contain cell name / value pair for input cells          
        Map<String, String> inputCellsMap = new HashMap<String, String>();

        // Will contain cell name for output cells
        List<String> outputCells = new ArrayList<String>();

        // Open the Excel file
        FileInputStream file = new FileInputStream(new File(args[0]));

        // Get the current workbook
        HSSFWorkbook workbook = new HSSFWorkbook(file);         

        // Get the input cells that need to be modified and
        // store their name and value in the inputCellsMap
        for (String element : args[1].split(";")) {
            inputCellsMap.put(element.split("=")[0], element.split("=")[1]);
        }

        // Get the output cells that will be accessed for resulting values
        for (String element : args[2].split(";")) {
            outputCells.add(element);           
        }

        // Loop through the cells that need to be modified and 
        // set the new value in the Excel document
        Iterator<Entry<String,String>> inputIterator = inputCellsMap.entrySet().iterator();
        while (inputIterator.hasNext()) {
            Map.Entry<String,String> inputEntry = (Map.Entry<String,String>) inputIterator.next();

            CellReference cellReferenceInput = new CellReference(inputEntry.getKey());
            int cellReferenceInputRow = cellReferenceInput.getRow();
            int cellReferenceInputColumn = cellReferenceInput.getCol();

            // Get sheet name for each input cell
            HSSFSheet inputSheet = workbook.getSheet(inputEntry.getKey().split("!")[0]);

            Row rowInput = inputSheet.getRow(cellReferenceInputRow);
            if (rowInput == null)
                rowInput = inputSheet.createRow(cellReferenceInputRow);
            Cell cellInput = rowInput.getCell(cellReferenceInputColumn, Row.CREATE_NULL_AS_BLANK);              
            cellInput.setCellValue(Integer.parseInt(inputEntry.getValue()));        
        }

        // Apply all formulas after altering cell values        
        workbook.getCreationHelper().createFormulaEvaluator().evaluateAll();        

        // Get the results from the output cells
        for (int i = 0; i < outputCells.size(); i++) {
            CellReference cellReferenceOutput = new CellReference(outputCells.get(i));
            int cellReferenceOutputRow = cellReferenceOutput.getRow();
            int cellReferenceOutputColumn = cellReferenceOutput.getCol();

            // Get sheet name for each output cell
            HSSFSheet outputSheet = workbook.getSheet(outputCells.get(i).split("!")[0]);

            Row rowOutput = outputSheet.getRow(cellReferenceOutputRow);
            Cell cellOutput = rowOutput.getCell(cellReferenceOutputColumn, Row.CREATE_NULL_AS_BLANK);

            // Display results
            switch (cellOutput.getCellType()) {
                case Cell.CELL_TYPE_BOOLEAN:
                    System.out.println(cellOutput.getBooleanCellValue());
                    break;
                case Cell.CELL_TYPE_NUMERIC:
                    System.out.println(cellOutput.getNumericCellValue());
                    break;
                case Cell.CELL_TYPE_STRING:
                    System.out.println(cellOutput.getStringCellValue());
                    break;
                case Cell.CELL_TYPE_BLANK:
                    break;              
                case Cell.CELL_TYPE_FORMULA:                            
                    switch (cellOutput.getCachedFormulaResultType()) {
                        case Cell.CELL_TYPE_STRING:
                            System.out.println(cellOutput.getRichStringCellValue());                            
                            break;
                        case Cell.CELL_TYPE_NUMERIC:
                            HSSFCellStyle style = (HSSFCellStyle) cellOutput.getCellStyle();
                            if (style == null) {
                                System.out.println(cellOutput.getNumericCellValue());
                            } else {
                                DataFormatter formatter = new DataFormatter();
                                System.out.println(formatter.
                                        formatRawCellContents(
                                                cellOutput.getNumericCellValue(), 
                                                style.getDataFormat(),
                                                style.getDataFormatString())
                                        );
                            }
                            break;
                        case HSSFCell.CELL_TYPE_BOOLEAN:
                            System.out.println(cellOutput.getBooleanCellValue());
                            break;
                        case HSSFCell.CELL_TYPE_ERROR:
                            System.out.println(ErrorEval.getText(cellOutput.getErrorCellValue()));                          
                            break;
                    }

                    break;
            }                           
        }           

        workbook.close();       
    }
}

最佳答案

case Cell.CELL_TYPE_FORMULA:                    
    System.out.println(cellOutput.getNumericCellValue());
    break;

实际上应该是:

case Cell.CELL_TYPE_FORMULA:                    
        System.out.println(cellOutput.getCellFormula());
        break;

之后您可以执行以下操作:

case Cell.CELL_TYPE_FORMULA:                    
    System.out.println(cellOutput.getCellFormula());
    switch(cellOutput.getCachedFormulaResultType()) {
        case Cell.CELL_TYPE_NUMERIC:
        System.out.println(cellOutput.getNumericCellValue());
        break;

See the docs for more

关于java - 尝试使用 Apache POI 从 Excel 工作簿获取公式时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32682665/

相关文章:

excel - VBA 去掉逗号

excel - 使用数组在工作表之间复制列

javascript - HTML 表格到 Excel - 格式和扩展名不匹配

java - Poi如何在更改样式后更改单元格类型

java - 启动时 JTextField 未显示在 JPanel 中

Java - 不能扩展类?

java - 如何在 apache poi 3.17 中调用 trackAllColumnsForAutoSizing() 方法

java - 如何使用 apache POI 在 docx 中插入当前日期字段

java - 从 JSP 页面运行 java 应用程序

java - 我的僵尸不会找到自己。