Skip to content
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

INT(1.99) doesn't return correct rounded value #983

Closed
250597197 opened this issue Dec 20, 2022 · 8 comments · Fixed by #1109
Closed

INT(1.99) doesn't return correct rounded value #983

250597197 opened this issue Dec 20, 2022 · 8 comments · Fixed by #1109

Comments

@250597197
Copy link

XSSFWorkbook,INT函数,在使用NumericCellValue获取公式值的时候,不会舍弃小数,例如1.99 在使用函数会取到2,但是1.9是正常的
但是在保存成excel的时候没问题。在使用NPOI创建XSSFWorkbook,并且给单元格赋公式取值的时候出现,超过1位小数且小数的结尾数字是9的时候

@tonyqus
Copy link
Member

tonyqus commented Dec 20, 2022

NumericCellValue不负责计算公式,那是单元格的原始值,含公式的计算结果你得用FormulaEvaluator。

@250597197
Copy link
Author

不,是这样的。
我使用NPOI创建了一个XSSFWorkbook,创建sheet,然后填充数据,并且给单元格设置了公式。
然后使用FormulaEvaluator对XSSFWorkbook进行了公式运算
然后我把运算后的sheet重新取出来。但是,在取数据的过程中
我发现其他的公式和函数的结果都是正常的,但是在INT()这个函数中。并没有正确返回结果,
我测试下来。
如:INT(1.9) 会正确运算,返回结果1.
INT(5.9) 会正确运算,返回结果5
但是在INT(1.99) 会返回结果2,只要是小数位数大于1,且是9结尾。这个运算结果就返回异常

@250597197
Copy link
Author

DataTable dt = new DataTable();
dt.TableName = "AA";
dt.Columns.Add("AA1", typeof(decimal));
dt.Columns.Add("AA2", typeof(string));
DataRow dr1 = dt.NewRow();
dr1["AA1"] = 1.99;
dr1["AA2"] = "INT(A2)";
dt.Rows.Add(dr1);
DataRow dr2 = dt.NewRow();
dr2["AA1"] = 3.99;
dr2["AA2"] = "INT(A3)";
dt.Rows.Add(dr2);
DataRow dr3 = dt.NewRow();
dr3["AA1"] = 8.99;
dr3["AA2"] = "INT(A4)";
dt.Rows.Add(dr3);

        XSSFWorkbook book = new XSSFWorkbook();         
        ISheet sheet1 = book.CreateSheet(dt.TableName);
        //模拟循环插入数据,并且根据生成的sheet转换成EXCEL的单元格坐标(A2,A3,A4),在给B列赋值公式
        
        //运算
        book.SetForceFormulaRecalculation(true);
        book.GetCreationHelper().CreateFormulaEvaluator().EvaluateAll();

        //取出运算完后的数据重新加载到DataTbale中
        //模拟循环取数据
        //取出的数据,INT没有舍弃小数。其他的函数正常。 由于代码量原因没有放出完整代码

@tonyqus tonyqus reopened this Dec 21, 2022
@tonyqus tonyqus changed the title INT函数,在使用NumericCellValue获取公式值的时候,不会舍弃小数 INT(1.99) doesn't return correct rounded value Dec 21, 2022
@tonyqus
Copy link
Member

tonyqus commented Dec 21, 2022

The current logic of INT function:

        public override double Evaluate(double d)
        {
            if (d > 0)
                return Math.Round(d - 0.49);
            else
                return Math.Round(d - 0.5);
        }

@250597197
Copy link
Author

那这个向下取整的方法就是有问题的啊。按照你这个方法
我按照你现有的逻辑测试。
1.99会返回2
3.99会返回4
但是有一个很有意思的问题
2.99会正确返回2
还有。当我把sheet保存进excel的时候。是正常的。。所以保存进excel后。是excel本身的计算功能在生效。
我想问一下近期有调整这个功能的计划吗

@tonyqus
Copy link
Member

tonyqus commented Dec 23, 2022

一般一个版本发布至少4-6个月,等不急的话,建议换其他库,谢谢。

@deleteJ
Copy link
Contributor

deleteJ commented Jun 27, 2023

Since excel INT function definition is "Rounds a number down to the nearest integer", should we change the function to Math.Floor

public class Int : OneArg
    {

        public override double Evaluate(double d)
        {
            return Math.Floor(d);            
        }

 }

The current logic of INT function:

        public override double Evaluate(double d)
        {
            if (d > 0)
                return Math.Round(d - 0.49);
            else
                return Math.Round(d - 0.5);
        }

@tonyqus
Copy link
Member

tonyqus commented Jun 27, 2023

PR is welcomed

@tonyqus tonyqus modified the milestones: NPOI 2.7.1, NPOI 2.7.0 Jun 27, 2023
tonyqus added a commit that referenced this issue Jun 29, 2023
fix issue #983 INT(1.99) doesn't return correct rounded value
@tonyqus tonyqus modified the milestones: NPOI 2.7.0, NPOI 2.6.2 Aug 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants