[API] Tout sur la variable tableau / table mémoire (array)
- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
[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.
***
- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
Déclaration des tableaux
Code : Tout sélectionner
Dim oTableau(50) As StringL'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 LongSi 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
.
- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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 StringCode : 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.
- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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 SubIl 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- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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 SubFaites l'expérience en enlevant l'instruction Preserve, le tableau sera alors vidé des 5 premiers éléments.
- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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.")- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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) = bPour 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 JimCe 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.
- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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) ' BobAutre syntaxe possible en extrayant le sous-tableau :
Code : Tout sélectionner
    Dim oSsTab As Variant
    oSsTab = oTab(1)
    Msgbox oSsTab(1) ' ZoePour 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.
- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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.DataLe 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.
- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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 = oSelectOn voit qu'il est très simple de coller un tableau dès lors que la plage d'arrivée est dimensionnée correctement.
- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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 = oResOn 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.
- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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 = oRgpOn 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.
- 
				Bidouille
- Webmestre
- Messages : 534
- Enregistré le : lun. mai 21, 2007 2:08 pm
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 = oRgpNB : 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 1 invité