英文:
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("./");
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);
// Search for the Range names and set the input values
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);
// 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 < 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<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);
// 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 < 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 +" : "+c.getRawValue());
}
}
wb.close();
}
}
答案1
得分: 1
你的代码部分应该设置值到单元格中,但实际上没有设置任何值进去。因此,由于没有设置单元格的值,这些单元格保持为空,导致公式显示 #N/A
错误。
这是因为空单元格不会匹配你在代码中测试的任何单元格类型。空白单元格的类型是 CellType.BLANK
,而不是 CellType.STRING
、CellType.NUMERIC
或 CellType.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<String, Object> 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 < 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 {
}
}
}
...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论