[Python 3] Extraire chaque mot d’une chaine de caractères

Ce second article consacré au langage Python s’adresse aux lecteurs ayant déjà quelques notions de base du langage; je m’efforcerai, néanmoins, de simplifier et d’expliquer au maximum chaque ligne de code. Pour ceux qui ne souhaitent pas s’embarrasser des explications, le script final se trouve à la fin de l’article.

Nous allons voir, ici, comment manipuler les « strings » (chaines de caractères – cdc) afin d’extraire chaque « mot » ( chaque groupe de caractères que nous appellerons ainsi par commodité) d’une cdc et l’enregistrer dans une « liste » (variable pouvant contenir plusieurs valeurs).

Prenons une cdc quelconque constituée de mots et enregistrons la dans une variable que nous appellerons cdc :

cdc = "A8zx 7r:t i 23.54 <i1 q+2N"

C’est autour des espaces que nous allons articuler notre travail puisque, ce sont finalement, eux qui définissent nos mots.

Commençons donc par compter le nombre d’espaces dans notre cdc :

esp = cdc.count(" ")

Que nous dit cette ligne ?
Dans notre variable cdc, autrement dit dans notre chaine : A8zx 7r:t i 23.54 , compte (.count) le nombre d’espaces (« ») et enregistre ce nombre dans la variable esp

Voyons ce que nous obtenons :

cdc = "A8zx 7r:t i 23.54 <i1 q+2N"
esp = cdc.count(" ")
print(esp)

Résultat : 5

Nous avons, effectivement 5 espaces dans notre cdc.
Il va maintenant s’agir de déterminer le début et la fin de chaque mot…
Nous allons le faire en identifiant les index (l’index correspond, ici, au numéro de chaque caractère dans notre cdc, le premier caractère de notre chaine ayant 0 pour index; le second, 1; le troisième, 2 etc..) de la première lettre de notre mot et de l’espace qui le termine.

Puisque, pour chaque mot, nos index vont changer, nous allons donc utiliser des variables pour identifier, pour chaque mot, l’index du début et celui de fin.
Soit deb l’index de début et fin l’index de fin.
L’index du premier caractère du premier mot de notre cdc correspond au premier caractère de notre cdc, il prend donc la valeur 0 :

deb = 0

Pour déterminer l’index du premier espace, nous utilisons un code très proche de celui que nous avons écrit pour compter le nombre d’espaces dans notre cdc :

fin = cdc.index(" ")

Nous avons remplacé la fonction count() par la fonction index(), qui détermine l’index de la première occurrence de la chaine se trouvant entre ses parenthèses, autrement dit, dans notre cas, l’espace.
Faisons un petit test :

cdc = "A8zx 7r:t i 23.54 <i1 q+2N"
fin = cdc.index(" ")
print(fin)

4

Le premier espace de notre cdc a 4 pour numéro d’index et se trouve en 5e position.

Il nous faut maintenant créer notre « liste », cette variable particulière qui va accueillir chaque mot de notre cdc. Il nous suffit de nommer notre variable, appelons la maListe par exemple, et de la faire suivre de = []; Python sait ainsi qu’il sagit d’une liste, vide pour l’instant.

maListe = []

Récapitulons : notre premier mot commence avec l’index 0 enregistré dans la variable deb et se termine par l’index 4 de notre premier espace, enregistré dans la variable fin.
Faisons un essai en extrayant le premier mot de notre chaine contenue dans la variable cdc.
Pour faire l’extraction, il suffit de faire suivre la notre cdc de [index du début:index de fin] soit :
A8zx 7r:t i 23.54 [0:4]

Contrôlons :

print("A8zx 7r:t i 23.54 <i1 q+2N"[0:4])

A8zx

Rendons notre code plus lisible et plus adapté à notre projet en remplaçant toutes nos valeurs absolues par des variables :

cdc[deb:fin]

Et puisque nous voulons enregistrer chaque mot dans notre liste pour, éventuellement, pouvoir le rappeler par la suite, nous allons modifier le code comme ceci :

maListe.append(cdc[deb:fin])

Ici, la fonction append() permet d’enregistrer un nouvel élément (l’extraction de notre mot, contenu dans entre les parenthèses) à notre liste maListe.
Bon, voilà pour le principe… maintenant, puisque nous avons plusieurs mots, il va falloir répéter ce principe autant de fois qu’on a de mots par l’intermédiaire d’une boucle.
Tout d’abord, nous allons déterminer le nombre de fois que l’on va répéter l’opération.
Dans notre cas de figure, nous avons 6 mots séparés par 5 espaces… En règle générale, nous aurons un mot de plus que d’espaces, on peut donc dire que notre nombre de mots est égal à notre variable esp + 1. Ecrivons donc notre boucle :

for i in range(0, esp + 1):

Qu’est ce que cela signifie ? traduisons mot à mot…

for : pour
i : i est notre compteur qui s’incrémente à chaque tour de la boucle
in : dans
range : champ
(0, esp + 1) : 0, 6
les 2 points : terminent la ligne et annoncent l(es)’instruction(s) à répéter.

Autrement dit, pour chaque valeur de i (i = 0, i = 1, i = 2…. i = 5; i est bien répété 6 fois entre sa valeur 0 et sa valeur 5 !!!), accomplir la tache d’extraction du mot et l’enregistrer dans la liste maListe.

Affichons les élements de notre liste maListe, à l’aide de la fonction print(),et voyons à quoi ressemble son contenu maintenant :

cdc = "A8zx 7r:t i 23.54 <i1 q+2N"

esp = cdc.count(" ")
deb = 0
fin = cdc.index(" ")
maListe = []

for i in range(0, esp + 1):
    maListe.append(cdc[deb:fin])
    print(maListe)

Avant de commenter le résultat, retenons qu’en langage Python, l’intentation (tabulation) a une importance capitale qui contribue à la lisibilité du code : toutes les actions qui doivent être répétées dans la boucle sont écrites en retrait d’une tabulation par rapport à la ligne qui initie notre boucle.

A8zx
A8zx A8zx
A8zx A8zx A8zx
A8zx A8zx A8zx A8zx
A8zx A8zx A8zx A8zx A8zx
A8zx A8zx A8zx A8zx A8zx A8zx

Bon, ce n’est pas encore le résultat espéré mais c’est plutôt encourageant : nous avons 6 lignes qui correspondent aux 6 répétitions de notre boucle, autrement dit, aux 6 mots contenus dans notre cdc; et à chaque nouvelle boucle, nous avons un mot qui s’ajoute aux précédents. Notre boucle fonctionne donc correctement, il va maintenant falloir lui faire extraire chaque mot de la cdc, et non pas répéter le premier mot uniquement.

Comment extraire le second mot ? Pourquoi ne pas amputer notre variable cdc du premier mot et recommencer notre routine ? Remplaçons notre variable cdc par sa nouvelle valeur :

cdc = cdc[fin+1:]

fin+1 (soit l’index 5 à ce niveau de l’opération) correspond à l’index du caractère qui suit notre premier espace (rappelons que la variable fin enregistre l’index de l’espace) donc il s’agit du caractère 7 de notre cdc.
La suite du code entre les crochets ne contient que :, autrement dit, puisqu’on ne spécifie pas l’index de fin, Python enregistre le reste de la cdc jusqu’au dernier caractère.
Contrôlons notre ligne de code :

cdc = "A8zx 7r:t i 23.54 <i1 q+2N"

esp = cdc.count(" ")
deb = 0
fin = cdc.index(" ")
maListe = []

for i in range(0, esp + 1):
    maListe.append(cdc[deb:fin])
    cdc=cdc[fin+1:]
    print(cdc)

