使用 NPOI 读取 xlsx 文件
参考网站:
- NuGet: https://www.nuget.org/packages/NPOI
- GitHub: https://github.com/nissl-lab/npoi
NPOI 没有官方文档, 都是通过 Demo 来传递用法的.
Excel 文件结构
- 一个
Excel文件被称为Workbook. - 每一个
Workbook中包含很多表格, 每一个表格被称为Sheet. - 每一个
Sheet中有很多行 (Row), 每一行中又有很多单元格 (Cell).
这构成了 Excel 的基本结构.
读取 Excel 文件
读取 Excel:
IWorkbook workbook = WorkbookFactory.Create("文件路径");
// 或
IWorkbook workbook = WorkbookFactory.Create(<stream>);

获得 Sheet 的方法有两种: 通过索引, 通过名字.
GetSheet()方法来获得对应名字的SheetGetSheetAt()方法来获得对应索引的Sheet

与之对应的还有获得所有名字的方法, 以及获得 Sheet 个数的属性等.

读取行与单元格
Excel 每一个表格中的行与单元格 (可简单视为列) 是自由格式. 即
- 从第几行开始到第几行结束不确定.
- 在指定行范围内存在空数据.
- 每一行的数据, 单元格也是自由的, 不确定从第几个单元格开始, 到第几个单元格结束.
将 Sheet 可以看成一个稀疏矩阵.
需要注意的是, Office 和 WPS 在处理行的时候, 有些时候不同, 读取需要进行校验.
所以读取行, 需要一个范围
FirstRowNum,0-base的索引.LastRowNum,0-base的索引.- 使用
ISheet的GetRow()方法来获得对应索引的行对象. 注意可能返回null.
ISheet sheet0 = workbook.GetSheetAt(0);
for (var rowIndex = sheet0.FirstRowNum; rowIndex < sheet0.LastRowNum; rowIndex++) {
IRow row = sheet0.GetRow(rowIndex);
}

需要注意的是, Row 索引的取值范围是闭区间.
单元格的读取逻辑是一样的. 每一个 IRow 都有:
FirstCellNumLastCellNumGetCell()方法

但需要注意的是, Cell 的索引也是 0-base, 也是稀疏的. 而 Cell 的索引取值范围是左闭右开区间.
读取单元格的值
单元格默认有几种数据类型:
常见的是: 字符串, boolean, 以及数字. 并且每一个数据类型对应不同的数据读取方式: ***CellValue.
- 如果是字符串类型, 需要通过
StringCellValue来取值. - 如果是数字类型, 需要通过
NumericCellValue来取值. - 等等.
如果使用错误的方式是无法取到数据的.
如果该单元格有公式, 取值得到的是公式的值, 而公式本身也以字符串形式存储在 CellFormula 中, 例如:


可以将其整理成扩展方法, 例如:
public static string GetString(this ICell cell) {
switch (cell.CellType) {
case CellType.String: return cell.StringCellValue;
case CellType.Boolean: return cell.BooleanCellValue.ToString();
case CellType.Numeric: return cell.NumericCellValue.ToString();
case CellType.Blank: return string.Empty;
default: return string.Empty;
}
}