Formules en VBA pour tableau structuré

bonjour;

dans les trois premières colonnes de la feuille 'dexp' j'ai decortiqué à la lumière des définition des codes en feuille 'param' le code qui est en colonne Tag de la feuille data,

comme mon vrai fichier comporte des milliers de lignes je galère pour copier en glissant les formules; je cherche alors à faire ces formules en vba

exemple pour le site: si le code est en 14 caractère alors soustraire le nom du site comme ceci (parfois le code est 15 caractère comme c le cas des dernières lignes)

25data-exp.zip (455.84 Ko)
=SIERREUR(SI(NBCAR(TAB_DATAfx[@Tag])=14;INDEX(TAB_ville_site;EQUIV(STXT(TAB_DATAfx[Tag];1;9);TAB_ville_site[VILLE.SIT_C];0);3);INDEX(TAB_ville_site;EQUIV(STXT(TAB_DATAfx[Tag];1;10);TAB_ville_site[VILLE.SIT_C];0);3));"")

comment faire ça en vba??

merci d'avance

Bonjour,

Vous positionner sur la cellule contenant la formule.

Basculer dans l'éditeur VBA, faire apparaitre la fenêtre exécution avec Ctrl-G

Dans la fenêtre exécution, taper la formule ?ActiveCell.Formula

La formule va être traduite en VBA. Il restera à doubler les "", là où ils apparaissent.

Bonjour Eric, Kamel,