7r:t i 23.54 i 23.54 54 1 q+2N
i 23.54
54
1 q+2N
N

Notre premier mot a disparu de notre variable cdc, c’est ce que nous voulions !
Le second mot de la cdc originelle est maintenant devenu le premier.
La boucle ne calcule plus que 5 lignes, ce qui est conforme à nos attentes… les autres lignes sont amputées, à chaque fois, par notre instruction cdc=cdc[fin+1:], qui modifie notre variable cdc.
Tout est normal.
Afin d’extraire notre nouveau « premier » mot, il va falloir recalculer sa variable fin; il s’agit juste de répéter la ligne fin = cdc.index(« »), dans notre boucle… afin que le calcul se refasse automatiquement pour chaque nouveau mot.
Testons :

cdc = "A8zx 7r:t i 23.54 <i1 q+2N"

esp = cdc.count(" ")
deb = 0
fin = cdc.index(" ")
maListe = []

for i in range(0, esp + 1):
    maListe.append(cdc[deb:fin])
    cdc=cdc[fin+1:]
    fin = cdc.index(" ")
    print(cdc)

ERREUR !!!

L’erreur était prévisible, à un moment donné, puisque notre dernier mot n’est pas suivi d’espace.
Python affiche donc un message d’erreur. Comment contourner le problème ? Avec une simple astuce : nous allons vérifier, à chaque fois que notre variable cdc est amputée d’un mot, qu’elle contient toujours au moins un espace et c’est notre fonction cdc.count(« ») qui va nous aider. Nous allons instruire Python au travers d’une « condition »; ajoutons les lignes suivantes à notre code :

    if cdc.count(" ")!=0:
        fin = cdc.index(" ")
    else:
        fin = len(cdc)

Vous noterez, tout d’abord, qu’encore une fois, nous indentons notre code selon le même principe que précédemment, avec notre boucle.
if : si
cdc.count(« ») : nombre d’espaces dans la variable cdc
!= : signifie littéralement différent, autrement dit, si le nombre d’espaces dans la variable cdc est différent de 0, donc tant qu’il y a des espaces, on recalcule la variable fin.
else: : sinon (s’il n’y a plus d’espace)
len(cdc) : len est l’abréaviation de length en anglais, autrement dit, la longueur. Ici, on entend le nombre total de caractères (restant à) de notre variable cdc. Cette information jouera le rôle d’index et définira le dernier caractère de notre dernier mot.

Revoyons la globalité de notre code en respectant l’indentation :

cdc = "A8zx 7r:t i 23.54 <i1 q+2N"

esp = cdc.count(" ")
deb = 0
fin = cdc.index(" ")
maListe = []

for i in range(0, esp + 1):
    maListe.append(cdc[deb:fin])
    cdc=cdc[fin+1:]
    if cdc.count(" ")!=0:
        fin = cdc.index(" ")
    else:
        fin = len(cdc)

et faisons un contrôle, cette fois ci, en bonne et due forme.
Nous allons contrôler toutes les valeurs enregistrées par notre variable maListe.
On appelle chacune d’entre elles par leur numéro d’index.
Dans ce cas précis, l’index ne sera plus la position du caractère dans la cdc mais la position de chaque mot dans la variable maListe.

for j in range(len(maListe)):
    print(maListe[j])

La première ligne incrémente la valeur j de 0 (sous entendu puisque non précisé) à len(maListe), c’est à dire ici le nombre d’éléments contenus dans maListe.
Autrement dit, pour chaque valeur contenue dans maListe à partir de 0, incrémente, à chaque fois j de 1 (
première valeur contenue dans maListe – A8zx – j = 0
deuxième valeur contenue dans maListe – 7r:t – j = 1
etc… ).
la seconde affiche l’élément de maListe dont l’index vaut j
Voici notre code :

cdc = "A8zx 7r:t i 23.54 <i1 q+2N"

esp = cdc.count(" ")
deb = 0
fin = cdc.index(" ")
maListe = []

for i in range(0, esp + 1):
    maListe.append(cdc[deb:fin])
    cdc=cdc[fin+1:]
    if cdc.count(" ")!=0:
        fin = cdc.index(" ")
    else:
        fin = len(cdc)

for j in range(len(maListe)):
    print(maListe[j])

A8zx
7r:t
i
23.54
<i1
q+2N

Tout semble marcher parfaitement, sauf que…
si nous changeons la valeur de notre variable cdc et lui attribuons une cdc sans espace

cdc = "q+2N"

notre programme va planter ! Puisque le programme ne trouve pas d’espace dans la cdc…
Pour cela nous allons légèrement modifier le début de notre script et notre variable fin en copiant-collant les lignes suivantes :

if cdc.count(" ")!=0:
    fin = cdc.index(" ")
else:
    fin = len(cdc)

à la place de :

fin = len(cdc)

voici, à présent, notre code qui fonctionne, quel que soit l’état de notre variable cdc:

maChaine = cdc = "A8zx 7r:t i 23.54 <i1 q+2N"

esp = cdc.count(" ")
deb = 0
if cdc.count(" ")!=0:
    fin = cdc.index(" ")
else:
    fin = len(cdc)
maListe = []

for i in range(0, esp + 1):
    maListe.append(cdc[deb:fin])
    cdc=cdc[fin+1:]
    if cdc.count(" ")!=0:
        fin = cdc.index(" ")
    else:
        fin = len(cdc)

for j in range(len(maListe)):
    print(maListe[j])

Avez vous remarqué que j’ai légèrement modifié la ligne de code contenant ma cdc ?

maChaine = cdc = "A8zx 7r:t i 23.54 <i1 q+2N"

A force d’amputer la variable cdc pour extraire chacun des mots, il ne reste plus de caractère dans ma variable cdc à la fin de mon opération.
En ajoutant maChaine, je conserve ainsi une copie exacte de la chaine initiale.

Nous avons maintenant un code qui marche mais qui ne plaira pas aux puristes :
notre condition

    if cdc.count(" ")!=0:
        fin = cdc.index(" ")
    else:
        fin = len(cdc)

est répétée 2 fois ! même si un simple copier-coller fait l’affaire, le code est lourd… le but du est de le rendre le plus lisible (plus simple ?!) possible… Pour cela, nous allons faire appel à une « fonction ». Le principe d’une fonction est le suivant : on lui envoie des données (ou pas), elle les traite et renvoie un résultat. Ici, nous allons envoyer la variable cdc pour que notre fonction vérifie si elle contient des espaces ou non.
Nous allons rédiger notre fonction en tout début de script.
Chaque fonction commence par la commande def, suivie du nom de la fonction suivie de parenthèses et de :
Nous appellerons notre fonction controle

def controle(zz):

Ici, nous avons inséré une variable, zz, entre les parenthèses de notre fonction afin de lui signifier que nous allons lui envoyer des informations lorsque nous l’appellerons, en l’occurrence, la variable cdc.

def controle(zz):

    if zz.count(" ")!=0:
        return zz.index(" ")
    else:
        return len(zz)

Encore une fois, l’indentation est extrêment importante, ici aussi; l’occulter conduira fatalement à une erreur de traitement.
Cette fonction ressemble sensiblement au code que nous utilisions auparavant pour déterminer la valeur de notre variable fin, à la différence que la variable cdc devient zz et que l’on intègre la commande return à la place de notre variable fin.
La variable cdc est donc remplacée par zz qui représente, dans notre fonction, la valeur qui sera traitée par la fonction.
La commande return se charge ensuite de renvoyer à la variable fin de notre programme principal, le résultat de son traitement.

