FAQ VBA

FAQ VBAConsultez toutes les FAQ
Nombre d'auteurs : 10, nombre de questions : 133, dernière mise à jour : 15 juin 2021
Sommaire→Excel→Plages→Manipuler des plages- 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).ClearContentsL'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
NextUsedRange 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.SelectSélectionner les cellules non vides de la colonne
Range("A1").EntireColumn.SpecialCells(xlCellTypeConstants).SelectAttention, 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)).SelectSélectionner une plage de valeurs continues
Range("A1", Range("A1").End(xlDown)).SelectSé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)).SelectC'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"), , xlAscendingIl 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 MsgExcel 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).ActivateCe 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 WithL'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).ClearContentscomme 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
NextCe 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



