![](/img/trans.png)
[英]How to use vlookup or formulas in SXSSFWorkbook with Apache POI?
[英]How can Apache POI use formulas in streaming mode?
我正在使用Apache POI 3.17(当前)。 当我使用HSSFCell.setFormula()插入诸如“ A1 + 17”之类的公式时,它将起作用。 当我在流模式下执行相同操作时,使用SXSSFCell.setFormula()公式会在输入行中出现(以“ =”开头),但单元格中的显示结果始终为0。
我尝试使用单元格类型NUMERIC和FORMULA。 这是我的最小无效示例:
final SXSSFWorkbook wb = new SXSSFWorkbook();
final SXSSFSheet sheet = wb.createSheet("Test-S");
final SXSSFRow row = sheet.createRow(0);
final SXSSFCell cell1 = row.createCell(0);
cell1.setCellType(CellType.NUMERIC);
cell1.setCellValue(124);
final SXSSFCell formulaCell1 = row.createCell(1);
formulaCell1.setCellType(CellType.FORMULA);
formulaCell1.setCellFormula("A1 + 17");
final SXSSFCell formulaCell2 = row.createCell(2);
formulaCell2.setCellType(CellType.NUMERIC);
formulaCell2.setCellFormula("A1+18");
FileOutputStream os = new FileOutputStream("/tmp/test-s.xlsx");
wb.write(os);
wb.close();
os.close();
尽管在输入行中正确显示了公式,但三个单元格显示为124/0/0。
任何提示表示赞赏。
它适用于Excel 2016,当我打开示例文件时,我在单元格中获得了正确的结果。 Excel的较旧版本可能对此处理方式稍有不同,请尝试通过以下两件事来强制对公式进行求值
// evaluate all formulas and store cached results
wb.getCreationHelper().createFormulaEvaluator().evaluateAll();
// suggest to Excel to recalculate the formulas itself as well
sheet.setForceFormulaRecalculation(true);
希望这两种方法之一也能使它对您有用。
答案没有回答为什么只有在将SXSSFCell
用作公式单元格的情况下,OpenOffice / Libreoffice才会出现此问题的问题。 当使用XSSFCell
作为公式单元格时,它不会发生。
答案是,即使根本不评估公式, SXSSFCell
始终使用单元格值。 最糟糕的是,如果根本不对公式求值,它将使用值0(零)。 这是数学中值0的根本滥用。 值0明确并不意味着没有价值或有一个未知的值。 这意味着存在值0,仅此而已。 因此该值0 不应该被用作没有评估式的缓存公式结果。 相反,在计算公式之前,不得使用任何值。 与XSSFCell
完全一样。
因此,真正正确的答案必须是apache poi
应该更正其SXSSFCell
代码。
解决方法:
import java.io.FileOutputStream;
import org.apache.poi.xssf.streaming.*;
import org.apache.poi.ss.usermodel.CellType;
import java.lang.reflect.Field;
import java.util.TreeMap;
public class CreateExcelSXSSFFormula {
public static void main(String[] args) throws Exception {
SXSSFWorkbook wb = new SXSSFWorkbook();
SXSSFSheet sheet = wb.createSheet("Test-S");
SXSSFRow row = sheet.createRow(0);
SXSSFCell cell = row.createCell(0);
cell.setCellValue(124);
SXSSFFormulaonlyCell formulacell = new SXSSFFormulaonlyCell(row, 1);
formulacell.setCellFormula("A1+17");
cell = row.createCell(2);
cell.setCellFormula("A1+17");
formulacell = new SXSSFFormulaonlyCell(row, 3);
formulacell.setCellFormula("A1+18");
cell = row.createCell(4);
cell.setCellFormula("A1+18");
wb.write(new FileOutputStream("test-s.xlsx"));
wb.close();
wb.dispose();
}
private static class SXSSFFormulaonlyCell extends SXSSFCell {
SXSSFFormulaonlyCell(SXSSFRow row, int cellidx) throws Exception {
super(row, CellType.BLANK);
Field _cells = SXSSFRow.class.getDeclaredField("_cells");
_cells.setAccessible(true);
@SuppressWarnings("unchecked") //we know the problem and expect runtime error if it possibly occurs
TreeMap<Integer, SXSSFCell> cells = (TreeMap<Integer, SXSSFCell>)_cells.get(row);
cells.put(cellidx, this);
}
@Override
public CellType getCachedFormulaResultTypeEnum() {
return CellType.BLANK;
}
}
}
当然,我应该提到我使用LibreOffice。 现在,我发现LibreOffice并非故意从Excel创建的工作表中重新计算公式,而是将POI表视为Excel创建的。
参见https://ask.libreoffice.org/en/question/12165/calc-auto-recalc-does-not-work/ 。
更改LibreOffice设置(工具–选项– LibreOffice Calc –公式–文件加载时重新计算)会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.