Il ne nous reste plus qu’à appeler notre fonction depuis notre programme principal en remplaçant, à chaque fois, cettte condition

if cdc.count(" ")!=0:
    fin = cdc.index(" ")
else:
    fin = len(cdc)

par

fin = controle(cdc)

Nous appelons la fonction par son nom. Entre parenthèses, nous lui adressons la variable qui doit être traitée; ensuite la commande return renvoie le résultat du traitement de notre fonction qui est enregistré dans la variable fin.

Voici le code final de notre projet :

def controle(zz):

    if zz.count(" ")!=0:
        return zz.index(" ")
    else:
        return len(zz)

maChaine = cdc = "A8zx 7r:t i 23.54 <i1 q+2N"

esp = cdc.count(" ")
deb = 0
fin = controle(cdc)
maListe = []

for i in range(0, esp + 1):
    maListe.append(cdc[deb:fin])
    cdc=cdc[fin+1:]

    fin = controle(cdc)

for j in range(len(maListe)):
    print(maListe[j])

A8zx
7r:t
i
23.54
<i1
q+2N

Voilà petit exercice qui nous a permis d’aborder certaines des techniques de base en programmation : variables, boucles, conditions, fonctions… gardons, néanmoins, en mémoire que l’on peut souvent améliorer un script comme c’est le cas ici !

Voici un autre script qui donne exactement le même résultat, en utilisant, la fonction split() qui sépare le contenu d’une cdc…

cdc = "A8zx 7r:t i 23.54 <i1 q+2N"
maListe = cdc.split(" ") # la fonction split sépare et enregistre chaque mot de notre cdc dans la liste maListe 

for i in maListe # boucle d'affichage du contenu de la liste maListe
    print(i)

A8zx
7r:t
i
23.54
<i1
q+2N

Voici une autre méthode qui utilise le principe des « listes en intention » pour l’affichage, que je n’aborderai pas ici, et qui présente le même résultat en rendant ce code encore plus minimaliste :

maListe = "A8zx 7r:t i 23.54 <i1 q+2N".split(" ")
[print(i) for i in maListe]

On pourrait encore réduire cet algorithme jusqu’à le faire tenir sur une simple ligne :

[print(i) for i in "A8zx 7r:t i 23.54 <i1 q+2N".split(" ")]

je ne recommande, cependant, pas de contracter un code à l’extrême, car il devient plus difficile à lire et à maintenir par la suite.

Pour terminer, je vous soumets l’écriture, qui selon moi, est la mieux optimisée puique :

  •  nous conservons notre chaine dans sa globalité dans la variable cdc.
  • nous enregistrons efficacement chaque mot dans notre liste maListe en une seule ligne de code.
  • nous affichons le résultat de notre opération d’extraction avec une écriture qui tient sur une seule ligne également.
cdc = "A8zx 7r:t i 23.54 <i1 q+2N"
maListe = cdc.split(" ")
[print(i) for i in maListe]

[Python 3] Affichage : la fonction print()

Ce premier article consacré au langage Python s’attachera à énumérer  les méthodes d’utilisation de la fonction print(); celle-ci permet l’affichage à l’écran des résultats d’une opération effectuée par le programme : il peut s’agir d’une chaine de caractères (cdc), du résultat d’un calcul arithmétique, etc… .

Dans la nouvelle version de Python (Python 3),  print() s’écrit toujours en minuscules et est systématiquement suivi de parenthèses qui renferment l’information à afficher. En règle générale, l’expression contenue entre les parenthèses est :

  1.  Toujours encadrée par des guillemets lorsqu’elle contient des caractères alphabétiques ou des signes autres que des nombres et les opérateurs .(virgule de la décimale qui est un point en Python) + – * /
  2. Encadrée par des guillemets lorsqu’une cdc numérique est considérée comme étant du texte (on n’attend pas le résultat d’un calcul).
  3. Jamais encadrée de guillemets lorsqu’il s’agit de variables (pour lesquelles nous consacrerons un chapitre).
    • affichage d’une cdc
      (le résultat de l’opération sera toujours présenté à la suite du code et sera affiché en violet.)
print("Bonjour")

Résultat : Bonjour

    • affichage d’un nombre
print(-1.5)

-1.5

  • calcul
print(32+7*2)

46

    • variable
      Outil très utilisé en informatique; la variable se charge de stocker une valeur qui pourra changer en cours de route. Ici, nous avons nommé notre variable maVar et lui avons successivement attribuée les valeurs 8, puis 125 puis Marie. En règle générale, une variable doit d’abord être déclarée (on doit lui affecter une valeur, même nulle) avant de pouvoir être utilisée.
maVar=8 #je déclare ma variable 
print(maVar)# je peux maintenant l'utiliser

8

maVar=125
print(maVar)

125

maVar="Marie"
print(maVar)

Marie

REMARQUES :

  1. Le signe # entame un commentaire utile au programmeur mais qui sera ignoré par Python.
  2. Les cdc contenant des caractères alphabétiques sont enregistrées avec des guillemets dans la variable alors que les nombres en sont, ici, exempts.
    • calcul de 2 variables
aa=3
bb=7
print(aa+bb)

10

    • variable de type string (c’est à dire : cdc) intégrée à un texte par des virgules (,)
      On encadre chaque bribe de texte avec des guillemets et on insère nos variables à l’aide de virgules.
monNom="Pierre"

print("Je m'appelle",monNom)
print(monNom,"est parti.")
print("Je m'appelle",monNom,"et j'habite à Paris.")

maSlt="Bonsoir,"
maVille="Lyon"
monAge=25

print(maSlt,"je m'appelle",monNom,", j'habite",maVille,"et j'ai",monAge,"ans.")

Je m’appelle Pierre
Pierre est parti.
Je m’appelle Pierre et j’habite à Paris.
Bonsoir, je m’appelle Pierre , j’habite Lyon et j’ai 25 ans.

REMARQUES :

  1. La virgule crée automatiquement un espace entre le texte et la valeur de la variable.
  2. Une variable n’est précédée d’une virgule que lorsque qu’elle suit un texte et est suivie d’une virgule que si elle précède un texte.
    • variable de type string (c’est à dire : cdc) intégrée à un texte par le signe plus (+)
      On encadre chaque bribe de texte avec des guillemets et on insère nos variables à l’aide du signe plus.

(si la dernière ligne du code ci-dessous n’apparait pas dans sa totalité sur votre écran, cliquez sur le code et maintenez le clic tout en dirigeant la souris vers la gauche.)

monNom="Pierre"

print("Je m'appelle"+monNom)
print(monNom+" est parti.")
print("Je m'appelle"+monNom+"et j'habite à Paris.")

maSlt="Bonsoir,"
maVille="Lyon"
monAge=25

print(maSlt+" je m'appelle "+monNom+", j'habite "+maVille+" et j'ai "+str(monAge)+" ans.")

Je m’appellePierre
Pierre est parti.
Je m’appellePierreet j’habite à Paris.
Bonsoir, je m’appelle Pierre, j’habite Lyon et j’ai 25 ans.

REMARQUES :

  1. Le signe plus ne crée pas automatiquement un espace entre le texte et la valeur de la variable, comme nous le montrent les exemples ci-dessus; il faut, si nécessaire, ajouter l’espace dans le texte qui précède ou qui suit la variable.
  2. La variable monAge, dans le dernier exemple, est incluse dans la fonction str() : il existe plusieurs types de variables (string pour les cdc, integer pour les nombres entiers, float pour les nombres décimaux etc…). Ici, il faut considérer que le signe plus « additionne » des données, or Python n’additionne que des données du même type. str() convertit le nombre entier 25 en une chaine alphanumérique de type texte, autrement dit 25 devient « 25 » et l’addition de cdc devient ainsi possible. Cette notion sera développée dans l’article consacré aux variables.
  3. Il est possible d’utiliser les 2 types de signes dans la même fonction print() pour concaténer (réunir) textes et variables, comme le montre l’exemple ci-dessous :
