65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 NPOI 读取 Excel

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.59/5 (9投票s)

2015 年 11 月 6 日

CPOL

1分钟阅读

viewsIcon

53161

获取 Excel 单元格值作为字符串

引言

这段 C# 代码片段演示了如何使用开源库 NPOI 读取 Microsoft Excel 文件中的单元格值。

参考资料:NPOI - https://npoi.codeplex.com/

背景

Excel 单元格可以包含不同类型的值。 此外,值可以从公式中计算得出。 在读取单元格值时,我们需要考虑到这些情况。

Using the Code

我编写了一个 abstractExcelFileReader,提供从 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();
    }
}

您需要实现这个 abstractExcelFileReader,它从 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 日 - 首次发布
© . All rights reserved.