How to get the value of cell containing a date and keep the original formatting using NPOI

对着背影说爱祢 提交于 2019-12-10 03:59:39

问题


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

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