使用 NPOI 读取 Excel
获取 Excel 单元格值作为字符串
引言
这段 C# 代码片段演示了如何使用开源库 NPOI 读取 Microsoft Excel 文件中的单元格值。
参考资料:NPOI - https://npoi.codeplex.com/
背景
Excel 单元格可以包含不同类型的值。 此外,值可以从公式中计算得出。 在读取单元格值时,我们需要考虑到这些情况。
Using the Code
我编写了一个 abstract
类 ExcelFileReader
,提供从 Excel 文件读取值的基本功能。
//
// ExcelFileReader
//
public abstract class ExcelFileReader
{
protected IWorkbook workbook;
protected DataFormatter dataFormatter;
protected IFormulaEvaluator formulaEvaluator;
//
// Initialize from a stream of Excel file
//
protected void InitializeMembers(Stream excelFileStream)
{
this.workbook = WorkbookFactory.Create(excelFileStream);
if (this.workbook != null)
{
this.dataFormatter = new DataFormatter(CultureInfo.InvariantCulture);
this.formulaEvaluator = WorkbookFactory.CreateFormulaEvaluator(this.workbook);
}
}
//
// Get formatted value as string from the specified cell
//
protected string GetFormattedValue(ICell cell)
{
string returnValue = string.Empty;
if (cell != null)
{
try
{
// Get evaluated and formatted cell value
returnValue = this.dataFormatter.FormatCellValue(cell, this.formulaEvaluator);
}
catch
{
// When failed in evaluating the formula, use stored values instead...
// and set cell value for reference from formulae in other cells...
if (cell.CellType == CellType.FORMULA)
{
switch (cell.CachedFormulaResultType)
{
case CellType.STRING:
returnValue = cell.StringCellValue;
cell.SetCellValue(cell.StringCellValue);
break;
case CellType.NUMERIC:
returnValue = dataFormatter.FormatRawCellContents
(cell.NumericCellValue, 0, cell.CellStyle.GetDataFormatString())
cell.SetCellValue(cell.NumericCellValue);
break;
case CellType.BOOLEAN:
returnValue = cell.BooleanCellValue.ToString();
cell.SetCellValue(cell.BooleanCellValue);
break;
default:
break;
}
}
}
}
return (returnValue ?? string.Empty).Trim();
}
//
// Get unformatted value as string from the specified cell
//
protected string GetUnformattedValue(ICell cell)
{
string returnValue = string.Empty;
if (cell != null)
{
try
{
// Get evaluated cell value
returnValue = (cell.CellType == CellType.NUMERIC ||
(cell.CellType == CellType.FORMULA &&
cell.CachedFormulaResultType == CellType.NUMERIC)) ?
formulaEvaluator.EvaluateInCell(cell).NumericCellValue.ToString() :
this.dataFormatter.FormatCellValue(cell, this.formulaEvaluator);
}
catch
{
// When failed in evaluating the formula, use stored values instead...
// and set cell value for reference from formulae in other cells...
if (cell.CellType == CellType.FORMULA)
{
switch (cell.CachedFormulaResultType)
{
case CellType.STRING:
returnValue = cell.StringCellValue;
cell.SetCellValue(cell.StringCellValue);
break;
case CellType.NUMERIC:
returnValue = cell.NumericCellValue.ToString();
cell.SetCellValue(cell.NumericCellValue);
break;
case CellType.BOOLEAN:
returnValue = cell.BooleanCellValue.ToString();
cell.SetCellValue(cell.BooleanCellValue);
break;
default:
break;
}
}
}
}
return (returnValue ?? string.Empty).Trim();
}
}
您需要实现这个 abstract
类 ExcelFileReader
,它从 this.workbook 获取 ISheet
对象,并操作其 IRow
对象以获取单元格值。
关注点
函数 GetFormattedValue()
中的 try
-catch
块通过获取缓存值(如果有)来处理公式评估失败的情况(例如,包含外部引用)。 然后,通过调用 SetCellValue()
函数将单元格值设置为缓存值,用于其他引用该单元格的公式。 对于数值,通过调用 DataFormatter.FormatRawCellContents()
函数获取格式化后的值。
类似地,函数 GetUnformattedValue()
获取单元格值作为 string
,不应用任何格式。 它识别数值单元格,可以应用格式,并从 ICell.NumericCellValue
属性获取未格式化的值。
CellType enum
没有像 DATE
这样的条目用于日期/时间值,这些值在 Excel 中存储为数字。 因此,没有直接的方法来识别单元格是否存储了日期/时间值。 我认为一种方法是通过参考 ICell.CellStyle.DataFormat
属性或 ICell.CellStyle.GetDataFormatString()
函数来查看其格式。
历史
- 2015 年 11 月 6 日 - 首次发布