ADO


Sub adoReference()
'Microsoft ActiveX DataObjects 6.1 Library activé

Application.ScreenUpdating = False

Sheets("Test").Cells.ClearContents

Dim aa As Variant

Dim myPath As String
myPath = ThisWorkbook.Path

Dim myFile As String
myFile = "ref.xlsx"

Dim tabName As String
'tabName = "Sheet1"
tabName = "info"

'connexion
Dim cnn As ADODB.Connection
Set cnn = New ADODB.Connection

'recordset
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset


'connection au fichier source
cnn.Open "Provider=Microsoft.ACE.OLEDB.12.0; Data Source = " & myPath & "\" & myFile & ";Extended Properties='Excel 12.0;HDR=yes'"

'On place le curseur côté client, cela permet de compter le nombre de lignes dans le recordset
'(si le curseur reste côté serveur, il renvoie la valeur -1)
rs.CursorLocation = adUseClient


'requête
Dim mQuery As String
myQuery = "SELECT *  FROM [" & tabName & "$A1:IV65536] " 'si le nom de la table (ici variable tabName) n'est pas précisé, il prend en compte le 1er onglet

'l'enregistrement de la requête dans le rs s'effectue normalement de la façon suivante :
'Set rs = cnn.Execute("SELECT * FROM [" & tabName & "$A1:IV65536] ")

'mais Set rs = cnn.Execute ne permet pas de compter le nombre de lignes dans le recordset, donc ici, on utilise rs.open
rs.Open myQuery, cnn

'enregistre le nombre de lignes enregistrées dan le rs
Dim sqlRowsCount As Integer
sqlRowsCount = rs.RecordCount

'recopie les en-têtes
Dim i As Integer
For i = 0 To rs.Fields.Count - 1
   Cells(1, i + 1).Value = rs.Fields(i).Name
Next i

'Definit la celllule à partir de laquelle recopier l'info dans l'onglet
Dim myRange As Range
Set myRange = Sheets("Test").Range("A" & Rows.Count).End(xlUp).Offset(1)

'vérifie qu'il existe bien des résultats à la requête
If sqlRowsCount = 0 Then
    aa = "No result"
Else
    'Copie les résultats de la requête directement sur la feuille de calcul
    'myRange.CopyFromRecordset rs
    
    'enregistre les résultats dans une variable aa
    aa = rs.GetRows
    
    'convertit la date en numero de série pour éviter que la transposition n'inverse le mois et la date
    For i = LBound(aa, 2) To UBound(aa, 2)
    aa(0, i) = CLng(aa(0, i))
    Next i
    
    'affichage
    myRange.Resize(UBound(aa, 2) + 1, UBound(aa) + 1) = Application.Transpose(aa)
    'formatage de la colonne de date
    Columns("A:A").NumberFormat = "dd/mm/yyyy"
End If

rs.Close
cnn.Close

Application.ScreenUpdating = True

End Sub

Fichiers :
ref
main

Publicités

Transposer des dates depuis une variable tableau

Exemple :
dateTranspose

Sub dateFormat()

'reset l'affichage
Columns("E:Z").ClearContents

'variable aa dans laquelle on enregistre les valeurs du tableau
Dim aa As Variant
aa = Range("A1").CurrentRegion

'transposition des valeurs de la variable sur la feuille Excel à partir de la
'cellule E1 - les 12 premières dates sont inversées par rapport aux valeurs
'initiales de la colonne A
[E1].Resize(UBound(aa), UBound(aa, 2)) = Application.Transpose(Application.Transpose(aa))

'boucle affichant correctement les dates contenues dans la variable aa
'sans passer par la commande de transposition : le problème de changement
'de date est dû à la commande de transposition (Application.Transpose) et non à 
'l'enregistrement des valeurs dans la variable aa
For i = LBound(aa) To UBound(aa)
   Cells(i, 9) = aa(i, 1)
Next i

