Npoi圆公式

Npoi Round Formula

我是 NPOI 的新手,在做项目时遇到了奇怪的问题,不知道如何解决 我正在读取来自 Excel sheet 的数据,其中包含 Round 函数并使用 npoi 评估器 XSSFFormulaEvaluator 重新评估单元格 直到这一刻之前的每一件事都对我很好,直到遇到这个问题 在 excel sheet 我有这个公式 =round(693.9648;2) 此数字的 excel 中的结果将是 693.96 但 NPOI Evaluator 的结果将是 693.97

任何人都知道我如何让评估者表现得像 excel sheet ?!

我遇到了几乎完全相同的问题。数字 481.75478 在 Excel ROUND() 函数中被用于 2dp。例如ROUND(481.75478, 2)

使用同一工作簿执行此操作时:

  • Excel 的计算结果为 481.75
  • NPOI 的计算结果为 481.76

这似乎与 NPOI 在 C# 中实现 Excel ROUND 函数的方式有关。最后,我下载了 NPOI 库的源代码,将 ROUND 函数更改为使用标准 .NET 舍入(使用 MidpointRounding.AwayFromZero 作为我们目的的参数)并使用我的自定义 DLL。

downloaded the source code并做了如下修改:

文件:\main\SS\Formula\Functions\MathX.cs

原码

    public static double Round(double n, int p)
    {
        double retval;

        if (double.IsNaN(n) || double.IsInfinity(n))
        {
            retval = double.NaN;
        }
        else if (double.MaxValue == n)
            return double.MaxValue;
        else if (double.MinValue == n)
            return 0;
        else
        {
            if (p >= 0)
            {
                int temp = (int)Math.Pow(10, p);
                double delta = 0.5;
                int x = p + 1;
                while (x > 0)
                {
                    delta = delta / 10;
                    x--;
                }
                retval = (double)(Math.Round((decimal)(n + delta) * temp) / temp);
            }
            else
            {
                int temp = (int)Math.Pow(10, Math.Abs(p));
                retval = (double)(Math.Round((decimal)(n) / temp) * temp);
            }
        }

        return retval;
    }

更新代码

    public static double Round(double n, int p)
    {
        double retval;

        if (double.IsNaN(n) || double.IsInfinity(n))
        {
            retval = double.NaN;
        }
        else if (double.MaxValue == n)
            return double.MaxValue;
        else if (double.MinValue == n)
            return 0;
        else
        {
            if (p >= 0)
            {
                // ***** updated to use .NET MidpointRounding.AwayFromZero rounding ***** //
                retval = (double)Math.Round((decimal)n, p, MidpointRounding.AwayFromZero);
            }
            else
            {
                retval = (double)(Math.Round((decimal)(n) / temp) * temp);
            }
        }

        return retval;
    }

Note/Disclaimer

这还没有经过测试,所以可能会导致其他一些无法预料的错误(我不确定为什么原始代码会进行某种增量化),但这解决了我遇到的舍入不同的问题在 Excel 和 NPOI 之间。如果我在愤怒中使用该应用程序时发现任何问题,我会回来更新答案。

更新2017-12-04

这已经投入生产一段时间了,没有任何问题。我还意识到我应该为此向项目 which I now have.

提交 PR