Manipuler les tables en VBA
Les tables font partie de la collection Listobjects qui a été mise en place avec la version 2003. On peut donc utiliser les propriétés et méthodes de cette collection, et l'enregistreur de macros vous permet d'y accéder facilement.
Mais les tables sont aussi des objets range (dans 2007) et donc on a parfois le choix entre plusieurs écritures pour réaliser la même action.
L'avantage d'utiliser l'objet range c'est que le nom donné par excel à une table est unique dans le classeur et que du coup il n'est pas nécessaire de préciser la feuille. De ce fait, même si vous déplacez votre table sur une autre feuille, votre code VBA restera valide. Si vous copiez une feuille entière contenant des tables, excel renommera automatiquement les tables sur la copie pour éviter les doublons dans les noms.
Cependant certaines fonctions ne sont pas disponibles avec l'objet range. Lorsque l'on utilise la collection listobjects, il est en revanche nécessaire de préciser la feuille contenant l'objet.
Il y a certaines différences entre la manipulation des listes (excel 2003) ou des tables (excel 2007 et suivantes) par VBA. Nous ne parlerons ici que des codes se rapportant aux versions 2007 et suivantes. Ceux qui souhaitent des précisions sur la manipulation des listes excel 2003 en VBA trouveront plus d'informations sur le site de Jan Karel Pieterse qui m'a été fort utile pour écrire cette page.
Manipulation de tables existantes
Reprenons notre exemple des pages précédentes avec la table data_famille située sur la feuille data.

dans lequel dans la ligne total nous avons la somme de la colonne, sauf pour 'courses_pax' (montant des courses par personne) et 'visites_pax' pour lesquelles figurent la moyenne de la colonne.
Déterminer si une cellule fait partie d'une table
Sub Appartenance()
If ActiveCell.ListObject Is Nothing Then
MsgBox "cette cellule n'appartient pas à une table"
Else
MsgBox ("cette cellule fait partie de la table " & ActiveCell.ListObject.Name)
End If
End SubPour compter les différents éléments de la table
Nombre de lignes (sans les entêtes et totaux) :
MsgBox (Range("data_famille").Rows.Count)Nombre de colonnes (sans les entêtes et totaux) :
MsgBox (Range("data_famille").columns.Count)Récupérer l'adresse de la table :
msgbox(range("data_famille").address)Si vous avez besoin de l'adresse de l'ensemble de la table utilisez cette syntaxe:
MsgBox (Sheets("data").ListObjects("data_famille").Range.Address)Sélectionner différents éléments de la table
| Pour sélectionner | le code : |
|---|---|
| Une colonne entière sans les entêtes ou totaux | range("data_famille[courses]").select |
| Une colonne entière avec les entêtes et totaux | range("data_famille[#ALL],[courses]]").select |
| Toute la table sauf les entêtes et totaux | range("data_famille[#ALL]").select |
| La ligne 5 | range("A5:G5").select ce qui impose de faire référence aux numéros de ligne ou de colonne, ou sinon,en utilisant la collection listobjects With Sheets("data") .ListObjects("data_famille").ListRows(4).Range.Select End With |
| La dernière ligne | With Sheets("data") .ListObjects("data_famille").ListRows(range("data_famille").rows.count).Range.Select End With |
Ajouter une ligne
Ajouter une ligne de total automatique et choisir les opérations à y effectuer
Sub AjouterTotal()
With Sheets("data").ListObjects("data_famille")
.ShowTotals = True
.ListColumns("nb personnes").TotalsCalculation = xlTotalsCalculationSum
.ListColumns("courses").TotalsCalculation = xlTotalsCalculationSum
.ListColumns("visites").TotalsCalculation = xlTotalsCalculationSum
.ListColumns("courses_pax").TotalsCalculation = xlTotalsCalculationAverage
.ListColumns("visites_pax").TotalsCalculation = xlTotalsCalculationAverage
.ListColumns("total dépenses").TotalsCalculation = xlTotalsCalculationSum
End With
End SubPour ajouter une ligne sous la dernière ligne de la table :
Dim LR as ListRows
Set LR = Range("data_famille[#Totals]").ListObject.ListRows.Add(AlwaysInsert:=True)
Il faut noter que si la table contient une ligne de totaux, la nouvelle ligne est insérée au dessus de celle-ci.
Insertion en haut de la table :
Range("data_famille").ListObject.ListRows.Add (1)Ajouter une ligne en 4° position :
Range("data_famille").ListObject.ListRows.Add Position:=4
ou
Range("data_famille").ListObject.ListRows.Add (4)
On peut ensuite ajouter des données dans la nouvelle ligne comme dans l'exemple ci-dessous.
Modification de la table en utilisant un formulaire pour la saisie des données
Ce premier formulaire va ajouter une famille et entrer les données correspondantes dans la table.

