问题
I have an Excel file that I edited using DevExpress and I am reading using NPOI. When I try to get the value of a date cell as string, it does not keep the original value.
For example:
In a DevExpress grid I set this value: 2016-08-12
. I want to obtain the same value in my string but instead I get 42689
.
My code to get the cell value is like this:
ICell cell = row.GetCell(i);
cell.SetCellType(CellType.String);
string fieldString = cell.StringCellValue;
result = result + ";" + FieldValue;
How can I get the original formatted date value?
回答1:
In Excel, dates are stored as numbers. If you want to get a formatted date, you'll need to check whether the cell contains a date (there's a utility method for that), then get the date value of the cell, get the data format, and finally convert the date to string using the format. You should not force the CellType
to string or else you will no longer be able to tell that the cell originally held a date. I would recommend making an extension method like this to get the formatted cell value based on its type:
using NPOI.SS.UserModel;
public static class NpoiExtensions
{
public static string GetFormattedCellValue(this ICell cell, IFormulaEvaluator eval = null)
{
if (cell != null)
{
switch (cell.CellType)
{
case CellType.String:
return cell.StringCellValue;
case CellType.Numeric:
if (DateUtil.IsCellDateFormatted(cell))
{
DateTime date = cell.DateCellValue;
ICellStyle style = cell.CellStyle;
// Excel uses lowercase m for month whereas .Net uses uppercase
string format = style.GetDataFormatString().Replace('m', 'M');
return date.ToString(format);
}
else
{
return cell.NumericCellValue.ToString();
}
case CellType.Boolean:
return cell.BooleanCellValue ? "TRUE" : "FALSE";
case CellType.Formula:
if (eval != null)
return GetFormattedCellValue(eval.EvaluateInCell(cell));
else
return cell.CellFormula;
case CellType.Error:
return FormulaError.ForInt(cell.ErrorCellValue).String;
}
}
// null or blank cell, or unknown cell type
return string.Empty;
}
}
Then, use it like this:
ICell cell = row.GetCell(i);
string fieldString = cell.GetFormattedCellValue();
result = result + ";" + FieldValue;
Optional: If you have any formulas in your cells and you want those formulas to be evaluated, then create an IFormulaEvaluator
based on your workbook type and pass the evaluator to the GetFormattedCellValue()
method. For example:
IFormulaEvaluator eval;
if (workbook is XSSFWorkbook)
eval = new XSSFFormulaEvaluator(workbook);
else
eval = new HSSFFormulaEvaluator(workbook);
...
ICell cell = row.GetCell(i);
string fieldString = cell.GetFormattedCellValue(eval);
result = result + ";" + FieldValue;
回答2:
If the file has custom formatted dates, you will need to test for those, otherwise the function returns a numeric. This version of Brian Rogers' answer will check:
public static string GetFormattedCellValue(this ICell cell, IFormulaEvaluator eval = null)
{
// https://github.com/tonyqus/npoi/blob/master/main/SS/UserModel/BuiltinFormats.cs
//*The first user-defined format starts at 164.
// var dataformatNumber = cell.CellStyle.DataFormat;
//var formatstring = cell.CellStyle.GetDataFormatString();
//e.g. m/d/yyyy\ h:mm:ss\ \ AM/PM\ #164
//e.g m/d/yyyy\ hh:mm #165
if (cell != null)
{
switch (cell.CellType)
{
case CellType.String:
return cell.StringCellValue;
case CellType.Numeric:
if (DateUtil.IsCellDateFormatted(cell))
{
DateTime date = cell.DateCellValue;
ICellStyle style = cell.CellStyle;
// Excel uses lowercase m for month whereas .Net uses uppercase
string format = style.GetDataFormatString().Replace('m', 'M');
return date.ToString(format);
}
else if(cell.CellStyle.DataFormat>=164 && DateUtil.IsValidExcelDate(cell.NumericCellValue) && cell.DateCellValue != null)
{
return cell.DateCellValue.ToString();
}
else
{
return cell.NumericCellValue.ToString();
}
case CellType.Boolean:
return cell.BooleanCellValue ? "TRUE" : "FALSE";
case CellType.Formula:
if (eval != null)
return GetFormattedCellValue(eval.EvaluateInCell(cell));
else
return cell.CellFormula;
case CellType.Error:
return FormulaError.ForInt(cell.ErrorCellValue).String;
}
}
// null or blank cell, or unknown cell type
return string.Empty;
}
来源:https://stackoverflow.com/questions/40426827/how-to-get-the-value-of-cell-containing-a-date-and-keep-the-original-formatting