'changement du type de Date à Long (CLng) - la valeur date devient un numéro de
'série - il suffira juste de reformater correctement la colonne de date pour que
'la transposition soit correcte
For i = LBound(aa) To UBound(aa)
   aa(i, 1) = CLng(aa(i, 1))
Next i
[K1].Resize(UBound(aa), UBound(aa, 2)) = Application.Transpose(Application.Transpose(aa))

End Sub

Fichier d’exemple au formar xls :
 dateTranspose

Pause

J’ai tenu à partager mes connaissances du VBA lorsque j’ai constaté que certaines techniques qui permettaient d’optimiser l’écriture d’un code étaient généralement peu voire pas utilisées.

J’estime avoir atteint mon objectif en vous présentant, entre autres, les principes des variables Tablo et du Dictionnaire… qui m’ont incité à commencer ce blog.

Souhaitant, aujourd’hui, me consacrer à l’apprentissage d’autres langages, je mets, au moins momentanément, un terme à ce blog et vous souhaite beaucoup de réussite en VBA.

[VBA] Etablir une condition en fonction du formatage d’une MFC

Il est fréquent de vouloir conditionner une action aux résultats d’une Mise en Forme Conditionnelle (MFC).
Or une MFC ne formate pas directement une cellule.
Pour vous en convaincre :

sélectionnez la cellule A1
saisissez le chiffre 5

puis, toujours en gardant le curseur sur la cellule A1

(pour Excel 2007) Accueil
Mise en forme conditionnelle
Règles de mise en surbrillance des cellules
Egal à

Une boite de dialogue apparait avec le chiffre 5 dans l’espace de gauche et « Remplissage rouge clair avec texte rouge foncé » dans l’espace de droite. Cliquez sur OK.

Notre cellule A1 devient rouge.
Appliquons à cette page la macro suivante :

Sub couleur()
Dim maCouleur As Long
maCouleur = Range("A1").Interior.Color
Range("B1").Interior.Color = maCouleur
End Sub

Nous enregistrons dans la variable maCouleur le N° de la couleur de fond de la cellule A1 maCouleur = Range("A1").Interior.Color puis allons demander à la macro d’appliquer la même couleur de fond à la cellule B1 Range("B1").Interior.Color = maCouleur. La cellule B1 reste blanche et si vous avez conservé le quadrillage de la feuille, celui-ci a disparu : ceci est caractéristique du coloriage des cellules.

Explications

Nous en déduisons qu’une MFC n’applique ses formats directement sur la cellule mais plutôt sur un « calque » (un peu à la façon de photoshop).

Dans l’exemple suivant, nous avons formaté la colonne A avec une MFC.

Nous récupérons les conditions de la MFC en sélectionnant la colonne A puis

Accueil
Mise en forme conditionnelle
Gérer les règles

MFC1

La boîte de dialogue nous apprend que pour la plage de cellules A1 à A20, le fond de toutes les cellules dont la valeur est inférieure à 5 est colorié en rouge.

MFC2

Nous allons créer une macro qui affichera un « x » à la droite de chaque cellule rouge de notre plage :

Sub MCF()
Dim Cel As Range
MsgBox "A partir de la couleur visible."
For Each Cel In Range("A1:A20")
    If Cel.Interior.Color = vbRed Then a.Offset(, 1) = "x"
Next Cel
End Sub

Pour chaque cellule de la plage A1-A20 For Each Cel In Range("A1:A20"), si la couleur de fond de la cellule est rouge If Cel.Interior.Color = vbRed, alors la cellule immédiatement à droite affiche « x »  Then a.Offset(, 1) = "x".
Comme nous pouvions nous y attendre, il ne se passe rien puisque la macro ne trouve pas de couleur dans la cellule.
Nous allons donc ajouter le code suivant à la suite du précédent :

MsgBox "A partir de la condition de la MFC."
For Each Cel In Range("A1:A20")
    If Cel < 5 Then Cel.Offset(, 1) = "x"
Next Cel

Il ne s’agit donc plus de vérifier la couleur de notre cellule mais de reprendre la condition de la MFC, c’est à dire vérifier si la valeur de la cellule est inférieure à 5 If Cel < 5 Then; et là, notre code fonctionne.

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