En cliquant sur le bouton OK, on ajoute une ligne à notre table, au dessus de la ligne des totaux puis on entre les données dans la nouvelle ligne ainsi créée.
Private Sub CmdOK_Click()
Dim LR As ListRow
Range("data_famille[#Totals]").Select 'pas besoin de préciser le nom de la feuille
Set LR = Selection.ListObject.ListRows.Add(AlwaysInsert:=True)
LR.Range.Cells(1, 1) = TxtNom
LR.Range.Cells(1, 2) = CInt(TxtNbPersonnes)
LR.Range.Cells(1, 3) = CSng(TxtCourses)
LR.Range.Cells(1, 4) = CSng(TxtVisites)
Unload UsfNewFamille
End SuBoucler sur plusieurs tables
With Worksheets("data") 'pas obligatoire, on peut boucler sur l'ensemble des tables
'd'un classeur si on ne précise pas la feuille
For Each tablo In .ListObjects
TN = tablo.Name
.Range(TN & "[#Totals]").Select
Set LR = Selection.ListObject.ListRows.Add(AlwaysInsert:=True)
LR.Range.Cells(1, 1) = TxtFamille
Next
End With
Boucler sur les cellules d'une colonne
Sub BouclerColonne()
Dim MaListe As ListObject
Dim cel As Range
Set MaListe = Sheets("data").ListObjects("data_famille")
For Each cel In MaListe.DataBodyRange.Columns(1).Cells
MsgBox cel.Address & " : " & CStr(cel.Value)
Next cel
End Sub
Trier et filtrer une table
Avec la version 2007 sont apparues de nouvelles possiblités pour trier et filtrer des plages de données. On peut bien sur les utiliser pour les tables. L'enregistreur des macro vous permettra d'accéder aux différentes possiblités facilement.
Voici par exemple comment trier la table sur la colonne "nb personnes" et cacher les lignes correspondant aux familles d'une seule personne :
Sub TrierEtFiltrer()
With Worksheets("data").ListObjects("data_famille")
.Sort.SortFields.Clear
.Sort.SortFields.Add Key:=Range("data_famille[[#Headers],[#Data],[nb personnes]]"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With .Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End WithCréer et annuler la création d'une table
Créer une table à partir d'une plage de données :
Sub CréerTable()
ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A$7:$F$16"), , xlYes).Name = _
"data_famille"
Range("data_famille[#All]").Select
ActiveSheet.ListObjects("data_famille").TableStyle = "TableStyleMedium2 2"
End SubL'enregistreur de macro vous permettra d'explorer le formatage de la table en fonction de vos choix. Il n'y a rien de bien particulier.
Transformer une table en plage de données "classique" :
Sub déListe()
Sheets("data").ListObjects("data_famille").Unlist
End Sub
Mots clefs associés à cette page : vba, tableau, table
- Vous devez vous identifier ou créer un compte pour écrire des commentaires

Merci Misange pour cette page
Merci Misange pour cette page qui m'a été très utile.
J'en profite pour apporter mon p'tit caillou ;-) pour corriger une petite coquille en rapport avec le tableau placé sous "Sélectionner différents éléments de la table"
range("data_famille[#ALL]").select ==> TOUT le tableau (y compris les en-têtes et la ligne de total si elle existe)
range("data_famille[#DATA]").select ==> QUE les données du tableau
@+ peper-eliot