[API] Tout sur la variable tableau / table mémoire (array)
[API] Tout sur la variable tableau / table mémoire (array)
Dans d'autres langages, on peut aussi les dénommer par table mémoire.
On les appelle comme cela car elles sont exactement représentées comme dans une feuille de calcul. L'accès se fait donc par un indice qui correspond à la ligne ou la colonne.
La vitesse d'exécution d'une variable tableau est beaucoup plus rapide que dans une feuille sous Calc.
Cela vient du fait que tout se passe en mémoire vive (RAM). Cela varie de la puissance de la machine mais on peut parler d'un facteur de 1 à 10.
Dès lors, faire des tris, du filtrage ou des recherches sera beaucoup plus rapide en passant par une variable tableau.
En revanche, il ne s'agit que de la transposition des données uniquement (chaîne ou nombre). Vous ne pouvez pas accéder à d'autres informations comme la mise en forme de la cellule ou la formule qu'elle contient. Si vous cherchez à récupérer cela, utilisez zBasic qui propose des fonctions en français très simples.
***
Déclaration des tableaux
Code : Tout sélectionner
Dim oTableau(50) As String
L'instruction Dim permet de dimensionner en mémoire la variable oTableau de 51 chaînes.
Pourquoi 51 ? Parce que l'index démarre à zéro.
Si vous voulez un tableau de 50 lignes, il suffit de déclarer 49 en valeur.
On peut aussi caractériser la variable avec d'autres types de données.
Code : Tout sélectionner
Dim oVal(9) As Long
Si vous ne passez aucun type, Basic déclarera votre tableau avec du Variant. C'est une variable passe-partout qui peut contenir n'importe quel type de donnée.
Simplification de déclaration
On peut aussi simplifier en "typant" la variable directement. Ainsi :
Code : Tout sélectionner
Dim oTableau$(50)
D'autres typages existent :
- % pour typer en entier
- & pour typer en entier long
- @ pour typer en monétaire
- etc
.
Décalage de l'index d'un tableau
Cela peut s'avérer pratique pour rendre compatible certaines données dont l'accès à un chiffre précis est nécessaire.
Ainsi la syntaxe suivante :
Code : Tout sélectionner
Dim oMois(1 To 12) As String
Code : Tout sélectionner
oMois(1) = "Janvier"
oMois(2) = "Février"
...
oMois(12) = "Décembre"
Les cas sont cependant peu nombreux, il est toujours préférable d'avoir un index à zéro.
L'option de déclaration Base
Rappelons que par défaut, le premier élément d'un tableau est l'élément 0.
Mais avec la ligne Option Base 1, le premier élément par défaut devient l'élément 1
Cette option est fortement déconseillé si vous voulez rester pleinement compatible avec l'extérieur.
Connaître les dimensions et parcourir
Un message "index out of bounds" se traduisant par un "index hors des limites" s'affichera.
Cela arrive souvent lorsque le tableau n'a pas été créé par vous et qu'il est renvoyé par un objet que vous interrogez.
Il faut donc connaître les dimensions du tableau avant d'en attaquer le contenu.
Deux instructions permettent de retourner l'index le plus petit et le plus grand.
LBound renvoie la valeur inférieure du tableau et UBound la valeur supérieure.
Ainsi, il est facile de parcourir un tableau pour le lire ou pour écrire dedans :
Code : Tout sélectionner
Sub ParcoursTableau
Dim a(10)
For i = LBound(a) To UBound(a)
a(i) = i
Next i
End Sub
Il est possible également de parcourir un tableau avec l'instruction Each ... In :
Code : Tout sélectionner
oTab = Array(1,2,3)
For Each elem In oTab
Msgbox elem
Next elem
Retailler un tableau
Cela peut être pratique si sa taille a été sous estimée au départ où que vous ne connaissez pas la taille finale de la table mémoire.
Mais attention, car Redim vide le contenu du tableau.
Si vous voulez conserver les valeurs, ajouter l'option Preserve.
Petit exemple :
Code : Tout sélectionner
Sub RetailleTableau()
' Création du tableau avec 5 éléments
Dim a(5)
For i = LBound(a) To UBound(a)
a(i) = i
Next i
' Retaillons le tableau à 10 éléments
ReDim Preserve a(1 To 10) ' anciennes valeurs préservées
For i = 6 To UBound(a)
a(i) = i
Next i
End Sub
Faites l'expérience en enlevant l'instruction Preserve, le tableau sera alors vidé des 5 premiers éléments.
Remplir un tableau
Ainsi :
Code : Tout sélectionner
a = Array(3, 4, 5, 6, 7, 8, 36, 10, 37, 38, 39, 14)
Autre exemple en reprenant notre tableau de mois pour le remplir avec Array :
Code : Tout sélectionner
Dim oMois(1 To 12) As String
oMois = Array("Jan.", "Fév.", "Mars", "Avr.", "Mai", _
"Juin", "Jui.", "Août", "Sep.", "Oct.", "Nov.", "Déc.")
Tableau plus complexe
Pour reprendre notre comparaison avec une feuille du tableur, nous n'avions jusqu'à présent qu'une seule colonne.
Un tableau peut bien sûr avoir plusieurs colonnes et plusieurs lignes.
Exemple avec cette forme :
Retranscription en Basic :
Code : Tout sélectionner
Dim Client(0 To 1)
a = Array(1, 2, 3, 4, 5)
b = Array("Tom", "Max", "Jim", "Joe", "Bob")
Client(0) = a
Client(1) = b
Pour obtenir les données, on indique les coordonnées colonne/ligne :
Code : Tout sélectionner
msgbox Client(0)(2) 'Renvoie 3
msgbox Client(1)(2) 'Renvoie Jim
Ce principe est identique avec le module Base lorsque vous exécutez une requête SQL. Cette dernière vous renvoie un tableau du même genre.
Tableau de tableaux
En déclarant le tableau principal comme "variable", les sous-tableaux sont imbriqués les uns à la suite des autres.
Code : Tout sélectionner
Dim oTab as variant
oTab = array( _
array("Max", "Joe", "Mel"),_
array("Lea", "Zoe", "Jim"),_
array("Wil", "Ron", "Tom"),_
array("Lou", "Bob", "Don"))
Pour récupérer une valeur :
Code : Tout sélectionner
Msgbox oTab(0)(2) ' Mel
Msgbox oTab(3)(1) ' Bob
Autre syntaxe possible en extrayant le sous-tableau :
Code : Tout sélectionner
Dim oSsTab As Variant
oSsTab = oTab(1)
Msgbox oSsTab(1) ' Zoe
Pour ce type de tableaux imbriqués, il n'existe pas de déclaration directe. Il faut passer par une boucle pour déclarer les sous-tableaux avec l'instruction DimArray.
Ainsi pour notre exemple, nous aurons le code suivant :
Code : Tout sélectionner
Dim oTab(0 To 3) as variant
For i = 0 to 3
oTab(i) = DimArray(2)
Next i
.
Récupérer une sélection dans une feuille
Dans une macro, il est possible en une ligne de récupérer cette sélection :
Code : Tout sélectionner
oSelect = ThisComponent.CurrentSelection.Data()
La variable récupérée sera sous la forme d'un tableau indexé de 0 à 2 et représentant les 3 lignes.
Puis de 3 sous-tableaux indexé de 0 à 3 représentant cette fois, les 4 colonnes.
Nous en revenons donc à l'accès sous cette forme :
Code : Tout sélectionner
msgbox oSelect (0)(1) ' va afficher 21
msgbox oSelect (2)(0) ' va afficher 13
Récupérer une plage dans une feuille
Classeur > Feuille > Plage > Données
Ce qui nous donne :
Code : Tout sélectionner
oDoc = ThisComponent ' Le classeur
oFeuil = oDoc.Sheets(0) ' La 1ere feuille qui est indexée à 0
oPlage = oFeuil.getCellRangeByName("A1:D3")
oSelect = oPlage.Data
Le tableau oSelect se manipule de la même façon que précédemment.
NB : si les données sont sous forme de texte, il est préférable d'utiliser la propriété DataArray.
Envoyer le contenu du tableau sur une feuille
Code : Tout sélectionner
oDoc = ThisComponent ' Le classeur
oFeuil = oDoc.Sheets(1) ' La 2e feuille
oPlage = oFeuil.getCellRangeByName("A1:D3")
oPlage.Data = oSelect
On voit qu'il est très simple de coller un tableau dès lors que la plage d'arrivée est dimensionnée correctement.
Ne copier qu'une ligne sur deux
Code : Tout sélectionner
oDoc = ThisComponent ' Le classeur
oFeuil = oDoc.Sheets(0) ' La 1ere feuille qui est indexée à 0
oPlage = oFeuil.getCellRangeByName("A1:G5")
oTab = oPlage.Data()
oRes = array(oTab(0),oTab(2),oTab(4))
oPlage = oFeuil.getCellRangeByName("A12:G14")
oPlage.Data() = oRes()
Pour ce 2e exemple, nous avons un nombre de lignes beaucoup plus important :
Code : Tout sélectionner
sPlage = "A1:C33"
oDoc = ThisComponent ' Le classeur
oFeuil = oDoc.Sheets(0) ' La 1ere feuille qui est indexée à 0
oPlage = oFeuil.getCellRangeByName(sPlage)
oTab = oPlage.Data
for i = LBound(oTab) To UBound(oTab)
Redim Preserve oRes(0 To i)
oRes(i) = oTab(j)
j = j+2
if j > UBound(oTab) then exit for
Next i
oFeuil = oDoc.Sheets(1) ' La 2e feuille
i = UBound(oRes)
j = UBound(oRes(i))
oPlage = oFeuil.getCellRangeByPosition(0,0,j,i)
oPlage.Data = oRes
On privilégiera cette fois, un getCellRangeByPosition pour déterminer la taille du nouveau tableau.
C'est beaucoup plus simple puisque l'on peut intégrer directement les informations de dimension pour la plage de destination.
Transposition
Elle est obtenue en échangeant les lignes et les colonnes :
Le code suivant fait la transposition du tableau A1:C2 en A1:B3 :
Code : Tout sélectionner
sPlage = "A1:C2"
oDoc = ThisComponent ' Le classeur
oFeuil = oDoc.Sheets(0) ' La 1ere feuille qui est indexée à 0
oPlage = oFeuil.getCellRangeByName(sPlage)
oTab = oPlage.Data
' Déclaration du tableau transposé
m = UBound(oTab)
n = UBound(oTab(0))
Dim oRes(n)
For i = 0 to n
oRes(i) = dimArray(m)
Next i
' Transposition
For i = 0 to m
For j = 0 to n
oRes(j)(i) = oTab(i)(j)
Next j
Next i
' Affichage du tableau transposé
oFeuil = oDoc.Sheets(1) ' La 2e feuille
oPlage = oFeuil.getCellRangeByPosition(0,0,m,n)
oPlage.Data = oRes
Regroupement
Attention : le tableau doit être trié sur la 1ere colonne.
Code : Tout sélectionner
sPlage = "A1:B9"
oDoc = ThisComponent ' Le classeur
oFeuil = oDoc.Sheets(0) ' La 1ere feuille qui est indexée à 0
oPlage = oFeuil.getCellRangeByName(sPlage)
oTab = oPlage.DataArray
' Déclaration du tableau de regroupement
m = UBound(oTab) ' valeur maximum
Dim oRgp(0 To m) as variant
For l = 0 to m
oRgp(l) = DimArray(1)
Next l
While i <= Ubound(oTab)
oRgp(k)(0) = oTab(i)(0)
For j = i to m
if (oRgp(k)(0) = oTab(j)(0)) then
oRgp(k)(1) = oRgp(k)(1) & oTab(j)(1) & " "
else
exit for
endif
Next
k = k + 1
i = j
Wend
Redim Preserve oRgp(0 To k-1) ' Réduction du tableau
oFeuil = oDoc.Sheets(1) ' La 2e feuille
i = UBound(oRgp)
j = UBound(oRgp(i))
oPlage = oFeuil.getCellRangeByPosition(0,0,j,i)
oPlage.DataArray = oRgp
On crée au départ un tableau de sortie aussi grand que celui en entrée.
Une fois le regroupement fait, on le redimensionne avant de le réintégrer dans la feuille.
NB : on rappelle que les données texte doivent être gérées avec la propriété DataArray.
Regroupement (II)
Code : Tout sélectionner
sPlage = "A1:B12"
oDoc = ThisComponent ' Le classeur
oFeuil = oDoc.Sheets(0) ' La 1ere feuille qui est indexée à 0
oPlage = oFeuil.getCellRangeByName(sPlage)
oTab = oPlage.DataArray
' Déclaration du tableau de regroupement
m = UBound(oTab) ' valeur maximum
Dim oRgp(0 To m) as variant
For o = 0 to m
oRgp(o) = DimArray(m)
Next o
While i <= Ubound(oTab)
l = 1
oRgp(k)(0) = oTab(i)(0)
' Complete le sous-tableau à vide
For j = 1 to m
oRgp(k)(j) = ""
Next j
For j = i to m
if (oRgp(k)(0) = oTab(j)(0)) then
oRgp(k)(l) = oTab(j)(1)
l = l + 1
else
exit for
endif
Next
k = k + 1
i = j
Wend
Redim Preserve oRgp(0 To k-1)
oFeuil = oDoc.Sheets(1) ' La 2e feuille
i = UBound(oRgp)
j = UBound(oRgp(i))
oPlage = oFeuil.getCellRangeByPosition(0,0,j,i)
oPlage.DataArray = oRgp
NB : laisser un tableau avec un contenu vide donne une erreur #N/D lors du transfert sur la feuille.
Qui est en ligne
Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 2 invités