apache poi,DataFormatter修剪值超过十进制的十位

时间:2018-09-25 13:46:54

标签: java apache-poi

所以我有一个简单的代码,可将值填充到数据库中

try {
    for(int indexRow = 1; indexRow < numberOfRecords; indexRow++) {
        record = new String[noOfColumns];
        for(int indexColumn = 0;indexColumn < noOfColumns; indexColumn++) {
            indexError = indexColumn;
            String value = "";
            XSSFRow row = sheet.getRow(indexRow);
            if(row != null) {
                XSSFCell cell = sheet.getRow(indexRow).getCell(indexColumn);

                if(cell != null) {
                    value = fmt.formatCellValue(cell);
                }
                record[indexColumn] = value;
            }
        }
        records.add(record);
    }
}

现在我也已经遍历了源代码,但是我找不到一种可以设置默认DataFormatter的方式,该方式可以更改DecimalFormat来适应额外的更改。 任何帮助将不胜感激 。 例如:在Excel中,我有 -5.57055337362326 但是通过代码它将其写入db -5.5705533736

2 个答案:

答案 0 :(得分:1)

重要DataFormatter.formatCellValue()方法的目的是按照 Excel 文档中显示的方式返回单元格的值。

假设您要在 Excel 中定义数字格式以显示4个小数位,并且文档看起来像这样:

Excel, 4 fractional digits

您的代码示例将返回-5,5706;如果您将数字格式更改为显示8位小数-结果将为-5,57055337

Excel 中的默认数字格式基于10位数字(在 Apache POI 中,请检查ExcelGeneralNumberFormat.decimalFormat常量),看起来它是用于您基于输出的文档。


解决方案

@samabcde提到过(添加我的答案以解决他的答案中的几个问题并提供其他详细信息),解决方案是改用cell.getNumericCellValue()

    DecimalFormat decimalFormat = new DecimalFormat("#.###############");
    String cellValue = decimalFormat.format(cell.getNumericCellValue());

在这里,我们使用"#.###############"格式的15位数字,因为它是maximum precision for Excel >>


其他信息

  1. 请注意本文:When reading Excel with POI, beware of floating points

  2. 根据DataFromatter的配置,您可以使用DataFormatter#setDefaultNumberFormat(Format format)设置默认数字格式,并且在您呼叫format.formatCellValue(cell)时将使用它,但仅在使用时使用 Excel 文档中未知/无效的格式。


P.S .:回答第一个评论

从您的评论中并不能完全清楚您要涵盖的所有情况,假设DataFormatter在所有情况下都适用于您,数字值除外,DecimalFormat的模式为"#.###############"在这种情况下为您工作。无论如何,如果您需要更具体的逻辑,只需检查其他条件即可。

请找到在这种情况下可以使用的实用方法:

private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.###############");
private static final DataFormatter DATA_FORMATTER = new DataFormatter();

public static String formatCellValue(HSSFCell cell) {
    if (cell != null && cell.getCellTypeEnum() == CellType.NUMERIC
            && !DateUtil.isCellDateFormatted(cell)) {
        return DECIMAL_FORMAT.format(cell.getNumericCellValue());
    } else {
        return DATA_FORMATTER.formatCellValue(cell);
    }
}

对于以下 Excel 文件:

Different formats

  • 字段 A1 的格式为 4个小数位,其实数值为28,9999999999999
  • 字段 A2 的格式为 4个小数位数,其实数值为-5.5
  • 字段 A3 具有默认的 Excel 格式,其实际值为28,9999999999999

上面的实用程序方法将在此处返回实数值,即:28,9999999999999-5.528,9999999999999

DataFormatter.formatCellValue()将返回其在 Excel 中的外观值,即:29,0000-5,500029

答案 1 :(得分:0)

丢失数字的原因

以下代码来自POI版本3.14,对于带有数字单元格的DataFormatter.formatCellValue方法,它将最终调用getFormattedNumberString方法。该代码为

private String getFormattedNumberString(Cell cell, ConditionalFormattingEvaluator 
    cfEvaluator) {

    Format numberFormat = getFormat(cell, cfEvaluator);
    double d = cell.getNumericCellValue();
    if (numberFormat == null) {
        return String.valueOf(d);
    }
    String formatted = numberFormat.format(new Double(d));
    return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation
}

numberFormat默认为DecimalFormat,具有10个小数位,假设您尚未设置任何格式,则值为'-5.57055337362326'的单元格将按预期返回'-5.5705533736'。< / p>

解决方案

如果仅需要确切的值,则使用cell.getNumericValue方法并创建DecimalFormat可以解决此问题。如果还需要更改Excel中的显示,那么我们需要创建一个自定义DataFormatter。以下示例说明了这两种解决方案:

import java.io.IOException;
import java.text.DecimalFormat;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class TestDataFormatter {
    public static void main(String[] args) throws IOException {
        Double testValue = Double.valueOf("-5.57055337362326");
        System.out.println("test value:\t\t" + testValue.toString());
        XSSFWorkbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet();
        Row row = sheet.createRow(0);
        Cell cell = row.createCell(0);
        cell.setCellValue(testValue);

        // 10 decimal place shown by default 
        DataFormatter dataFormatter = new DataFormatter();
        String defaultFormatted = dataFormatter.formatCellValue(cell);
        System.out.println("default formatted:\t" + defaultFormatted);

        // Create custom format
        XSSFCellStyle style = workbook.createCellStyle();
        DataFormat customDataFormat = workbook.createDataFormat();
        int dataFormatIndex = customDataFormat.getFormat("0.00000000000000");
        style.setDataFormat(dataFormatIndex);
        cell.setCellStyle(style);
        String customFormatted = dataFormatter.formatCellValue(cell);
        System.out.println("custom formatted:\t" + customFormatted);

        // Get numeric value and then format by DecimalFormat
        System.out.println("get numeric:\t\t" + cell.getNumericCellValue());
        System.out.println(
                "format numeric:\t\t" + new DecimalFormat("0.00000000000000").format(cell.getNumericCellValue()));
        workbook.close();
    }
}