Apache Poi – 单元格中的值在现有工作簿中出现错误后不会被重新计算

huangapple go评论90阅读模式
英文:

Apache Poi - Value in a cell having error in existing workbook is not recalculated

问题

以下是您提供的代码的翻译部分:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
import org.apache.poi.xssf.usermodel.XSSFName;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class GetDataFromExcel {

    public static void main(String[] args) throws IOException {
        getData();
    }

    public static void getData() throws IOException {

        String s, cCellName, cString;
        XSSFName namedCell;
        AreaReference aref;
        CellReference[] crefs;
        XSSFRow r;
        XSSFCell c;
        XSSFSheet sheet = null;

        File directory = new File("./");
        s = directory.getAbsolutePath();
        s = s.substring(0, s.length() - 2);
        InputStream ExcelFileToRead = new FileInputStream(s + "/src/main/java/Excel/Test1.xlsx");
        XSSFWorkbook wb = new XSSFWorkbook(ExcelFileToRead);

        // 搜索范围名称并设置输入值
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("loanamount", 2000000);
        map.put("age", 25);
        map.put("smoker", "Y");
        map.put("loanterm", 23);

        for (HashMap.Entry<String, Object> entry : map.entrySet()) {
            cCellName = entry.getKey();
            namedCell = wb.getName(cCellName);
            // 检索命名范围中的单元格并测试其内容
            aref = new AreaReference(namedCell.getRefersToFormula(), null);
            crefs = aref.getAllReferencedCells();

            for (int i = 0; i < crefs.length; i++) {

                sheet = wb.getSheet(crefs[i].getSheetName());
                r = sheet.getRow(crefs[i].getRow());
                c = r.getCell(crefs[i].getCol(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                // 根据单元格类型等提取单元格内容
                cString = entry.getValue().toString(); // 添加缺失单元格检查
                if (c.getCellType() == CellType.STRING) {
                    c.setCellValue(cString);
                } else if (c.getCellType() == CellType.NUMERIC) {
                    c.setCellValue(Double.parseDouble(cString));
                } else if (c.getCellType() == CellType.BOOLEAN) {
                    c.setCellValue(cString);
                } else {
                }
            }
        }

        sheet = wb.getSheetAt(0);

        XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);

        // 获取所有所需的输出值
        Iterator<String> i;
        ArrayList<String> outputValues = new ArrayList<String>();
        outputValues.add("rate");
        outputValues.add("premium");
        i = outputValues.iterator();
        while (i.hasNext()) {
            cCellName = i.next();
            namedCell = wb.getName(cCellName);
            // 检索命名范围中的单元格并测试其内容
            aref = new AreaReference(namedCell.getRefersToFormula(), null);
            crefs = aref.getAllReferencedCells();

            for (int j = 0; j < crefs.length; j++) {
                sheet = wb.getSheet(crefs[j].getSheetName());
                r = sheet.getRow(crefs[j].getRow());
                c = r.getCell(crefs[j].getCol(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                // 根据单元格类型等提取单元格内容
                System.out.println(cCellName + " : " + c.getRawValue());
            }
        }
        wb.close();
    }
}

请注意,此翻译仅包含您提供的代码部分,不包括任何其他内容。

英文:

I have an existing Excel workbook in which two "output" cells (with range name "rate" and "premium") have formulas based on values in other "input" cells (i.e. range names "loamamount", "loanterm", "age" and "smoker").

If, in the Excel workbook, I make all the input cells empty then the formulae evaluate to "#N/A". However when I populate the correct values in the input cells through poi and use the command

XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);

The value in the two cells is not recalculated and remains "#N/A".

Can anyone help me understand what I am doing wrong? The code is as follows:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
import org.apache.poi.xssf.usermodel.XSSFName;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class GetDataFromExcel {
public static void main(String[] args) throws IOException {
getData();
}
public static void getData() throws IOException {
String s, cCellName, cString;
XSSFName namedCell;
AreaReference aref;
CellReference[] crefs;
XSSFRow r;
XSSFCell c;
XSSFSheet sheet = null;
File directory = new File(&quot;./&quot;);
s = directory.getAbsolutePath();
s = s.substring(0, s.length() - 2);
InputStream ExcelFileToRead = new FileInputStream(s + &quot;/src/main/java/Excel/Test1.xlsx&quot;);
XSSFWorkbook wb = new XSSFWorkbook(ExcelFileToRead);
// Search for the Range names and set the input values
HashMap&lt;String, Object&gt; map = new HashMap&lt;String, Object&gt;();
map.put(&quot;loanamount&quot;, 2000000);
map.put(&quot;age&quot;, 25);
map.put(&quot;smoker&quot;, &quot;Y&quot;);
map.put(&quot;loanterm&quot;, 23);
for (HashMap.Entry&lt;String, Object&gt; entry : map.entrySet()) {
cCellName = entry.getKey();
namedCell = wb.getName(cCellName);
// Retrieve the cell at the named range and test its contents
aref = new AreaReference(namedCell.getRefersToFormula(), null);
crefs = aref.getAllReferencedCells();
for (int i = 0; i &lt; crefs.length; i++) {
sheet = wb.getSheet(crefs[i].getSheetName());
r = sheet.getRow(crefs[i].getRow());
c = r.getCell(crefs[i].getCol(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
// extract the cell contents based on cell type etc.
cString = entry.getValue().toString(); // Add missing cell check
if (c.getCellType() == CellType.STRING) {
c.setCellValue(cString);
} else if (c.getCellType() == CellType.NUMERIC) {
c.setCellValue(Double.parseDouble(cString));
} else if (c.getCellType() == CellType.BOOLEAN) {
c.setCellValue(cString);
} else {
}
}
}
sheet = wb.getSheetAt(0);
XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
// wb.getCreationHelper().createFormulaEvaluator().evaluateAll();
// Get all the output values requested
Iterator&lt;String&gt; i;
ArrayList&lt;String&gt; outputValues = new ArrayList&lt;String&gt;();
outputValues.add(&quot;rate&quot;);
outputValues.add(&quot;premium&quot;);
i = outputValues.iterator();
while (i.hasNext()) {
cCellName = i.next();
namedCell = wb.getName(cCellName);
// retrieve the cell at the named range and test its contents
aref = new AreaReference(namedCell.getRefersToFormula(), null);
crefs = aref.getAllReferencedCells();
for (int j = 0; j &lt; crefs.length; j++) {
sheet = wb.getSheet(crefs[j].getSheetName());
r = sheet.getRow(crefs[j].getRow());
c = r.getCell(crefs[j].getCol(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);/////
// extract the cell contents based on cell type etc.
System.out.println(cCellName +&quot; : &quot;+c.getRawValue());
}
}
wb.close();
}
}

答案1

得分: 1

你的代码部分应该设置值到单元格中,但实际上没有设置任何值进去。因此,由于没有设置单元格的值,这些单元格保持为空,导致公式显示 #N/A 错误。

这是因为空单元格不会匹配你在代码中测试的任何单元格类型。空白单元格的类型是 CellType.BLANK,而不是 CellType.STRINGCellType.NUMERICCellType.BOOLEAN。因此,你的所有 if... 条件都不会成立,因此不会向单元格中设置任何值。

与其尝试根据不能适用于空单元格的单元格类型来设置单元格值,不如根据输入值的类型来设置单元格值。

示例:

...
for (HashMap.Entry<String, Object> entry : map.entrySet()) {
    cCellName = entry.getKey();
    namedCell = wb.getName(cCellName);
    // 获取命名区域处的单元格并测试其内容
    aref = new AreaReference(namedCell.getRefersToFormula(), null);
    crefs = aref.getAllReferencedCells();

    for (int i = 0; i < crefs.length; i++) {

        sheet = wb.getSheet(crefs[i].getSheetName());
        r = sheet.getRow(crefs[i].getRow());
        c = r.getCell(crefs[i].getCol(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
        // 根据输入值类型设置单元格值
        Object o = entry.getValue();
        if (o instanceof String) {
            c.setCellValue((String)o);
        } else if (o instanceof Number) {
            c.setCellValue(((Number)o).doubleValue());
        } else if (o instanceof Boolean) {
            c.setCellValue((Boolean)o);
        } else {
        }
    }
}
...
英文:

Your code part which should set values into cells does not set values into cells. So because there are no cell values set and the cells remain empty, the formulas will result in #N/A error.

This is because blank cells will not be of any cell type you are testing in your code. A blank cell is of CellType.BLANK and not CellType.STRING nor CellType.NUMERIC nor CellType.BOOLEAN. So none of your if... will be true and so no value will be set into the cells.

Rather than trying to set cell values dependent of cell types which cannot exist for blank cells, you should put cell values dependent on entry value type.

Example:

...
for (HashMap.Entry&lt;String, Object&gt; entry : map.entrySet()) {
cCellName = entry.getKey();
namedCell = wb.getName(cCellName);
// Retrieve the cell at the named range and test its contents
aref = new AreaReference(namedCell.getRefersToFormula(), null);
crefs = aref.getAllReferencedCells();
for (int i = 0; i &lt; crefs.length; i++) {
sheet = wb.getSheet(crefs[i].getSheetName());
r = sheet.getRow(crefs[i].getRow());
c = r.getCell(crefs[i].getCol(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
// put cell values dependent on entry value type
Object o = entry.getValue();
if (o instanceof String) {
c.setCellValue((String)o);
} else if (o instanceof Number) {
c.setCellValue(((Number)o).doubleValue());
} else if (o instanceof Boolean) {
c.setCellValue((Boolean)o);
} else {
}
}
}
...

huangapple
  • 本文由 发表于 2020年8月20日 20:26:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/63505098.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定