【问题标题】:Read csv data with ACE OLEDB Engine, how to detect errors in data使用 ACE OLEDB Engine 读取 csv 数据,如何检测数据中的错误
【发布时间】:2019-11-14 22:43:13
【问题描述】:

在 Excel VBA 中,我尝试使用 ACE OLEDB 引擎和 schema.ini 文件读取 CSV 文本文件。这可行,但是当数据中出现错误时,我希望 ACE OLEDB 引擎抛出异常。

但是,它只是将数据中的错误值读取为 null,将它们作为空值传递,并且它只是继续,没有任何错误消息。尤其是对于大型数据集,这是行不通的,因为无法手动轻松发现任何错误。

这是一个制表符分隔的数据集,有一些故意的错误来重现它。

OrderID OrderDate   Amount  Price   ArtNo   
40361   07/09/2019  2   59.95   4006633374668   
40362   07/10/2019  2   42,95   4006633146647   
40363   07/11/2019  1   69.75   4016987119501   
40364   07/12/2019  4   4.99    4082300264630   
40365   07/13/2019  1   39.95   4026736081348   
40366   07/14/2019  1   230.00  4013872786831   
40367   07/29/2019  1   42.95   4006633294256   
40368   07/30/2019  1   3,299.00    GTIN:0191215072422  
40369   07/31/2019  1   86.95   4010858791506   
40370   07/32/2019  10  8.99    4029416288686   

以及对应的schema.ini文件

[测试数据.txt]
日期时间格式=m/d/yyyy
DecimalSymbol=.
格式=制表符分隔
Col1=OrderID 整数宽度 5
Col2=OrderDate 日期宽度 10
Col3=数量整数宽度 2
Col4=价格浮动宽度 10
Col5=ArtNo 文字宽度 13

使用 ACE OLEDB 连接到文本数据文件并执行SELECT * FROM textfile 后,结果如下:

有些单元格是空的,即使数据文件中有值。
B:值“42,95”是DecimalSymbol 设置为点的错误。
D:值“3,299.00”是一个错误,因为千位逗号
E:值“07/32/2019”的日期不正确
F*: 值 "GTIN:0191215072422" 太长,E9 在 13 个字符处被截断(*图中未标注)

(顺便说一句,日期值 A 也被错误地解释了,即使设置 DateTimeFormat=m/d/yyyy 是正确的,但 C 是正确的,可能只是因为日期高于 12,但 Excel 总是对日期格式感到不安,所以我只是忽略这里)

以下是使用 ACE OLEDB 引擎加载文本数据文件的 VBA 代码。

Sub ReadCsvTest(sPath As String, sFile As String, sBOM As String)

    Dim Wsh As Worksheet
    Dim AdoConnect As ADODB.Connection ' Tools > References > select "Microsoft ActiveX Data Objects x.x Library"
    Dim AdoRcrdSet As ADODB.Recordset
    Dim strSQL As String
    Dim sField As String
    Dim sValue As String
    Dim i As Integer
    Dim iRow As Integer
    ' not sure what it does, but just set sBOM = "\xEF\xBB\xBF"

    ' Add a new sheet
    With ActiveWorkbook
        Set Wsh = .Sheets.Add(After:=.Sheets(.Sheets.Count))
        'Wsh.Name = NewSheetName        'rename new Sheet
    End With

    Set AdoConnect = New ADODB.Connection
    AdoConnect.Provider = "Microsoft.ACE.OLEDB.12.0"
    AdoConnect.ConnectionString = "Data Source=" & sPath & ";Extended Properties='text';"
    AdoConnect.Open

    strSQL = "select * from " & sFile
    Set AdoRcrdSet = New ADODB.Recordset
    AdoRcrdSet.Open strSQL, AdoConnect

    ' header column names
    For i = 0 To AdoRcrdSet.Fields.Count - 1
        sField = WorksheetFunction.Substitute(AdoRcrdSet.Fields(i).Name, sBOM, "")
        Wsh.Cells(1, i + 1).Value = sField
    Next

    ' row values
    iRow = 2
    AdoRcrdSet.MoveFirst
    While Not AdoRcrdSet.EOF
        For i = 0 To AdoRcrdSet.Fields.Count - 1
            sValue = IIf(IsNull(AdoRcrdSet.Fields(i).Value), "", AdoRcrdSet.Fields(i).Value)
            Wsh.Cells(iRow, 1 + i).Value = sValue
        Next

        AdoRcrdSet.MoveNext
        iRow = iRow + 1
    Wend

End Sub

顺便说一句,我知道我也可以使用打开文件对话框并手动设置每列的数据类型和格式,但这完全忽略了 schema.ini。此外,对于其他用途,需要使用 ACE OLEDB 引擎。

所以我的问题是,是否有可能检测到这些类型的数据错误? 我可以以某种方式区分数据错误和实际空/空值吗? 或者我可以在连接字符串中使用额外的设置来让 ACE OLEDB 引擎抛出错误,或者让它设置错误值而不是 null?

【问题讨论】:

  • 不,这完全取决于生成 .csv 文件的人负责正确地完成工作。对于那个程序员来说很容易做到并解决真正的问题。在 VBA 代码中解析 CSV 并不少见,而且很容易用 google 搜索,但不是你想要的。
  • 如果你想处理 CSV 错误,你必须编写特定的验证器,这可能适用于你的具体情况。

标签: csv validation error-handling oledb


【解决方案1】:

对于任何对此问题感兴趣的人,我最终创建了一个CSV Lint plug-in for Notepad++

插件可以自动检测csv的类型(逗号、制表符等)和列的数据类型。此数据定义基于 schema.ini 格式。然后插件可以根据此元数据验证数据。

自动列检测大部分时间都有效,它并不总是能正确检测数据类型。但是,您可以在验证数据文件之前手动编辑元数据,所以这应该不是问题。它也适用于固定宽度的数据文件,它包括一个语法高亮选项,如您在屏幕截图中所见。

我希望更新这个 Notepad++ 插件,增加额外的功能,但它非常适合检测 csv 文件中的数据错误。

插件可以在这里获取:
http://github.com/BdR76/CSVLint

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    • 2010-09-12
    相关资源
    最近更新 更多