如何在VBA中自动执行功率查询?

时间:2018-07-17 16:48:38

标签: excel vba excel-vba powerquery

我在工作表1中有数据。通常,我会进行功率查询并进行转换,然后关闭并加载到现有工作表2中。

我想使用VBA将其自动化,在这里我可以自动运行电源查询并填充到工作表2的转换。

宏记录器似乎不允许我记录这些步骤。而且,这样做的在线情况还很少。

尝试一些简单的代码:

Sub LoadToWorksheetOnly()

'Sub LoadToWorksheetOnly(query As WorkbookQuery, currentSheet As Worksheet)
    ' The usual VBA code to create ListObject with a Query Table
    ' The interface is not new, but looks how simple is the conneciton string of Power Query:
    ' "OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=" & query.Name

    query = Sheets("Sheet6").Range("A1").value 'here is where my query from power query is. I put the text from power query avanced editor in another sheet cell.
    currentSheet = ActiveSheet.Name
    With ActiveSheet.ListObjects.Add(SourceType:=0, Source:= _
        "OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=" & query.Name _
        , Destination:=Sheets("target").Range("$A$1")).QueryTable
        .CommandType = xlCmdDefault
        .CommandText = Array("SELECT * FROM [" & query.Name & "]")
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .PreserveColumnInfo = False
        .Refresh BackgroundQuery:=False
    End With

End Sub

这是我尝试手动加载到新工作表时的问题。

enter image description here

3 个答案:

答案 0 :(得分:10)

在制品:

那么如何写就足够了?最重要的是,您应该使用内置工具来设置查询。不是VBA。您可以通过适当的方法加载数据,该方法可以来自文件,循环访问文件夹,Web,数据库中的文件...。您可以从外部来源导入,也可以从内部来源加载。请查看here,以获取有关从外部来源进行加载的更多信息。

在您保护好源代码并加载好源代码之后,将向您显示查询编辑器,您可以在其中执行转换steps

关键是,当您使用UI执行步骤时,M代码是在后台编写的,并且构成了可重复使用查询的基础,前提是您不更改源格式或位置。

以您为例,当您执行了步骤并希望进行查询时,然后关闭并加载到sheet2。

在此步骤中,首次设置时,您将选择工作表2作为关闭并加载目的地:

Close and load

注意:选择现有工作表时,请确保工作表2已经存在,并且可以手动编辑工作表2!在建议的范围之前。


您遇到了问题,因为您一直尝试使用代码来重新创建所有这些。 别。使用UI进行设置并加载到sheet2。然后,打开查询编辑器以编辑步骤和/或刷新查询以使用新的/刷新的数据加载现有的sheet2。


一些刷新查询的可用方法:

查询将通过VBA刷新/手动刷新到其位于(Sheet2)的工作表或工作簿本身,例如Sheet2.CalculateThisWorkbook.RefreshAll,手动按下“数据”标签中的“刷新工作簿”按钮(实际上这些都是多余的)

Refresh all tab

更多有针对性的方法:

工作表2中的查询表的VBA

ThisWorkbook.Worksheets("Sheet2").ListObjects(1).QueryTable.Refresh BackgroundQuery:=False   

将以上内容更改为适当的表格,等等。

右键单击查询表本身,然后选择刷新:

Refresh

单击右侧工作簿查询窗口中的刷新按钮以进行相关查询(带有绿色圆圈箭头的图标)

Refresh


Ken Pulls VBA方式(由我负责编辑)

Option Explicit
Public Sub UpdatePowerQueries()
    ' Macro to update my Power Query script(s)

    Dim lTest As Long, cn As WorkbookConnection
    On Error Resume Next
    For Each cn In ThisWorkbook.Connections
        lTest = InStr(1, cn.OLEDBConnection.Connection, "Provider=Microsoft.Mashup.OleDb.1", vbTextCompare)
        If Err.Number <> 0 Then
            Err.Clear
            Exit For
        End If
        If lTest > 0 Then cn.Refresh
    Next cn
    On Error GoTo 0
End Sub

您完全不需要通过VBA完成所有这些工作。使用VBA可能会感到有些棘手的数据操作,然后让powerquery访问作为数据源处理的数据。您可以通过让一个子调用处理例程,然后使用上面列出的vba命令方法之一来解雇整个工作。有更多方法,当我有更多时间时,我会添加它们。


