Aide sur Power Query
Bonjour,
Je rencontre un problème sur PowerQuery : lorsque j'importe des lignes avec conditions d'une autre feuille, j'aimerais qu'elles se sauvegardent or ce n'est pas le cas. En effet, lorsque la feuille source est modifiée, la feuille où j'importe est aussi modifiée. Par exemple, nous avons :
- Feuille Entrée (Source)
- Feuille B2, Psy, Méd (où j'importe à partir de la feuille Entrée)
- Conditions : Seules les lignes qui contiennent la lettre V aux colonnes "Tests" et "Avis CRE" sont importées.
Du coup j'actualise une fois : ça marche.
Mais étant donné que j'utilise une macro qui supprime les lignes comportant la lettre V aux colonnes "Tests" et "Avis CRE" dans la feuille Entrée, à la deuxième actualisation après avoir utilisé la macro, la feuille B2, Psy, Méd devient vide. Et il est là mon soucis, je voudrais uniquement importer des lignes avec une/des conditions en parcourant certaines colonnes d'une feuille à l'autre, mais je n'y arrive pas avec PowerQuery. Je mettrais en pièce jointe mon fichier (il faudra juste modifier la source pour les requêtes).
Je n'arrive pas à comprendre, ça fait une semaine que je bidouille Excel et à chaque fois je rencontre un problème c'est juste insupportable et je commence à perdre espoir avec ce logiciel. Si vous avez une alternative à PowerQuery, telle qu'une macro, ça ne me pose aucun soucis.
Merci aux personnes qui voudront m'aider, car je désespère vraiment.
Bonjour
PowerQuery effectue des requêtes : il est donc normal que l'actualisation restitue le dernier état, comme le fait aussi un TCD
Si tu veux garder les lignes il faut copier le résultat dans un onglet, sans lien avec la requête après chaque utilisation...
Bonjour
PowerQuery effectue des requêtes : il est donc normal que l'actualisation restitue le dernier état, comme le fait aussi un TCD
Si tu veux garder les lignes il faut copier le résultat dans un onglet, sans lien avec la requête après chaque utilisation...
Merci de ta réponse.
Le problème est que j'aimerais le faire pour plusieurs feuilles et d'automatiser la chose au maximum. Aurais-tu un modèle de code VBA qui puisse le faire sans PowerQuery ?
RE
Ton fichier joint pointe sur des fichiers externes donc on ne peux visualiser le déroulement.
Si le but est juste de récupérer les lignes contenant un simple filtre Entrée puis une copie des lignes filtrées suffit, inutile d'utiliser PowerQuery.
L'enregistreur de macros te donnera l’essentiel du code qu'on pourra t'aider à améliorer.
bonjour
salut Chris
ne vaut-il pas mieux faire une requête Power Query, puis éventuellement créer une courte macro (donc fiable) qui actualise la requête ?
certains le font pour les TCD
note : j'actualise TOUJOURS en manuel
comme Microsoft nous y incite (ils n'ont pas fourni l'automatisme, il y a une raison)
amitiés
Salut JMD
Là le demandeur veut en quelque sorte archiver des listes dont la source disparait donc qu'une requête ne peut retrouver.
Du coup un filtre suffit avant l'archivage...
re
d'où viennent les données d'origine ?
pourquoi sont-elles écrasées ? (c'est rarissime de nos jours où le prix des disques durs est si bas)
RE
Alors merci pour vos réponses. J'ai donc utiliser l'enregistreur de macro et en fouillant un peu sur Internet, j'ai réussi à assembler un truc fonctionnel mais pas opti et très redondant (c'est un bon début vu que je ne connais rien du langage VBA).
Si vous avez des questions par rapport au code, n'hésitez pas car je serais ravi de pouvoir l'optimiser même s'il n'est pas trop long à exécuter.
Bonjour
Pour le 1er cas
Dim rng As Range
Dim lastline As Long
'Pour sélectionner l'onglet
ThisWorkbook.Worksheets("Entrée").Activate
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=16, Criteria1:="V"
rng.AutoFilter Field:=18, Criteria1:="V"
lastline = Sheets("B2, Méd, Psy").Cells(Rows.Count, 1).End(xlUp).Row + 1
'Copier la sélection filtrée
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
rng.Copy Destination:=Sheets("B2, Méd, Psy").Cells(lastline, 1)
'Supprimer les lignes
rng.Rows.EntireRow.Delete
'Désactiver le filtre
ActiveSheet.ShowAllData
Tu peux refaire de même pour les autres feuilles en recommençant à Set rng=ActiveSheet.Range("A1").CurrentRegion
Bonjour
Pour le 1er cas
Dim rng As Range Dim lastline As Long 'Pour sélectionner l'onglet ThisWorkbook.Worksheets("Entrée").Activate Set rng = ActiveSheet.Range("A1").CurrentRegion rng.Select 'Filtrer la sélection rng.AutoFilter Field:=16, Criteria1:="V" rng.AutoFilter Field:=18, Criteria1:="V" lastline = Sheets("B2, Méd, Psy").Cells(Rows.Count, 1).End(xlUp).Row + 1 'Copier la sélection filtrée Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count) rng.Copy Destination:=Sheets("B2, Méd, Psy").Cells(lastline, 1) 'Supprimer les lignes rng.Rows.EntireRow.Delete 'Désactiver le filtre ActiveSheet.ShowAllData
Tu peux refaire de même pour les autres feuilles en recommençant à Set rng=ActiveSheet.Range("A1").CurrentRegion
J'obtiens une erreur :/.
J'ai réussi à optimiser mon code un peu et j'ai résolu un problème majeur. Cependant je bloque sur quelque chose de très simple : il me faudrait un moyen de sélectionner la première ligne vide dans une feuille spécifique et d'y coller ce que j'ai copié avec Selection.Copy. Il me manque que cette partie et après je ne vous embête plus c'est promis
Je mettrais le code en pièce jointe, et merci encore.
RE
J'obtiens une erreur :/.
Où ? Laquelle ?
Ce genre de commentaire n'apporte aucune piste.
Si tu n'as pas une ligne vide sous la ligne de titre cela fonctionne...
Je 'ai testé sur ton fichier dont j'ai rempli au moins une colonne de la ligne sous le titre et cela fonctionne
Je t'ai donné le moyen d'optimiser en ne changeant pas d'onglet à tout bout de champ puisque copy... destination évite cela...
Et même si tu gardes ton code, la réponse est dans celui que j'ai posté
Edit : En plus si tes onglets cibles sont sous forme de tableau structuré et respectent la règle (pas de ligne vide), il suffit, pour ajouter en fin de tableau, d'utiliser
With Worksheets("Nom onglet").Listobjects(1).Range.
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
RE
J'obtiens une erreur :/.
Où ? Laquelle ?
Ce genre de commentaire n'apporte aucune piste.
Si tu n'as pas une ligne vide sous la ligne de titre cela fonctionne...
Je 'ai testé sur ton fichier dont j'ai rempli au moins une colonne de la ligne sous le titre et cela fonctionne
Je t'ai donné le moyen d'optimiser en ne changeant pas d'onglet à tout bout de champ puisque copy... destination évite cela...
Et même si tu gardes ton code, la réponse est dans celui que j'ai posté
J'ai rien dis, ça marche parfaitement autant pour moi. Et c'est plus rapide merci. Par contre, je rencontre un soucis avec ton code que j'ai réussi à résoudre avec la condition de la feuille vide après le filtre (voir mon code).
En effet si je relance ton code une deuxième fois, il me copie colle ce qui reste dans la feuille Entrée après le premier run du code, ce que je ne veux pas faire car le code risque d’être lancé plusieurs fois.
EDIT : J'ai réussi à régler le soucis (voir le code ci joint)
Je rencontre encore un soucis et c'est celui la que je n'arrive pas à corriger. Lorsque j'applique le code pour deux colonnes différentes et que je copie colle vers une même feuille, il me supprime ce que j'ai collé au premier run.
Je te laisse voir dans le code en pièce jointe et le tester. Tu remarqueras qu'il copiera uniquement les lignes avec "NV" dans la colonne "Avis CRE", parce qu'il remplace les lignes avec "NV" dans la colonne Tests et car le code se finit par le traitement de la colonne Avis CRE.
Il me faudrait donc soit un moyen d'associer les deux avec un opérateur OU (j'aimerais éviter les filtres avancées parce que j'ai essayé et ça fait planté le code) ou bien de copier coller par la suite en sélectionnant la première colonne vide.
Merci encore pour ton aide c'est vraiment la dernière chose qui bloque à mon avis.
RE
Regarde mon edit du post précédent où on utilise les tableaux
Sub Test()
Dim rng As Range
Dim lastline As Long
'Pour sélectionner l'onglet
ThisWorkbook.Worksheets("Entrée").Activate
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=16, Criteria1:="V"
rng.AutoFilter Field:=18, Criteria1:="V"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
If rng.SpecialCells(xlCellTypeVisible).Cells.Count > 1 Then
'Copier la sélection filtrée
With Worksheets("B2, Méd, Psy").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes
rng.Rows.EntireRow.Delete
'Désactiver le filtre
End If
ActiveSheet.ShowAllData
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=16, Criteria1:="NV"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
If rng.SpecialCells(xlCellTypeVisible).Cells.Count > 1 Then
'Copier la sélection filtrée
With Worksheets("NV").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes
rng.Rows.EntireRow.Delete
End If
ActiveSheet.ShowAllData
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=18, Criteria1:="NV"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
If rng.SpecialCells(xlCellTypeVisible).Cells.Count > 1 Then
'Copier la sélection filtrée
With Worksheets("NV").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes
rng.Rows.EntireRow.Delete
End If
ActiveSheet.ShowAllData
End Sub
Re,
Je n'avais pas vu ton edit sorry.
Ça fonctionne à merveille merci, mais le problème que j'ai résolu vient de réapparaitre : lorsque je relance une deuxième fois le programme ne fonctionne pas (il fait n'importe quoi pour préciser). C'est peut-être le fait que mes données sont devenues en forme de tableau et que la ligne de code correspondant au test pour savoir si la feuille est vide ne fonctionne plus ? Je vais essayer de résoudre le problème.
Merci encore Chris
RE
Tu devrais avoir une erreur car ton test ne fonctionne pas (tableau ou pas) si tu lances 2 fois de suite
J'ai ajouté une variable Atraiter qui teste autrement : adapter selon le contexte
Sinon explique ce qui se passe
Sub Test()
Dim rng As Range
Dim lastline As Long
Dim Atraiter As Long
'Pour sélectionner l'onglet
ThisWorkbook.Worksheets("Entrée").Activate
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=16, Criteria1:="V"
rng.AutoFilter Field:=18, Criteria1:="V"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
Atraiter = Application.WorksheetFunction.Subtotal(103, Range(rng.Columns(16).Address))
If Atraiter > 0 Then
'Copier la sélection filtrée
With Worksheets("B2, Méd, Psy").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes
rng.Rows.EntireRow.Delete
'Désactiver le filtre
End If
ActiveSheet.ShowAllData
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=16, Criteria1:="NV"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
Atraiter = Application.WorksheetFunction.Subtotal(103, Range(rng.Columns(16).Address))
If Atraiter > 0 Then
'Copier la sélection filtrée
With Worksheets("NV").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes
rng.Rows.EntireRow.Delete
End If
ActiveSheet.ShowAllData
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=18, Criteria1:="NV"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
Atraiter = Application.WorksheetFunction.Subtotal(103, Range(rng.Columns(18).Address))
If Atraiter > 0 Then
'Copier la sélection filtrée
With Worksheets("NV").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes
rng.Rows.EntireRow.Delete
End If
ActiveSheet.ShowAllData
End Sub
Ça fonctionne à merveille !! Je vais terminer mon code avec ton modèle, en espérant que je ne rencontre pas un autre soucis. Si ce n'est pas le cas, je mettrais le sujet en résolu.
Mille merci encore Chris
Hé bien j'ai pas de chance (ou peut-être de mon incompétence) , je rencontre une erreur d’exécution "1004" : Erreur définie par l'application ou par l'objet.
C'est au niveau de cette ligne là : Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count) pour la feuille B2, Méd, Psy. Merci encore pour ton aide.
Sub Test()
Dim rng As Range
Dim lastline As Long
Dim Atraiter As Long
'Pour sélectionner l'onglet source
ThisWorkbook.Worksheets("Entrée").Activate
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=16, Criteria1:="V"
rng.AutoFilter Field:=18, Criteria1:="V"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
Atraiter = Application.WorksheetFunction.Subtotal(103, Range(rng.Columns(16).Address))
If Atraiter > 0 Then
'Copier la sélection filtrée vers la feuille cible
With Worksheets("B2, Méd, Psy").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes importées
rng.Rows.EntireRow.Delete
End If
'Désactiver le filtre
ActiveSheet.ShowAllData
'Pour sélectionner l'onglet source
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=16, Criteria1:="NV"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
Atraiter = Application.WorksheetFunction.Subtotal(103, Range(rng.Columns(16).Address))
If Atraiter > 0 Then
'Copier la sélection filtrée vers la feuille cible
With Worksheets("NV").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes importées
rng.Rows.EntireRow.Delete
End If
'Désactiver le filtre
ActiveSheet.ShowAllData
'Pour sélectionner l'onglet source
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=18, Criteria1:="NV"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
Atraiter = Application.WorksheetFunction.Subtotal(103, Range(rng.Columns(16).Address))
If Atraiter > 0 Then
'Copier la sélection filtrée vers la feuille cible
With Worksheets("NV").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes importées
rng.Rows.EntireRow.Delete
End If
'Désactiver le filtre
ActiveSheet.ShowAllData
'Pour sélectionner l'onglet source
ThisWorkbook.Worksheets("B2, Méd, Psy").Activate
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=24, Criteria1:="V"
rng.AutoFilter Field:=25, Criteria1:="V"
rng.AutoFilter Field:=26, Criteria1:="V"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count) [b][u]------> ICI [/u][/b]
Atraiter = Application.WorksheetFunction.Subtotal(103, Range(rng.Columns(16).Address))
If Atraiter > 0 Then
'Copier la sélection filtrée vers la feuille cible
With Worksheets("V").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes importées
rng.Rows.EntireRow.Delete
End If
'Désactiver le filtre
ActiveSheet.ShowAllData
'Pour sélectionner l'onglet source
ThisWorkbook.Worksheets("B2, Méd, Psy").Activate
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=24, Criteria1:="NV"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
Atraiter = Application.WorksheetFunction.Subtotal(103, Range(rng.Columns(16).Address))
If Atraiter > 0 Then
'Copier la sélection filtrée vers la feuille cible
With Worksheets("NV").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes importées
rng.Rows.EntireRow.Delete
End If
'Désactiver le filtre
ActiveSheet.ShowAllData
'Pour sélectionner l'onglet source
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=25, Criteria1:="NV"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
Atraiter = Application.WorksheetFunction.Subtotal(103, Range(rng.Columns(16).Address))
If Atraiter > 0 Then
'Copier la sélection filtrée vers la feuille cible
With Worksheets("NV").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes importées
rng.Rows.EntireRow.Delete
End If
'Désactiver le filtre
ActiveSheet.ShowAllData
'Pour sélectionner l'onglet source
Set rng = ActiveSheet.Range("A1").CurrentRegion
rng.Select
'Filtrer la sélection
rng.AutoFilter Field:=26, Criteria1:="NV"
'Tester si la feuille est vide
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1, rng.Columns.Count)
Atraiter = Application.WorksheetFunction.Subtotal(103, Range(rng.Columns(16).Address))
If Atraiter > 0 Then
'Copier la sélection filtrée vers la feuille cible
With Worksheets("NV").ListObjects(1)
.ListRows.Add
y = .ListRows.Count
rng.Copy Destination:=.ListColumns(1).DataBodyRange.Cells(y, 1)
End With
'Supprimer les lignes importées
rng.Rows.EntireRow.Delete
End If
'Désactiver le filtre
ActiveSheet.ShowAllData
End Sub
Hé bien j'ai rien dis, il marche parfaitement. Merci encore Chris ! Sans toi je pense que je n'aurais jamais réussi ! J
re
Utilise le mode débug
met un point d'arrêt sur la ligne "rng.Select" avant le PB et vérifie l'adresse de rng (mettre un espion rng.address)
Si rng est totalement vide de données, on ne peut resizer car sa hauteur est 1 et donc 0 e marche pas
A noter que pour tester ici ATraiter doit se référer à l'une des colonne de filtre et non 16 (j'avais préciser la nécessité d'adapter au contexte)
Mais de façon générale si tu filtres des Tableaux structurés il faudrait un code adapté aux tableaux et plus utiliser ActiveSheet.Range("A1").CurrentRegion
Le plus simple serait donc de mettre le 1er tableau aussi en tableau structuré pour tout gérer de même...