如何从异常提取特定信息自定义消息?Excel强类型数据集转换问询
嘿,我来帮你搞定这两个实际开发里的问题——DataSet转强类型DataTable,还有怎么从异常里挖有用信息做自定义提示!
一、完善DataSet到强类型DataTable的转换
你已经有了转换方法的开头,接下来核心是字段映射+空值/类型安全处理,毕竟Excel里的空单元格、格式不规范的数据很容易搞崩转换逻辑。这里给你补全并优化代码:
public DocAdmin.GHDefinitionDataTable ConvertDataTable(DataTable dtOriginal) { DocAdmin.GHDefinitionDataTable ghDefinition = new DocAdmin.GHDefinitionDataTable(); // 先做前置校验:原始表为空直接返回空的强类型表 if (dtOriginal?.Rows.Count == 0) return ghDefinition; // 遍历原始Excel表的每一行 foreach (DataRow originalRow in dtOriginal.Rows) { // 新建强类型行(强类型DataTable自动生成的NewXXXRow方法) DocAdmin.GHDefinitionRow newRow = ghDefinition.NewGHDefinitionRow(); // 逐个字段映射——这里要根据你的强类型表字段和Excel列名对应调整 // 示例:假设强类型表有Id、DefinitionName、CreateDate三个字段 if (!originalRow.IsNull("Id")) newRow.Id = (int)originalRow["Id"]; // 字符串类型可以用空合并运算符处理空值 newRow.DefinitionName = originalRow["DefinitionName"]?.ToString() ?? string.Empty; if (!originalRow.IsNull("CreateDate")) newRow.CreateDate = (DateTime)originalRow["CreateDate"]; // 其他字段同理,一定要注意数据类型匹配,比如Excel里的数字可能是double类型,转int要显式转换 // 将组装好的行添加到强类型表 ghDefinition.AddGHDefinitionRow(newRow); } return ghDefinition; }
几个关键提醒:
- 字段名要对应:如果Excel列名和强类型表字段名不一样,要手动映射(比如Excel列是"GH编号",强类型是"Id",就写
newRow.Id = (int)originalRow["GH编号"]) - 必须做空值判断:用
originalRow.IsNull(列名)避免空单元格导致的InvalidCastException - 类型转换要严谨:比如Excel里的数字默认是
double,转int要显式用Convert.ToInt32()或者强制转换,避免隐式转换报错
二、从异常中提取特定信息生成自定义提示
异常处理要分场景针对性捕获,不同阶段的异常(Excel读取、数据转换)有不同的信息可以提取,给你分情况说明:
1. Excel读取阶段的异常
ExcelDataReader针对文件损坏、格式不匹配会抛出InvalidDataException,你可以提取异常消息甚至内部异常的细节:
try { using (var stream = File.Open("目标文件.xlsx", FileMode.Open, FileAccess.Read)) { // 注意!.xls用CreateBinaryReader,.xlsx要用CreateOpenXmlReader,别搞混了! var excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream); var conf = new ExcelDataSetConfiguration() { ConfigureDataTable = _ => new ExcelDataTableConfiguration() { UseHeaderRow = true // 用Excel第一行作为列名,方便后续字段映射 } }; var excelDataSet = excelReader.AsDataSet(conf); // 调用转换方法 var ghTable = ConvertDataTable(excelDataSet.Tables[0]); } } catch (InvalidDataException ex) { // 组装用户友好的提示 string customMsg = $"Excel文件读取失败:{ex.Message}"; // 如果有内部异常,补充更细节的信息 if (ex.InnerException != null) customMsg += $" 详情:{ex.InnerException.Message}"; // 这里可以把提示显示给用户,比如MessageBox.Show(customMsg)或者返回给前端 }
2. 数据转换阶段的异常
在转换强类型表时,最常见的是格式错误(比如字符串转int失败),你可以在转换方法里捕获并定位到具体行:
// 重载方法,返回错误信息 public DocAdmin.GHDefinitionDataTable ConvertDataTable(DataTable dtOriginal, out string errorMsg) { errorMsg = string.Empty; DocAdmin.GHDefinitionDataTable ghDefinition = new DocAdmin.GHDefinitionDataTable(); if (dtOriginal?.Rows.Count == 0) return ghDefinition; foreach (DataRow originalRow in dtOriginal.Rows) { try { DocAdmin.GHDefinitionRow newRow = ghDefinition.NewGHDefinitionRow(); // 字段映射逻辑... newRow.Id = originalRow.IsNull("Id") ? 0 : Convert.ToInt32(originalRow["Id"]); newRow.DefinitionName = originalRow["DefinitionName"]?.ToString() ?? string.Empty; ghDefinition.AddGHDefinitionRow(newRow); } catch (FormatException ex) { // 定位到具体行(Excel行号从1开始,表头占一行,所以+2) int rowNum = dtOriginal.Rows.IndexOf(originalRow) + 2; errorMsg += $"第{rowNum}行数据格式错误:{ex.Message}\n"; } catch (InvalidCastException ex) { int rowNum = dtOriginal.Rows.IndexOf(originalRow) + 2; errorMsg += $"第{rowNum}行字段类型不匹配:{ex.Message}\n"; } } return ghDefinition; }
调用时就可以拿到详细的错误提示:
string convertError; var ghTable = ConvertDataTable(excelDataSet.Tables[0], out convertError); if (!string.IsNullOrEmpty(convertError)) { Console.WriteLine($"数据转换失败:\n{convertError}"); // 或者显示给用户:MessageBox.Show(convertError) }
3. 通用异常兜底
对于其他未知异常,给用户的提示要友好,内部可以记录详细的异常信息(比如堆栈、异常类型)用于排查:
catch (Exception ex) { // 给用户的友好提示 string userMsg = "操作失败,请检查文件格式或数据是否正确。"; // 内部日志记录详细信息(用你项目里的日志框架,比如NLog、Serilog) string logMsg = $"异常类型:{ex.GetType().Name},消息:{ex.Message},堆栈:{ex.StackTrace}"; // Logger.Error(logMsg); // 显示提示 MessageBox.Show(userMsg); }
内容的提问来源于stack exchange,提问作者Dopefish
相关产品推荐
相关产品推荐