[VBA] La variable « Dictionnaire »

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

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

Dictionnary

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

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

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

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

ii = Dico.keys
jj = Dico.items

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

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

Explications

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

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

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

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

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

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

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

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

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

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

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

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

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

[VBA] Lister les fichiers et sous-dossiers d’un dossier

Dans cet article, nous allons voir les outils à notre disposition pour répertorier le contenu d’un dossier.
Nous distinguerons ici deux cas de figure : les fichiers de ce dossier et ses sous-dossiers.

Fichiers

Sub Fichiers()
Application.ScreenUpdating = False
Dim myPath As String, myFile As String

myPath = ThisWorkbook.Path
myFile = Dir(myPath & "\*.xls*")

c = 1
Do While myFile <> ""
    Cells(c, 1) = myFile
    myFile = Dir()
    c = c + 1
Loop

End Sub

Explications

Après avoir sauvegardé le classeur sur le disque dur (de préférence dans un dossier qui contient des fichiers et des sous-dossiers) et lui avoir affecté la macro ci-dessus, nous allons passer à l’étude détaillée de sa construction.

Une fois les variables déclarées, la ligne myPath = ThisWorkbook.Path enregistre dans la variable myPath, le chemin d’accès(.Path) au dossier contenant ce classeur (ThisWorkbook). Nous avons récupéré un chemin d’accès relatif, c’est à dire qui changera en fonction de l’emplacement du fichier dans tel ou tel dossier, par opposition à un chemin d’accès absolu comme myPath = "C:\Utilisateurs\moi" qui ne changera pas, quel que soit l’emplacement de notre classeur.

La variable myFile récupère, le nom du fichier. On reconnait ici la variable myPath qui contient le chemin d’accès auquel nous ajoutons les caractères suivants & "\*.xls*" : & nous permet de concaténer le chemin d’accès au reste des commandes à sa droite afin de définir le chemin d’accès et le nom du fichier.

Entre les guillemets, nous retrouvons les indiquations suivantes : le séparateur \ nous informe du prochain niveau du chemin d’accès; l’extention .xls* indique à la macro de ne considérer que les fichiers Excel; enfin le joker * signifie que * peut représenter un caractère quelconque, une chaîne de caractères quelconques, ou aucun caractère.
Ainsi, notre extension .xls* peut prendre les valeurs xls, xlsx, xlsm, xlsb et le joker * qui précède l’extension de fichier peut avoir n’importe quel nom.

Enfin, la commande Dir(), qui encadre notre expression, dit à la macro de considérer les informations qu’elle contient non pas comme une quelconque chaîne de caractères mais comme un fichier.

Nous entamons notre boucle qui va générer la liste des fichiers Excel dans la première colonne de l’onglet actif.
Do While myFile <> "" ordonne à la macro de boucler (Do While) tant que la valeur (nom du fichier) de la variable myFile n’est pas nulle (<> «  » littéralement : ne vaut pas rien) dans le dossier actif.

La ligne Cells(c, 1) = myFile se charge d’inscrire le nom du fichier dans la feuille Excel.

La commande Dir() n’accepte qu’une seule valeur à la fois; la ligne  myFile = Dir() enregistre dans myFile le nom du fichier .xls* suivant.

Notons que si l’on veut la liste de tous les fichiers, quel que soit leur type, il suffit juste d’écrire myFile = Dir(myPath & "\*")

Cas pratique

Sub Verif()

Application.ScreenUpdating = False
Dim wB As Workbook
Dim myPath As String, myFile As String

myPath = ThisWorkbook.Path & "\"
aa = "Exemple.xls"
myFile = Dir(myPath & aa)

If myFile = "" Then
    Workbooks.Add
    Set wB = ActiveWorkbook
    wB.SaveAs aa
    wB.Close
Else
    MsgBox "Le fichier " & aa & " existe."
End If

End Sub

