问题
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