使用ExcelDataReader读取文件时#N/A等被识别为字符串而非空值的问题
解决ExcelDataReader读取文件时所有内容识别为字符串导致计算异常的问题
嘿,这个问题我太熟了!ExcelDataReader默认确实会把所有单元格内容一股脑当成字符串读,包括#N/A、#VALUE!这些Excel错误值,后续做计算的时候肯定会炸锅。结合你给出的代码框架,给你几个实用的解决思路:
方案1:逐行读取时手动判断类型与错误值
你可以在读取每一行数据的时候,利用ExcelDataReader自带的方法判断单元格的真实类型,同时手动识别Excel错误字符串,提前处理掉这些会导致计算异常的内容:
FileStream stream = File.Open(strFilePath, FileMode.Open, FileAccess.Read); string extension = System.IO.Path.GetExtension(strFilePath).ToLower(); IExcelDataReader excelReader; // 初始化对应格式的Reader if (extension.Equals(".csv")) { excelReader = ExcelReaderFactory.CreateCsvReader(stream); } else if (extension.Equals(".xls")) { excelReader = ExcelReaderFactory.CreateBinaryReader(stream); } else if (extension.Equals(".xlsx")) { excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream); } else { throw new NotSupportedException("不支持当前文件格式"); } // 逐行读取并处理数据 while (excelReader.Read()) { for (int columnIndex = 0; columnIndex < excelReader.FieldCount; columnIndex++) { // 先判断是否为空或Excel内置错误值(部分版本中#N/A会被识别为DBNull) if (excelReader.IsDBNull(columnIndex)) { // 这里可以给默认值,比如0、null,或者直接跳过计算 var processedValue = null; continue; } // 获取单元格的真实类型,进行对应转换 Type fieldType = excelReader.GetFieldType(columnIndex); if (fieldType == typeof(int)) { int intValue = excelReader.GetInt32(columnIndex); // 执行整数相关计算 } else if (fieldType == typeof(double)) { double doubleValue = excelReader.GetDouble(columnIndex); // 执行浮点相关计算 } else if (fieldType == typeof(string)) { string cellValue = excelReader.GetString(columnIndex); // 手动识别Excel错误字符串 bool isExcelError = cellValue.Equals("#N/A", StringComparison.OrdinalIgnoreCase) || cellValue.Equals("#VALUE!", StringComparison.OrdinalIgnoreCase); if (isExcelError) { // 错误值处理逻辑,比如设为默认值或跳过 continue; } else { // 尝试把字符串转换为数值类型(针对CSV这类纯文本格式) if (int.TryParse(cellValue, out int parsedInt)) { // 用parsedInt做计算 } else if (double.TryParse(cellValue, out double parsedDouble)) { // 用parsedDouble做计算 } } } } } // 记得关闭Reader释放资源 excelReader.Close();
方案2:通过DataSet配置自动识别列类型
如果你习惯用DataSet来处理数据,可以配置ExcelDataReader的转换规则,让DataSet自动识别列的类型,同时过滤错误值:
FileStream stream = File.Open(strFilePath, FileMode.Open, FileAccess.Read); string extension = System.IO.Path.GetExtension(strFilePath).ToLower(); IExcelDataReader excelReader; // 初始化Reader(同方案1) if (extension.Equals(".csv")) { excelReader = ExcelReaderFactory.CreateCsvReader(stream); } else if (extension.Equals(".xls")) { excelReader = ExcelReaderFactory.CreateBinaryReader(stream); } else if (extension.Equals(".xlsx")) { excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream); } else { throw new NotSupportedException("不支持当前文件格式"); } // 配置DataSet的转换规则 var dataSetConfig = new ExcelDataSetConfiguration() { ConfigureDataTable = (_) => new ExcelDataTableConfiguration() { UseHeaderRow = true, // 如果文件有表头,开启这个会更利于类型识别 // 自定义列类型转换逻辑 TransformColumn = (table, columnIndex) => { // 这里可以根据列名或内容预判类型,比如假设第一列是整数 if (columnIndex == 0) { table.Columns[columnIndex].DataType = typeof(int); } else { table.Columns[columnIndex].DataType = typeof(double); } } } }; // 转换为DataSet DataSet dataSet = excelReader.AsDataSet(dataSetConfig); DataTable firstTable = dataSet.Tables[0]; // 遍历DataTable处理数据 foreach (DataRow row in firstTable.Rows) { foreach (DataColumn column in firstTable.Columns) { // 检查是否是错误值或无法转换的内容 if (row.IsNull(column) || System.Text.RegularExpressions.Regex.IsMatch(row[column].ToString(), "#N/A|#VALUE!", System.Text.RegularExpressions.RegexOptions.IgnoreCase)) { continue; } // 直接用强类型做计算 if (column.DataType == typeof(int)) { int value = (int)row[column]; // 计算逻辑 } } } excelReader.Close();
额外提醒: 对于CSV文件,因为本身是纯文本格式,ExcelDataReader很难自动识别数值类型,所以最好用int.TryParse或double.TryParse做二次转换,确保能把可计算的字符串转成数值;而#N/A这类错误值,不同版本的ExcelDataReader处理方式可能不同,建议同时检查IsDBNull和字符串内容,避免遗漏。
内容的提问来源于stack exchange,提问作者Maryam Dairkee
相关产品推荐
相关产品推荐