monObjet ="voiture"
print("La",monObjet+" est rouge.")

La voiture est rouge.

    • fonction format()
      Cette fonction bien pratique s’affranchit des contraintes des guillemets et des signes de concaténation. La fonction format() est introduite par un point juste après le guillemet de fin et encadre l’ensemble des variables utilisées dans le texte. Chaque variable est intégrée aux texte par des accolades et le numéro de l’accolade correspond à l’ordre dans lequel la variable apparait dans la fonction format().
print("{0} a eu {1} ans. On a fêté les {1} ans de {0}." .format("Pierre", 25))

Pierre a eu 25 ans. On a fêté les 25 ans de Pierre.

REMARQUE :

Le numéro de la première accolade est toujours 0

    • concaténation avec le signe %
      Proche de la fonction format(), cette méthode introduit chaque variable dans le texte par le signe % suivi d’une lettre indiquant le type de la variable :
      %s : cdc
      %d : nombre entier
      %f : nombre décimal
      %.Xf : X désignant un nombre entier indiquant le nombre de décimales après la virgule.
      Le signe % derrière le guillemet de fermeture introduit la valeur de chaque variable dans l’ordre d’apparition respectif dans le texte.
monA=12
monB=35.6
monC="abcd"
monD=7.8251896
print("A=%d, B=%f, D=%.3f, C=%s et Z=%f // A=%d " %(monA,monB,monD,monC,483,monA))

A=12, B=35.600000, D=7.825, C=abcd et Z=483.000000 // A=12

Affichage d’une liste (la liste est une variable particulière qui permet d’enregistrer plusieurs valeurs).

maListe=[1,3,5,7,9]
print("ma Liste : %s " %(maListe))

[0, 1, 2, 3, 4]

    • affichage des caractères spéciaux avec le signe : \
      Le signe \ désactive la fonction spéciale de certains caractères spéciaux comme les guillemets et permet ainsi de les afficher dans la fonction print().
print("le mot \"table\" apparait entre guillemets")
print("le mot \\table\\ apparait entre backslashes")

le mot « table » apparait entre guillemets
le mot \table\ apparait entre backslashes

    • le saut de ligne : \n
      La combinaison suivante : \n permet d’effectuer un saut de ligne dans une fonction print().
print("Pierre prend le train \n pour se rendre à Paris.")

Pierre prend le train
pour se rendre à Paris.

    • les tabulations : \t
      La combinaison : \t permet de créer des tabulations dans une fonction print().
aaName="Pierre"
aaDate="01/01/1985"
aaSS="1 85 01 75 136 242 - 34"
print("Name : \t\t\t\t\t%s\nDate de naissance : \t%s\nNuméro de SS : \t\t\t%s"%(aaName, aaDate,aaSS))
#Name : 	            Pierre
#Date de naissance : 	01/01/1985
#Numéro de SS :         1 85 01 75 136 242 - 34

Voici le rendu de la tabulation sur PyCharm (cliquez sur l’image pour l’agrandir) :

Screen Shot 2015-05-19 at 17.05.26

    •  remplacer le saut de ligne de la fonction print()  avec la commande end
      Placé à la fin de la fonction print(), la commande end remplace le retour chariot programmé par défaut. Cette méthode est effective avec les boucles que nous aborderons aussi dans un prochain article. Pour l’exemple, voici une boucle à laquelle nous demandons de répéter 4 fois la fonction print(). Ainsi, au lieu d’afficher 4 fois ok en passant à la ligne à chaque fois, le saut de ligne est, ici remplacé par un espace.
for a in range(4):
    print("ok", end= " ")

ok ok ok ok

    • remplacer la virgule (l’espace) de concaténation avec la commande sep
aa="Jean"
print("Bonjour",aa,".", sep="!¡")

Bonjour!¡Jean!¡.

[VBA] La variable « Dictionnaire »

Outre sa rapidité, le « Dictionnaire » est une variable particulière qui a pour fonction de gérer les doublons.
Il intervient dans une grande variété de cas de figures et fait partie des outils indispensables à maîtriser lorsqu’on travaille avec des bases de données.
Le dictionnaire est une variable qui va enregistrer une série de « clés » (Key) uniques; chaque clé composant le dictionnaire est accompagnée d’un « élément » (Item), dont la valeur est modifiable.

Dans l’exemple ci-dessous, qui va préciser l’utilité et le fonctionnement du dictionnaire, nous souhaitons calculer le montant total des factures pour chaque client, sachant que la première facture donne automatiquement lieu à une réduction de 10%.

Dictionnary

Option Base 1
Sub test()
'Dans la fenêtre VBA, sélectionner Outils, Références et cocher Microsoft Scripting Runtime
Dim Dico As Object
Dim c As Byte
Dim ii As Variant, jj As Variant
Set Dico = CreateObject("scripting.dictionary")

c = 2
Do Until IsEmpty(Cells(c, 1))
If Not Dico.exists(Cells(c, 1).Value) Then
    Dico(Cells(c, 1).Value) = 0.9 * Cells(c, 3)
Else
    Dico(Cells(c, 1).Value) = Dico(Cells(c, 1).Value) + Cells(c, 3)
End If
c = c + 1
Loop

Range("E1").Resize(Dico.Count, 1) = Application.Transpose(Dico.keys)
Range("F1").Resize(Dico.Count, 1) = Application.Transpose(Dico.items)

Range("G1") = Application.Index(Dico.keys, 3)
Range("H1") = Application.Index(Dico.items, 3)

ii = Dico.keys
jj = Dico.items

Range("I1") = ii(3)
Range("J1") = jj(3)

Set Dico = Nothing: Erase ii: Erase jj
End Sub

Explications

Nous allons, en premier lieu, nous rendre dans la fenêtre VBA, sélectionner Outils, Références et cocher Microsoft Scripting Runtime : nous venons d’accéder à une « librairie » qui nous permet d’avoir des fonctionnalités supplémentaires.

La première étape consiste à créer un « objet » : nous commençons par déclarer la variable que nous nommons Dico Dim Dico As Object; nous créons, ensuite, l’objet Dico Set Dico = CreateObject("scripting.filesystemobject").

A partir d’une boucle classique, nous allons ensuite enregistrer chaque nouveau client de la colonne A dans le dictionnaire. la condition If Not Dico.exists(Cells(c, 1).Value) Then vérifie si la valeur de notre cellule existe déjà dans le dictionnaire ou pas. Son utilisation est très simple; le nom de l’objet créé (Dico) est suivi de la commande .exists et de la valeur à vérifier (Cells(c, 1).Value). Il est préférable de préciser que l’on cherche à enregistrer la valeur (Value) de la cellule (Cells(c,1)) afin que le dictionnaire ne la confonde pas avec la plage de la même cellule.
Cette condition que nous venons de mettre en place n’est, en général, pas nécessaire mais elle est utile dans notre cas de figure.