计算:

如果您的计算依赖于powerquery的输出,则有4个明显的立即选项:

  1. 将这些计算尽可能添加到powerquery中。它支持计算列,用户定义的函数以及更多其他功能。
  2. 将powerquery输出添加到数据模型,并使用数据模型执行包括已计算字段在内的计算。这也使您可以使用时间智能功能。
  3. 如果范围在刷新时发生变化,请使用VBA将计算结果添加到工作表2中的适当区域
  4. 如果刷新后范围没有变化,只需将您的公式排除在外即可。

答案 1 :(得分:4)

我不同意以上回答的前提; VBA绝对适合于PowerQuery的自动化,并且对于重复工作特别有效。诀窍是先在PowerQuery中创建所需的查询,然后使用“高级编辑器”捕获M。将其复制并存储在工作簿的单元格中或单独的文本文件中。

method由Gil Raviv详细描述。为了方便起见,我将M存储在文本文件中而不是工作簿中,并使用以下命令加载它:

Function LoadTextFile(FullFileName As String) As String
  With CreateObject("Scripting.FileSystemObject")
    LoadTextFile = .OpenTextFile(FullFileName, 1).readall
  End With 
End Function

关于文本文件的好处是它们独立于excel,并且可以被许多工作簿重复使用。

这里有一些M:

let
// load the reference file (variables are shown in capitals;  
// variable values are replaced with strings from the excel control workbook)
    Source = Excel.Workbook(File.Contents(PATH_AND_NAME), null, true),
    ImportSheet = Source{[Item=SHEET_NAME,Kind="Sheet"]}[Data],
    #"Promoted Headers" = Table.PromoteHeaders(ImportSheet),
    #"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"ACCOUNT", type text}})
in
    #"Changed Type"

一旦(从工作簿或文本文件)加载到VBA中,就可以在VBA中对其进行编辑,例如,通过替换占位符或在必要时使用M命令名称来定位和更改行,例如

    ' create the M script to read the M file that will do the import
        M_Script = LoadTextFile(M_Source)

    ' insert the path
        M_Script = Replace(M_Script, "PATH_AND_NAME", """" & qSource & """") 

    ' insert the worksheet name
        If wksName <> "" Then M_Script = Replace(M_Script, "SHEET_NAME", """" & wksName & """")

下一步是加载查询。我使用technique described by Gil进行以下操作:

Dim qry As WorkbookQuery

If DoesQueryExist(qName) Then 
    ' Deleting the query 
    Set qry = ThisWorkbook.Queries(qName) 
    qry.Delete 
End If 

Set qry = w.queries.Add(qName, M_Script, qSource)

' We check if data should be loaded to Data Model 
shouldLoadToDataModel = ThisWorkbook.Worksheets(1).Cells(13, "D") 

' We check if data should be loaded to worksheet 
shouldLoadToWorksheet = ThisWorkbook.Worksheets(1).Cells(13, "E") 

If shouldLoadToWorksheet Then 
    ' We add a new worksheet with the same name as the Power Query query 
    Set currentSheet = Sheets.Add(After:=ActiveSheet) 
    currentSheet.Name = qName 

    If Not shouldLoadToDataModel Then 
        ' Let's load to worksheet only 
        LoadToWorksheetOnly qry, currentSheet 
    Else 
        ' Let's load to worksheet and Data Model 
        LoadToWorksheetAndModel qry, currentSheet 
    End If 
ElseIf shouldLoadToDataModel Then 
    ' No need to load to worksheet, only Data Model 
    LoadToDataModel qry 
End If 

Gil的代码允许将数据导入到数据模型或工作表中。 OP需要第二个,如果遵循该方法,则转换后的数据应出现在工作表中。

答案 2 :(得分:1)

这次对话有点晚了,但是我发现通过编辑Formula属性来在VBA中更新Power Query非常容易。

首先更新let..in公式。然后刷新使用它的连接

Dim pqFormula as String
pqFormula = "let..in"

Dim pqName as String
pqName = "<Name of the connection>"

' Update the formula for the specific power query.
ThisWorkbook.queries(pqName).Formula = pqFormula

' Refresh the connection
ThisWorkbook.Connections("Query - " & pqName).Refresh

该连接上的所有表都应立即更新。

此致