Pallier la limite de la méthode SpecialCells de VBA/Excel

Contenu du snippet

La méthode VBA Specialcells applicable à un objet Range de Excel est utile et très pratique.
Elle a cependant une limite gênante : elle ne peut recenser d'un seul coup plus d'un certain nombre d'aires (areas) résultant de son application. Ce nombre est égal à la moitié de la limite d'un type integer. Pourquoi la moitié ? Tout simplement parce-qu'il lui faut prévoir le pire des cas de fractionnement : une cellule sur deux correspondant au critère appliqué à la méthode.
Comment pallier cet inconvénient ? En traitant par blocs de cellules dont le nombre n'excède pas la moitié de la limite d'un type integer.
Ce qui veut clairement dire qu'il va falloir diviser encore par le nombre de colonnes de la plage. C'est ce que fait le petit code/snippet qui suit :
1) la fonction :
Private Function plage_specialcells(p As Range, nature As Integer, typ As Byte) As Range
  Dim plage_bloc As Range, nb As Long, taille_bloc As Integer, nb_blocs As Integer, dep As Long, fin As Long, i As Long
  nb = p.Rows.Count
  taille_bloc = 16385 ' à votre gré entre 2 et 16385 maximum : taille de bloc à traiter en boucle
  taille_bloc = taille_bloc  p.Columns.Count ' car le nb de cellules d'une ligne est celui de ses colonnes
  nb_blocs = nb  taille_bloc
  If typ = 0 Then typ = 2
  For i = 0 To nb_blocs + 1
    dep = p.Offset(i * taille_bloc).Row '- 1
    fin = dep + taille_bloc - 1
    If fin > nb Then fin = nb
    On Error Resume Next ' pour le cas ou aucune cellule concernée
    Set plage_bloc = Range(p.Cells(dep, 1), p.Cells(fin, p.Columns.Count)).SpecialCells(nature, typ)
    On Error GoTo 0
    If Not plage_bloc Is Nothing Then
      If plage_specialcells Is Nothing Then
         Set plage_specialcells = plage_bloc
      Else
         Set plage_specialcells = Union(plage_specialcells, plage_bloc)
      End If
    End If
    If fin >= nb Then Exit Function
  Next
End Function

2) un exemple d'utilisation :
Application.ScreenUpdating = False
  Dim nature As Integer, typ As Byte, plage_traitee As Range, plage_desti As Range
  Set plage_traitee = Range("A1:B50123") ' ===>> ici la plage à traiter
  nature = xlCellTypeBlanks ' par exemple (ou autre nature de votre choix)
  typ = 0 ' ===>> mettre 0 pour tous types ou 16 (xlErrors) ou 4 (xlLogical ou 1 (xlNumbers) ou 2 (xlTextValues)
  Set plage_desti = plage_specialcells(plage_traitee, nature, typ)
  Application.ScreenUpdating = True
  '============== le reste n'est là que pour visualiser le résultat, si on le souhaite
  If Not plage_desti Is Nothing Then plage_desti.Select Else MsgBox "aucune correspondance"

Compatibilité : VBA/Excel - toutes versions

A voir également