【问题标题】:How to avoid Power Query error with empty query from VBA Excel?如何避免来自 VBA Excel 的空查询的 Power Query 错误?
【发布时间】:2020-11-21 14:11:41
【问题描述】:

我想将一个文本文件导入 Excel,通过 VBA 宏过滤我想要的内容。数据量很大,所以我有效地使用了 Power 查询。我有一个列表,其中列出了要以不同方式过滤和处理的几件事,并且此列表可能会更改。因此,对于要过滤的每个“功能”,我都会在新工作表中重新加载查询。 如果过滤器使查询为空,我会从 Power Query 中收到一个我无法跳过的错误:

Application.EnableEvents = False
Application.ScreenUpdating = False
Application.DisplayAlerts = False 

调试我看到在查询创建和粘贴到工作表之间出现错误,见下面代码中的(*)。

有人知道是否有办法将记录数放入查询中,以便能够使用 if 语句并跳过粘贴阶段?

我唯一的另一个想法是为每个特征自动写入一行到 txt 文件中进行过滤,但这不是一个优雅的方法

我不明白的事情是使用函数出现问题,见下文,但不直接使用宏。 当我使用该函数时,显示的错误并不总是出现,但无论如何代码完成了函数但主宏停止了。

test.txt

946737295   9CE78280    FF  1   5   FF  FF  FF  FF  FF
946737295   9CE78280    C0  FF  0   0   0   0   FF  FF
946737295   9CE68082    C0  4   0   FF  FF  FF  FF  FF

宏是:

Function readTxt(input_path As String, Pgn As String, B2 As String, B3 As String) As Boolean

    Dim Wb As Workbook
    Dim Ws As Worksheet
    Dim Conn As WorkbookConnection
    Dim mFormula As String
    Dim query As WorkbookQuery
    
    Set Wb = ActiveWorkbook
    Set Ws = Wb.ActiveSheet
    
    On Error Resume Next
    
    Application.EnableEvents = False
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
       

    mFormula = "let " & _
        "Source = Csv.Document(File.Contents(""" & input_path & """),[Delimiter=""#(tab)"", Columns=10, Encoding=65001, QuoteStyle=QuoteStyle.Csv])," & _
        "#""Step1"" = Table.SelectRows(Source, each Text.Contains([Column2], """ & Pgn & """) and [Column5] = """ & B3 & """ and [Column4] = """ & B2 & """)," & _
        "#""Step2"" = Table.RemoveColumns(Step1,{""Column2"", ""Column3"", ""Column4"", ""Column5"", ""Column9"", ""Column10""})" & _
        "in #""Step2"""
    
    Set query = Wb.Queries.Add("test_7", mFormula)

    With Ws.ListObjects.Add(SourceType:=0, Source:= _
         "OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=" & "test_7" & ";Extended Properties=""""", Destination:=Ws.Range("A3"), XlListObjectHasHeaders:=xlYes).QueryTable
         '.ListObject.TotalsRowRange
         .CommandType = xlCmdSql
         .AdjustColumnWidth = False
         .ListObject.Name = "test"
         .CommandText = "SELECT * FROM [" & "test_7" & "]" 
         .Refresh BackgroundQuery:=False
     End With
         
     If Err.Number <> 0 Then
            Err.Clear
     End If
      
      query.Delete
         
    Application.EnableEvents = True
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
    
    readTxt = True 'output
    
    On Error GoTo 0

End Function
Sub readTxt()
Dim Wb As Workbook
Dim Ws As Worksheet
Dim Conn As WorkbookConnection
Dim mFormula As String
Dim query As WorkbookQuery

Set Wb = ActiveWorkbook

Dim i As Integer
Dim C3 As String

    On Error Resume Next
    
    Application.EnableEvents = False
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False

C3 = "F2"

For i = 1 To 2
       
    If i = 2 Then
        C3 = "FF"
        Sheets.Add After:=ActiveSheet
    End If
    Set Ws = Wb.ActiveSheet

    mFormula = "let " & _
        "Source = Csv.Document(File.Contents(""C:\test.txt""),[Delimiter=""#(tab)"", Encoding=65001, QuoteStyle=QuoteStyle.Csv])," & _
        "#""Step1"" = Table.SelectRows(Source, each Text.Contains([Column2], ""E7"") and [Column3] = """ & C3 & """)" & _
        "in #""Step1"""
        
    Set query = Wb.Queries.Add("Test_text", mFormula)
    
    ' (*) THE ERROR OF POWER QUERY APPEARS HERE
    
    With Ws.ListObjects.Add(SourceType:=0, Source:= _
         "OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=" & "Test_text" & ";Extended Properties=""""", Destination:=Ws.Range("A3"), XlListObjectHasHeaders:=xlYes).QueryTable
         .CommandType = xlCmdSql
         .AdjustColumnWidth = False
         .ListObject.Name = "test"
         .CommandText = "SELECT * FROM [" & "Test_text" & "]"
         .Refresh BackgroundQuery:=False
     End With
     
     query.Delete
 
Next

    Application.EnableEvents = True
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
    
    On Error GoTo 0
      
End Sub

谢谢, 鲁杰罗

【问题讨论】:

  • 那么,如果我理解正确,您是说当 txt 文件中没有数据时会引发错误?
  • 代码在提供的示例中为我工作。 Query 不会返回任何数据,因为您在第二步中添加的过滤器会返回一个空表。这也是我在 excel 表中得到的。代码也适用于空文本文件。也许行为取决于版本。
  • 谢谢,你有没有在没有数据的步骤之后尝试过有数据的步骤?例如带有[Column3] = ""F1"" 的工作表和带有[Column3] = ""FF"" 的第二个工作表
  • 我为什么要这样做?你提供了 M 代码,所以我接受了。你是说你得到了上面代码的错误,不是吗?顺便说一句,我得到了 version2.86.725.0 32 位的 PQ。
  • 我编辑了代码以使其更清晰,但这样似乎可以工作。实际上我在函数中使用了这段代码,我尝试加载它

标签: excel vba text-files powerquery can-bus


【解决方案1】:

您可以使用此代码检查步骤(表)是否具有某些特定列:

let Source = Csv.Document(File.Contents("C:\temp\test.txt"),[Delimiter=";", Encoding=65001, QuoteStyle=QuoteStyle.Csv]),
    #"Step1" = Table.SelectRows(Source, each Text.Contains([Column2], "E7") and [Column3] = "F1"),
    result_error = "Some error",
    check_columns = Table.HasColumns(#"Step1", {"Column2", "Column3"}),
    result = if check_columns = true then #"Step1" else result_error
in result

查看 check_columns 步骤和条件结果

【讨论】:

  • 感谢 Ricardo,它可能对我必须做的另一项检查很有用。在所描述的情况下,我或多或少总是有相同的列,但在某些情况下行是 0
  • 我现在不在办公桌前,但按照同样的逻辑,使用 Table.RowCount 函数
  • 我尝试使用 Table.RowCount 并且它至少有一行但代码仍然停止。我看到问题也出现在文件过滤器的其他键上。阅读另一个线程,我了解这可能是与 txt 的大尺寸相关的错误。 link italic bold 详细信息中的错误消息是“MashupResource 的 PageReader 不可用”。电源查询 2.78.5740.481 64 位
  • 也许提供一个包含所有列的 txt 示例文件的链接
  • link 到 txt 30Mb 文件,上面的宏给出错误:“MashupResource 的 PageReader 不可用”,F2 为空,但有数据
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-22
  • 1970-01-01
  • 1970-01-01
  • 2011-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多