使用 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()
方法来获得对应名字的Sheet
GetSheetAt()
方法来获得对应索引的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
都有:
FirstCellNum
LastCellNum
GetCell()
方法
但需要注意的是, 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;
}
}