最近要帮客户写个小工具,来对多个Excel文件进行数据汇总,其中主要涉及到对数据的读取和分类,在读取数据时就遇到了好几个坑,这里主要说下日期类型数据的读取
NPOI内置的单元格值类型有Unknown
、Numeric
、String
、Formula
、Blank
、Boolean
、Error
,但是其中没有日期类型,最开始我的取单元格值的方法如下:
switch (cell.CellType)
{
case CellType.String:
return cell.StringCellValue;
case CellType.Numeric:
return cell.NumericCellValue;
case CellType.Boolean:
return cell.BooleanCellValue;
case CellType.Error:
return cell.ErrorCellValue;
case CellType.Formula:
BaseFormulaEvaluator evaluator;
if (sheet is XSSFSheet)
{
evaluator = new XSSFFormulaEvaluator(sheet.Workbook);
}
else
{
evaluator = new HSSFFormulaEvaluator(sheet.Workbook);
}
var formulaValue = evaluator.Evaluate(cell);
if (formulaValue.CellType == CellType.Numeric)
{
return formulaValue.NumberValue;
}
else if (formulaValue.CellType == CellType.String)
{
return formulaValue.StringValue;
}
return cell.ToString();
default:
return cell.ToString();
}
测试时发现,日期类型的单元格在代码中获取到的CellType
为Numeric
,最后获取到的是一个数字,不是日期,翻了源码,找到了一个类DateUtil
,里面提供了一个方法IsCellDateFormatted
可以判断单元格的值是不是日期类型,还提供了一个方法GetJavaDate
可以把获取到的数字转化成日期格式,所以我对代码进行了修改
switch (cell.CellType)
{
case CellType.String:
return cell.StringCellValue;
case CellType.Numeric:
if (DateUtil.IsCellDateFormatted(cell))
{
return cell.DateCellValue;
}
return cell.NumericCellValue;
case CellType.Boolean:
return cell.BooleanCellValue;
case CellType.Error:
return cell.ErrorCellValue;
case CellType.Formula:
BaseFormulaEvaluator evaluator;
if (sheet is XSSFSheet)
{
evaluator = new XSSFFormulaEvaluator(sheet.Workbook);
}
else
{
evaluator = new HSSFFormulaEvaluator(sheet.Workbook);
}
var formulaValue = evaluator.Evaluate(cell);
if (formulaValue.CellType == CellType.Numeric)
{
return formulaValue.NumberValue;
}
else if (formulaValue.CellType == CellType.String)
{
return formulaValue.StringValue;
}
return cell.ToString();
default:
return cell.ToString();
}