1 回答
TA贡献1842条经验 获得超21个赞
你的观察是正确的。该问题的出现是因为一般的浮点问题。可以简单地表示为:
...
System.out.println(1.7/20.0); //0.08499999999999999
System.out.println((21.7-20.0)/20.0); //0.08499999999999996
...
如您所见,双精度值 1.7 除以双精度值 20.0 得到 0.08499999999999999。这很好,因为使用 时该值将被视为 0.085 DecimalFormat。但更复杂的方程 (21.7-20.0)/20.0 结果为 0.08499999999999996。这显然低于 0.085。
Excel尝试通过浮点值的附加规则来解决这些问题。它始终仅使用浮点值的 15 位有效十进制数字。类似的事情也是如此Excel:
...
BigDecimal bd = new BigDecimal((21.7-20.0)/20.0);
System.out.println(bd.round(new MathContext(15)).doubleValue()); //0.085
...
apache poi's FormulaEvaluator和 it's 的DataFormatter行为都不像这Excel一点。这就是差异的原因。
人们可以拥有一个自己的,与/org/apache/poi/ss/usermodel/DataFormatter.javaMyDataFormatter的唯一区别是:
...
private String getFormattedNumberString(Cell cell, ConditionalFormattingEvaluator cfEvaluator) {
if (cell == null) {
return null;
}
Format numberFormat = getFormat(cell, cfEvaluator);
double d = cell.getNumericCellValue();
java.math.BigDecimal bd = new java.math.BigDecimal(d);
d = bd.round(new java.math.MathContext(15)).doubleValue();
if (numberFormat == null) {
return String.valueOf(d);
}
String formatted = numberFormat.format(Double.valueOf(d));
return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation
}
...
然后使用 thatMyDataFormatter而不是DataFormatter会更符合 的Excel行为。
例子:
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
class CreateExcelEvaluateFormula {
public static void main(String[] args) throws Exception {
Workbook workbook = new XSSFWorkbook();
CreationHelper creationHelper = workbook.getCreationHelper();
FormulaEvaluator formulaEvaluator = creationHelper.createFormulaEvaluator();
Sheet sheet = workbook.createSheet();
Row row = sheet.createRow(0);
Cell cell = row.createCell(0); cell.setCellValue(21.7);
cell = row.createCell(1); cell.setCellValue(20.0);
cell = row.createCell(2); cell.setCellFormula("(A1-B1)/B1");
formulaEvaluator.evaluateFormulaCell(cell);
double d = cell.getNumericCellValue();
System.out.println(d); //0.08499999999999996
MyDataFormatter dataFormatter = new MyDataFormatter();
String myFormat="0%";
CellUtil.setCellStyleProperty(cell, CellUtil.DATA_FORMAT, creationHelper.createDataFormat().getFormat(myFormat));
String val = dataFormatter.formatCellValue(cell, formulaEvaluator);
System.out.println(val); //9%
FileOutputStream out = new FileOutputStream("Excel.xlsx");
workbook.write(out);
out.close();
workbook.close();
}
}
添加回答
举报