【问题标题】:VBA recordset created from TXT file returns Null values (Excel 2013)从 TXT 文件创建的 VBA 记录集返回 Null 值 (Excel 2013)
【发布时间】:2018-10-25 16:11:19
【问题描述】:

我是在 VBA 中使用记录集的新手,这个问题让我发疯。

我得到一个大报告(cca 57000 行),它保存为带有标签的文本文件。我的任务是删除不必要的数据,插入其他数据并创建数据透视表之类的东西。现在这个任务是在 Excel 中手动完成的,它会产生一个使用不便的大文件。所以我想在一个记录集中导入TXT文件并用SQL语句操作数据,并将结果保存在一个单独的Excel文件中。

我已经设法直接从 TXT 导入数据。 .CountRecord 显示正确的记录数,但它们为 Null。 我尝试从.Execute.Open 创建记录集,结果相同。 这是我的 VBA 代码:

Sub user_statistic_report()

Dim sPath As String
Range("A1").EntireRow.Delete

Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
With cn
    .Provider = "Microsoft.Jet.OLEDB.4.0;"
    .Properties("Data Source") = "C:\\Mydocs\raport\" 'sample path
    .Properties("Extended properties") = "text;HDR=No;FMT=Delimited;"
    .Open
End With

rs.CursorLocation = 3 'someone told it helped him but it did not a trick for me
'later I'd like to select only rows with specific conditions
rs.Open "SELECT * FROM [b.txt]", cn, 3
Debug.Print "Number of records:", rs.RecordCount

Set dbFields = rs.Fields
For i = 0 To dbFields.Count - 1
    Debug.Print "Column #", i, dbFields.Item(i).Name
Next i

Debug.Print "Recordset item", rs(3)

rs.Close
cn.Close
Set cn = Nothing
Set rs = Nothing

End Sub

这是我在即时窗口中看到的内容:

Number of records:           5<BR> 
Column #       0            F1<BR>
Column #       1            F2<BR>
Column #       2            F3<BR>
Column #       3            F4<BR>
Recordset item              Null<BR>

这是我的示例 TXT 文件 b.txt。每行都以制表符开头:

    Col1    Col2    Col3
    11  12  13
    21  22  23

这里是 schema.ini

[b.txt]
Format=TabDelimited
ColNameHeader=False
MaxScanRows=0

您能否告知为什么记录集返回 Null 值?

更新: 问题出在我的 TXT 文件中,它以某种方式损坏。我已经在文件中重新输入了值,脚本现在可以工作了。

【问题讨论】:

  • 如果您将rs(3) 更改为rs.RecordCount,它会达到您的预期吗?或rs(2)rs(1)rs(0)。顺便说一句,这句话很奇怪 - .CountRecord 显示正确的记录数,但它们是 Null。
  • @Vityata,问题是我可以使用 rs.RecordCount(5 条记录)检索记录数,但是 rs(i)、rs.Fields(I) 的所有值都是 Null。

标签: vba excel ado recordset


【解决方案1】:

我假设您还想打印字段的值,而不仅仅是字段名称。

像这样修改你的代码

Set dbFields = rs.Fields
For i = 0 To dbFields.Count - 1
    Debug.Print "Column #", i, dbFields.Item(i).Name
Next i


rs.MoveFirst
Do While Not rs.EOF
    Debug.Print rs.Fields(1).Value, rs.Fields(2).Value, rs.Fields(3).Value
    rs.MoveNext
Loop

下面的部分将打印字段的值。

您的问题是您误解了行的输出

Debug.Print "Recordset item", rs(3)

这一行打印字段号3的值,最好写

Debug.Print "Recordset item", rs.fields(3).value

并且该字段可能包含 Null

更新你可以试试下面的代码。您需要添加一个reference to ADODB

Option Explicit

Sub user_statistic_report()

Dim sPath As String
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset

    Set cn = CreateObject("ADODB.Connection")
    Set rs = CreateObject("ADODB.Recordset")
    With cn
        .Provider = "Microsoft.Jet.OLEDB.4.0;"
        .Properties("Data Source") = "C:\\Mydocs\raport\"    'sample path
        .Properties("Extended properties") = "text;HDR=No;FMT=Delimited;"
        .Open
    End With

    rs.CursorLocation = adUseClient    'someone told it helped him but it did not a trick for me
    'later I'd like to select only rows with specific conditions
    rs.Open "SELECT * FROM [b.txt]", cn, adOpenStatic
    Debug.Print "Number of records:", rs.RecordCount

    Dim wks As Worksheet
    Set wks = ActiveSheet

    wks.UsedRange.Clear
    WriteToSheet wks, rs

    rs.Close
    cn.Close
    Set cn = Nothing
    Set rs = Nothing

End Sub


Sub WriteToSheet(ByVal sh As Worksheet, ByVal rs As ADODB.Recordset)

Dim dbfields As ADODB.Fields
Dim i As Long, j As Long

    ' Write Heading resp. Field names in row 1
    Set dbfields = rs.Fields
    For i = 0 To dbfields.Count - 1
        sh.Cells(1, i + 1).Value = dbfields.Item(i).Name
    Next i

    ' Write values of the recordset starting at row 3
    j = 2
    rs.MoveFirst
    Do While Not rs.EOF
        For i = 0 To dbfields.Count - 1
            sh.Cells(j, i + 1).Value = rs.Fields.Item(i).Value
        Next i
        rs.MoveNext
        j = j + 1
    Loop

End Sub

UPDATE 2那是文本文件

那是十六进制视图

这就是excel用脚本读取文件的结果

所以,文件的内容是

制表符 11 制表符 制表符 13 CRLF

制表符 21 制表符 22 制表符 23 CRLF

制表符 31 制表符 32 制表符 33 CRLF

制表符 制表符 42 制表符 43 CRLF

【讨论】:

  • 感谢您的评论,但遗憾的是 Fields 集合的元素值仍然为空。我想知道我的 TXT 文件是否一切正常,因为使用的算法似乎适用于 Internet 上的其他人。
  • 当然你必须知道你的文本文件的结构。一件奇怪的事情是文本文件的每一行都以制表符开头。这意味着您将获得四列,并且只有三列是非常必要的。而且我不确定您的字段是否真的由制表符分隔,但这是必要的,因为您期望以这种方式。你的字段之间真的总是有一个标签还是只在你的行首?那么,11 12 13 之间真的有制表符吗?
  • 是的,我的字段之间总是有标签,每一行都以标签开头(报告是从 SAP 生成的,这就是它如此奇怪的原因)。我也尝试只使用一列(如 A 1 2 3),但结果是一样的。
  • 您的代码对我有用。我调整了文本文件。如果我将以下两个没有值的选项卡放入文件中,我将得到一个值为 Null 的字段,这是预期的。因此,您可能需要提供有关文件内容的更多信息。
  • 能否分享一下您在文本文件中做了哪些调整?我有这样的( 用于制表符,| 用于一行): Column1Column2etc| 值1值2等|
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-25
  • 1970-01-01
相关资源
最近更新 更多