La commande suivante mérite quelques explications : Dico(Cells(c, 1).Value) = 0.9 * Cells(c, 3). Cela veut dire que si la valeur de notre cellule en colonne A apprait pour la première fois (donc la condition évoquée par la ligne de code précédente) alors la valeur de la cellule de la colonne C correspondante doit être enregistrée à 90% de sa valeur (0.9 * Cells(c, 3)).
Nous devons maintenant comprendre les informations que nous avons de part et d’autre de notre signe =
La partie de gauche Dico(Cells(c, 1).Value) est la clé.
La clé est une valeur unique (pour la première ligne de notre tableau, notre clé = CLient 1), c’est à dire qui ne sera enregistrée qu’une seule fois et qui fait office de « case variable » dans laquelle nous allons enregistrer la valeur de la facture en colonne C -10%.
Autrement dit, notre variable Client 1 a une valeur de 0.9 * 100 donc Client 1 (Key) = 90 (Item)
Pareil, pour la deuxième ligne de notre tableau : Client 15 (Key) = 99 (Item)
etc…
Le principe est exactement le même que celui ou c=c+1 : à gauche, la variable et à droite, le calcul reprenant l’ancienne valeur de cette même variable et l’actualisant; c’est ce qui se passe lorsque notre condition n’est plus vérifiée, autrement dit si notre Key existe déjà, dans la ligne suivante : Dico(Cells(c, 1).Value) = Dico(Cells(c, 1).Value) + Cells(c, 3).

Reprenons l’exemple de notre premier client : Client 1 = 90
Lorsque la boucle va, à nouveau, rencontrer la valeur Client 1 dans notre tableau, en ligne N° 15, alors Client 1 = Client 1 + 230, autrement dit Client 1 = 90 + 230, donc Client 1 (Key) = 320 (Item).

Nous transposons ensuite les résultats de notre dictionnaire dans sur la feuille Excel.
Range("E1").Resize(Dico.Count, 1) = Application.Transpose(Dico.keys)
Range("F1").Resize(Dico.Count, 1) = Application.Transpose(Dico.items)

La transposition se fait ici en deux étapes, la première concernant les Keys et la seconde, les Item.
Voir l’article suivant pour de plus amples détails concernant la transposition.
La seule différence avec une transposition de variable tableau, est que la commande Ubound est remplacée par Dico.Count qui a exactement la même fonction et qui compte le nombre d’éléments que contient le dictionnaire.

On peut également extraire une valeur unique, Key ou Item : nous disposons de deux outils pour cela.
La première consiste à identifier la valeur voulue à partir de son index, c’est à dire son rang dans la série d’éléments de même nature à laquelle elle appartient.
Range("G1") = Application.Index(Dico.keys, 3)
Range("H1") = Application.Index(Dico.items, 3)

La seconde méthode que l’on rencontre consiste à enregistrer l’ensemble des Key dans une variable et l’ensemble des Items, dans une autre.
ii = Dico.keys
jj = Dico.items

L’extraction se fait ensuite selon le même principe, même si la syntaxe est différente; on va redemander le N° d’index de la valeur à extraire; à noter qu’ici l’Option Base 1 ne fonctionne pas et que la première valeur est la valeur N° 0.

Range("I1") = ii(3)
Range("J1") = jj(3)

Il ne nous reste plus qu’à libérer la mémoire de nos variables :
Set Dico = Nothing: Erase ii: Erase jj

Ci-dessous le fichier au format .xls contenant les exemples de cet article.
Dictionnaire

[VBA] Boostez la vitesse d’exécution de vos macros en utilisant les « variables Tableau » 3/3

Retranscrire les données d’une variable sur la feuille Excel

Le dernier article de cette série s’attachera à retranscrire les données contenues dans une variable sur la feuille Excel.
Ce sujet a déjà été partiellement abordé dans les articles précédents à des fins d’exemples; nous allons maintenant étudier en détail les mécanismes de cette fonction.

Reprenons l’exemple de l’article précédent

Plage VT

Supposons que nous devions recopier ce tableau à partir de la cellule E1.
Une méthode consiste à enregistrer le tableau dans une variable nommée aa puis à recopier chaque valeur contenue dans la variable par l’intermédiaire de boucles entrelacées.

Option Base 1
Sub Boucle()
Dim aa As Variant
aa = Range("A1").CurrentRegion

For a = LBound(aa) To UBound(aa)
    For b = LBound(aa, 2) To UBound(aa, 2)
        Cells(a, b + 4) = aa(a, b)
    Next b
Next a
End Sub

La première boucle For a = LBound(aa) To UBound(aa) traite chaque ligne du tableau enregistré dans notre variable et le seconde, For b = LBound(aa, 2) To UBound(aa, 2), chaque colonne de chaque ligne.
Cette macro recopie le tableau, cellule par cellule; la méthode reste chronophage.

La seconde méthode enregistre le tableau dans la variable aa et retranscrit la variable immédiatement dans la feuille Excel.

Option Base 1
Sub Boucle2()
Dim aa As Variant, Tablo() As Variant
Dim c As Byte
aa = Range("A1").CurrentRegion

Range("E1").Resize(UBound(aa, 1), UBound(aa, 2)) = aa
End Sub

Il est nécessaire de définir avec précision les dimensions de la plage qui va accueillir les valeurs du tableau.
Nous savons que la commande Ubound(aa,1) nous permet de définir le nombre total de lignes de la variable et que le nombre total de colonnes est obtenu grâce à la commande Ubound(aa,2).
Il suffit donc de redimensionner la cellule E1 par le nombre de lignes et par le nombre de colonnes pour définir la plage d’accueil Range("E1").Resize(UBound(aa, 1), UBound(aa, 2)) et de coller l’information avec =aa.

Il est parfois nécessaire d’inverser le sens lignes/colonnes :

Range("E1").Resize(UBound(aa, 2), UBound(aa, 1)) = Application.Transpose(aa)

On inverse donc l’ordre des commandes de redimensionnement et l’on fait précéder la variable aa de la commande Application.Transpose qui indique à Excel d’inverser le sens lignes/colonnes.

On peut choisir de ne copier q’une ligne :

Range("E1").Resize(1, UBound(aa, 2)) = Application.Index(aa, 5)

C’est la fonction Index qui définit le classement d’un objet parmi une collection d’objets similaires, suivi du nom de la variable et du N° de ligne (ici, la ligne N° 5) qui nous permet de recopier une ligne bien précise.

Le principe est exactement le même pour recopier une colonne :

Range("E1").Resize(UBound(aa, 1), 1) = Application.Index(aa, , 2)

La colonne 2 est, ici, recopiée : la double virgule (aa, , 2) indique au programme qu’il sagit d’une colonne.

On peut aussi décider de copier une ligne en sens vertical :

Range("E1").Resize(UBound(aa, 2), 1) = Application.Transpose(Application.Index(aa, 5))

ou, à l’inverse, copier une colonne dans le sens horizontal :

Range("E1").Resize(1, UBound(aa, 1)) = Application.Transpose(Application.Index(aa, , 2))

Il est aussi possible de copier plusieurs lignes de la variable aa dans une variable tablo et retranscrire les lignes sélectionnées sur la feuille Excel; ici nous enregistrons les lignes paires dans le tablo :

For a = LBound(aa) To UBound(aa)'dela première à la dernière ligne du tableau dans la variable aa
    If a Mod 2 = 0 Then'si le N° de ligne est pair
        c = c + 1'incrémente la variable c de 1
        ReDim Preserve Tablo(c)'redimensionne le tablo
        Tablo(c) = Application.Index(aa, a)'enregistrer toute la ligne dans le tablo
    End If
Next a
Range("E1").Resize(UBound(Tablo, 1), UBound(aa, 2)) = Application.Transpose(Application.Transpose(Tablo))'transposition

Nous remarquons que la commande Application.Transpose est doublée : la ligne de code Range("E1").Resize(UBound(Tablo, 1), UBound(aa, 2)) = Tablo ne fonctionne pas.

Voici comment enregistrer certaines lignes (toujours les lignes paires) de la variable aa et transposer (inverser le sens lignes/colonnes) leur écriture :

