How to get the full value from an excel cell, not the displayed (rounded) value?

旧时模样 提交于 2019-12-10 18:39:39

问题


I'm having an issue retrieving the exact value from an cell from a worksheet. If I open the file the cell has a decimal number which it's shown only with 4 decimals, but if I click on the particular cell, the value is different, having 6 decimals. I know it's a setting applied to the cell in order to show only 4 decimals.

Now I'm trying to retrieve the cell's data in C#, using ClosedXML.Excel, not Microsoft.Office.Interop.Excel, but the only thing I'm able to get is the 4 decimals value, not the "whole" one, which is a great issue as I have calculation later on and I have big differences due to the missing 2 decimals.

I have tried using inputSheet.Worksheet.Cell(row,col).GetDouble(), or Convert.ToDouble(inputSheet.Worksheet.Cell(row, col).Value), or even to refer to the "RichText" property, or ...ToString("0.000000"), but no matter what I use, I can only retrieve the 4 decimal value instead of the full 6 decimals one.


回答1:


I got a look at the source code of the library, here is what the Value getter does:

get
{
    string str = this.FormulaA1;
    if (!XLHelper.IsNullOrWhiteSpace(str))
    {
        string str2;
        string sName;
        if (str[0] == '{')
        {
            str = str.Substring(1, str.Length - 2);
        }
        if (str.Contains<char>('!'))
        {
            sName = str.Substring(0, str.IndexOf('!'));
            if (sName[0] == '\'')
            {
                sName = sName.Substring(1, sName.Length - 2);
            }
            str2 = str.Substring(str.IndexOf('!') + 1);
        }
        else
        {
            sName = this.Worksheet.Name;
            str2 = str;
        }
        if (this._worksheet.Workbook.WorksheetsInternal.Any<XLWorksheet>(w => (string.Compare(w.Name, sName, true) == 0)) && XLHelper.IsValidA1Address(str2))
        {
            return this._worksheet.Workbook.Worksheet(sName).Cell(str2).Value;
        }
        object obj2 = this.Worksheet.Evaluate(str);
        IEnumerable enumerable = obj2 as IEnumerable;
        if ((enumerable != null) && !(obj2 is string))
        {
            using (IEnumerator enumerator = enumerable.GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    return enumerator.Current;
                }
            }
        }
        return obj2;
    }
    string s = this.HasRichText ? this._richText.ToString() : this._cellValue;
    if (this._dataType == XLCellValues.Boolean)
    {
        return (s != "0");
    }
    if (this._dataType == XLCellValues.DateTime)
    {
        return DateTime.FromOADate(double.Parse(s));
    }
    if (this._dataType == XLCellValues.Number)
    {
        return double.Parse(s);
    }
    if (this._dataType == XLCellValues.TimeSpan)
    {
        return TimeSpan.Parse(s);
    }
    return s;
}

I noticed, that when it reach string s = this.HasRichText ? this._richText.ToString() : this._cellValue;, if you have never called cell.RichText (so neither viewing it with the debugger) you get the correct value, because this.HasRichText is false because the class has still not assigned the correct value to it. When it(this.HasRichText) is true, you get this._richText.ToString(), that is the formatted number. So, if you access the Value property before accessing RichText you should get the correct value, anyway you can get _cellValue using reflection, then convert it to double like this:

var theRealDoubleValue = Convert.ToDouble(yourCell.GetType().GetField("_cellValue", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(yourCell));


来源:https://stackoverflow.com/questions/35861860/how-to-get-the-full-value-from-an-excel-cell-not-the-displayed-rounded-value

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!