Как получить значение ячейки, содержащей дату, и сохранить исходное форматирование с помощью NPOI

У меня есть файл Excel, который я редактировал с помощью DevExpress, и я читаю с помощью NPOI. Когда я пытаюсь получить значение ячейки даты в виде строки, исходное значение не сохраняется.

Например: в сетке DevExpress я установил это значение: 2016-08-12. Я хочу получить такое же значение в своей строке, но вместо этого получаю 42689.

Мой код для получения значения ячейки выглядит следующим образом:

    ICell cell = row.GetCell(i);
    cell.SetCellType(CellType.String);
    string fieldString = cell.StringCellValue;
    result = result + ";" + FieldValue; 

Как я могу получить исходное отформатированное значение даты?


person Mochoa    schedule 04.11.2016    source источник
comment
Пожалуйста, уточните вопрос.   -  person Mitulát báti    schedule 04.11.2016
comment
Проверьте эту ссылку stackoverflow.com/questions/45330079/   -  person kumar chandraketu    schedule 18.10.2018


Ответы (2)


В Excel даты хранятся в виде чисел. Если вы хотите получить отформатированную дату, вам нужно проверить, содержит ли ячейка дату (для этого есть служебный метод), затем получить значение даты ячейки, получить формат данных и, наконец, преобразовать дату в строка с использованием формата. Вы не должны заставлять CellType быть строкой, иначе вы больше не сможете сказать, что ячейка изначально содержала дату. Я бы порекомендовал создать такой метод расширения, чтобы получить отформатированное значение ячейки в зависимости от ее типа:

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;
    }
}

Затем используйте его следующим образом:

ICell cell = row.GetCell(i);
string fieldString = cell.GetFormattedCellValue();
result = result + ";" + FieldValue;

Необязательно: если у вас есть какие-либо формулы в ячейках и вы хотите, чтобы эти формулы оценивались, создайте IFormulaEvaluator на основе типа вашей книги и передайте оценщик методу GetFormattedCellValue(). Например:

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;
person Brian Rogers    schedule 11.11.2016
comment
Это должно быть помечено как правильный ответ, в основном это важная часть, если (DateUtil.IsCellDateFormatted(cell))... вы возвращаете дату, иначе возвращаете число. - person Yogurtu; 24.06.2018
comment
В вашем образце есть проблема. Excel также использует мм для месяцев и минут. Что делать, если формат Excel гггг-мм-дд чч:мм:сс. Если вы замените mm на MM, ваши минуты изменятся на месяцы. Ваш образец — хороший указатель, но неполный. - person VikciaR; 15.12.2020

Если в файле есть даты в пользовательском формате, вам нужно будет проверить их, иначе функция вернет числовое значение. Эта версия ответа Брайана Роджерса проверит:

 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;
    }
person mosheb    schedule 16.05.2019