c = 0
For a = LBound(aa) To UBound(aa)
    If a Mod 2 = 0 Then
        c = c + 1
        ReDim Preserve Tablo(c)
        Tablo(c) = Application.Index(aa, a)
    End If
Next a
Range("E1").Resize(UBound(aa, 2), UBound(Tablo, 1)) = Application.Transpose(Tablo)

Encore une fois, il nous suffit d’inverser les commandes de redimensionnement et d’appliquer la transposition.

Juste pour information, voici une alternative simple qui procède à l’inscription des colonnes voulues sur la feuille Excel sans les enregistrer dans la variable tablo au préalable.

c = 0
For a = LBound(aa, 2) To UBound(aa, 2)
    If a Mod 2 = 1 Then
        c = c + 1
        Cells(1, 4 + c).Resize(UBound(aa), 1) = Application.Index(aa, , a)
    End If
Next a

Voici le même résultat, en employant le tablo :

c = 0
For a = LBound(aa, 2) To UBound(aa, 2)
    If a Mod 2 = 1 Then
        c = c + 1
        ReDim Preserve Tablo(c)
        Tablo(c) = Application.Transpose(Application.Index(aa, , a))
    End If
Next a
Range("E1").Resize(UBound(aa, 1), UBound(Tablo, 1)) = Application.Transpose(Tablo)

Ici, nous usons d’un artifice pour pouvoir obtenir le résultat voulu : lorsque nous enregistrons nos colonnes dans le tablo, nous les enregistrons en tant que lignes, c’est pour cela que nous utilisons la commande de transposition une première fois dans la ligne de code Tablo(c) = Application.Transpose(Application.Index(aa, , a)) puis nous retransposons lors de l’inscription dans la feuille Excel les informations du tablo.

Enfin, pour faire une vraie transposition de certaines des colonnes retranscrites en lignes, il nous faut encore jongler avec la commande de transposition :

c = 0
For a = LBound(aa, 2) To UBound(aa, 2)
    If a Mod 2 = 1 Then
        c = c + 1
        ReDim Preserve Tablo(c)
        Tablo(c) = Application.Transpose(Application.Index(aa, , a))
    End If
Next a
Range("E1").Resize(UBound(Tablo, 1), UBound(aa, 1)) = Application.Transpose(Application.Transpose(Tablo))

Il nous faut faire une première transposition lors de l’enregistrement de la colonne dans le tablo, puis une double transposition lors de l’inscription sur la feuille Excel.

Nous venons de faire un tour assez complet des possiblités de retranscription des données d’une variable sur la feuille Excel.

Cette série d’articles est maintenant complète… certains concepts peuvent paraître un peu abstraits, au premier abord, mais avec un peu de pratique, les outils décrits dans ces 3 billets vous permettront de gérer rapidement et efficacement de grandes quantités de données à traiter.

Ci-dessous le fichier au format .xls contenant les exemples de cet article.
variables-tablo-3

[VBA] Boostez la vitesse d’exécution de vos macros en utilisant les « variables Tableau » 2/3

Les variables à deux dimensions

Excel possède une fonctionnalité très astucieuse qui permet d’enregistrer simplement et rapidement une plage de données.
Supposons que nous souhaitions enregistrer la plage ci-dessous dans une variable que l’on nommera aa.

Plage VT

il nous suffit juste de taper la commande suivante : aa = Range("A1").CurrentRegion

Voilà, le tour est joué… pour vous en convaincre, nous allons recopier le contenu de la variable aa un peu plus loin dans la feuille à partir de la cellule J1.

Sub PlageVar()

Dim aa As Variant
aa = Range("A1").CurrentRegion
Range("J1").Resize(UBound(aa, 1), UBound(aa, 2)) = aa

End Sub

Les 2 dimensions dont il est question correspondent aux lignes (1ere dimension) et aux colonnes (2eme dimension) de ce tableau enregistrées dans notre variable aa.
Nous avions vu, dans notre article précédent la commande Ubound().
Ajoutons la ligne suivante à notre macro :
MsgBox "Le nombre de lignes enregistré dans notre variable est de : " & UBound(aa, 1) & " et le nombre de colonnes est de : " & UBound(aa, 2)

Le sens de la commande Range("J1").Resize(UBound(aa, 1), UBound(aa, 2)) devient alors limpide : on redimensionne la cellule J1 pour avoir une plage de 20 lignes (UBound(aa, 1)) et 3 colonnes (UBound(aa, 2)).
Une fois la plage définie sur notre feuille Excel, un simple = aa nous permet de faire la copie.

Ajoutons également cette ligne juste après la précédente :
MsgBox "La cellule en 4eme ligne, 3eme colonne a la valeur " & aa(4, 3)

Cet exemple montre que, finalement, l’extraction des données d’une variable est très similaire à celui d’une cellule, il nous suffit de faire suivre le nom de notre valriable de son N° de ligne et de son N° de colonne, rien de plus simple.
Ci-dessous, le code complet :

Option Base 1
Sub PlageVar()

Sheets("PlageVar").Select

Dim aa As Variant
aa = Range("A1").CurrentRegion

Range("J1").Resize(UBound(aa, 1), UBound(aa, 2)) = aa

MsgBox "Le nombre de lignes enregistré dans notre variable est de : " & UBound(aa, 1) & " et le nombre de colonnes est de : " & UBound(aa, 2)
MsgBox "La cellule en 4eme ligne, 3eme colonne a la valeur " & aa(4, 3)

End Sub

Prenons le cas pratique suivant (le fichier Excel contenant tous les exemples de cet article se trouve à la fin de celui-ci) :

Employe mois

Supposons que nous souhaitions extraire tous les employés de la région Europe de ce tableau, voici le code :

Option Base 1
Sub Exp()

Dim aa As Variant, Tablo() As Variant
Dim i As Byte, j as Byte, c As Byte

Application.ScreenUpdating = False
Sheets("Exp").Select
Range("A20").CurrentRegion.ClearContents

aa = Range("A1").CurrentRegion

For i = LBound(aa, 1) To UBound(aa, 1)
    If aa(i, 2) = "Europe" Then
        c = c + 1
        ReDim Preserve Tablo(14, c)
        Tablo(1, c) = aa(i, 1)
        Tablo(2, c) = aa(i, 2)
        Tablo(3, c) = aa(i, 3)
        Tablo(4, c) = aa(i, 4)
        Tablo(5, c) = aa(i, 5)
        Tablo(6, c) = aa(i, 6)
        Tablo(7, c) = aa(i, 7)
        Tablo(8, c) = aa(i, 8)
        Tablo(9, c) = aa(i, 9)
        Tablo(10, c) = aa(i, 10)
        Tablo(11, c) = aa(i, 11)
        Tablo(12, c) = aa(i, 12)
        Tablo(13, c) = aa(i, 13)
        Tablo(14, c) = aa(i, 14)
    End If
Next i
    Range("A20").Resize(UBound(Tablo, 2), UBound(Tablo, 1)) = Application.Transpose(Tablo)

End Sub

Première étape : Nous enregistrons le tableau dans notre variable aa aa = Range("A1").CurrentRegion.
Ensuite, la boucle vérifie, pour chaque employé, la zone à laquelle il appartient For i = LBound(aa, 1) To UBound(aa, 1).
La commande Ubound() nous est maintenant familière, il s’agit du nombre total d’entrées, ici, dans notre première dimension.
La commande Lbound() est nouvelle; elle identifie le N° de la première entrée d’une variable… utile lorsqu’on ne veut pas se préoccuper de savoir si la première entrée a un index de 0 ou de 1… ici, on l’occurence, le problème ne se pose pas parce que nous avons spécifié Option Base 1 en début de code.

