如何从加密DataTable读取指定列并解决KostenArt列不存在报错?
问题根因
核心问题出在FileGenerator.ReadFromProtectedFile方法的旧版文件解析逻辑,以及异常被吞导致问题难以定位:
- 旧格式加密文件没有带列名+类型的头行定义,但代码仍然将第一行数据当做列定义行解析,第一行第一个单元格的内容会被设为第一列的列名,自然不存在
KostenArt这个预期列名 - 旧格式分支仅按索引设置了列的数据类型,没有手动指定固定列名,和你代码中预期的列名完全不匹配
ConvertDataTableToListOfISAACService方法捕获ArgumentException后没有任何日志或抛出逻辑,掩盖了错误的具体上下文
修复方案
1. 修复ReadFromProtectedFile旧格式列名逻辑
在旧格式分支(ColDef.Length <=1)中,按你定义的固定列名手动赋值,修改代码如下:
If ColDef.Length > 1 Then myCol.DataType = Type.GetType(ColDef(1)) myCol.ColumnName = ColDef(0) ' 新格式保留原有列名 Else ' 手动指定旧格式的固定列名,和MainForm定义的常量完全匹配 Dim oldFormatColumnNames As New List(Of String) From { "KostenArt", "UANR", "Ueberbegriff", "Benennung", "Anzahl", "Einheit", "Einzelkosten", "Gesamtmenge", "Summencode" } If Counter < oldFormatColumnNames.Count Then myCol.ColumnName = oldFormatColumnNames(Counter) Else myCol.ColumnName = $"Column{Counter}" ' 多余列默认命名 End If ' 原有旧格式类型赋值逻辑保留 Select Case Counter Case 4, 8, 10 myCol.DataType = GetType(Integer) Case 6 myCol.DataType = GetType(Double) Case Else myCol.DataType = GetType(String) End Select End If
建议将列名常量抽到公共工具类中,保证FileGenerator和MainForm的列名定义完全一致,避免后续维护不一致
2. 转换前增加列存在性校验,优化异常处理
修改ConvertDataTableToListOfISAACService方法,先判断所有必填列是否存在,避免取值报错,同时不要吞关键异常:
Private Function ConvertDataTableToListOfISAACService(dt As DataTable, lst As List(Of ISAACService)) As List(Of ISAACService) ' 先校验必填列是否存在 Dim requiredColumns As New List(Of String) From {KostenArt, UANR, Ueberbegriff, Benennung, Anzahl, Einheit, Einzelkosten, Gesamtmenge, Summencode} For Each col In requiredColumns If Not dt.Columns.Contains(col) Then Throw New ArgumentException($"导入文件缺少必填列:{col},请检查文件格式") End If Next For Each row As DataRow In dt.Rows Dim ISAAC As New ISAACService( row(KostenArt).ToString, row(UANR).ToString, row(Ueberbegriff).ToString, row(Benennung).ToString, CDbl(row(Anzahl)), row(Einheit).ToString, CDbl(row(Einzelkosten)), CInt(row(Gesamtmenge)), row(Summencode).ToString ) lst.Add(ISAAC) Next Return lst End Function
3. 可选排查优化
如果修复后还有问题,可以加一行代码输出实际生成的列名,快速确认解析结果是否符合预期:
dt1 = FileGenerator.ReadFromProtectedFile(OpenFileDialog1.FileName) ' 输出所有列名到调试窗口 For Each col As DataColumn In dt1.Columns Debug.WriteLine($"列名:{col.ColumnName},类型:{col.DataType.Name}") Next dgv1.DataSource = dt1
内容的提问来源于stack exchange,提问作者idontgetit
相关产品推荐
相关产品推荐

