如何使用ExcelDataReader读取XLS文件中Defined Names(命名区域)的值
ExcelDataReader读取Defined Names(命名区域)值的方法
AsDataSet() 转换过程不会保留命名区域相关元数据,命名区域信息直接挂载在IExcelDataReader实例的DefinedNames属性上,结合已加载的DataSet表数据即可读取对应值,具体实现步骤如下:
1. 读取命名区域定义
在执行完AsDataSet()加载全量表数据后,直接遍历reader.DefinedNames集合即可拿到所有命名区域的基础信息:
// 读取XLS格式文件用CreateBinaryReader,XLSX格式替换为CreateOpenXmlReader即可 using var reader = ExcelReaderFactory.CreateBinaryReader(fileStream); var excelDataSet = reader.AsDataSet(new ExcelDataSetConfiguration { ConfigureDataTable = (_) => new ExcelDataTableConfiguration { UseHeaderRow = true } }); // 遍历所有命名区域 foreach (var definedName in reader.DefinedNames) { // 命名区域名称 string name = definedName.Name; // 所属工作表索引,值为-1时代表是工作簿全局级命名 int sheetIndex = definedName.SheetIndex; // 引用内容:可能是单元格/区域引用、常量、公式,格式如 "Sheet1!$A$1:$C$5" string referenceContent = definedName.Text; // 是否为Excel自动生成的隐藏命名(如打印区域、筛选范围) bool isHidden = definedName.IsHidden; }
2. 解析引用获取对应值
根据referenceContent的格式判断内容类型,再从DataSet中匹配对应取值:
- 如果是常量、公式类命名,直接取
referenceContent即可拿到定义值 - 如果是单元格/单元格区域引用,先匹配所属DataTable,再解析行列索引从表中取值
// 示例:读取指定名称的单元格类命名区域值 var targetDefinedName = reader.DefinedNames.First(item => item.Name == "你的命名区域名称"); DataTable sourceTable; if (targetDefinedName.SheetIndex == -1) { // 全局命名:从引用内容中拆分表名,自动处理表名带单引号的场景 string rawRef = targetDefinedName.Text; string tableName = rawRef.Split('!')[0].Trim('\''); sourceTable = excelDataSet.Tables[tableName]; } else { // 工作表级命名:直接按索引取对应表 sourceTable = excelDataSet.Tables[targetDefinedName.SheetIndex]; } // 解析单元格引用(示例处理固定$列$行格式,多单元格区域可扩展正则匹配起止行列) string cellPart = targetDefinedName.Text.Contains('!') ? targetDefinedName.Text.Split('!')[1] : targetDefinedName.Text; cellPart = cellPart.Replace("$", ""); // 拆分列字母、行号 string columnLetters = new string(cellPart.TakeWhile(char.IsLetter).ToArray()); int excelRowNum = int.Parse(new string(cellPart.SkipWhile(char.IsLetter).ToArray())); // 索引转换:Excel行号从1开始,开启UseHeaderRow时第一行是表头,数据行从0基索引开始,因此需要减2 int dataRowIndex = excelRowNum - 2; // 列索引需自行实现列字母转0基数字索引的逻辑(A=0、B=1...Z=25、AA=26,按26进制转换即可) int dataColumnIndex = ConvertColumnLetterToIndex(columnLetters); // 最终获取命名区域对应的值 object namedRangeValue = sourceTable.Rows[dataRowIndex][dataColumnIndex];
注意事项:
- 如果未开启
UseHeaderRow,行索引转换时只需要减1(将Excel 1起始行号转为0基索引即可)- 不需要读取系统自动生成的隐藏命名时,可通过
isHidden == false过滤掉无关项- 多单元格区域命名可在解析单元格部分时,拆分
:前后的起止单元格,分别解析行列后遍历范围读取所有值
内容的提问来源于stack exchange,提问作者Val
相关产品推荐
相关产品推荐