L’exemple ci-dessus détermine si le fichier d’un dossier existe et le crée s’il ne le trouve pas.
Après aovir défini le chemin d’accès au dossier myPath = ThisWorkbook.Path & "\", enregistré le nom du fichier dans la variable aa aa = "Exemple.xls" et specifié dans la variable myFile que la chaine de caractères (chemin d’accès + nom du fichier) devait être considérée comme représentant un fichier myFile = Dir(myPath & aa); nous définissons une condition qui va déterminer si le fichier Exemple.xls existe dans le dossier auquel appartient le classeur qui contient la macro If myFile = "" Then.
La ligne If myFile = "" Then nous indique que si le fichier n’existe pas, alors on crée un nouveau classeur Workbooks.Add, on l’enregistre dans la variable wB Set wB = ActiveWorkbook, sauvegarde le nouveau classeur du nom enregistré dans aa wB.SaveAs aa et on ferme le classeur wB.Close.
Si le fichier existe Else, un message nous prévient de son existence MsgBox "Le fichier " & aa & " existe".

Dossiers méthode 1

Sub Dossiers()

Application.ScreenUpdating = False
Dim myPath As String, myFolder As String

myPath = ThisWorkbook.Path
myFolder = Dir(myPath & "\*", vbDirectory)

c = 1
Do While myFolder <> ""

    If GetAttr(myPath & "\" & myFolder) = vbDirectory Then
        Cells(c, 2) = myFolder
        c = c + 1
    End If
    myFolder = Dir()

Loop
End Sub

La méthode pour faire la liste des sous-dossiers d’un dossier est très similaire à ce que l’on vient de voir avec les fichiers, à deux détails près.
La première différence consiste à inclure les sous-dossiers dans la liste qui va être générée; il suffit d’ajouter la commande vbDirectory lorsque nous spécifions notre fichier myFolder = Dir(myPath & "\*", vbDirectory).
La seconde insère une condition qui va différencier les fichiers des sous dossiers; nous allons utiliser la commande GetAttr qui nous permet de déterminer les caractéristiques d’un fichier ou d’un dossier If GetAttr(myPath & "\" & myFolder) = vbDirectory Then. Ainsi, la macro n’inscrit que les noms de fichiers.

Dossiers méthode 2

Sub Dossiers2()
'Dans la fenêtre VBA, sélectionner Outils, Références et cocher Microsoft Scripting Runtime
Application.ScreenUpdating = False
Dim myPath As String, mainFolder As Folder
Dim aa As Object

Set aa = CreateObject("scripting.filesystemobject")
myPath = ThisWorkbook.Path

Set mainFolder = aa.GetFolder(myPath)

c = 1
For Each f In mainFolder.SubFolders
    Cells(c, 3) = f
    c = c + 1
Next f

End Sub

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

La première étape consiste à créer un « objet » : nous commençons par déclarer la variable, nommée aa, qui correspond à cet objet Dim aa As Object; nous créons, ensuite, l’objet aa Set aa = CreateObject("scripting.filesystemobject").
Après avoir précisé le chemin d’accès à notre dossier que nous enregistrons dans la variable myPath, nous utilisons la commande Set mainFolder = aa.GetFolder(myPath) pour identifier le dossier contenant notre classeur et l’enregistrer dans la variable mainFolder.
Enfin, la boucle For Each f In mainFolder.SubFolders va lister l’ensemble des sous-dossiers (avec leur chemin d’accès) du dossier contenant notre fichier.

Ce dernier code va nous permettre de voir comment naviguer de dossier en dossier en modifiant le code précédent.

Sub Dossiers3()
'Dans la fenêtre VBA, sélectionner Outils, Références et cocher Microsoft Scripting Runtime
Application.ScreenUpdating = False
Dim myPath As String, myFolder As String, mainFolder As Folder
Dim aa As Object

Set aa = CreateObject("scripting.filesystemobject")
myPath = ThisWorkbook.Path
ChDir (myPath)
ChDir ("..")
myFolder = CurDir(myPath)

Set mainFolder = aa.GetFolder(myFolder)

c = 1
For Each f In mainFolder.SubFolders
    Cells(c, 4) = f
    c = c + 1
Next f

Columns("D").AutoFit
End Sub

Voici la partie du code qui a été ajoutée/modifiée :

ChDir (myPath)
ChDir ("..")
myFolder = CurDir(myPath)
Set mainFolder = aa.GetFolder(myFolder)

la commande ChDir change le répertoire ou le dossier courant par défaut.
Le répertoire courant est normalement le lecteur C; la commande ChDir (myPath) ordonne à la macro de considérer le répertoire contenant notre fichier comme étant le dossier par défaut.
ChDir ("..") signifie à la macro de considérer le dossier « parent » au dossier actuel par défaut, c’est à dire le dossier le contenant, comme étant le nouveau dossier de référence.
La ligne suivante myFolder = CurDir(myPath) nous permet, grâce à la commande CurDir, d’enregistrer notre nouveau chemin d’accès dans la variable myFolder.
C’est, enfin, cette fois-ci, la variable, non pas myPath, comme dans l’exemple précédent, mais myFolder, qui nous permet, ici, dans la ligne suivante, Set mainFolder = aa.GetFolder(myFolder), d’enregistrer le chemin d’accès du dossier parent de celui dans lequel se trouve notre fichier.
La boucle effectue l’affichage des sous-dossiers appartenant au dossier parent du dossier dans lequel se trouve notre fichier.

Juste pour info., voici un petit complément avec le code pour établir la liste des sous-dossiers du dossier parent selon la première méthode :

Sub Dossiers4()
Dim myPath As String, myFolder As String

myPath = ThisWorkbook.Path
ChDir (myPath)
ChDir ("..")
myPath = CurDir(myPath)

myFolder = Dir(myPath & "\*", vbDirectory)

c = 1
Do While myFolder <> ""
    If GetAttr(myPath & "\" & myFolder) = vbDirectory Then
        Cells(c, 5) = myFolder
        c = c + 1
    End If
    myFolder = Dir()
Loop
End Sub

A noter que ce programme semble avoir du mal à reconnaitre certains dossiers Windows mais fonctionne parfaitement avec les dossiers créés par l’utilisateur.

Ci-dessous le fichier au format .xls contenant les exemples de cet article.
Listings fichiers classeurs

[VBA] Sélectionner un tableau sans son en-tête

Voici une petite ligne de code astucieuse qui vous permet de sélectionner la plage entière d’un tableau sur la feuille Excel, hormis son en-tête, ce qui peut être pratique pour intégrer l’ensemble des valeurs du tableau dans une variable, par exemple.

Pour un tableau composé de plusieurs lignes et de plusieurs colonnes et dont l’en-tête commence dans la cellule A1 :

Range("A1").CurrentRegion.Offset(1).Resize(Range("A1").CurrentRegion.Rows.Count - 1, Range("A1").CurrentRegion.Columns.Count).Select

Explications

Nous connaissons maintenant bien Range("A1").CurrentRegion qui sélectionne toutes les cellules faisant partie de la plage de la cellule A1.
La commande Offset(1) représente un décalage vers le bas d’une ligne. Voir l’article suivant pour plus d’infos sur le fonctionnement de la commande Offset.
Nous savons aussi que la commande Resize redimensionne une cellule ou une plage de cellules et qu’elle est suivie du nombre de lignes et du nombre de colonnes permettant de redimensionner notre cellule de référence A1.
Tout logiquement, Range("A1").CurrentRegion.Rows.Count - 1 représente le nombre de lignes de notre plage.
Rows.Count repprésente le nombre de lignes de notre plage Range("A1").CurrentRegion; nous déduisons 1 car nous avons décalé notre plage de 1 vers le bas.

Il en va exactement de même pour le nombre de colonnes Range("A1").CurrentRegion.Columns.Count.
Une petite ligne qui peut s’avérer pratique, à adapter en fonction de vos besoins.