FAQ VBA
FAQ VBAConsultez toutes les FAQ
Nombre d'auteurs : 10, nombre de questions : 133, dernière mise à jour : 15 juin 2021
- Comment décaler une plage ?
- Comment redimensionner une plage ?
- Que représente l'objet Area ?
- Quelles différences entre UsedRange et CurrentRegion ?
- Comment sélectionner les cellules d'une colonne ?
- Peut-on récupérer une plage de cellules contenant les cellules en erreurs ?
- Comment trier une plage ?
- Comment savoir si une plage fait référence à une cellule ou à plusieurs, voire à plusieurs plages ?
- Comment récupérer la plage filtrée par AutoFilter ?
- Pourquoi ai-je une erreur lors d'une recherche si la valeur n'existe pas ?
- Comment effacer les valeurs d'un tableau sans effacer les formules et les titres ?
- Je veux retrouver toutes les cellules ayant un fond particulier, mais le code est très long, que faire ?
- Comment demander à l'utilisateur de sélectionner une plage de cellule ?
On utilise généralement la méthode OffSet. Ainsi
Range
(
"A1:C1"
).Offset
(
1
, 1
)
renvoie la plage (Range) "B2:D2". Dans certains cas particuliers, on peut utiliser les méthodes Next ou Previous pour décaler vers des cellules adjacentes. Par exemple
MsgBox
Range
(
"A1"
).Next.Address
(
True
, True
, xlA1, False
)
Renvoie $B$1
On utilise la méthode Resize pour redimensionner une plage quand on connaît le nombre de lignes et de colonnes de la nouvelle plage.
MsgBox
Range
(
"A1"
).Resize
(
3
, 2
).Address
(
True
, True
, xlA1)
Renvoie $A$1:$B$3. Notons que comme dans le cas de Offset l'objet renvoyé est un Range. Il est donc possible de combiner plusieurs de ces ordres.
Range
(
"A1"
).Resize
(
3
, 2
).Offset
(
,1
).ClearContents
L'objet Area n'existe pas. Il existe une collection Areas qui renvoie l'ensemble des plages continues d'un objet Range. En lui-même, tout objet Range possède au moins un élément dans sa collection Areas, qui peut être lui même si Range est une plage continue. En générale on énumère la collection.
Dim
objRange As
Range
For
Each
objRange In
Range
(
"A3:A12,D10:E21,I1:I16"
).Areas
objRange.Merge
False
Next
UsedRange est la plage des cellules utilisées dans une feuille. CurrentRegion est la plage rectangulaire de cellules non vides qui entourent l'objet Range sur lequel on fait l'appel de CurrentRegion. CurrentRegion doit être utilisé avec précaution car il a parfois un comportement piégeux. Imaginons qu'il existe un tableau rempli en A1:C3 et que toutes les autres cellules soit vides, alors
MsgBox
Cells
(
2
, 4
).CurrentRegion.Address
(
True
, True
, xlR1C1)
Renvoie R1C1:R3C4
Plusieurs cas : Sélectionner toute la colonne
Range
(
"A1"
).EntireColumn.Select
Sélectionner les cellules non vides de la colonne
Range
(
"A1"
).EntireColumn.SpecialCells
(
xlCellTypeConstants).Select
Attention, si vous voulez compter dans les cellules non vides, celles qui contiennent une formule il faut
Application.Union
(
Range
(
"A1"
).EntireColumn.SpecialCells
(
xlCellTypeConstants), Range
(
"A1"
).EntireColumn.SpecialCells
(
xlCellTypeFormulas)).Select
Sélectionner une plage de valeurs continues
Range
(
"A1"
, Range
(
"A1"
).End
(
xlDown)).Select
Sélectionner de la première à la dernière cellule non vide en prenant les cellules vides incluses
Range
(
"A1"
, Range
(
"A1"
).EntireColumn.Find
(
What:=
"*"
, SearchDirection:=
xlPrevious)).Select
C'est assez simple :
Dim
objWorksheet As
Worksheet, objRange As
Range
Set
objWorksheet =
ThisWorkbook.Worksheets
(
1
)
Set
objRange =
objWorksheet.UsedRange.SpecialCells
(
xlCellTypeFormulas, xlErrors)
C'est assez logique puisque seules les cellules contenant une formules peuvent être en erreur.
En supposant que je veuille trier la plage J1:L20 par ordre croissant dans la colonne J puis dans la colonne L
Range
(
"J1:L20"
).Sort
Range
(
"J1"
), xlAscending, Range
(
"L1"
), , xlAscending
Il faut utiliser la propriété Count des collections visées. C'est la collection Cells pour le nombres de cellules, Areas pour le nombre de plages. Un code Exemple pourrait être.
Dim
Msg As
String
, objRange As
Range
With
ThisWorkbook.Worksheets
(
1
).Range
(
"A3:A11,D7:E14,G1:G4,I15:J23,C22:F22"
)
Msg =
"La plage contient "
&
.Cells.Count
&
" cellules dans "
&
.Areas.Count
&
" plages continues"
&
vbCrLf
For
Each
objRange In
.Areas
Msg =
Msg &
"La plage "
&
objRange.AddressLocal
(
False
, False
, xlA1) &
" contient "
&
objRange.Cells.Count
&
" cellules"
&
vbCrLf
Next
End
With
MsgBox
Msg
Excel masque les lignes ne répondant pas au filtre, il suffit donc de récupérer la plage des cellules visibles.
Range
(
"A2:C21"
).AutoFilter
Field:=
1
, Criteria1:=
">10"
,
Range
(
"A2:C21"
).SpecialCells
(
xlCellTypeVisible).Copy
Destination:=
Range
(
"A24"
)
Le problème ne vient pas de la recherche mais de l'appel d'une propriété / méthode sur l'objet renvoyé. Je prends un exemple standard produit par l'enregistreur de macro.
Range
(
"A2:C21"
).Select
Selection.Find
(
What:=
"170"
, After:=
ActiveCell, LookIn:=
xlValues, LookAt _
:=
xlPart, SearchOrder:=
xlByRows, SearchDirection:=
xlNext, MatchCase:=
_
False
).Activate
Ce code fonctionnera sans problème pour peu que la valeur cherchée existe dans la plage. En effet la méthode Find renvoie un objet Range désignant la cellule contenant la valeur ou Nothing si celle-ci n'existe pas. Dans le cas de ce code elle va donc tenter de faire Nothing.Activate d'où l'erreur. Pour utiliser correctement la recherche, utilisez le type de code suivant :
Dim
objCell As
Range, PremAdresse As
String
, PlageResult As
Range
With
Range
(
"A2:C21"
)
Set
objCell =
.Find
(
What:=
"170"
, After:=
ActiveCell, LookIn:=
xlValues, LookAt:=
xlPart, SearchOrder:=
xlByRows, SearchDirection:=
xlNext)
If
Not
objCell Is
Nothing
Then
PremAdresse =
objCell.Address
Do
If
PlageResult Is
Nothing
Then
Set
PlageResult =
objCell
Else
Set
PlageResult =
Application.Union
(
objCell, PlageResult)
End
If
Set
objCell =
.FindNext
(
objCell)
Loop
While
Not
objCell Is
Nothing
And
objCell.Address
<>
PremAdresse
End
If
End
With
L'objet plageResult contiendra toutes les cellules contenant la valeur, ou nothing si cette valeur n'existe pas.
On travaille sur la méthode SpecialCells
Range
(
"A1:F21"
).SpecialCells
(
xlCellTypeConstants, xlNumbers).ClearContents
comme je l'ai dit dans une autre réponse, il faut éviter les longues énumérations. Supposons que je veuille trouver toutes les cellules ayant un fond bleu.
For
Each
objCell In
ThisWorkbook.Worksheets
(
1
).Cells
If
objCell.Interior.ColorIndex
=
5
Then
If
objRange Is
Nothing
Then
Set
objRange =
objCell
Else
Set
objRange =
Application.Union
(
objCell, objRange)
End
If
End
If
Next
Ce code est facile à écrire mais très long à exécuter. Pour accélérer la méthode je vais utiliser le regroupement des propriétés. Dans Excel, lorsqu'une propriété est équivalente pour toutes les cellules d'une plage, elle est renvoyée comme propriété de la plage, sinon c'est Null qui est renvoyé. Dès lors je vais parcourir les colonnes et ne garder que celles contenant au moins une cellule ciblée. Puis je ferais le parcours des lignes de la même façon. Par intersection, il sera facile de composer ma plage de retour.
Dim
objRange As
Range, PlageRed As
Range, objCell As
Range, PlageResult As
Range
'réduction de la plage
For
Each
objRange In
ThisWorkbook.Worksheets
(
1
).Columns
If
IsNull
(
objRange.Interior.ColorIndex
) Then
If
PlageRed Is
Nothing
Then
Set
PlageRed =
objRange
Else
Set
PlageRed =
Application.Union
(
objRange, PlageRed)
End
If
End
If
Next
'travail en ligne
For
Each
objRange In
ThisWorkbook.Worksheets
(
1
).Rows
If
IsNull
(
objRange.Interior.ColorIndex
) Then
For
Each
objCell In
Application.Intersect
(
objRange, PlageRed).Cells
If
objCell.Interior.ColorIndex
=
5
Then
If
PlageResult Is
Nothing
Then
Set
PlageResult =
objCell
Else
Set
PlageResult =
Application.Union
(
objCell, PlageResult)
End
If
End
If
Next
End
If
Next
PlageResult.Select
Vous connaissez surement la fonction InputBox, mais connaissez-vous la méthode InputBox de l'objet Application ?
Pour tous les détails sur cette méthode, reportez-vous à l'aide en ligne de VBA Excel, mais voici un exemple pour générer une boite de dialogue qui attend une cellule ou un groupe de cellules :
Dim
P As
Range
On
Error
Resume
Next
Set
P =
Application.InputBox
(
"Sélectionnez une cellule ou une plage :"
, Type
:=
8
)
On
Error
GoTo
0
If
P Is
Nothing
Then
MsgBox
"Sélection annulée"
Pour information, les autre types disponibles pour la méthode InputBox :
0 : Formule
1 : Nombre
2 : String
4 : Booléen
8 : Range
16 : Erreur
64 : Tableau