Excel Vba Intro
This study has not yet been peer reviewed.
Un tableau croisé dynamique (TCD) permet d’analyser une liste de données. Cette notion est considérée comme la plus puissante d’Excel ; Le TCD fournit des statistiques détaillées sur votre liste, selon la manière dont il est construit ; On construit un TCD en effectuant un glisser-déposer d’étiquettes de colonnes sur l’une des quatre zones du TCD. Le champ « Plage » permet d’obtenir un filtre.
Un double-clic sur l’étiquette de colonne schématisée dans le menu « Disposition » permet d’accéder à des options de mises en forme (moyenne, pourcentages etc.) Les groupes, accessibles à partir du menu « Données » permettent de grouper des éléments du TCD en un paquet, et donc de simplifier sa lecture.
une macro C’est une suite d’instructions que vous exécutez quand vous voulez.
développeur -> insérer -> bouton de contrôle (ex. bouton de la macro)
Outils d’analyses de simulation
Excel est un outil de gestion de données mais il peut aussi faire le travail à notre place dans beaucoup de situations. C’est le cas avec les outils d’analyse de simulation. Ces outils permettent de connaître les situations possibles grâce au modèle déjà en place et donc en émettant des hypothèses et connaître les résultats de ces hypothèses. Il existe plusieurs outils sous Excel, mais les deux plus importants que nous allons étudier sont la valeur cible et le solveur. En effet, vous avez, dans votre classeur, un grand nombre de formule dépendante des unes et des autres. Vous souhaitez faire varier le résultat en changeant les valeurs de certaines cellules. Sans ces outils, vous allez essayer en modifiant les unes après les autres les valeurs sans vous souvenir du résultat que les différentes combinaisons donnent et donc passer un temps fou à connaître la meilleur combinaison possible. Nous allons donc apprendre à créer des scénarios qui vont nous donner les combinaisons les meilleures possibles. La valeur cible Commençons doucement avec le premier outil : la valeur cible. Cet outil permet de déterminer le résultat voulu et Excel va changer lui même les valeurs affectant ce résultat pour trouver une combinaison possible et réelle. Vous aurez plus qu’à regarder si les valeurs vous conviennent.
onglet Données, dans le groupe Outils de données cliquez sur Analyse de scénarios puis sur Valeur cible..
Il suffit alors de remplir les trois champs : La cellule à définir : on ne peut pas la modifier car elle contient la formule. C’est à cette cellule qu’on attribue la valeur fixe. La valeur à atteindre : c’est la valeur fixe dont je parle juste avant, c’est la valeur à laquelle doit être égale la cellule que l’on souhaite définir. La cellule à modifier : c’est la cellule dont la valeur va être modifiée après avoir cliqué sur OK
Un outil très simple et efficace pour trouver une valeur. Seulement maintenant, je souhaiterais modifier les deux valeurs pour avoir le même résultat… Je veux bien négocier mais je veux bien aussi baisser mon taux de marque. Pour cela, Excel propose un autre outil : le solveur. Le solveur Avant de commencer à l’utiliser, il faudrait qu’il soit disponible. On va donc commencer par l’installer. Pour cela, cliquez sur le gros bouton Office en haut à gauche du logiciel puis sur Options Excel, dans la catégorie Compléments du volet de gauche. En bas de la fenêtre, dans la liste Gérer vérifiez que Compléments Excel soit sélectionné. Cliquez sur le bouton Atteindre, dans la fenêtre qui s’ouvre cochez Complément Solver et cliquez sur Ok. Patientez le temps de l’installation. Si tout a bien fonctionné, dans l’onglet Données est apparu un groupe tout à droite Analyse avec dans ce groupe Solver.
Macros et VBA
renommage du module: bouton « Fenêtre Propriétés (F4) »
Sub nom_de_la_macro()
'Un commentaire commence par une apostrophe '
End Sub
Le VBA est un langage orienté objet.
L’accès aux objets se fait comme suit :
nom_de_la_classe("Nom de l'instance de cette classe")
le big des big objets, c’est Application, qui désigne l’application Microsoft Excel. Lui-même contient la classe Workbooks, qui regroupe tous les classeurs Workbook ouverts. Et Workbook contient la classe Worksheets, qui contient toutes les feuilles Worksheet du classeur désigné
la méthode Activate, qui active (qui vous amène) là où vous lui demandez. Par exemple, je veux aller de la première feuille à la deuxième. Il va falloir donc nommer notre classeur et deux feuilles, afin de donner un itinéraire.
Enregistrez votre classeur en le nommant “Essai”. Renommez une première feuille “Départ” et l’autre “Arrivée”. En se plaçant sur la feuille Départ, On part de l’application, pour aller vers le classeur “Essai” et vers la feuille “Arrivée”. Le code est donc
Sub trajet()
Application.Workbooks("Essai").Worksheets("Arrivée").Activate
'On part de l'application vers l'instance Essai de la classe
Workbooks
'ensuite, on va à l'objet Arrivée de la classe Worksheets
End Sub
si on est sûr d’être dans Excels et et dans le classeur Essai, on peut simplement écrire
Sub trajet()
Worksheets("Arrivée").Activate
'On part de l'application vers l'instance Essai de la classe
Workbooks
'ensuite, on va à l'objet Arrivée de la classe Worksheets
End Sub
La classe Workbooks désigne tous les classeurs ouverts. La classe Worksheets désigne toutes les feuilles du classeur actif.
Autre exemple: en amont, sélectionner des cellules, clic droit -> “Définir un nom”, appeler “ma_plage” Macro pour changer l’emplacement de la cellule active
Sub MaSelection()
Range("Ma_Plage").Select
' on sélectionne la plage Ma_Plage, qui relève de la classe Range,
à l'aide de la méthode Select
Range("C11").Activate
'la cellule C11 devient la cellule active de la sélection, avec la
méthode Activate
End Sub
Maintenant, nous allons nous intéresser aux propriétés de l’objet ( = instance).
Voici comment nous pourrions accéder à ces propriétés (toujours en supposant que notre maison est bien issue de la classe Maisons et que l’objet se nomme Ma_Maison) :
Maisons("Ma_Maison").couleur = "verte"
'On dit que nous souhaitons accéder à l'objet Ma_Maison, de la
classe Maisons
'nous accédons à la propriété couleur et nous lui affectons une
valeur
La taille du texte est contenue dans une propriété appelée Size. Cette propriété n’accepte que des valeurs numériques
La police se trouve dans la propriété Name. Cette propriété attend une chaîne de caractères.
Le soulignement est géré par la propriété underline. Cette propriété n’accepte que des constantes. Oui, ces mystérieuses constantes qui commencent par xl. Sachez que la valeur xlUnderlineStyleSingle applique un soulignement simple au texte. En effet, avec xlUnderlineStyleDouble, on peut appliquer au texte deux traits de soulignement.
Le gras est une propriété à lui tout seul : Bold, qui signifie “gras” en anglais. Vous remarquerez d’ailleurs au fil du cours que le VBA a une syntaxe très proche de l’anglais. Bold n’accepte que deux valeurs : True ou False ; c’est donc un booléen. Si la propriété vaut True, le texte sélectionné sera mis en gras. Dans le même genre, sachez qu’il existe la propriété Italic, qui est également un booléen et qui gère la mise en italique du texte.
Sub texte()
Selection.Font.Size = 14
Selection.Font.Name = "Euclid"
Selection.Font.Underline = xlUnderlineStyleSingle
Selection.Font.Bold = true
End Sub
la structure en With … End With
With nom_de_votre_objet
'on fait ici nos
.propriété_1
.propriété_2
.propriété_3
modifications sur les propriétés par exemple :
= valeur_1
= valeur_2
= valeur_3
End With
ainsi on peut écrire
Sub texte()
With Selection.Font
.Size = 14
.Name = "Euclid"
.Underline = xlUnderlineStyleSingle
.Bold = true
End With
End Sub
Sélectionner des cellules
Sélection de la cellule C5:
Sub tests_selection()
Range("C5").Select
End Sub
sélectionner plusieurs cellules les séparant par des virgules Sélection des cellules C5, D4 et F8 :
Range("C5, D4, F8").Select
Votre objet peut aussi être une plage de cellules.
Range("B2:E8").Select
Les cellules sont des instances de Range, mais aussi de la classe Cells. Voyez plutôt ces deux codes comparatifs qui exécutent exactement la même chose :
' avec Range
Range("E3").Select
' avec Cells
Cells(3, 5).Select
syntaxe avec Cells
Cells(ligne, colonne).Select
attention: C’est exactement l’inverse de l’adressage que nous connaissons dans le tableur.
NB: pour avoir le numéro de colonne (plutôt que des lettres) -> peut être changé dans « Option Excel ». Dans la fenêtre qui s’ouvre cliquez à gauche sur « Formules » et dans la rubrique « Manipulation de formules », cochez la case « Style de référence L1C1 » :
Décaler une sélection:
- La cellule active est gérée par la classe
ActiveCell. - La classe nouvelle qui effectuera le décalage est
Offset. Cette dernière attend 2 arguments : le nombre de lignes puis le nombre de colonnes du décalage.
Sub decalages()
'La cellule active ne bouge pas :
ActiveCell.Offset(0, 0).Select
'Décalage d'une ligne vers le bas et d'une colonne vers la droite :
ActiveCell.Offset(1, 1).Select
'Décalage d'une ligne vers le haut et de trois colonnes vers la gauche :
ActiveCell.Offset(-1, -3).Select
End Sub
Sélectionner des lignes:
Les lignes du tableur sont des objets de la classe Rows.
Exemple: sélection de la 2ème ligne du classeur actif. On utilise toujours la même méthode (Select). C’est juste la classe qui change.
Rows("2").Select
On peut aussi sélectionner une plage de lignes contiguës :
' Sélection des lignes 2 à 5 incluses :
Rows("2:5").Select
Les lignes peuvent aussi être discontinues. Dans ce cas, la syntaxe est la suivante :
Range("2:2, 5:5, 6:8").Select
' Les lignes 2, 5 et la plage des lignes 6 à 8 seront sélectionnées.
Les lignes sont gérées par Rows mais pour faire des sélections d’objets discontinus on retourne vers la classe Range.
Sélection des colonnes: avec la classe Columns
'Sélection de la colonne C :
Columns("C").Select
'Sélection des colonnes C, D, E et F :
Columns("C:F").Select
Et comme pour les lignes, la classe Range pour la sélection d’objets discontinus :
'Sélection des colonnes A, C et G :
Range("A:A, C:C, G:G").Select
création de variable: déclaration explicite
Dim ma_variable_explicite [As type]
Règles pour la déclaration de variables
Il y a des règles à respecter lorsque vous déclarez une variable :
- Elle doit commencer par une lettre
- Elle ne doit contenir que des lettres, des chiffres et le caractère de soulignement. Les espaces sont interdits !
- Elle est limitée à 40 caractères.
- Elle ne doit pas être identique à un mot réservé.
Dim est un mot réservé, il sert à déclarer une variable, ne peut pas être utilisé comme nom de variable.
On ne peut pas non plus attribuer à une variable le nom Sub, mot réservé pour déclarer les procédures.
On peut ensuite attribuer une valeur à notre variable :
ma_variable_explicite = 10
Déclaration implicite: encore plus simple
ma_variable_implicite = 6
La variable est utilisée directement. Elle n’a pas été déclarée avec Dim. Le programme demande automatiquement de créer cette variable, qui sera par défaut de type Variant et aura pour valeur 6.
Cette approche est plus rapide, mais peut poser problème et engendrer des erreurs difficiles à détecter, par exemple si vous n’orthographiez pas correctement le nom de la variable dans une commande ultérieure du programme.
Une déclaration implicite peut aussi rendre votre code plus difficile à comprendre ultérieurement et pour les autres.
On peut obliger à déclarer les variables grâce à la fonction Option Explicit. Doit se placer dans chaque module, avant le code des procédures.
Petit programme pour afficher une boite de dialogue avec le texte “Bonjour”
Sub bonjour()
MsgBox "Bonjour"
End Sub
Autre exemple:
Sub test()
Dim ma_variable As String
ma_variable = "Bonjour"
MsgBox "Cette phrase affiche la valeur de ma variable : " & ma_variable
MsgBox "Cette phrase affiche le nom de ma variable : " & "ma_variable"
End Sub
Le & permet la concaténation de chaines.
Type des variables: un type de données peut être attribué à une variable ce qui permet de déterminer le type d’information que la variable peut stocker. Cette décision peut avoir un effet sur l’efficacité de votre code. Si aucun type de données n’est spécifié, le type par défaut est Variant. Exemple:
Dim ma_variable As String
Une variable de type Variant peut stocker tous les types de données, par exemple, du texte, des nombres, des dates ou bien
encore d’autres informations. Elle peut même stocker un tableau entier. Elle peut modifier librement son type
pendant l’exécution du code alors que ceci est impossible à réaliser avec un autre type de données.
La fonction VarType permet de trouver le type de données que contient une variable Variant.
Exemple:
Sub TestVariables()
' On déclare implicitement une variable qui est du texte.
ma_variable = "le_site_du_zéro"
'On affiche le type de la variable
MsgBox VarType(ma_variable)
'On change la valeur de la variable pour mettre un nombre
ma_variable = 4
'On affiche le nouveau type de la même variable
MsgBox VarType(ma_variable)
End Sub
La fonction VarType va retourner un chiffre qui correspond à un type:
0 Empty
1 Null
2 Integer
3 Long
4 Single
5 Double
6 Currency
7 Date/Time
8 String
Même si Variant stocke tout type de données, il n’est pas indifférent à ce qu’il contient. Exemple: si on essaie d’effectuer des calculs avec une variable de type
Variant mais contenant du texte, une erreur apparait.
IsNumeric est une fonction qui permet de savoir si la variable est de type numérique ou non, renvoie Vrai si la variable comprend un nombre, sinon elle renvoie Faux.
Les types numériques sont (caractère de déclaration)
Byte: nombre entier sur 1 octet 0Integer: nombre entier sur 2 octets (%)Long: integer sur 4 octets (&)Single: un nombre en virgule flottant sur 4 octets (!)Double:Singlesur 8 octets (#)Currency: nombre sur 8 octets avec une partie décimale fixe (@)
Tous permettent de stocker des nombres.
Pour de petits entiers -> Integer (Byte si l’on est sûr que c’est un petit nombre) Pour un très gros entier -> Long. C’est la même chose pour Single et Double mais pour les nombres décimaux. Currency est moins souvent utilisé.
Le caractère de déclaration est utilisé pour faciliter les déclarations de variable. Au lieu de mettre As Integer, on va simplement coller le caractère % à la variable pour la déclarer comme un Integer. Exemple:
'Ces deux lignes exécutent la même chose
Dim ma_variable%
Dim ma_variable As Integer
'D'autres exemples de déclaration de variables
Dim age As Byte
Dim annee As Integer
Dim salaire_Zidane As Long
Dim un_pourcentage As Currency
Dim une_fraction As Single
Dim une_grosse_fraction As Double
On peut déclarer plusieurs variables sur une même ligne (avec un seul Dim). Mais pour le type, il faut le spécifier à chaque fois. S’il n’est pas spécifié après chaque variable, le type Variant est appliqué aux variables sans type spécifique.
Type String: pour une variable contenant du texte.
Par défaut, la longueur de la chaîne de caractère est variable. On peut alors, pour économiser de la mémoire, fixer la longueur de la chaîne à un maximum, au moment de la déclaration avec *.
Il existe aussi un caractère de déclaration pour ce type de variable: $.
Par exemple pour une chaîne qui ne pourra dépasser 50 caractères:
Dim du_texte As String * 50
Si la chaîne est inférieure au maximum, elle est comblée avec des espaces. A l’inverse, si elle est trop longue, elle est coupée après le 50ème caractère et le reste est perdu.
Une chaîne de longueur fixe peut comporter jusqu’à 65’500 caractères alors qu’une chaîne de longueur variable peut comporter jusqu’à 2’000’000 de caractères.
Le type Empty est attribué à une variable ne contenant rien (ex: variable déclarée mais à laquelle n’est affectée aucune valeur)
On peut vérifier si une variable contient quelque chose ou si elle a été définie avec un type grâce à la fonction IsEmpty.
' On déclare une variable sans type donc un Variant
Dim ma_variable_vide
' On déclare une variable de type String (du texte)
Dim mon_texte As String
' On n'affecte aucune valeur ni à l'une ni à l'autre variable
' On affiche le type des deux variables
MsgBox VarType(ma_variable_vide)
MsgBox VarType(mon_texte)
Le type Null : valeur spéciale utilisée pour indiquer des données inconnues ou manquantes. Sauf si indiqué comme tel, les variables ne sont pas initialisées à Null. La valeur Null n’est pas égale à 0. Pour savoir si une variable est de type Null, utiliser la fonction IsNull.
Sub TestNull()
' On crée une variable à laquelle on attribue la valeur Null (sans
guillemet)
ma_variable = Null
' On teste le type de la variables
MsgBox IsNull(ma_variable)
End Sub
Le type Date: on ne peut définir une variable avec le type Date dès la déclaration. Elle se “transforme” en type Date une fois que la valeur est égale à une date.
Les dates et heures sont stockées sous forment de nombres en virgule flottante. La partie entière représente le nombre de jours écoulés depuis le 31 décembre 1899. La partie décimale représente les heures, minute et secondes exprimées comme une portion de 24 heures (0,5 = 12 heures). Pour savoir si la valeur d’une variable est une date: la fonction IsDate.
la_date = "23-07-2010"
MsgBox IsDate(la_date)
' Ce code affiche Vrai.
La date peut être renseignée avec différents séparateurs (tirets, points ou slashs). L’année peut comporter que deux chiffres. Il faut faire attention à la configuration du format de date qui peut faire varier la reconnaissance de date (JJ-MM-AAAA ou MM-JJ-AAAA).
Le type booléen: type de variable qui prend 2 valeurs différentes (True ou False). L’avantage est que ce type de variable ne demande que 2 octets pour être stockéé. Exemple:
' Une variable qui vaut Vrai
ma_variable = True
' Une variable qui vaut Faux
ma_variable = False
La fonction VarType renvoie 11 quand la variable est un booléen.
Le type Objet: variables faisant référence à des objets (e.g. les classeurs, les feuilles, les cellules ou même l’application). Ce type de variable occupe 4
octets.
L’instruction Set permet d’attribuer une référence d’objet à la variable. Par contre, ce type de variable prend de la place et on libère donc la mémoire grâce à Nothing (cf. exemple ci-dessous).
Sub test()
' On crée une variable qui a pour type une feuille.
' De ce fait, on peut lui attribuer une valeur spécifique : une feuille d'un classeur.
Dim Ws As Worksheet
' On attribue la 1ere feuille du classeur dans la variable grâce à Set
Set Ws = Sheets(1)
' On affiche le nom de la première feuille
MsgBox Ws.Name
' On libère ensuite la mémoire
Set Ws = Nothing
End Sub
Ceci est réalisable avec une feuille ou un classeur ou une cellule. En combinant tout ça, on obtient ceci :
' On attribue des variables : c comme classeur pour Workbook, f comme feuille pour Worksheet.
Dim c As Workbook, f As Worksheet
' On associe à c le premier classeur
Set c = Workbooks("classeur1")
' On associe à f la feuille 1 du classeur 1
Set f = c.Worksheets("feuil1")
' On affiche la valeur de la première cellule de la première feuille, du premier classeur
MsgBox f.Range("A1").Value
On aurait pu aussi associer Range("A1") à une variable pour raccourcir le code si on avait à l’utiliser souvent. Ce code est utile et
remplace ce code :
Workbooks("classeur1").Worksheets("feuil1").Range("A1").Value
Ce que nous avons fait avant peut paraitre plus long, mais très pratique par la suite, en effet, la simple lettre f remplace tout ce code :
Workbooks("classeur1").Worksheets("feuil1")
Les tableaux: pour la déclaration, comme pour les variables simples, on utilise Dim puis le nom de la variable et enfin le type de la variable.
Exemple: création d’un tableau de 51 cellules (de 0 à 50) sur une colonne:
Dim invite(50) As String
Un tableau fonctionne comme une feuille Excel, la colonne A est notre tableau et chaque ligne est une entrée. On peut ainsi mettre en cellule A1 le nom du premier invité en A2, le deuxième, ainsi de suite. En VBA, on n’utilise pas A1, A2… mais invite(0), invite(1)…
Attention ! Un tableau commence à 0 et non à 1.
On peut donc maintenant attribuer un nom à chaque invité, exemple:
invite(0)="Robert"
invite(1)="Marcel"
invite(2)="André"
invite(3)="Vital"
'...
Un tableau peut prendre tous les types de variables et il est limité à 32 767 éléments.
Les tableaux commencent à 0 mais on peut modifier cette base avec la fonction Option Base. Comme pour la fonction Option Explicit, il faut la placer avant tout code dans un module dans la section de déclarations comme ceci :
Option Base 1
Les tableaux commenceront alors à 1. Cette base de 1 peut être unique à un tableau en utilisant le mot-clé To.
Dim mon_tableau(1 To 15) as String
Ce tableau comprend 15 éléments de type String.
Les tableaux multidimensionnels: tableaux à plusieurs dimensions. Exemple:
' On crée un tableau de 11 colonnes et 5 lignes
Dim mon_tableau(10, 4) As String
' On peut alors attribuer des valeurs aux différents éléments du tableau
mon_tableau(0, 0) = "Première cellule"
mon_tableau(4, 2) = "Cellule de la 5ème colonne et 3ème ligne"
Ce n’est pas fini. Même si ce tableau comporte alors 55 cellules, on peut le dupliquer dans une troisième dimension. Ça fonctionne toujours de la même façon :
Dim super_tableau(5, 3, 6) As String
Ce tableau comporte donc 7 feuilles de 6 colonnes et 4 lignes. Ce qui nous fait 168 cellules et éléments qui peuvent prendre une valeur.
On dit que le nombre de dimensions peut monter jusqu’à 5, mais la gestion de ces tableaux devient très difficile. De plus, plus on donne de dimensions, plus on augmente l’espace utilisé par la mémoire. De ce fait, au bout d’une certaine quantité de mémoire utilisée, le programme peut ralentir le fonctionnement de la machine. Attention donc à ne pas utiliser de l’espace inutilement.
Si une variable est déclarée au sein d’une procédure, seul le code au sein de cette procédure peut accéder à cette variable. La portée est locale à cette procédure. Parfois il est nécessaire de permettre l’utilisation des variables par plusieurs procédures ou même par la totalité de l’application; on peut déclarer une variable au niveau local, au niveau du module ou bien au niveau global.
Une variable locale est utilisée dans une procédure et uniquement dans cette procédure si bien qu’une fois la procédure terminée, la variable n’est plus accessible. De ce fait, une variable appelée ma_variable peut avoir une valeur dans une première procédure et ce même nom de variable utilisé dans une autre procédure peut avoir une autre valeur. En effet, on aura créé deux variables différentes puisque dans deux procédures différentes. Par défaut, on crée des variables locales.
La variable de niveau module permet d’y accéder partout dans un module et donc dans toutes les procédures mais pas dans le reste de l’application. Elle reste en vie durant tout le temps d’exécution de l’application et conserve leur valeur. Pour qu’elle soit utile dans tout le module, la variable doit être déclarée avant toute procédure dans les déclarations.
Les variables globales sont déclarées dans la section des déclarations comme pour les variables de module. Par contre, une variable globale va être précédée de Global au lieu de Dim. Les variables globales existent et conservent leur valeur pendant toute la durée de l’exécution de l’application. Cette variable globale est déclarée au début de n’importe quel module, car celle-ci
est accessible dans tous les modules.
Global ma_variable_globale
Toutes les portées de variables que l’on vient de voir ont une durée de vie définie et finissent par mourir. Les variables locales sont réinitialisées quand la procédure se termine, les variables de module et globales sont réinitialisées et donc leurs valeurs sont détruites après la fin de l’exécution de l’application.
Pour pallier à la destruction des variables, on peut remplacer Dim par Static pour que les valeurs soient préservées même après la fin de l’exécution de l’application ou de la procédure. On déclare ainsi des variables statiques.
Static ma_variable_statique
Pour ne pas mettre Static devant toutes les variables d’une procédure, on peut ajouter Static avant la déclaration de procédure.
Static Sub procedure_variables_statiques
Une variable ne peut changer sa portée au cours de l’exécution du code. Mais il est possible d’avoir deux variables du même nom, mais pas de la même portée. Par exemple, avoir une variable ma_variable de type global et une autre variable ma_variable de type local dans une procédure. Dans cette procédure, on peut donc faire référence à deux variables différentes qui portent le même nom. La variable locale aura le dessus sur la variable globale. Si on veut appeler la variable globale dans cette procédure, il faut alors changer le nom d’une des variables.
Attention! Cette notion de préséance est difficile à intégrer et est une source d’erreur. Le meilleur moyen de l’éviter, c’est de donner des noms différents à toutes les variables.
Les constantes sont en réalité des variables qui ne sont jamais modifiées. Elles contiennent des valeurs qui sont utilisées sans arrêt dans le code et fournissent des raccourcis pour ces valeurs constantes particulières. On ne peut évidement pas modifier une constante et pour la déclarer on n’utilise pas Dim mais Const.
Const nom_chemin = "D:\Utilisateur\"
Il existe des constantes prédéfinies dans le modèle d’objet d’Excel (cf. plus loin dans le cours).
Il est possible de définir un type de variable grâce au mot clé Type, pour créer son propre type de variable à partir des types déjà existant. La définition du type doit être avoir lieu dans la section des déclarations d’un module.
Type joueur
tribu As String
vies As Byte
points As Integer
End Type
Ce code crée un nouveau type appelé joueur qui contient des informations sur la tribu, le nombre de vies et le nombre de points d’un joueur. Ce type s’ajoute automatiquement à la liste déroulante comme les autres types déjà existants. On peut l’utiliser comme les autres types. Exemple :
' On déclare une variable joueur
Dim bat538 As joueur
' On renseigne les différents champs du type
bat538.tribu = "Zér0"
bat538.vies = 5
bat538.points = 0
'On affiche un à un les paramètres
MsgBox bat538.tribu
MsgBox bat538.vies
MsgBox bat538.points
On peut aussi créer un tableau à partir du nouveau type créé.
Exemple de condition en VBA
Sub test_condition()
Dim age As Byte
age = 20
' Si vous avez un age supérieur ou égal à 18 :
If age >= 18 Then
MsgBox "Vous êtes un adulte"
' Sinon :
Else
MsgBox "Vous êtes encore mineur"
End If
End Sub
Ou en utilisant ElseIf
Sub test_condition()
Dim age As Byte
age = 20
If age >= 18 Then
MsgBox "Vous êtes un adulte"
ElseIf age < 8 Then
MsgBox "Vous êtes un surdoué pour être ici à votre âge !"
Else
MsgBox "Vous êtes encore mineur"
End If
End Sub
Pour simplifier la comparaison multiple: Select Case, permet de simplifier la succession de ElseIf.
Exemple:
Sub test_note()
Dim note As Byte
note = 12.4
Select Case (note)
Case Is < 8
MsgBox "Vous n'avez pas votre baccalauréat"
Case Is < 10
MsgBox "Vous devez aller aux rattrapages"
Case Is < 12
MsgBox "Félicitations ! Vous avez votre bac !"
Case Is < 14
MsgBox "Vous avez la mention Assez Bien"
Case Is < 16
MsgBox "Vous avez la mention Bien"
Case Is < 18
MsgBox "Vous avez la mention Très Bien"
Case Else
MsgBox "Vous avez les félicitations du jury et les miennes par la même occasion"
End Select
End Sub
Autre forme possible avec Case
Select Case (note)
Case 1
MsgBox "La note est de 1"
Case 2, 3
MsgBox "La note est de 2 ou 3"
Case 4 To 6
MsgBox "La note est de 4, 5 ou 6"
Case Is > 6
MsgBox "La note est supérieure à 6"
Case Else
MsgBox "La note est inférieure à 1"
End Select
Commandes conditionnelles multiples: And et Or. Exemple:
' Pour l'opérateur And c'est comme ceci :
If age < 18 And sexe = "Masculin" Then
MsgBox "Vous n'êtes encore qu'un garçon..."
Else
MsgBox "Soit plus de 18 ans, soit vous êtes de sexe féminin"
End If
' Pour l'opérateur Or C'est la même chose
If pointure < 40 Or taille < 34
...
End If
Autres opérateurs logiques:
Not: inverse une condition. Exemple:If Not(2 = 3) Then MsgBox "Les valeurs ne sont pas égales" Else MsgBox "Les valeurs sont égales" End IfXor: très semblable à Or. Mais pourXorsi deux conditions sont vraies, alors c’est le code de la deuxième partie qui est exécutée. VBA considère que deux conditions vraies donnent faux avecXor.Is: pour comparer deux objets VBA.Like:
Comparaison de deux chaînes de caractères: avec Like. La correspondance entre deux chaînes peut être seulement les n premiers caractères ou simplement au niveau de la casse (majuscule ou minuscule).
On utilise un mot-clé Option Compare que l’on doit écrire dans la section des déclarations. Ce mot clé peut être suivi de deux
valeurs : Binary (une lettre en majuscule et la même lettre en minuscule ne sont pas considérées comme identiques; défaut si non précisé) ou Text (ne fait pas de différences entre minuscule et majuscule). Exemple:
Option Compare Binary
Sub test()
If "Site du Zéro" = "site du zéro" Then
MsgBox "Les chaînes sont exactement les mêmes"
Else
MsgBox "Il y a des différences entre les chaînes de caractères"
End If
End Sub
Si on veut comparer que quelques caractères, on peut utiliser des caractères joker.
?remplace un seul caractère, mais n’importe lequel*remplace quant à lui une chaîne de caractères (zéro ou plusieurs caractères). Je vous présente un tableau avec les caractères de comparaison et leur signification.- [Liste_de_caractères] Remplace un seul caractère de la liste
- [!Liste_de_caractères] Un seul caractère absent de la liste.
Simplification pour la liste de caractères: [a-f] correspond à [abcdef]
Boucle For ... Next
For nombre = 1 to 10
MsgBox nombre
Next nombre
A la fin de la boucle, il faut dire au programme de passer à la valeur suivante par le mot-clé Next suivi du nom de la variable.
Modifier le pas grâce à Step:
For nombre = 0 to 10 Step 2
MsgBox nombre
Next nombre
Step fonctionne également à l’envers
Sub rebours()
For n = 5 To 1 Step -1
MsgBox n
Next n
MsgBox "Boom !"
End Sub
Boucle pratique pour balayer lignes et colonnes. Exemple avec l’affectation à chaque entrée d’un tableau une lettre de l’alphabet :
Sub alphabet()
Dim lettre(25) as String
For n = 0 To 25
lettre(n) = Chr(n+65)
Next n
For n = 0 To 25
MsgBox lettre(n)
Next n
End Sub
Dans un premier temps, on crée un tableau de 26 entrées (nombre de lettres de notre alphabet). Dans une première boucle, on affecte à chaque entrée une lettre de l’alphabet, dans la seconde boucle on affiche ces lettres.
Chr est une fonction de VBA qui permet de renvoyer la lettre qui correspond à un code numérique. Ce code est le ASCII (American Standard Code of Information Interchange ou Code standard américain pour les échanges d’information). Ainsi avec Chr(n+65) ce code chaque nombre correspond à une lettre et par exemple A = 65, B = 66 et ainsi de suite.
Comme notre code commence à 0, il faut ajouter 65 pour avoir la lettre A. Quand n est égal à 1, on ajoute 65 pour obtenir 66 et la lettre B. Chr permet de convertir ce nombre en lettre et on affecte cette valeur à l’entrée du tableau correspondante.
Les boucles peuvent être imbriquées. Exemple:
Sub test_tableau()
For colonne = 1 To 5
For ligne = 1 To 5
MsgBox Chr(colonne+64) & ligne
Next ligne
Next colonne
End Sub
Dans la boucle For Each, on n’utilise pas d’indice qu’elle parcourt automatiquement tous les éléments de la classe (aussi appelée collection).
Cela est très pratique si vous avez besoin de rechercher un objet particulier (avec une condition à l’intérieur de la boucle) au sein de la collection pour le supprimer. L’objet supprimé va décaler les objets vers le haut et il y aura donc moins d’objets à parcourir. Avec cette boucle, tous les objets sont parcourus sans erreur, avec la boucle For..Next, il y aura une erreur à la fin puisqu’il aura un objet non créé.
Exemple: afficher dans une boite de dialogue le nom de chaque feuille de calculs.
Sub afficher_noms()
Dim une_feuille As Worksheet
For Each une_feuille In Worksheets
MsgBox une_feuille.Name
Next une_feuille
End Sub
La boucle Do Until est similaire, elle continue de tourner tant qu’une condition est respectée
Sub test_boucle()
ma_variable = 0
Do Until ma_variable = 10
ma_variable = ma_variable + 1
MsgBox ma_variable
Loop
End Sub
La variable est incrémentée manuellement. Le mot-clé la variable puis on affiche sa valeur. La fin de la boucle est signalée avec le mot-clé Loop.
Attention à ne pas faire de boucles infinies !
La boucle While ... Wend continue de boucler tant que la condition spécifiée est vraie. La boucle s’arrête dès que la condition est fausse. Exemple:
Sub test_while()
ma_variable = 0
While ma_variable < 12
ma_variable = ma_variable + 1
MsgBox ma_variable
Wend
End Sub
Quand la boucle doit remonter on utilise le mot-clé Wend (qui signifie s’acheminer) comme on utilise Loop dans la boucle Do Until.
Sortie anticipée d’une boucle:
- avec le mot-clé
Exit Forpour les bouclesFor ... NextetFor Each - avec le mot-clé
Exit Dopour une boucleDo Until
Dans le cas d’une boucle For ... Next, la valeur de l’indice (de la variable) est préservée.
Si les boucles sont imbriquées, on ne sort que de la boucle dans laquelle on se trouve. Il ne sortira pas de la boucle extérieure à moins d’y placer une autre instruction Exit.
Exemple:
Sub test_sortie()
For variable = 1 To 100
If variable = 50 Then
Exit For
End If
Next variable
MsgBox variable
End Sub
Pour les variables Date, pour obtenir le numéro du jour de la semaine, la fonction WeekDay() attend en paramètre une variable de type Date et renvoie un entier (1 pour Dimanche, …, 7 pour Samedi).
Exemple pour le problème suivant: Combien de premiers du mois sont tombés un dimanche entre le premier janvier 1901 et le 31 décembre 2000 ?
Sub probleme19 ()
Dim dateFin As Date, dateActuelle As Date
dateActuelle = "01/01/1901" ' on commence au 01/01/1901
dateFin = "31/12/2000"
Range("A1").Select 'on sélectionne la première cellule pour y
afficher le premier résultat
While dateActuelle <= dateFin
If WeekDay(dateActuelle) = 1 And Day(dateActuelle) = 1 Then
ActiveCell.Value = dateActuelle ' on écrit le résultat dans la
cellule active
ActiveCell.Offset(1, 0).Select
dateActuelle = dateActuelle + 1 ' on passe au jour suivant
Else
dateActuelle = dateActuelle + 1
End If
Wend
End Sub
Les modules
Un module représente la feuille dans lequel vous écrivez votre code depuis le début. Ils sont rattachés à des classeurs et le code de ces modules peut ainsi agir sur tout le classeur.
Deux dossiers: les objets du classeur Microsoft Excel Objets et les modules dans le classeur Modules
Les procédures codées peuvent aussi être exécutées en faisant appel à elle par le biais d’une autre procédure.
Les fonctions créées dans VBA peuvent aussi être appelées dans les cellules directement comme on appelle la fonction SOMME.
Il y a 2 types de procédures:
1) les sous-routines: permettent d’exécuter du code mais ne renvoie aucune valeur; se déclarent à l’aide de Sub et se termine par End Sub
2) les fonctions: renvoient une valeur; se déclarent à l’aide de Function et se termine par End; les fonction doivent être appelées via une variable pour qu’il y ait une valeur de retour (ex: maintenant=Now()).
Les deux types de procédures acceptent les paramètres.
Exemple de fonction:
Function multiplier(nombre1, nombre2)
multiplier = nombre1*nombre2
End Function
Une fois votre fonction créée, elle apparait dans la liste déroulante de droite au dessus de la zone de code. Elle peut alors être utilisée dans VBA mais aussi dans Excel.
Exemple: utilisation dans Excel (dans une cellule)
=multiplier(3;4)
Exemple: utilisation dans une sous-routine
Sub test()
Dim variable1 As Byte, variable2 As Byte
variable1 = 3
variable2 = 5
resultat = multiplier(variable1, variable2)
MsgBox resultat
End Sub
La sous-routine ne retourne rien du tout directement et elle ne peut donc pas être utilisée directement dans une feuille de calculs à la manière d’une fonction. Est utile pour éviter d’écrire plusieurs fois la même chose. Les sous-routines permettent de décomposer un gros code en plusieurs portions.
Exemple d’une sous-routine:
Sub affichage_prenom(prenom)
MsgBox "Votre prénom est : " & prenom
End Sub
Une sous-routine peut être appelée dans une procédure. La sous-routine peut être appelée comme une fonction en affichant son nom puis les paramètres si elle en prend entre
parenthèses. Mais on peut aussi utiliser le mot-clé Call (celui-ci permet de voir que c’est une sous-routine et qu’elle ne renvoie rien).
' Ces deux lignes font la même chose
Call ma_sous_routine(parametre)
ma_sous_routine(parametre)
Exemple d’utilisation de la sous-routine
Sub test()
' On crée une variable prénom et on lui attribue une valeur
Dim prenom As String
prenom = "Baptiste"
' On utilise notre sous-routine pour afficher le prénom
affichage_prenom (prenom)
' On crée une variable âge ayant pour valeur 20
Dim age As Byte
age = 20
' On réutilise la sous-routine pour montrer que malgré le code entre les deux,
' la sous-routine continue de faire la même chose.
affichage_prenom (prenom)
End Sub
La variable envoyée à la sous-routine ne doit pas forcément être la même que le nom de la variable utilisée dans la sous-routine. on peut très bien faire ça :
' On utilise toujours la même sous-routine avec la variable prenom
Sub test()
Dim pseudo As String
pseudo = "Baptiste"
affichage_prenom (pseudo)
Dim age As Byte
age = 20
affichage_prenom (pseudo)
End Sub
VBA vous permet de définir vos fonctions ou sous-routines privées ou publiques à l’aide des mots-clés Private ou Public.
Par défaut, VBA les créées en publiques. Le fait qu’une fonction ou sous-routine soit publique permet à cette procédure d’être accessible dans tous les modules de l’application. De plus, elles feront partie de la liste des macros que l’on peut attribuer sur une feuille de calcul.
Pour les procédures privées, il suffit de mettre le mot-clé Private devant la déclaration de fonction ou sous-routine. Ainsi, on peut avoir des procédures qui ont le même nom dans des modules différents et qui exécutent un code différent. Ces fonctions privées ne peuvent être utilisées par un utilisateur dans la feuille de calcul. C’est le même système que pour les variables locales ou globales.
Private Sub sous_routine_privee()
End Sub
Quand on déclare des procédures avec des paramètres, par défaut, il sont de types Variant. Mais on peut attribuer un autre type de données à ces paramètres
Function afficher_resultat(resultat As Integer)
Avantage à déclarer des types de données : introduire une discipline dans le code car la procédure recherche un certain type d’informations. Avec le type par défaut, Variant, la procédure accepte n’importe quoi. Si on spécifie que le paramètre est une chaîne de caractères, une erreur se produira si ce n’est pas une chaîne de caractères qui est passée en paramètre.
On peut rendre certains arguments optionnels en utilisant le mot-clé Optional.
Function test(parametre1 As Byte, Optional parametre2 As Byte)
Cette fonction demande un paramètre obligatoire de type Byte qui est parametre1 et un paramètre optionnel de type Byte qui est parametre2.
Un paramètre optionnel doit être énoncé APRÈS les paramètres obligatoires.
On peut envoyer à une fonction une variable de deux façon différentes. Soit on envoie la variable elle-même, soit une copie.
Pour envoyer une variable dans une fonction ou sous-routine, sans modifier ce nombre, on peut envoyer une copie de la variable à la fonction.
Se fait en utilisant le mot-clé ByVal. De ce fait, la valeur réelle de la variable n’est pas modifiée.
Si on utilise le mot-clé ByRef, on envoie la référence de la variable (l’adresse), la sous-routine peut alors accéder à la
vraie valeur et la modifier. Dans ce cas, la variable est modifiée même dans la procédure qui appelle la sous-routine ou la fonction.
Par défaut, les arguments sont passés par référence.
' Passe la référence en argument.
Sub MaProcedure_1(ByRef x As Integer)
x = x * 2
End Sub
' Passe la valeur en argument.
Sub MaProcedure_2(ByVal y As Integer)
y = y * 2
End Sub
' ByRef est la valeur par défaut si non spécifiée.
Sub MaProcedure_3(z As Integer)
z = z * 2
End Sub
Sub Test()
' On utilise une variable pour la faire changer
Dim nombre_a_change As Integer
nombre_a_change = 50
' On applique à notre variable la première sous-routine
MaProcedure_1 nombre_a_change
MsgBox nombre_a_change
' On applique à notre variable la deuxième sous-routine
MaProcedure_2 nombre_a_change
MsgBox nombre_a_change
' On applique à notre variable la troisième sous-routine
MaProcedure_3 nombre_a_change
MsgBox nombre_a_change
End Sub
Étant donné que la variable est passée grâce à la référence, la variable est modifiée dans la sous-routine mais aussi dans la procédure qui appelait la sous-routine. Dans un second temps, on applique la deuxième sous-routine. Dans celle-ci, on envoie une copie de la valeur. Elle fait le même calcul mais avec une copie. Enfin, dans la troisième, aucun mot-clé n’est utilisé. Par défaut nous envoyons la référence et donc la vraie valeur à la sous-routine. Celle-ci effectue donc le même calcul et modifie la variable de la procédure appelante.
Les boîtes de dialogue usuelles: MsgBox et InputBox (qui permet de récupérer des informations)
MsgBox (Prompt, [Buttons] As VbMsgBoxStyle = vbOkOnly, [title],
[helpfile], [context]) As VbMsgBoxResult
La fonction peut prendre jusqu’à 5 paramètres. Le As permet de préciser le type de valeur qu’il faut indiquer ou que la fonction
retourne.
Dans une MsgBox à trois boutons, c’est bien la valeur de retour (stockée dans une variable) qui permettra de savoir où a cliqué l’utilisateur et d’agir en conséquence ! MsgBox() retourne un Long, c’est-à-dire un entier.
Sub maBoite()
Dim retour As Long
retour = MsgBox ( Prompt := " Je suis un Zér0 !" )
End Sub
:= permet d’indiquer le paramètre auquel nous attribuons une valeur
La syntaxe suivante est tout aussi correcte :
retour = MsgBox ( " Je suis un Zér0 !" )
prompt est le seul paramètre obligatoire, il attend une chaîne de caractères (String) et représente le message qui sera affiché dans la boîte.
Le paramètre buttons n’est pas obligatoire. A la place, il faut mettre une constante du type VbMsgBox. Par défaut, VBA applique la constante vbOkOnly, ce qui veut dire que par défaut, toutes vos MsgBox auront un bouton Ok. VBA met à disposition plusieurs constantes, à appeler par leur nom (vbOkOnly, vbOkCancel, vbYesNoCancel, vbYesNo) ou par leur valeur numérique (0, 1, 2, 3; respectivement).
Par exemple, pour créer une MsgBox qui affiche “ Salut ! “ et qui propose comme boutons “ Ok “ et “ Annuler “ :
retour = MsgBox ( Prompt := " Salut ! ", Buttons := vbOkCancel)
ou encore :
retour = MsgBox (" Salut ! ", 1)
La première solution, plus explicite, est à préférer.
Programmation événementielle: exécuter tel ou tel bloc d’instructions en fonction du signal reçu par le programme - signal généralement émis par l’utilisateur.
La valeur renvoyée par MsgBox dépend du bouton pressé par l’utilisateur.
Bouton -> Constante de retour -> Valeur numérique retour
OK -> vbok -> 1
Annuler -> vbCancel -> 2
Oui -> vbYes -> 6
Non -> vbNo -> 7
Exemple:
Sub questionVitale()
Dim retour As Long
' on crée une MsgBox "Oui - Non ":
retour = MsgBox( Prompt := "Êtes-vous vraiment un Zér0 ?", Buttons
:= vbYesNo )
'Si on a cliqué sur Oui, on souhaite la bienvenue :
If retour = vbYes Then
MsgBox "Bienvenue !"
'Sinon, on affiche un autre message moins amical :) :
Else
MsgBox "Ouste !"
End If
End Sub
If retour = vbYes peut être remplacé par If retour = 6, équivalent.
La fonction InputBox() permet de créer une boîte de dialogue avec un champ de texte pour que
l’utilisateur y saisisse quelque chose. Prototype:
InputBox(Prompt, [Title], [Default], [XPos], [YPos], [HelpFile], [Context]) As String
La fonction renvoie un String, c’est-à-dire une chaîne de caractères. Que soit saisi un mot ou un nombre, il sera converti en String.
Quelques fonctions d’Excel utiles: SOMME, PRODUIT, QUOTIENT, MOD, PGCD, SOMME.SI, SOMMEPROD, RACINE, PI, ARRONDI, ARRONDI.INF, ARRONDI.SUP, SI, ET, OU, SIERREUR, COLONNE, LIGNE, RECHERCHEV, RECHERCHEH, RECHERCHE, TRANSPOSE, MAX, MIN, MOYENNE, MEDIANE, ECARTYPE, FREQUENCE, NB, NBVAL, NB.VIDE, NB.SI, CONCATENER, EXACT, CHERCHE, DROITE, GAUCHE, MAJUSCULE, MINUSCULE, NOMPROPRE, NBCAR, REMPLACER
Quelques fonctions Date et Heure: AUJOURDHUI, MAINTENANT, ANNEE, MOIS, JOUR, HEURE, MINUTE, SECONDE, JOURSE, NO.SEMAINE, DATE, NB.JOURS.OUVRES, SERIE.JOUR.OUVRE
Retour de fonctions
(source: https://docs.microsoft.com/fr-fr/dotnet/visual-basic/programming-guide/language-features/procedures/how-to-return-a-value-from-a-procedure)
(source: https://docs.microsoft.com/fr-fr/dotnet/visual-basic/language-reference/statements/function-statement#returning-from-a-function)
Pour retourner une valeur à partir d’une fonction, on peut affecter la valeur au nom de la fonction ou l’inclure dans une instruction Return.
1) Return assigne simultanément la valeur de retour et quitte la fonction:
Function MyFunction(ByVal j As Integer) As Double
Return 3.87 * j
End Function
2) À au moins un emplacement dans la Function, assigner une valeur au nom de la procédure. Quand on exécute Exit Function End Function, la dernière valeur assignée au nom de la procédure sera retournée. L’exemple suivant affecte la valeur de retour au nom de la fonction myFunction, puis utilise l’ Exit Function instruction pour retourner.
Function MyFunction(ByVal j As Integer) As Double
MyFunction = 3.87 * j
Exit Function
End Function
Les Exit Function et Return <instructions> provoquent une sortie immédiate d’une Function. Un nombre quelconque d’Exit Function et Return <instructions> peuvent apparaître n’importe où dans la procédure, et ces instructions peuvent être mélangées (mais on ne peut avoir qu’un seul End Function)
Si on utilise Exit Function sans assigner de valeur au nom de la fonction, la procédure retourne la valeur par défaut pour le type de données spécifié comme returntype. Si returntype n’est pas spécifié, la procédure retourne Nothing, la valeur par défaut pour Object.
Exemple: créer un damier coloré avec 1 case sur 2 grisée (source: https://www.excel-pratique.com/fr/vba/boucles_suite)
Sub exerciceBoucles()
Dim colonne As Integer, ligne As Integer
'Boucle des lignes
For ligne = 1 To 10
'Boucle des colonnes
For colonne = 1 To 10
Cells(ligne, colonne) = (ligne - 1) * 10 + colonne
'Coloration d'une cellule sur 2
If (ligne + colonne) Mod 2 = 0 Then 'Si le reste de la division par 2 = 0
Cells(ligne, colonne).Interior.Color = RGB(220, 220, 220)
End If
Next
Next
End Sub
Exemple: utilisation d’une variable pour sélectionner une cellule (& pour la concaténation !)
(source: https://docs.microsoft.com/fr-fr/office/vba/library-reference/concepts/getting-started-with-vba-in-office)
Sub Macro1()
If Worksheets(1).Range("A1").Value = "Yes!" Then
Dim i As Integer
For i = 2 To 10
Worksheets(1).Range("A" & i).Value = "OK! " & i
Next i
Else
MsgBox "Put Yes! in cell A1"
End If
End Sub
Exemple: supprimer des lignes vides dans une feuille de calcul Excel (source: https://docs.microsoft.com/fr-fr/office/vba/library-reference/concepts/getting-started-with-vba-in-office)
Sub DeleteEmptyRows()
SelectedRange = Selection.Rows.Count
ActiveCell.Offset(0, 0).Select
For i = 1 To SelectedRange
If ActiveCell.Value = "" Then
Selection.EntireRow.Delete
Else
ActiveCell.Offset(1, 0).Select
End If
Next i
End Sub
Les objets Excel
(source: https://www.lecompagnon.info/vba-excel/vba_objetsExcel.htm)
Les cellules Excel sont des objets de la classe Range.
Range("plage")est un objet contenant la plage nommée…plage(accessible après avoir nommé cette plage dans Excel).Range("A1:H5")est un objet contenant la plageA1:H5Evaluate("A1:H5")ou[A1:H5]est équivalent exactement àRange("A1:H5").Cells(3,5)est un objet contenant la celluleE5(ligne 3, colonne 5). Attention !Cellsutilise l’adressage Ligne, Colonne, alors que Excel utilise Colonne, Ligne.Range("A1").Offset(3,5)est un objet contenant la plage F4 soit un déplacement de 3 lignes et 5 colonnes à partir deA1.
Ces deux dernières techniques peuvent être utilisées avec l’objet Range pour désigner des plages.
Range(Cells(3,5), Range("A1").Offset(3,5))est un objet contenant la plageE3:F4.
L’utilisation d’un nom de plage au lieu d’une adresse permettra de déplacer la plage dans Excel sans devoir modifier la programmation VBA. Il est donc FORTEMENT suggéré de manipuler les lignes d’une liste de données ainsi:
- Nommez la cellule de gauche de l’entête de liste.
- Utilisez la notation
Range(nom).Offset(ligne,colonne)pour représenter les champs de la liste.
Pas de différence entre une plage et une cellule (une cellule est simplement une plage ne contenant qu’une cellule).
Range("A1:B9") est un objet de la même classe que Range("A1") et possède donc les mêmes propriétés (dont les valeurs peuvent être différentes) et méthodes.
Un objet Range est aussi une collection de cellules. Comme une cellule est un Range (d’une cellule), c’est une collection ne comptant qu’un objet.
Un Range est donc une collection de collections.
Certaines propriétés du modèle objet Excel contiennent des plages spécifiques:
Cells= Plage qui contient toutes les cellules d’une feuille:ActiveSheet.Cells Sheets("Province").CellsUsedRange= Plage qui contient TOUTES les cellules occupées d’une feuille:ActiveSheet.UsedRange Sheets("Province").UsedRangeCurrentRegion= Plage continue (limitée par des lignes et des colonnes vides) dont fait partie la cellule:Range("Titre").CurrentRegionRows= Collection des lignes d’une plage. Permet d’obtenir une ligne d’une plage:Range("ListeProvinces").Rows(1) Range("Titre").CurrentRegion.Rows(1)Columns= Collection des colonnes d’une plage. Permet d’obtenir une colonne d’une plage:Range("ListeProvinces").Columns(1) Range("Titre").CurrentRegion.Columns(1)SpecialCells= Plages spéciales d’une plage Excel:SpecialCells(xlCellTypeBlanks) Cellules vides SpecialCells(xlCellTypeConstants). Cellules contenant des constantes SpecialCells(xlCellTypeFormulas). Cellules contenant des formules SpecialCells(xlCellTypeLastCell). Dernière cellule dans la plage utilisée SpecialCells(xlCellTypeVisible).Toutes les cellules visibles ...
Quelques propriétés des objets Range:
ColumnNuméro de la colonne de gauche de la plage.Range("B4:H6").Columnvaut 2Columns.CountNombre de colonnes de la plage.Range("B4:H6").Columns.Countvaut 7RowNuméro de la ligne du haut de la plageRows.CountNombre de lignes de la plageCountNombre de cellules de la plageCurrentRegionPlage continue (limitée par des lignes et des colonnes vides) dont fait partie la cellule.End(xlDown)Cellule de la dernière ligne à la fin de la zone qui contient la plage. Correspond aux touches Fin+Bas.End(xlToRight)Cellule de la dernière colonne à la fin de la zone qui contient la plage. Correspond aux touches Fin+Droite.TextValeur AFFICHÉE de la cellule, donc évaluée et formatée.ValueValeur ÉVALUÉE de la cellule.WorksheetObjetWorksheetqui est la feuille qui contient la plage
Les feuilles Excel sont des objets de la classe Worksheet.
Elles sont regroupées dans la collection Worksheets et dans la collection Sheets.
On peut manipuler une feuille de classeur par son nom:
Worksheets("Provinces")est la feuille nommée province.Sheets("Provinces")est aussi la feuille nommée province.
Différence: la collection Sheets contient aussi les objets Chart du classeur.
Les classeurs Excel sont des objets de la classe Workbook.
Tous les classeurs ouverts sont regroupés dans la collection Workbooks.
Workbook("VBA Exemples.xls")est le classeur VBAExemples.xls
La programme Excel lui-même, lorsque démarré, est un objet de la classe Application.
Le classeur actif est: Application.ActiveWorkbook ou plus simplement ActiveWorkbook.
Le classeur contenant le code VBA en cours d’exécution est: Application.ThisWorkbook ou plus simplement ThisWorkbook.
La feuille active du classeur actif est: Application.ActiveWorkbook.ActiveSheet ou plus simplement ActiveSheet.
La cellule active de la feuille active du classeur actif est: Application.ActiveWorkbook.ActiveSheet.ActiveCell ou plus simplement ActiveCell.
La cellule active de la feuille nommée Province du classeur actif est: Application.ActiveWorkbook.Worksheets("Province").ActiveCell ou plus simplement Worksheets("Province").ActiveCell.
L’objet Selection est l’objet passe-partout, qui contient ce qui est sélectionné dans le classeur Excel. Ce peut être une plage, un graphique, un tableau croisé ou n’importe quoi. L’utilisation de Selection en VBA est à éviter, puisqu’il risque fort de contenir une sélection inattendue lors de l’exécution du programme.
La barre d’état de la fenêtre Excel est l’objet StatusBar.
Méthodes Excel
La plupart des opérations que l’utilisateur peut faire en Excel peuvent être programmées en VBA grâce aux méthodes des différents objets du modèle objet Excel.
Voici les plus intéressantes:
EvaluatePermet d’exécuter en VBA une formule Excel (ce qui est à droite du signe = dans une cellule). Peut être remplacée par les par les crochets:[2+2]équivaut àEvaluate("2+2")et vaut 4. Attention ! ce qui est incorrect dans une cellule est incorrect pourEvaluate.[A1]` équivaut à `Range("A1").Value` `[Sum("A2:H6")]` exécute la formule Excel `Somme("A2:H6")`IntersectRetourne une plage formée des cellules communes de deux plages. Cette méthode permet de savoir si une cellule appartient à une plage.Intersect(Range("A1:C4"),Range("B2:D5"))` ' équivaut à `Range("B2:C4") (Intersect(Range("B6"),Range("Provinces") is Nothing)` ' est faux si `B6` fait partie de la plage `Provinces`.CalculateRecalcule la feuille ou le classeur Excel. ` Calculate;ActiveWorksheet.Calculate`SaveEnregistre le classeurActiveWorkbook.SaveQuitFerme Excel. Attention, si le classeur a été modifié mais non sauvegardé, la boîte de dialogue de sauvegarde d’Excel sera affichée.`Application.Quit`Clear,ClearContents,ClearFormatsEffacent respectivement les cellules, les contenus ou les formats d’une plage.Range("A1").Clear Worksheet("Tableaux").ClearCopyCopie le contenu d’une plage dans une autre ou dans le presse-papierRange("A1").Copy Range("B1") 'copie le contenu de A1 dans B1 Range("A1").Copy 'copie le contenu de A1 dans le presse-papier>PasteSpecial Colle le contenu d’une plage ou du presse-papier dans une plage. On peut spécifier le type de collage spécial: xlPasteAll (défaut), xlPasteAllExceptBorders, xlPasteColumnWidths. xlPasteComments, xlPasteFormats, xlPasteFormulas, xlPasteFormulasAndNumberFormats, xlPasteValidation, xlPasteValues ou xlPasteValuesAndNumberFormats.
Range("Total").Copy ' copie la plage Total dans le presse-papier Range("A1").PasteSpecial (xlPasteValues) copie la VALEUR du presse-papier dans la cellule A1. li>FindetFindNextCes deux méthodes permettent d’effectuer une recherche dans une plage de cellules.SelectSélectionne une cellule ou une feuille Excel. À éviter la plupart du temps en programmation VBA, car le déplacement du curseur Excel est rarement souhaitable pendant l’exécution d’un programme VBA.SortTri de plage. Voir l’aide VBA Excel pour en connaître le fonctionnement. Il est aussi utile d’utiliser l’enregistreuse de macro-commandes sur un tri manuel des données pour en analyser les paramètres.
Principaux événements Excel
Objet -> Événement -> Paramètres -> Se produit lorsque
WorkbookOpen- Le classeur Excel est ouvertWorkbookBeforeCloseCancelLorsqu’une demande de fermeture du classeur a été faiteWorkbookSheetChangeSheetla feuille modifiée;Targetla plage modifiée Lorsqu’une cellule ou plage du classeur est modifiéeWorksheetChangeTargetla plage modifiée Lorsqu’une cellule ou plage de la feuille qui contient la procédureSubest modifiéeWorksheetSelectionChangeTargetla nouvelle plage sélectionnée Lors de la sélection d’une autre plage dans un classeur
Remarquez que dans les événements SheetChange, Change et SelectionChange, VBA n’a pas directement accès aux valeurs précédant le changement, ni à un paramètre Cancel pour annuler le changement. Il faut utiliser une astuce pour empêcher le changement.
On peut désactiver le traitement des événements, en utilisant la propriété EnableEvents.
Autres objets intéressants
Me
C’est un objet Excel ou VBA contenant le code en cours d’exécution. Si le code appartient à une feuille, c’est un objet Worksheet contenant cette feuille.
Me est le plus souvent utilisé pour désigner le formulaire VBA (Forms) contenant le code en cours d’exécution. On évite ainsi de nommer le formulaire
dans le code VBA , ce qui donne des programmes plus faciles à utiliser dans d’autres formulaires.
Me.Namecontient le nom du formulaire en cours d’exécution.-
Me.Close(utilisation la plus fréquente) ferme le formulaire qui contient cette ligne. Err
C’est un objet VBA contenant la dernière erreur rencontrée. Ses propriétés permettent d’en connaître la nature:
Err.Descriptioncontient la description de la dernière erreur rencontrées par VBA.
VBA peut déclencher une erreur avec Err:
-Err.Raise 18 simule une interruption par l’utilisateur (Ctrl-Break).
FileSystemObjectC’est l’objet contenant des instructions permettant à VBA d’accéder à l’arborescence de dossiers et de fichiers de l’ordinateur. ATTENTION ce n’est pas un objet VBA ni un objet Excel, mais un objet de la librairie Microsoft Scripting Runtime.
Objets intéressants:
DrivesCollection d’objets DriveDriveObjet contenant un lecteurFoldersCollection d’objets FolderFolderObjet contenant un dossierFilesCollection d’objets FileFileObjet contenant un fichier
Un objet FileSystemObject contient une collection Drives.
Chaque objet Drive de la collection Drives contient une collection Folders et une collection Files.
Chaque objet Folder d’une collection Folders contient une collection Folders et une collection Files.
Chaque objet File d’une collection Files contient un fichier (document Windows).
Cette structure permet de parcourir l’arborescence de documents en VBA comme avec l’explorateur Windows.
####### Objet implicite (With)
Il arrive fréquemment qu’une série d’instructions utilise le même objet. L’écriture (et la lecture) du code VBA devient alors fastidieuse, avec la répétition incessante de la même référence.
L’instruction With permet de réduire les répétitions. Par exemple le code:
If Target.Interior.Color = Range("CouleurVerrou").Interior.Color Then
Application.EnableEvents = False 'Empêcher une boucle d'événements
Application.Undo 'Annuler le changement
Application.EnableEvents = True 'Très important de réactiver
End If
peut être remplacé par celui-ci:
With Application
If Target.Interior.Color = Range("CouleurVerrou").Interior.Color Then
.EnableEvents = False 'Empêcher une boucle d'événements
.Undo 'Annuler le changement
.EnableEvents = True 'Très important de réactiver
End If
End With
Boites de dialogue et formulaire:
https://www.lecompagnon.info/vba-excel/vba_dialogues_et_formulaires.htm
Exercices Objets Excel
(source: https://www.lecompagnon.info/vba-excel/vba_objetsExcel.htm) Exemple 1: Changer la couleur d’arrière-plan des cellules modifiées.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
'Changer l'arrière-plan d'une cellule modifiée
'Target est la plage modifiée (voir les paramètres de la procédure, ci-dessus)
Target.Interior.Color = vbYellow 'Jaune
End Sub
Il est possible de restreindre les modifications à une seule feuille:
- en insérant le code dans la procédure événementielle Worksheet_Change du module associé à la feuille voulue; ou
- en insérant un test sur le nom de la feuille (
Sh.Name) dans le code suggéré (en le laissant dans le module associé au classeur) (cette solution limite l’éparpillement du code dans plusieurs modules et produit donc un programme plus facile à comprendre et à modifier plus tard)
Exemple 2: Une fonction qui affiche le contenu réel d’une cellule.
Function fnValeurCellule(rCellule)
'Retourne le contenu (formule ou valeur) de la cellule en paramètre
If TypeName(rCellule) <> "Range" Then ' <> est pour "différent de"
fnValeurCellule = "Erreur de paramètre"
Exit Function
End If
fnValeurCellule = rCellule.Formula
End Function
Exemple 3: Empêcher la modification des cellules dont l’arrière-plan est rouge.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
'Empêcher la modification de cellules dont l'arrière-plan est d'une couleur choisie par l'utilisateur
'Note: la feuille doit contenir une cellule nommée CouleurVerrou de la couleur choisie
'Target est la plage modifiée (voir les paramètres de la procédure, ci-dessus)
If Target.Interior.Color = Range("CouleurVerrou").Interior.Color Then
Application.EnableEvents = False 'Empêcher une boucle d'événements
Application.Undo 'Annuler le changement
Application.EnableEvents = True 'Très important de réactiver
End If
End Sub
L’utilisation de la propriété EnableEvents pour empêcher que l’instruction suivante (la méthode Undo) provoque l’événement Workbook_SheetChange et entraîne ainsi une succession sans fin d’exécution de la procédure Sub correspondante (Workbook_SheetChange appelant Workbook_SheetChange appelant Workbook_SheetChange, etc.)
Exemple 4: Empêcher la modification des cellules ne faisant pas partie d’une plage.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
'Empêcher la modification de cellules en dehors d'une plage nommée ZoneDeSaisie
'Note: le classeur doit contenir une plage nommée ZoneDeSaisie
'Target est la plage modifiée (voir les paramètres de la procédure, ci-dessus)
If Intersect(Target, Range("ZoneDeSaisie")) Is Nothing Then
Application.EnableEvents = False 'Empêcher une boucle d'événements
Application.Undo 'Annuler le changement
Application.EnableEvents = True 'Très important de réactiver
End If
End Sub
Exemple 5: Empêcher le déplacement du curseur Excel tant qu’une condition n’est pas respectée.
L’événement qui nous intéresse est SelectionChange, qui n’a pas de paramètre Cancel, donc qu’on ne peut pas annuler directement.
La méthode Undo ne fonctionne pas non plus, car elle n’annule pas le déplacement. De plus, elle risquerait d’annuler une modification, alors qu’on ne veut annuler que le déplacement.
Il faudra donc que le programme garde trace de la dernière cellule sélectionnée.
Function fnDéplacementValide()
'Retourne Vrai si la somme des cellules de la plage ZoneDeSaisie est égale à 10
fnDéplacementValide = ([sum(ZoneDeSaisie)] = 10)
End Function
Function fnPlageAdansPlageB(plageA, PlageB)
'Retourne Vrai si plageA est complètement dans PlageB ou l'inverse
If Intersect(plageA, PlageB) Is Nothing Then
fnPlageAdansPlageB = False
Else
fnPlageAdansPlageB = (Intersect(plageA, PlageB).Count = plageA.Count)
End If
End Function
Exemple 6: Trouver toutes les cellules d’une feuille contenant le mot Liberté.
Function fnTrouveMotDansPlage(sMot, rPlage)
'Retourne une plage formée des cellules de rPlage contenant sMot
Dim rTrouvée As Range 'contiendra les cellules trouvées
Dim rCellule As Range 'contiendra chaque cellule testée, à tour de rôle
For Each rCellule In rPlage 'Pour chaque cellule de rPlage
'Si sMot est dans rCellule
If InStr(UCase(rCellule.Value), UCase(sMot)) > 0 Then
If rTrouvée Is Nothing Then 'Première cellule trouvée
Set rTrouvée = rCellule
Else 'Cellules trouvées suivantes
Set rTrouvée = Union(rTrouvée, rCellule)
End If
End If
Next
Set fnTrouveMotDansPlage = rTrouvée
End Function
Le nombre de cellules contenant le mot Liberté trouvées dans la plage A1:C6 peut maintenant être obtenu avec l’expression VBA:
fnTrouveMotDansPlage("Liberté", Range("A1:C6")).Count
ou avec la formule Excel
=NBVAL(fnTrouveMotDansPlage("Liberté";A1:C6))
On peut mettre ces cellules en rouge avec l’instruction VBA:
fnTrouveMotDansPlage("Liberté", Range("A1:C6")).interior.color = vbRed
- Puisqu’elle retourne une plage de cellules, elle ne peut pas être utilisée directement dans une cellule du classeur Excel. En effet, une cellule ne peut pas contenir une plage.
- Mais on peut l’utiliser comme paramètre de type plage dans une fonction Excel (cf. deuxième utilisation ci-dessus)
- La fontion
Excel Nb.Si()joue un rôle semblable, mais dans sa version simple(=NB.SI(A1:C6;"Liberté"))ne comptera que les cellules dont la valeur est égale à la valeur cherchée, contrairement àfnTrouveMotDansPlagequi trouve les cellules qui contiennent la valeur. De plus,fnTrouveMotDansPlageretourne la plage et non le nombre. On peut donc manipuler le résultat en VBA en lui assignant un nom de variable:dim rPlageTrouvée as Range Set rPlageTrouvée = fnTrouveMotDansPlage("Liberté", Range("A1:C6"))
Le même résultat peut être obtenu en utilisant les méthodes Find et Findnext dans une boucle cherchant les cellules d’une plage.
Function fnTrouveMotDansPlage(sMot, rPlage)
'Retourne une plage formée des cellules de rPlage contenant sMot
Dim rTrouvées As Range
Dim rCelluleTrouvée As Range
Dim rPremièreTrouvée As Range
Set rCelluleTrouvée = rPlage.Find(sMot)
If rCelluleTrouvée Is Nothing Then
Exit Function 'Aucune occurrence
End If
'Find et FindNext trouveront toutes les occurrences,
'puis recommenceront à la première
'Il faut donc chercher jusqu'à ce qu'on trouve la première à nouveau.
Set rPremièreTrouvée = rCelluleTrouvée
Set rTrouvées = rCelluleTrouvée
Set rCelluleTrouvée = rPlage.FindNext(rCelluleTrouvée)
Do While Not rCelluleTrouvée = rPremièreTrouvée
Set rTrouvées = Union(rTrouvées, rCelluleTrouvée)
Set rCelluleTrouvée = rPlage.FindNext(rCelluleTrouvée)
Loop
Set fnTrouveMotDansPlage2 = rTrouvées
End Function
Exemple 7: Obtenir le nom et la taille du dossier contenant le classeur Excel actif.
Function fnDossier(Optional param = 0)
'Retourne le nom du dossier et/ou l'espace qu'il utilise
'La ligne suivante requiert une référence à Microsoft Scripting Runtime
Dim fso As New Scripting.FileSystemObject
If param = 1 Then
fnDossier = ActiveWorkbook.Path
Exit Function
ElseIf param = 2 Then
fnDossier = (fso.GetFolder(ActiveWorkbook.Path).Size) / 1024
Exit Function
Else
fnDossier = ActiveWorkbook.Path & ": " & _
Round(fso.GetFolder(ActiveWorkbook.Path).Size / 1024, 2) & _
" Ko"
End If
End Function
Une fonction ne peut retourner qu’une seule valeur, alors qu’ici on veut le nom te la taille du dossier. On utilise donc un paramètre pour spécifier la valeur voulue (1 retourne le nom, 2 retourne la taille), et si le paramètre est omis, la fonction retourne les deux dans une chaîne de caractères.
Exercices Tests et branchements
(source: https://www.lecompagnon.info/vba-excel/vba_tests.htm) Exemple 1: Tester si une cellule Excel nommée “Nombre” contient un nombre.
Sub sExempleTest2()
'Vérifier si la cellule "Nombre" contient un nombre
If Not IsNumeric(Range("Nombre").Value) Then
MsgBox"La valeur n'est pas numérique"
Exit Sub
End If
End Sub
Exemple 2: Programmer une fonction qui retourne le nom d’une province, à partir d’un sigle.
Function fnNomProvince2(SigleProvince)
'Auteur: Michel Berthiaume
'Retourner le nom d'une province
Dim sSigleProvince As String
'D'abord tester la validité du paramètre
If TypeName(SigleProvince) = "Range" Then
sSigleProvince = UCase(SigleProvince.Value)
ElseIf TypeName(SigleProvince) = "String" Then
sSigleProvince = UCase(SigleProvince)
Else
fnNomProvince2 = "sigle inconnu"
Exit Function
End If
'Rendu ici, sSigleProvince contient une version en majuscules du sigle
If sSigleProvince = "AB" Then
fnNomProvince2 = "Alberta"
ElseIf sSigleProvince = "BC" Then
fnNomProvince2 = "Colombie Britannique"
ElseIf sSigleProvince = "PE" Then
fnNomProvince2 = "Île-du-Prince-Édouard"
ElseIf sSigleProvince = "NS" Then
fnNomProvince2 = "Nouvelle-Écosse"
ElseIf sSigleProvince = "NU" Then
fnNomProvince2 = "Nunavut"
ElseIf sSigleProvince = "ON" Then
fnNomProvince2 = "Ontario"
ElseIf sSigleProvince = "QC" Then
fnNomProvince2 = "Québec"
ElseIf sSigleProvince = "SK" Then
fnNomProvince2 = "Saskatchewan"
ElseIf sSigleProvince = "NF" Then
fnNomProvince2 = "Québec"
ElseIf sSigleProvince = "NT" Then
fnNomProvince2 = "Territoires du Nord-Ouest"
ElseIf sSigleProvince = "YK" Then
fnNomProvince2 = "Yukon"
Else
fnNomProvince2 = "Sigle inconnu"
End If
End Function
ou en utilisant l’Instruction Select (sans avantage important sur la version précédente):
Function fnNomProvince3(SigleProvince)
'Retourner le nom d'une province
Dim sSigleProvince As String
'D'abord tester la validité du paramètre
If TypeName(SigleProvince) = "Range" Then
sSigleProvince = UCase(SigleProvince.Value)
ElseIf TypeName(SigleProvince) = "String" Then
sSigleProvince = UCase(SigleProvince)
Else
fnNomProvince3 = "sigle inconnu"
Exit Function
End If
'Rendu ici, sSigleProvince contient une version en majuscules du sigle
Select Case sSigleProvince
Case "AB"
fnNomProvince3 = "Alberta"
Case "BC"
fnNomProvince3 = "Colombie Britannique"
Case "PE"
fnNomProvince3 = "Île-du-Prince-Édouard"
Case "NS"
fnNomProvince3 = "Nouvelle-Écosse"
Case "NU"
fnNomProvince3 = "Nunavut"
Case "ON"
fnNomProvince3 = "Ontario"
Case "QC"
fnNomProvince3 = "Québec"
Case "SK"
fnNomProvince3 = "Saskatchewan"
Case "NF"
fnNomProvince3 = "Québec"
Case "NT"
fnNomProvince3 = "Territoires du Nord-Ouest"
Case "YK"
fnNomProvince3 = "Yukon"
Case Else
fnNomProvince3 = "Sigle inconnu"
End Select
End Function
Exercices: Erreurs
(source: https://www.lecompagnon.info/vba-excel/vba_erreurs.htm)
Exemple 1: Capturer n’importe quelle erreur
Function fnMoyenneMoinsMin(rPlage)
'Calculer la moyenne 'moins la valeur la plus basse des valeurs d'une plage
Dim cSomme As Currency
Dim cMin As Currency
Dim rCellule As Range
On Error GOTO Erreur:
'Initialiser à la 1ère valeur de la plage
cMin = rPlage.Cells(1, 1).Value
For Each rCellule In rPlage
cSomme = cSomme + rCellule.Value
cMin = fnMin(rCellule.Value, cMin)
Next
fnMoyenneMoinsMin = (cSomme - cMin) / (rPlage.Count - 1)
Exit Function
Erreur:
fnMoyenneMoinsMin = "Erreur: " & Err.Description
End Function
Remarquez la présence de Exit Function avant l’étiquette Erreur: évite que la gestion d’erreur soit exécutée lorsqu’il n’y a pas d’erreur. La présence d’une étiquette n’interrompt pas la procédure.
Exemple 2: Capturer une erreur spécifique
Sub EnregistrerClasseur()
'enregistrer le classeur
On Error GoTo Erreur:
ActiveWorkbook.Save
Exit Sub
Erreur:
If Err.Number = 1004 Then
If MsgBox("Le fichier est en lecture seule. SVP corriger et cliquer Ok" & _
vbCrLf & "ou cliquer annuler", vbOKCancel) = vbOK Then
Resume
End If
End If
End Sub
Exemple 3: utiliser la gestion d’erreur à d’autres fins
Function fnMin(a, b)
'Retourne le minimum de a ou b
'Retourne Null si la comparaison est impossible
On Error GoTo Erreur
If a < b Then
fnMin = a
Else
fnMin = b
End If
Exit Function
Erreur: 'Gère les comparaisons impossibles, comme les pommes vs les oranges
fnMin = ""
End Function
Exercices: Boucles
(source: https://www.lecompagnon.info/vba-excel/vba_boucles.htm)
Exemple 1: boucle de collection
Supposons une plage de cellules Excel nommée ListeProvinces: écrire une fonction VBA qui retourne le nom associé au sigle
Function fnNomProvince4(SigleProvince)
'Retourner le nom d'une province
Dim sSigleProvince As String
Dim rCellule As Range
fnNomProvince4 = "sigle inconnu" 'Réponse par défaut
'D'abord tester la validité du paramètre
If TypeName(SigleProvince) = "Range" Then
sSigleProvince = UCase (SigleProvince.Value)
ElseIf TypeName(SigleProvince) = "String" Then
sSigleProvince = UCase(SigleProvince)
Else
Exit Function
End If
'Rendu ici, sSigleProvince contient une version en majuscules du sigle
'Pour chaque cellule de colonne 1 de la plage nommée ListeProvinces
For Each rCellule In Range("ListeProvinces").Columns(1).Cells
If sSigleProvince = UCase(rCellule.Value) Then 'Valeur trouvée
fnNomProvince4 = rCellule.Offset(0, 1).Value 'Valeur de la cellule à droite
Exit For 'inutile de continuer: on sort de la boucle.
End If
Next
End Function
La même, en utilisant un compteur de lignes:
Function fnNomProvince5(SigleProvince)
'Auteur: Michel Berthiaume
'Retourner le nom d'une province
Dim sSigleProvince As String
Dim lLigne as Long
fnNomProvince5 = "sigle inconnu" 'Réponse par défaut
'D'abord tester la validité du paramètre
If TypeName(SigleProvince) = "Range" Then
sSigleProvince = UCase (SigleProvince.Value)
ElseIf TypeName(SigleProvince) = "String" Then
sSigleProvince = UCase(SigleProvince)
Else
Exit Function
End If
'Rendu ici, sSigleProvince contient une version en majuscules du sigle
'On fait varier lLigne de 1 au nombre de lignes de la plage nommée ListeProvinces
For lLigne = 1 to Range("ListeProvinces").Rows.Count
If sSigleProvince = Range("ListeProvinces").Cells(lLigne, 1).Value Then
fnNomProvince5 = Range("ListeProvinces").Cells(lLigne, 2).Value 'Valeur de la cellule à droite
Exit For 'inutile de continuer: on sort de la boucle.
End If
Next
End Function
Exemple 2: boucle avec compteur et accumulateur
On veut une fonction fnMoyennePlus qui calcule la moyenne des valeurs positives d’une plage.
Function fnMoyennePlus(Plage)
'Calculer la moyenne des valeurs positives d'une plage
Dim cSomme as Currency
Dim cCompteur as Currency
Dim rCellule as Range
'D'abord tester la validité du paramètre
If TypeName(Plage) <> "Range" Then
Exit Function
End If
For each rCellule in Plage
If rCellule.Value > 0 Then
cSomme = cSomme + rCellule.Value
cCompteur = cCompteur +1
End If
Next
If cCompteur > 0 Then 'Éviter les divisions par 0
fnMOyennePlus = cSomme/cCompteur
EndIf
End Function
Une variante de la même fonction:
Function fnMoyennePlus1(Plage)
'Calculer la moyenne des valeurs positives d'une plage
Dim lNoCellule As Long
Dim cSomme as Currency
Dim cCompteur as Currency
Dim rCellule as Range
'D'abord tester la validité du paramètre
If TypeName(Plage) <> "Range" Then
Exit Function
End If
For lNoCellule = 1 to Plage.Cells.Count
If Plage.Cells(lNoCellule).Value > 0 Then
cSomme = cSomme + Plage.Cells(lNoCellule).Value
cCompteur = cCompteur + 1
End If
Next
If cCompteur > 0 Then 'Éviter les divisions par 0
fnMoyennePlus1 = cSomme/cCompteur
EndIf
End Function
Finalement, une variante plus classique de cette solution, utilisant un compteur de lignes et un compteur de colonnes:
Function fnMoyennePlus2(Plage)
'Calculer la moyenne des valeurs positives d'une plage
Dim lNoLigne As Long
Dim lNoColonne As Long
Dim cSomme as Currency
Dim cCompteur as Currency
Dim rCellule as Range
'D'abord tester la validité du paramètre
If TypeName(Plage) <> "Range" Then
Exit Function
End If
For lNoLigne = 1 to Plage.Rows.Count 'Pour chaque ligne
For lNoColonne = 1 to Plage.Columns.Count 'Pour chaque colonne
If Plage.Cells(lNoLigne,lNoColonne).Value > 0 Then
cSomme = cSomme + Plage.Cells(lNoLigne,lNoColonne).Value
cCompteur = cCompteur + 1
End If
Next
Next
If cCompteur > 0 Then 'Éviter les divisions par 0
fnMoyennePlus1 = cSomme/cCompteur
EndIf
End Function
Exemple 3: boucles de lecture
Dans une boucle de lecture, le nombre d’itérations n’est pas connu au départ. L’utilisation de For...Next n’est donc pas approprié.
Ici, on veut saisir une série de nombres qui seront inscrits dans la feuille Excel.
Sub SaisirNombres()
'Saisir des nombres et les inscrire dans une feuille Excel
Dim sSaisie As String
Dim lNoLigne As Long
'Dans la boucle de lecture "standard", la première valeur est lue AVANT d'entrer dans la boucle
sSaisie = InputBox("Entrer une valeur", "Inscription de valeurs dans une feuille")
Do Until sSaisie = "" 'Le bouton Annuler de InputBox renvoie la chaîne nulle
If IsNumeric(sSaisie) Then
lNoLigne = lNoLigne + 1 'Prochaine ligne de la feuille Excel
Range("A1").Offset(lNoLigne, 0).Value = sSaisie
End If
sSaisie = InputBox("Entrer une valeur", "Inscription de valeurs dans une feuille")
Loop
End Sub
Ce type de boucle est utilisé pour lire des données venant de requêtes SQL, de fichiers conventionnels, etc. Notez qu’il y a lecture AVANT d’entrer dans la boucle, puis une autre immédiatement avant la fin, et que le test de fin de lecture est en début de boucle. La première instruction de lecture est automatique (implicite) dans l’ouverture d’une requête SQL.
Une autre façon d’arriver au même résultat:
Sub SaisirNombres1()
'Saisir des nombres et les inscrire dans une feuille Excel
Dim sSaisie As String
Dim lNoLigne As Long
Do
Do
sSaisie = InputBox("Entrer une valeur", "Inscription de valeurs dans une feuille")
Loop Until IsNumeric(sSaisie) Or Len(sSaisie) = 0
If Len(sSaisie) = 0 Then
lNoLigne = lNoLigne + 1 'Prochaine ligne de la feuille Excel
Range("A1").Offset(lNoLigne, 0).Value = sSaisie
End If
Loop Until sSaisie = "" 'Le bouton Annuler de InputBox renvoie la chaîne nulle
End Sub
Exercices: Tableaux et collections
(source: https://www.lecompagnon.info/vba-excel/vba_collections.htm)
Exemples
Sub ExemplesTableaux()
'Exemples de manipulation de collection et de tableau
Dim cNombres() As Currency
Dim vTableau() As Variant
Dim lLigne As Long, lColonne As Long
Dim tDépart As Date
With Worksheets("Tableaux")
Cells.Clear
'Créer une matrice 10000x100 de nombres dans Excel
tDépart = Now 'Date et heure du départ
For lLigne = 1 To 10000
For lColonne = 1 To 100
.Cells(lLigne, lColonne) = lLigne + lColonne
Next
Next
MsgBox "Création de matrice Excel en " & Round((Now - tDépart) * 24 * 60 * 60, 2) & " secondes"
'Créer une matrice 10000x100 de nombres dans VBA
ReDim cNombres(1 To 10000, 1 To 100)
tDépart = Now 'Date et heure du départ
For lLigne = 1 To 10000
For lColonne = 1 To 100
cNombres(lLigne, lColonne) = lLigne + lColonne
Next
Next
MsgBox "Création de matrice VBA en " & Round((Now - tDépart) * 24 * 60 * 60, 10) & " secondes"
'Copie d'une matrice Excel dans un tableau VBA
'ATTENTION: le tableau DOIT ÊTRE DE TYPE Variant
'Le tableau est automatiquement redimensionné aux dimensions de la plage
vTableau = Range(.Cells(1, 1), .Cells(1000, 100))
'Copie d'une matrice VBA dans un tableau Excel
.Cells.Clear
.Range(.Cells(1, 1), .Cells(UBound(vTableau, 1), UBound(vTableau, 2))) = vTableau
End With
End Sub
Autres exemples
https://www.fil.univ-lille1.fr/~sedoglav/VisualBasic/Cours01.pdf
Dim Salaire,RemboursementMensuel As Decimal
Select Case (RemboursementMensuel/Salaire)*100
case Is >= 33# MsgBox("ca va pas \^etre possible")
case 30# To 32# MsgBox("ca va \^etre juste")
case 20# To 29# MsgBox("c’est OK")
case Else MsgBox("en chaussette")
End Select
Dim mat1(3,3) As Integer = { {1,2,3}, {4,5,6}, {7,8,9} }
Dim mat2(3,3) As Integer = { {9,8,7}, {6,5,4}, {3,2,1} }
Dim res(3,3) As Integer
For i As Integer=0 To 2
For j As Integer=0 To 2
res(i,j) = mat1(i,j)+mat2(i,j)
Next j
Next i
https://www.fil.univ-lille1.fr/~sedoglav/VisualBasic/Cours03.pdf
par valeur : c’est une copie qui est pass ́ee en parametrea la fonction. Cette derniere peut manipuler la copiemais ne peut pas modifier les valeurs des variables de laroutine appelantes ;2.par r ́ef ́erence : c’est une copie de l’adresse d’unevariable d ́efinie dans l’espace d’adressage de la fonctionappelante qui est pass ́ee en parametre. Cette fois, laroutine appel ́ee peut modifier les variables de la routineappelantes.
Function SquareFct( ByVal P As Integer ) As Integer
P *=P ’le param\‘etre s’utilise comme
Return P ’ une variable usuelle
End Function
Sub SquareProc( ByRef Q As Integer )
Q *=Q
End Function
Sub Main()
Dim X,Y As Integer
X=2
Y=3
X=SquareFct(X)
SquareProc(Y)
End Sub
Attention, sans pr ́ecision sur le type de passage :Function SquareFct( P As Integer ) As Integer
https://www.fil.univ-lille1.fr/~sedoglav/VisualBasic/Cours03.pdf
SurchargeLa signature d’une routine est constitu ́ee d’un identificateuret d’une liste de param`etre — avec de plus d’une valeur deretour pour une fonction.Il est possible d’utiliser plusieurs fois le mˆeme identificateurpour diff ́erentes signatures. Dans ce cas, cette identificateurestsurcharg ́e.
Overloads Function Square (ByVal X As Integer) As Integer
return X*X
End Function
Overloads Function Square (ByVal X As Double) As Double
return X*X
End Function
Lors de l’appel, la premiere version rencontr ́ee de la fonctioncorrespondant aux parametres fournis est ex ́ecut ́ee.
https://www.fil.univ-lille1.fr/~sedoglav/VisualBasic/Cours04.pdf D ́eclaration d’ ́enum ́erationOn peut d ́efinir des valeurs invariables li ́ees logiquemententre elles ; une d ́eclaration de mod`ele d’ ́enum ́eration est :
Enum Identificateur [As DataType]
IdentificateurDeMembre1 = ValeurInt1
...
IdentificateurDeMembreN = ValeurIntN
End Enum
AvecDataTypeune valeur entiere (Byte,ULong, etc). Sanssp ́ecification de valeur d’initialisationValeurIntJ, leJiememembre correspondant est initialis ́e `aJ−1. Par exemple, onpeut repr ́esenter les joursouvrablesde la semaine ainsi :
Enum JourOuvrable As UInteger
Lundi = 1
Mardi = 2
Mercredi = 3
Jeudi = 4
Vendredi = 5
End Enum
Une ́enum ́eration se d ́eclare hors des sous-routines.
L’op ́erateur.permet d’avoir acces au champs de lad ́eclaration du modele de l’ ́enum ́eration.IOn peut d ́eclarer une variable qui ayant pour type lemod`ele de l’ ́enum ́eration.
Function Cours (Dim JoursDeTP As JourOuvrable) As Boolean
If JoursDeTP=JourOuvrable.Mercredi
Or JoursDeTP=JourOuvrable.Vendredi
then return True
End If
Return False
End Function
D ́eclaration de structureUnestructureregroupe plusieurs valeurs de types diff ́erentsen une mˆeme entit ́e.Ielle est compos ́ee d’une suite de membres ;Ichaque membre porte un nom interne `a la structure ;Ile type des membres peut ˆetre quelconque (l’imbricationde structure est possible).
Structure IdentificateurDeModele
Dim IdentificateurMembre1 As Type1
....
Dim IdentificateurMembreN As TypeN
End Structure
Par exemple, on peut d ́eclarer le mod`ele de structure :
Structure Eleve
Dim nom As String
Dim note As UByte
End Structure
Utilisation de structureL’utilisation d’une structure n ́ecessite — outre les op ́erateurscourants — l’op ́erateur.d’acc`es aux membres :
Sub affichage(ByVal param As Eleve)
MsgBox("Nom : " & param.nom & " Note : " & param.note")
End Sub
Sub Main()
Dim etudiant As Eleve
etudiant.nom="Bill Gates"
etudiant.note=0
affichage(etudiant)
End Sub
Exemple: calculer la somme d’une plage (source: http://eric.univ-lyon2.fr/~ricco/cours/excel/EXCEL%20-%20Cours%20-%20Programmation%20VBA.pdf, slide 33)
'Travail sur le type Range avec un For Each
Public FunctionMaSommeRangeEach(plageAs Range) As Double
'variables intermédiaires
Dim s As Double, celluleAs Range
'initialisation de la somme
s = 0
'parcours de la plage de cellules
For Each cellule In plage
s = s + cellule.Value
Next cellule
'renvoyer le résultat
MaSommeRangeEach= s
End Function
Le type de variant peut gérer tout type de valeurs. Il est très souple, particulièrement commode quand on ne connaît pas à l’avance le type à utiliser. Mais attention, il ne faut pas en abuser, il est très lent parce que multiplie les vérifications à chaque accès à la variable correspondante On peut s’en servir pour renvoyer un tableau. Une fonction peut donc renvoyer plusieurs valeurs d’un coup, à l’instar des fonctions matricielles d’Excel (il faut valider la saisie de la fonction avec la séquence de touches CTRL + MAJ + ENTREE).
(dans la barre de fonction d’Excel: c’est bien une fonction matricielle comme peuvent en témoigner les accolades { } qui encadrent l’appel de la fonction)
'renvoyer plusieurs valeurs
Public Function MonMinMax(a As Double, b As Double) As Variant
'un tableau interne -matrice 2 lignes et 1 colonne
Dim tableau(1 To 2, 1 To 1) As Double
'identifier le min et le max
If (a < b) Then
tableau(1, 1) = a
tableau(2, 1) = b
Else
tableau(1, 1) = b
tableau(2, 1) = a
End If
'renvoyer le tableau
MonMinMax= tableau
End Function
Simulation valeurs TVA: (source: http://eric.univ-lyon2.fr/~ricco/cours/excel/EXCEL%20-%20Cours%20-%20Programmation%20VBA.pdf (slide 42))
SubSimulationTVA()
'variables
Dim pht As Double, pttc As Double
Dim tva As Double
Dim i As Long
'début d'écriture des valeurs en ligne 2
i = 2
'récupérer la valeur du PHT
pht= Cells(1, 2).Value 'enB1'faire varier la tva de 10%à 30%avec un pas de 5%
For tva= 10 To 30 Step5
'insérer la valeur de la TVA en B2
Cells(2, 2).Value = tva
'Récupérer le prix ttc en B3
pttc= Cells(3, 2).Value
'inscription des valeurs TVA en colonne D
Cells(i, 4).Value = tva
'PTTC en colonne E
Cells(i, 5).Value = pttc
'passage à la ligne suivante
i = i + 1
Next tva
End Sub
Exemple mettre en police verte les cellules contenant une valeur paire http://eric.univ-lyon2.fr/~ricco/cours/excel/EXCEL%20-%20Cours%20-%20Programmation%20VBA.pdf, slide 44
SubMesValeursPaires()
'variable intermédiaire
Dim cellule As Range
'boucler sur la sélection
For Each cellule In Selection
'tester le contenu
If (cellule.ValueMod2 = 0) Then
'modifier la couleur de la police
cellule.Font.ColorIndex= 4
End If
Next cellule
End Sub
Dans une sélection, de nouveau les coordonnées sont relatives c.-à-d. le coin en haut à gauche d’une sélection correspond à la cellule (ligne n°1, colonne n°1) quelle que soit la position de la sélection dans la feuille; donc on aurait pu écrire:
SubMesValeursPairesBis()
'variables intermédiaires
Dim i As Long, j As Long
'boucler sur les lignes
For i = 1 To Selection.Rows.Count
'boucler sur les colonnes
For j = 1 To Selection.Columns.Count
'tester le contenu
If (Selection.Cells(i, j).Value Mod 2 = 0) Then
'modifier la couleur de la police
Selection.Cells(i, j).Font.ColorIndex= 4
End If
Next j
Next i
End Sub
Exemple: Identifier la première cellule contenant la valeur minimale dans une plage, mettre sa police en bleu. http://eric.univ-lyon2.fr/~ricco/cours/excel/EXCEL%20-%20Cours%20-%20Programmation%20VBA.pdf, slide 46
Attention ! Range est un objet. Une affectation pour une variable objet doit être réalisée à l’aide de l’instruction Set
SubMonMinBleu()
'variables intermédiaires min va servir de cellule témoin
Dim cellule As Range, min As Range
'initialisation du témoin sur la 1ère cellule
Set min= Selection.Cells(1, 1)
'parcourir
For Each cellule In Selection
'comparer avec le contenu de la cellule témoin
If (cellule.Value< min.Value) Then
'màj de la cellule témoin
Setmin= cellule
End If
Next cellule
'mettre la couleur pour la cellule minimale
min.Font.ColorIndex= 5
End Sub
Une sélection peut être multiple aussi c.-à-d. contenant plusieurs “zones”
le même mot clé Selection peut être exploité
Selection.Areas.Count: Nombre de “zones” dans la sélectionSelection.Areas(k): Accès à la zone n°k (qui est de typeRange).Areasest une collection de zones.
Exemple: Pour chaque zone, mettre en police bleue la cellule contenant la valeur minimale Selection.Areasest une collection. On peut utiliser un For Each. On aurait pu aussi passer par un accès indicé.
SubMonMinZoneBleu()
'var. intermédiaires
Dim zone As Range, min As Range
'pour chaque zone
For Each zone In Selection.Areas
'à l'intérieur de chaque zone'initialisation
Set min = zone.Cells(1, 1)
'parcours des cellules
For Each cellule In zone
'comparer
If (cellule.Value< min.Value) Then
'màjde la variable témoin
Set min = cellule
End If
Next cellule
'mettre la couleur pour la cellule minimale
min.Font.ColorIndex= 5
'passage à la zone suivante
Next zone
End Sub
Excel dispose de fonctions natives puissantes. Exemple afficher la moyenne pour une sélection
SubMaMoyenneSelection()
'var. intermédiaire
Dim moyenne As Double
'vérifier la sélection
If (Selection.Areas.Count> 1) Then
MsgBox("Attention, ce n'est pas une sélection simple")
Else
'faire calculer la moyenne de la sélection par Excel
moyenne = Application.WorksheetFunction.Average(Selection)
MsgBox("La moyenne est " & Str(moyenne))
End If
End Sub
Astuces VBA
https://www.excel-pratique.com/fr/astuces_vba
Exemple 1: calculer le nombre de jours dans un mois ou définir le dernier jour du mois
Sub nb_jours_mois()
'Une date quelconque pour cet exemple
date_test = CDate("6/2/2012")
'Mois / année de la date
mois = Month(date_test)
annee = Year(date_test)
'Calcul du premier jour du mois suivant
date_mois_suivant = DateSerial(annee, mois + 1, 1)
'Date du dernier jour
dernier_jour_mois = date_mois_suivant - 1
'Nombre de jour dans le mois (= dernier jour)
nb_jours = Day(dernier_jour_mois)
End Sub
Pour l’utiliser en tant que fonction en ajoutant le code suivant dans un module :
Function NB_JOURS(date_test As Date)
NB_JOURS = Day(DateSerial(Year(date_test), Month(date_test) + 1, 1) - 1)
End Function
Exemple d’utilisation de la fonction en VBA :
Sub exemple()
test = NB_JOURS(Range("A1"))
MsgBox test
End Sub
Exemple 2: dernière ligne d’un tableau
Il arrive fréquemment de devoir insérer des données à la suite d’un tableau sur une feuille Excel, et pour faire cela, il faut connaître le numéro de la première ligne disponible de ce tableau.
La dernière ligne non vide d’un tableau s’obtient à l’aide de :
Cells(Rows.Count, colonne).End(xlUp).Row
Pour déterminer quelle est la dernière cellule non vide d’une colonne (remplacer “colonne” par 1; pour la colonne A dans cet exemple) :
Sub exemple()
derniereLigne = Cells(Rows.Count, 1).End(xlUp).Row
MsgBox derniereLigne
End Sub
Si on dispose d’une lettre au lieu d’un numéro de colonne, utiliser Range au lieu de Cells :
Sub exemple()
derniereLigne = Range("A" & Rows.Count).End(xlUp).Row + 1
MsgBox derniereLigne
End Sub
Exemple 3: véfifier si une valeur est entièrement en majuscules
Sub test()
ma_valeur = "BonJOUR"
If ma_valeur = UCase(ma_valeur) Then 'Test si en majuscules
MsgBox "Oui, ma_valeur est (entièrement) en majuscules."
Else
MsgBox "Non, ma_valeur n'est pas (entièrement) en majuscules." '<= Valeur renvoyée (car ma_valeur contient des minuscules)
End If
End Sub
Exemple 4: tester si une chaîne de caractères est un palindrome
Function palindrome(valeur)
palindrome = StrReverse(valeur) = valeur
End Function
Exemple 5: modifier la mise en forme de certains caractères
En utilisant Characters avec la syntaxe: Range("A1").Characters(NO_DEPART, NB_DE_CARACTERES)
Sub test()
For ligne = 1 To 12
'Contenu de la cellule
contenu = Cells(ligne, 1)
'Contenu divisé en un tableau de 3 parties
tab_contenu = Split(contenu, " ")
'Longueur de la partie 1
longueur_partie_1 = Len(tab_contenu(0))
'Longueur de la partie 2
longueur_partie_2 = Len(tab_contenu(1))
'Partie 1 en ITALIQUE
Cells(ligne, 1).Characters(1, longueur_partie_1).Font.Italic = True
'Partie 2 en GRAS
Cells(ligne, 1).Characters(longueur_partie_1 + 2, longueur_partie_2).Font.Bold = True
Next
End Sub
Exemple 6: remplacer des caractères
Avec la fonction Replace :
Replace(texte, valeur_avant, valeur_après)
'ou
Replace(texte, valeur_avant, valeur_après, départ, nombre, casse)
Exemple pour effacer les tirets:
Sub remplacer()
ma_chaine = "CH-34-763-92-FR-1"
MsgBox Replace(ma_chaine, "-", " ") 'Renvoie : CH 34 763 92 FR 1
End Sub
Exemple 7: supprimer des espaces inutiles
La fonction Trim permet de retirer les espaces inutiles au début et à la fin d’une chaîne de caractères.
Sub exemple()
ma_variable = Trim(Range("A3"))
MsgBox ma_variable 'Renvoie "Excel-Pratique.com"
End Sub
Exemple 8: chercher une valeur à l’intérieur d’une chaine de caractères
La fonction InStr vérifie si une chaîne de caractères contient une valeur définie et renvoie la position de la première valeur trouvée (ou 0 si la valeur n’a pas été trouvée dans la chaîne).
InStr(départ, texte, valeur_à_rechercher)
'ou
InStr(départ, texte, valeur_à_rechercher, casse)
Lorsqu’il y a plusieurs positions à relever, il est possible de créer une boucle et de quitter celle-ci lorsque InStr renvoie 0 (= plus de résultat) :
Sub exemple()
ma_chaine = "6397-GA12-D3-FR-GA15-XT-54PGA-GAO-4-TE-6GA9"
positions = "" 'Pour enregistrer la liste des résultats
separateur = "" 'Séparateur pour la liste des résultats (vide pour la première position)
derniere_pos = 1 'Dernière position (pour le premier argument de InStr)
Do
pos = InStr(derniere_pos, ma_chaine, "GA")
If pos Then 'Si pas égal à 0
positions = positions & separateur & pos
separateur = "-"
derniere_pos = pos + 1
End If
Loop While pos > 0
'Résultat
MsgBox positions
End Sub
Exemple 9: rechercher la position d’une valeur dans une variable tableau (Array)
Function array_pos(tableau, recherche)
'https://www.excel-pratique.com/fr/astuces_vba/recherche-position-tableau-array
array_pos = -1
For ii = LBound(tableau) To UBound(tableau)
If tableau(ii) = recherche Then 'Si valeur trouvée
array_pos = ii
Exit For
End If
Next
End Function
La fonction array_pos renverra ensuite la position de la première valeur trouvée dans le tableau (ou la valeur -1 si la valeur n’a pas été trouvée dans le tableau).
Voici un exemple simple qui va rechercher la présence de la valeur de la variable valeur_a_rechercher dans le tableau mon_tableau et afficher ensuite sa position dans une MsgBox :
Sub test()
mon_tableau = Array(23, 67, 38, 17, 854, 9, 92)
valeur_a_rechercher = 9
MsgBox array_pos(mon_tableau, valeur_a_rechercher)
End Sub
Exemple 10: rechercher une valeur dans une variable tableau (Array)
Function in_array(tableau, recherche)
'https://www.excel-pratique.com/fr/astuces_vba/recherche-tableau-array
in_array = False
For i = LBound(tableau) To UBound(tableau)
If tableau(i) = recherche Then 'Si valeur trouvée
in_array = True
Exit For
End If
Next
End Function
La fonction in_array renverra ensuite True ou False en fonction du résultat.
Voici un exemple simple qui va rechercher la présence de la valeur de la variable valeur_a_rechercher dans le tableau mon_tableau et afficher Vrai ou Faux dans une MsgBox :
Sub test()
mon_tableau = Array(23, 67, 38, 17, 854, 9, 92)
valeur_a_rechercher = 17
MsgBox in_array(mon_tableau, valeur_a_rechercher)
End Sub