je propose ceci, cette macro met la ville, le site et la mesure dans une plage à côté de votre tableau (ou on pouvait aussi l'ajouter au tableau).

Sub Kamel()
     Dim LO, cVille, cMes, cSite, aA, aOut, i, sp, x, s

     Set LO = Sheets("data").Range("A1").ListObject     'tableau de vos données
     Set cVille = Sheets("param").ListObjects("TAB_Ville").DataBodyRange     'plage du tableau de vos villes
     Set cMes = Sheets("param").ListObjects("TAB_Mes").DataBodyRange     'plage du tableau de vos mesures
     Set cSite = Sheets("param").ListObjects("TAB_ville_site").DataBodyRange     'plage du tableau de vos sites

     aA = LO.DataBodyRange.Columns(1).Value2     'lire 1ière colonne de vos données
     ReDim aOut(1 To UBound(aA), 1 To 3)     'preparer un tableau avec le même nombre de lignes et 3 colonnes

     On Error Resume Next
     For i = 1 To UBound(aA)                 'boucler vos données
          sp = Split(aA(i, 1), ".")          'diviser sur le "."
          aOut(i, 1) = WorksheetFunction.VLookup(sp(0), cVille, 2, 0)     'rechercher la ville
          aOut(i, 2) = WorksheetFunction.VLookup(sp(0) & "." & sp(1), cSite, 3, 0)     'rechercher le site
          aOut(i, 3) = Application.WorksheetFunction.VLookup(sp(2), cMes, 2, 0)     'rechercher la mesure
          If Err.Number <> 0 Then s = s & ", " & i: Err.Clear
     Next
     On Error GoTo 0

     LO.DataBodyRange.Offset(, 10).Resize(, 3).Value = aOut     'coller les résultats à côté du tableau initial
     If Len(s) Then MsgBox Mid(s, 3), vbInformation, "lignes avec des erreurs"

End Sub

Bonjour,
Une approche Power Query.
Cdlt.

26data-exp.zip (383.24 Ko)

Bonjour Eric Kergresse, Bart et Jean-Eric

Ce matin j'ai eu juste le temps de tester la petite astuce de traduction de Eric Kergrese, et c'est utile !

Bart et Jean Eric je vais examiner vos propositions dès que j'aurais un peu de temps libre merci à tous pour l’intérêt accordé.

Je vous tiens au courant.

@tt

Bonjour à tous

comme mon vrai fichier comporte des milliers de lignes je galère pour copier en glissant les formules; je cherche alors à faire ces formules en vba

Un double clic sur la poignée de recopie de la cellule suffit à recopier jusqu'en bas

Inutile de coder pour cela !

Re bonsoir ;

@ Jean-Eric ta méthode fonctionne, j jeté un coup d’œil sur les étapes , je suppose qu’elle utilise la même approche que la macro de Bart sauf qu’en power query, mais pour moi qui a le défaut de ne pas avoir un « bon appétit » pour les méthodes power query, pourtant puissantes, je la garde pour y revenir au besoin. Merci.


@ Bart est -il possible de me donner quelques éclaircissements :

1 / pour étendre le tableau et inclure les autres colonnes (day , heure , valeur) si possible tout sur une autre feuille

J essayé aOut(i, 4) = aA(i, 1).Offset(, 1) mais c une grave erreur

Comment écrire aOut(i, 4) en fonction de la colonne N°2 du tableau (l’équivalant de la formule « = TAB_DATAfx[@d] »

2/

Set LO = Sheets("data").Range("A1").ListObject 
: tu dis que c le tableau de mes données donc c’est ’’TAB_DATAfx’’ ?

Je vois que c une curieuse façon de se référer à ce tableau !

3/

aA = LO.DataBodyRange.Columns(1).Value2
: pourquoi Value2 ?

4/

sp = Split(aA(i, 1), ".")
: pourquoi aA qui est à une dimension devient aA(i, 1) ?

Cordialement

Bonsoir 78chris exemple dans ce classeur feuille 'f2' : je double clic sur la croix noir en bas à droite de A2 : rien !

23test1.xlsx (36.38 Ko)

re,

nouvelle version

27data-exp.zip (594.69 Ko)

les dates (et currency/monnaie) se lisent mieux avec Value2. Il faut ajouter des colonnes avec Redim et "preserve". On peut aussi assigner un tableau par une cellule de ce tableau

Sub Kamel()
     Dim LO, cVille, cMes, cSite, aA, i, sp, s, sh, MyColumns, iCol, LO2

     Set LO = Sheets("data").Range("A1").ListObject     'tableau de vos données = tableau avec cette cellule dans sa plage
     Set cVille = Sheets("param").ListObjects("TAB_Ville").DataBodyRange     'plage du tableau de vos villes
     Set cMes = Sheets("param").ListObjects("TAB_Mes").DataBodyRange     'plage du tableau de vos mesures
     Set cSite = Sheets("param").ListObjects("TAB_ville_site").DataBodyRange     'plage du tableau de vos sites

     aA = LO.Range.Value2                    'lire vos données & entêtes complètement (avec dates ou currency toujours Value2 (!))
     ReDim Preserve aA(1 To UBound(aA), 1 To UBound(aA, 2) + 3)     'ajouter 3 nouvelles colonnes vides, mais conserver le reste
     aA(1, UBound(aA, 2) - 2) = "Ville"      'première nouvelle colonne sera "ville" (entête)
     aA(1, UBound(aA, 2) - 1) = "Site"       '2ième nouvelle colonne sera "Site" (entête)
     aA(1, UBound(aA, 2)) = "Mesure"         'dernière nouvelle colonne ser "Mesure" (entête)

     On Error Resume Next                    'continuer en cas d'erreur, si par exemple, on ne trouve pas la ville, le site ou la mesure
     For i = 2 To UBound(aA)                 'boucler vos données sans les entêtes
          sp = Split(aA(i, 1), ".")          'diviser sur le "."
          aA(i, UBound(aA, 2) - 2) = WorksheetFunction.VLookup(sp(0), cVille, 2, 0)     'rechercher la ville
          aA(i, UBound(aA, 2) - 1) = WorksheetFunction.VLookup(sp(0) & "." & sp(1), cSite, 3, 0)     'rechercher le site
          aA(i, UBound(aA, 2)) = Application.WorksheetFunction.VLookup(sp(2), cMes, 2, 0)     'rechercher la mesure
          If Err.Number <> 0 Then s = s & ", " & i: Err.Clear     'on sauvegarde toutes les lignes avec des erreurs
     Next
     On Error GoTo 0

     Set sh = Sheets.Add(after:=Sheets(Sheets.Count))     'ajouter une nouvelle feuille
     MyColumns = Array(2, 3, 5, 6, 7, 4)     'supposons(!) qu'on veut cette séquence de colonnes, pas la séquence originale
     With sh.Range("A1").Resize(UBound(aA), UBound(MyColumns) + 1)     'plage pour nos données avec autant de colonnes
          For iCol = 0 To UBound(MyColumns)
               .Offset(, iCol).Resize(, 1).Value = Application.Index(aA, 0, MyColumns(iCol))
          Next
          .Columns(1).NumberFormat = "dd/mmm/yy"     'date
          .Columns(2).NumberFormat = "hh:mm:ss"     'heure
          .EntireColumn.AutoFit
          Set LO2 = .Parent.ListObjects.Add(Source:=.Offset(0))     'c'est un tableau maintenant
     End With

     If Len(s) Then MsgBox Mid(s, 3), vbInformation, "lignes avec des erreurs"

End Sub

Bonjour

Bonsoir 78chris exemple dans ce classeur feuille 'f2' : je double clic sur la croix noir en bas à droite de A2 : rien !

Pour que la poignée de recopie fonctionne il faut avoir une colonne déjà remplie à gauche ou à droite

Dans ton cas :

  1. sélectionner la valeur ou la formule et la copier
  2. taper dans la zone de nom l'adresse de dernière cellule: A5000 par exemple
  3. utiliser CTRL flèche haut puis coller

Pour 4 colonnes, on copie les 4 cellules et, entre l'étape 2 et 3, on sélectionne les 4 cellules de la ligne 5000

Bonjour; c résolu

@Bart ça marche

je reviens si je ne comprend pas quelque chose car mon but n'est pas seulement de résoudre mais de mieux comprendre.

@78chris ça marche aussi (théoriquement, tel que mon problème est posé, ta façon suffit, mais j'imagine qu'il y a des cas où il est mieux avec macro (Bart peut-être peut dire quelque chose?) )

Merci à tous

@tt

re,

@Bart : juste quelques explications : franchement j'ai du mal à comprendre le aA et sa manipulation:

UBound(aA, 2) = nb de colonnes ! existe-t-il UBound(aA, 3) ? par exemple?

aussi:

sh.Range("A1").Resize(UBound(aA), UBound(MyColumns) + 1).Offset(, iCol).Resize(, 1).Value = Application.Index(aA, 0, MyColumns(iCol))

dans index pourquoi le 0 (Row_num =0 ?)

et index ici s'applique d'un seul coup à toutes les lignes ?

@tt

re,

si aA a 3 dimensions, oui

Sub test()

     Dim aA(1 To 4, 2 To 5, 3 To 6)
     For i = 1 To 3
          MsgBox LBound(aA, i) & "   " & UBound(aA, i)     'lowerbound and upperbound
     Next

End Sub

ce 0 veut dire toutes les lignes (on peut aussi utiliser une sélection de lignes).

Rechercher des sujets similaires à "formules vba tableau structure"