-
Notifications
You must be signed in to change notification settings - Fork 771
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix the rounding issue for numeric type formatting #650
base: trunk
Are you sure you want to change the base?
Conversation
Resolve the current issue with the DecimalFormat class when the incoming obj is of type Double or Float. For example, if a Double type value of 1.005 is passed in, and the corresponding cell in Excel is of numeric type and set to keep two decimal places. Formatting the Double value 1.005 will be problematic; it will be formatted as 1.00, which is inconsistent with the behavior of Excel and does not perform rounding correctly
Can you provide test cases that prove there is an issue? I added 648a2e5 and these tests seem fine. |
I disabled the float test because it is actually failing. @YUFEIFUT I would still be interested in getting more background as to what is failing for you - a code sample would be ideal. A unit test, even better. |
Here are my test Excel file and the corresponding Java test code that can reproduce the issue I mentioned: package org.example;
import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class ReadExcelFile {
public static void main(String[] args) {
try {
// Create a File object pointing to the Excel file to be read
File file = new File("E:\\MyFile\\OpenSource\\test_poi_deciaml\\test_poi_deciaml\\src\\test\\test_files\\test_decimal.xlsx");
FileInputStream fis = new FileInputStream(file);
// Select the corresponding Workbook object based on the file extension
Workbook workbook = null;
if (file.getName().endsWith(".xls")) {
workbook = new HSSFWorkbook(fis);
} else if (file.getName().endsWith(".xlsx")) {
workbook = new XSSFWorkbook(fis);
}
// Get the first sheet
assert workbook != null;
Sheet sheet = workbook.getSheetAt(0);
// Create an object for formatting cell content
HSSFDataFormatter dataFormatter = new HSSFDataFormatter();
// Iterate over each row
for (Row row : sheet) {
// Iterate over each column
for (Cell cell : row) {
// Format the cell content using HSSFDataFormatter
String cellValue = dataFormatter.formatCellValue(cell);
System.out.print(cellValue + "\t");
}
System.out.println();
}
// Close the workbook and input stream
workbook.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} As shown in the image pic1.png, the original content of the cell at position A1 is 1.005. I have set the cell's format to numeric with two decimal places, so the value displayed in the Excel software is 1.01. I believe that the value obtained using HSSFDataFormatter to format the cell should also be 1.01, not 1.00, so I think this is incorrect. After my debugging, I found that the issue lies in the format method of the InternalDecimalFormatWithScale class within the DataFormatter class. It seems to have made a mistake when using DecimalFormat. Specifically, when it formats the incoming Double type value, it directly uses the method public DecimalFormat.format(Object number, StringBuffer toAppendTo, FieldPosition pos) with the original Double parameter. Since Double is an imprecise type, I tried replacing the original first parameter with new BigDecimal(obj.toString()). And then,it get 1.01 for A1 cell. |
I added 6e07ce5 based on your test case. But it passes without your code change. |
I cannot reproduce the issue. I will not change the runtime code. |
POI 5.2.5 is released and POI 5.3.0 is being released right now. |
ok |
Resolve the current issue with the DecimalFormat class when the incoming obj is of type Double or Float. For example, if a Double type value of 1.005 is passed in, and the corresponding cell in Excel is of numeric type and set to keep two decimal places. Formatting the Double value 1.005 will be problematic; it will be formatted as 1.00, which is inconsistent with the behavior of Excel and does not perform rounding correctly