J'ai des données dans la feuille 1. Normalement, je vais dans Power query et fais mes transformations, puis ferme et charge dans une feuille existante 2.
Je souhaite automatiser cette opération à l'aide de VBA, où je peux simplement exécuter ma requête d'alimentation automatiquement et renseigner la transformation en feuille 2.
L'enregistreur de macros ne semble pas me permettre d'enregistrer les étapes. Et il n'y a pas beaucoup de choses en ligne à faire à ce sujet.
Essayer un code plus simple:
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
Voici mon problème lorsque vous essayez de charger manuellement une nouvelle feuille.
WIP:
Alors, comment écrire cela pour être suffisant? En bout de ligne, vous devez configurer votre requête à l'aide des outils intégrés, et non de VBA. Vous chargez vos données via la méthode appropriée (fichier, boucle de fichiers dans un dossier, Web, base de données, etc.). La liste s’allonge. Vous pouvez importer depuis des sources externes et charger depuis interne. Jetez un oeil ici pour plus d'informations sur le chargement à partir de sources externes.
Une fois que vous avez sécurisé votre source et que celle-ci est chargée, l'éditeur de requêtes vous permettra de réaliser votre transformation steps .
Le fait est que lorsque vous effectuez vos étapes à l'aide de l'interface utilisateur, le code M est écrit en arrière-plan et constitue la base d'une requête réutilisable, à condition de ne pas modifier le format ou l'emplacement de la source.
Dans votre cas, lorsque vous avez effectué vos étapes et que vous avez une requête comme vous le souhaitez, vous fermez et chargez dans sheet2.
A cette étape, lors de la première configuration, vous sélectionnerez la feuille 2 comme destination de fermeture et de chargement:
NB: Lorsque vous sélectionnez une feuille existante, assurez-vous que la feuille 2 existe déjà et que vous pouvez modifier manuellement la feuille Sheet2! devant la plage suggérée.
Vous rencontrez des problèmes parce que vous essayez de recréer tout cela avec du code.
Ne pas Configurez-le à l'aide de l'interface utilisateur et chargez-le dans sheet2. A partir de là, ouvrez l'éditeur de requête pour modifier les étapes et/ou actualisez la requête pour charger la feuille2 existante avec de nouvelles données/actualisées.
Certaines des méthodes disponibles pour actualiser votre requête:
La requête sera actualisée par VBA/Actualisation manuelle de la feuille dans laquelle elle réside (Feuille2), ou du classeur lui-même, par ex. Sheet2.Calculate
, ThisWorkbook.RefreshAll
, en appuyant manuellement sur le bouton d'actualisation du classeur dans l'onglet Données (ce sont toutes vraiment excessives)
Méthodes plus ciblées:
VBA pour la table de requête de la feuille 2:
ThisWorkbook.Worksheets("Sheet2").ListObjects(1).QueryTable.Refresh BackgroundQuery:=False
Changez ce qui précède pour le tableau approprié, etc.
Cliquez avec le bouton droit de la souris sur la table de requête et sélectionnez Actualiser:
Cliquez sur le bouton d'actualisation dans la fenêtre de requêtes du classeur à droite de la requête en question (icône avec des flèches vertes)
Le Ken Pulls moyen VBA (édition mineure de moi)
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
Vous ne devriez pas vraiment avoir besoin de faire tout ce travail via VBA. Vous pouvez avoir certaines manipulations de données délicates que vous vous sentez plus à l'aise avec VBA, puis un accès PowerQuery qui traite les données comme source. Vous pouvez déclencher la totalité du lot en ayant un sous-programme qui appelle la routine de traitement puis utilise l'une des méthodes de commande VBA répertoriées ci-dessus. Il y a plus de méthodes et je les ajouterai quand j'ai plus de temps.
Calculs:
Si vos calculs dépendent de la sortie PowerQuery, vous avez 4 options immédiates évidentes:
Je suis en désaccord avec la prémisse de la réponse ci-dessus; VBA convient parfaitement à l’automatisation de PowerQuery et est particulièrement efficace pour les travaux répétitifs. L'astuce consiste à créer d'abord la requête dont vous avez besoin dans PowerQuery, puis à utiliser l'éditeur avancé pour capturer le M.. Copiez-le et stockez-le, soit dans une cellule du classeur, soit dans un fichier texte séparé.
La méthode est décrite en détail par Gil Raviv. Pour plus de commodité, je stocke mon M dans des fichiers texte au lieu du classeur et le charge avec:
Function LoadTextFile(FullFileName As String) As String
With CreateObject("Scripting.FileSystemObject")
LoadTextFile = .OpenTextFile(FullFileName, 1).readall
End With
End Function
L'avantage des fichiers texte est qu'ils sont indépendants d'Excel et peuvent être réutilisés par de nombreux classeurs.
Voici quelques 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"
Une fois chargé dans VBA (à partir d'un classeur ou d'un fichier texte), le M peut être modifié dans VBA, par exemple en substituant des mots de substitution, ou en utilisant les noms de commande M pour localiser et modifier les lignes si nécessaire, par exemple.
' 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 & """")
L'étape suivante consiste à charger la requête. Je le fais en utilisant le technique décrite par Gil comme suit:
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
Le code de Gil permet d'importer des données dans le modèle de données ou dans une feuille de calcul. Le PO nécessite le second et si la méthode est suivie, les données transformées doivent apparaître dans la feuille de calcul.