Nous définissons ensuite la condition : If aa(i, 2) = "Europe" Then exactement comme nous le ferions pour analyser le contenu de la cellule; nous l’avons vu précédemment il nous suffit simplement de changer la commande Cells et la remplacer par le nom de notre variable pour que la macro travaille au niveau de la mémoire plutôt que des cellules.

Si la condition est vérifiée, nous alimentons une variable tablo qui va enregistrer toutes les informations relatives aux lignes dont la colonne C = »Europe ». Puisque nous ne connaissons pas à l’avance le nombre d’employés de la zone Europe, nous allons bâtir notre tablo au fur et à mesure que le programme rencontrera la valeur Europe; nous allons donc utiliser la commande Redim Preserve, pour redimensionner notre variable tablo.

Important
Dans une variable à 2 dimensions, nous ne pouvons redimensionner qu’une seule des deux dimensions. C’est toujours celle qui est déclarée en 2eme position !
Jusqu’ici, la première dimension de notre variable tablo correspondait au nombre de lignes de notre tableau et la seconde, au nombre de colonnes.

Dans notre cas de figure, le nombre de colonnes restera toujours le même, à savoir 14.
Le nombre de lignes est, lui, inconnu et peut évoluer. La variable c sera incrémentée au fur et à mesure que la condition sera vérifiée et nous servira à redimensionner notre tablo c = c + 1. La commande Redim Preserve se rédige donc ainsi : ReDim Preserve Tablo(14, c)

Nous devons maintenant enregistrer chaque valeur des lignes correspondant au critère « Europe » dans la variable tablo.
C’est ce que font les 14 lignes de code suivantes : Tablo(1, c) = aa(i, 1)
La première valeur de la « ligne » c de notre variable tablo = la 1ere valeur de la « ligne » i de la variable aa (qui correspond à la cellule (i, 1)). et ainsi de suite.

Une fois la boucle terminée, nous allons donc inscrire le résultat de notre recherche.
Nous avons vu, au début de cet article qu’il suffisait de redimensionner une plage à partir d’une cellule et d’y affecter le contenu de notre variable. c’est exactement ce que fait la commande suivante : Range("A20").Resize(UBound(Tablo, 2), UBound(Tablo, 1)) = Application.Transpose(Tablo).

