web-dev-qa-db-ja.com

日付を含むセルの値を取得し、NPOIを使用して元のフォーマットを維持する方法

DevExpressを使用して編集したExcelファイルがあり、NPOIを使用して読んでいます。日付セルの値を文字列として取得しようとすると、元の値が保持されません。

例:DevExpressグリッドで、次の値を設定しました:2016-08-12。文字列で同じ値を取得したいのですが、代わりに42689を取得します。

セル値を取得するための私のコードは次のようになります。

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

元のフォーマットされた日付値を取得するにはどうすればよいですか?

10
Mochoa

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;
_
12
Brian Rogers

ファイルにカスタム形式の日付がある場合は、それらをテストする必要があります。そうでない場合、関数は数値を返します。ブライアンロジャースの答えのこのバージョンはチェックします:

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