Elle redimmensionne la cellule A20 du nombre total de lignes Resize(UBound(Tablo, 2)(qui est maintenant la 2eme dimension, puisque nous avons inversé le sens de nos dimensions à cause de la contrainte imposée par notre variable tablo de ne pouvoir redimensionner qu’une seule des deux dimensions) et du nombre total de colonnes UBound(Tablo, 1) contenus dans notre tablo.

Puisque nous avons inversé le sens lignes/colonnes lors de l’enregistrement, il va nous falloir récupérer le sens originel de nos dimensions; c’est ce que se charge de faire la commande Application.Transpose(tablo).
Mais nous reviendrons plus en détail sur la copie du contenu des variables sur la feuille Excel dans le 3eme et dernier article dédié aux variables Tableau.

Ce petit exemple nous a permis de mieux comprendre le fonctionnement des variables Tableau, cependant on peut améliorer et simplifier son code.

La première modification va porter sur cette ligne de code : ReDim Preserve Tablo(14, c)
Le nombre de colonnes, 14, est, ici, fixe… mais peut-être qu’à l’avenir, ce document sera amené à évoluer et le nombre de colonnes pourrait changer, donc autant mettre cette valeur sous forme de variable, ainsi, nous n’aurons pas à modifier la macro en cas de changement du tableau. Nous savons maintenant définir le nombre de colonnes de notre variable aa en utilisant la commande Ubound(aa,2); il nous suffit juste de remplacer 14 par cette commande : ReDim Preserve tablo(UBound(aa, 2), c).

L’autre changement consiste à améliorer l’enregistrement de toutes les valeurs d’une ligne dans notre tablo.
Nous avons écrit 14 lignes de commande pour enregistrer les valeurs des 14 colonnes du tableau.
Nous allons donc modifier le code pour contourner cette manipulation assez fastidieuse et introduire une boucle qui enregistrera automatiquement toutes les données relatives à une même ligne dans le tablo.

For j = LBound(aa, 2) To UBound(aa, 2)
    tablo(j, c) = aa(i, j)
Next j

For j = LBound(aa, 2) To UBound(aa, 2) nous dit de boucler entre les N° de la première et la dernière colonne contenues dans la variable aa.

Puis nous remplaçons les N° de colonne par la variable j : tablo(j, c) = aa(i, j), qui, tour à tour, prend le N° de chacune des 14 colonnes de notre exemple et remplace les 14 lignes de code.

Notre nouveau code ressemble à ça :

Option Base 1
Sub Exp()

Dim aa As Variant, tablo() As Variant
Dim i As Byte, j As Byte, c As Byte

Application.ScreenUpdating = False
Sheets("Exp").Select
Range("A20").CurrentRegion.ClearContents

aa = Range("A1").CurrentRegion

For i = LBound(aa, 1) To UBound(aa, 1)
    If aa(i, 2) = "Europe" Then
        c = c + 1
        ReDim Preserve tablo(UBound(aa, 2), c)
        For j = LBound(aa, 2) To UBound(aa, 2)
            tablo(j, c) = aa(i, j)
        Next j

    End If
Next i
    Range("A20").Resize(UBound(tablo, 2), UBound(tablo, 1)) = Application.Transpose(tablo)

End Sub

Rédigé ainsi, le code est plus digeste à lire mais il persiste un inconvénient : pour chaque ligne enregistrée, la commande For i = LBound(aa, 1) To UBound(aa, 1) boucle 14 fois, ce qui, dans l’absolu, peut prendre énormément de temps si le nombre de lignes et de colonnes devient important.

Nous allons donc faire en sorte qu’à chaque fois qu’une ligne doit être enregistrée dans le tablo, elle le soit dans son intégralité.

C’est la commande Index que nous avons déjà étudiée dans nos articles précédents qui va nous permettre de réaliser cette manipulation. Pour rappel, l’index est le N° d’un objet dans une collection d’objets de même nature. Ici, il va s’agir de déterminer une ligne de la variable aa parmi toutes les autres lignes de cette même variable et l’enregistrer dans le tablo.

Nous avons vu, au début de cet article, qu’une variable pouvait contenir une infinité d’informations lorsque nous avons écrit la commande aa = Range("A1").CurrentRegion.
Nous allons procéder exactement de la même façon pour l’enregistrement d’une ligne de aa dans tablo : nous allons donc redéfinir notre variable tablo comme n’ayant qu’une seule dimension et non plus 2, il nous suffit, pour cela de modifier la commande Redim Preserve comme ceci : ReDim Preserve tablo(c).
Nous n’avons plus qu’à enregistrer la ligne entière avec ce code : tablo(c) = Application.Index(aa, i) qui signifie concrêtement : dans la « case » c de la variable tablo, enregistrer la « ligne entière » i de la variable aa.

Il nous reste à modifier la ligne qui permet d’inscrire les données du tablo dans la feuille Excel :
Range("A20").Resize(UBound(tablo), UBound(aa, 2)) = Application.Transpose(Application.Transpose(tablo))

A noter qu’on peut identifier une valeur parmi les 14 de chaque ligne; toujours en utilisant la fonction Index :
Supposons que l’on veuille récupérer la 6eme valeur de la 5eme ligne de notre tablo : MsgBox Application.Index(tablo(5), 6)

Et voici le code complet pour notre dernier exemple :

Option Base 1
Sub Exp()
Dim aa As Variant, tablo() As Variant
Dim i As Byte, j As Byte, c As Byte

Application.ScreenUpdating = False

Sheets("Exp").Select
Range("A20").CurrentRegion.ClearContents

aa = Range("A1").CurrentRegion

For i = LBound(aa, 1) To UBound(aa, 1)
    If aa(i, 2) = "Europe" Then
        c = c + 1
        ReDim Preserve tablo(c) 'cas N° 3
        tablo(c) = Application.Index(aa, i)
    End If
Next i

Range("A20").Resize(UBound(tablo), UBound(aa, 2)) = Application.Transpose(Application.Transpose(tablo))
MsgBox Application.Index(tablo(5), 6)

End Sub

Nous avons fait le tour de ce qu’il faut savoir sur les variables Tableau, dans le dernier volet de cette série d’articles, nous examinerons plus en détail les outils à notre disposition pour retranscrire les valeurs d’une variable sur la feuille Excel.

Ci-dessous le fichier au format .xls contenant les exemples de cet article.
Variables tablo 2

[VBA] Boostez la vitesse d’exécution de vos macros en utilisant les « variables Tableau » 1/3

Introduction aux variables Tableau

Cet article suppose que les notions de base comme les boucles, condtions, déclarations de variables etc… sont acquises.

Les 2 macros suivantes ont exactement la même fonction : inscrire automatiquement 50 000 valeurs comprises entre 1 et 10 respectivement dans les colonnes A et B.

Sub FeuilleExel()
Application.ScreenUpdating = False
Sheets("Comp").Select
t = Timer
For a = 1 To 50000
    Cells(a, 1) = Application.WorksheetFunction.RandBetween(1, 10)
Next a
MsgBox Timer - t
End Sub

La première macro, ci-dessus, génère chaque valeur aléatoire et l’écrit immédiatement dans la cellule suivante de la colonne A.

Sub VariableTableau()
Dim tablo()
ReDim tablo(50000, 1)
Application.ScreenUpdating = False
Sheets("Comp").Select
t = Timer
For a = 1 To UBound(tablo)
      tablo(a, 1) = Application.WorksheetFunction.RandBetween(1, 10)
Next a
Cells(1, 2).Resize(UBound(tablo), 1) = tablo
MsgBox Timer - t
End Sub

La seconde macro génère chaque valeur aléatoire dans la mémoire de l’ordinateur et là conserve jusqu’à la fin de l’opération.
Elle colle, ensuite, la liste complète des valeurs dans la colonne B.

Lancez, tour à tour, les 2 macros et relevez les chronos respectifs : le résultat est sans appel, la 2nde macro, qui utilise les variables, exécute son calcul environ 4 fois plus vite que celle qui retranscrit les résultats directement sur la feuille de calcul.
L’intérêt d’utiliser les variables dans le traitement des données, lorsque celle-ci sont nombreuses, est indéniable.

Qu’est ce qu’une variable tableau ?

Une variable tableau (on l’appellera « tablo ») est une variable un peu particulière qui permet d’enregistrer plusieurs informations sur plusieurs « dimensions ».
Nous reviendons sur le principe de dimensions dans le prochain article.
Comment enregistrer plusieurs informations dans un tablo ?
Prenons un exemple :

Nous souhaitons enregistrer les chiffres de 0 à 9 dans notre tablo.
Nous commençons donc par déclarer notre tablo, comme nous le ferions avec n’importe quelle autre variable…
dim tablo() as byte
… à la seule différence que nous avons ajouté des parenthèses à la fin de notre variable, ceci pour indiquer nous allons travailler sur un type de variable un bien défini.
Avant d’enregistrer nos valeurs numériques dans notre tablo, nous allons devoir indiquer, au préalable, au programme, le nombre de valeurs que doit recevoir notre variable, à savoir 10. Pour cela, nous allons devoir la « redimensionner » :
Redim tablo(10)
Nous pouvons maintenant créer une boucle pour enregistrer chacune des 10 valeurs dans notre tablo

Sub BoucleTablo()

Dim a As Byte
Dim tablo() As Byte
ReDim tablo(10)

For a = 0 To 9
    tablo(a) = a
    Cells(a, 1) = tablo(a)
Next a

End Sub

La valeur entre parenthèses est le N° d’index de notre tablo, autrement dit, le N° de la « case » virtuelle dans laquelle va être enregistrée notre valeur numérique.
Par défaut, l’index de la première case est toujours 0 .
Le VBA nous permet de modifier cette configuration pour que le 1er N° d’index soit 1 : il suffit d’inscrire le code suivant Option Base 1 avant de déclarer notre macro Sub BoucleTablo().
Nous adoptons l’Option Base 1 qui évitera pas mal de confusions et modifions donc notre code pour le rendre plus cohérent avec le choix de notre option.

Option Base 1
Sub BoucleTablo()

Dim a As Byte, tablo() As Byte
ReDim tablo(10)
Sheets("Exp 1").Select

For a = 1 To 10
    tablo(a) = a
    Cells(a, 1) = tablo(a)
Next a

End Sub

Pour info
Dans cet exemple, chaque valeur est enregistrée dans le tableau puis inscrite dans la cellule.
Il existe des méthodes plus efficaces pour inscrire les données du tablo sur la feuille, cela fera l’objet d’un prochain article.

Nous venons de voir comment enregistrer un nombre défini de valeurs dans un tablo; mais comment dimensionner le tablo lorsque l’on ne connait pas à l’avance le nombre d’éléments à enregistrer ?

C’est la commande Redim Preserve qui va nous permettre de prendre en charge cette situation.
Nous allons légèrement modifier la macro précédente pour illustrer notre propos.
Nous utiliserons la commande RandBetween pour générer aléatoirement un nombre de valeurs compris entre 5 et 50 à enregistrer dans notre tablo; le modulo (Mod) nous permettra de sélectionner et enregistrer dans le tablo uniquement les valeurs paires.

Sub RedimPreserve()

Dim a As Byte, tablo() As Byte, c As Byte

Sheets("Exp 1").Select
Columns(6).ClearContents

For a = 1 To Application.WorksheetFunction.RandBetween(5, 50)'génère une valeur comprise entre 5 et 50
    If a Mod 2 = 0 Then 'si le modulo de a/2 = 0 (autrement dit si le nombre a est pair)
        c = c + 1
        ReDim Preserve tablo(c)
        tablo(c) = a
        Cells(c, 6) = tablo(c)
    End If
Next a

End Sub

For a = 1 To Application.WorksheetFunction.RandBetween(5, 50)
Le nombre max de la boucle, généré aléaoirement, est donc inconnu à l’avance.

If a Mod 2 = 0 Then
La condition vérifie si la valeur a est paire ou impaire.

c = c + 1
Si a est paire, alors c est incrémenté de 1

ReDim Preserve tablo(c)
et notre tablo redimensionné avec la nouvelle valeur de c.

tablo(c) = a
La valeur a est enregistrée dans le tablo.

Une autre commande importante, lorsqu’on utilise les tablo, est la commande Ubound(nom du tablo), qui nous permet de connaitre le nombre de valeurs contenues dans le tablo. Elle sera particulièrement utile lorsque nous voudrons retranscrire les données contenues dans le tablo, sur la feuille Excel.
Insérez la commande MsgBox UBound(tablo) après la boucle.

Cet article d’introduction sur les variables tablo nous a permis d’en comprendre les principes.
Dans le prochain article, nous aborderons les tablo à 2 dimensions.

Ci-dessous le fichier au format .xls contenant les exemples de cet article.
Variables tablo 1