Icône de la ressource

VBA - Range Exclusion - Exclure un Range d'un autre Range V5

Dudu2

XLDnaute Barbatruc
Dudu2 a soumis une nouvelle ressource:

VBA - Range Exclusion - Exclure un Range d'un autre Range - VBA - Range Exclusion - Exclude a Range from another Range

Le fichier à télécharger contient:
  1. Le Module_RangeExclusionByAddresse
  2. Le Module_RangeExclusionByRanges
  3. Le Module_Test et le UserForm1 pour mettre en évidence le résultat des fonctions d'exclusions de Ranges.
Commentaires préliminaires:
  • VBA a prévu 2 fonctions de manipulation...

En savoir plus sur cette ressource...
 

bsalv

XLDnaute Occasionnel
pour exclure 2 plages assez compliqués (beaucoup de areas). Utilisez une feuille auxiliaire pour déterminer la plage exclusive.
Pour l'exemple ici, pour le teste, alternativement chaque une cellule change de zone,
 

Pièces jointes

  • Range Functions.xlsm
    51.2 KB · Affichages: 1

Dudu2

XLDnaute Barbatruc
Bonjour,
En effet, en passant pas une feuille intermédiaire ça le fait.
En fait ce sont les Union() qui prennent de plus en plus de temps jusqu'à durer excessivement longtemps au fur et à mesure qu'on les accumule et même jusqu'à devenir totalement rédhibitoire. Ça rend aussi l'exclusion par adresse inutilisable au-delà d'une certaine complexité des ranges.

J'ai essayé de faire des Unions par adresse mais ce n'est pas jouable, je ne me souviens plus pourquoi.
Sauf peut-être à faire des Unions temporaire par adresse dans un String et faire un Union final avec les adresses par groupes de 255 caractères max. A supposer que la fonction Union() Excel le supporte mieux, ce dont je doute.
Mais ça ne fonctionne que si on n'a pas besoin du Range issu des Unions temporaires, ce qui est peut-être le cas de l'exclusion. Faut que je regarde.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
J'ai essayé en faisant des Unions temporaires par adresse pour faire un Union final avec l'adresse finale découpée en morceaux de 255 caractères pour grouper les Union().
Ça divise par 3 le temps d'exécution, c'est déjà ça.
Mais ça reste bien moins rapide que ta solution par feuille.
 

Dudu2

XLDnaute Barbatruc
Inspiré de ton approche mais tout en table et en bénéficiant des Unions temporaires par adresse pour limiter les appels à la fonction Union(), voici une autre version de l'exclusion qui dépote. Du coup je me demande si je conserve la version précédente.
 

Dudu2

XLDnaute Barbatruc
Finalement, j'ai replacé la méthode d'Exclusion initialement par adresses pour utiliser une table.
Ce qui peut encore prendre du temps c'est le décompte et l'élimination des cellules dites "Area Overlap" car il faut comparer chaque Area avec toutes les autres et dans ce classeur c'est un cas spécial.
Pour le test j'ai inhibé cette option car de toutes façons il n'y a pas de "Area Overlap".

Edit: En tous cas merci pour avoir réveillé des idées sur cette fonction d'Exclusion.
 

Pièces jointes

  • Range Functions Variations.xlsm
    47.8 KB · Affichages: 1
Dernière édition:

bsalv

XLDnaute Occasionnel
j'ai remplacé l'Union par un dictionaire et celui coupe l'adresse des plages en morceaux de <=255.
Un exemple exagéré, une grille de 100*100 avec chaque cellule alternative = resultat est une plage de 5.000 areas en 14 sec.
On peut faire quelque chose similaire pour les "overlaps"
 

Pièces jointes

  • Range Functions Variations.xlsm
    74.4 KB · Affichages: 1

Dudu2

XLDnaute Barbatruc
Pour les "Area Overlaps" j'ai adopté le même système que pour les Range c'est à dire un table.
Le problème de ces "Overlaps", c'est que c'est chaque Area versus toutes les autres et rien que de compter les cellules des "Overlaps" pour n+1 Areas c'est n * (n-1) / 2 (Somme de i = 1 à n) comparaisons.

Ou alors il faudrait reconstituer tout le Range sans comparer les Areas, toujours via une table.
En fait la fonction d'Exclusion passant déjà par une table, ce n'est pas nécessaire pour son Range résultat.
C'est pour les autres fonctions.
 

Dudu2

XLDnaute Barbatruc
Voilà, le traitement des "Area Overlaps" est basé, comme pour l'Exclusion, sur une fonction qui mappe le Range dans un Table qui représente ses cellules et une autre fonction qui mappe la Table sur un Range.

Et j'ai mis à jour la ressource:
 

Pièces jointes

  • Range Functions Variations.xlsm
    63.5 KB · Affichages: 0

bsalv

XLDnaute Occasionnel
j'ai ajouté la macro pour le "overlap" pour des zones assez complexes.
donc maintenant on a la macro "Plage_Overlap" et macro "Plage_Exclusif"
Avec des plages simples, le temps d'exécution est plus long, mais dès que ces plages contiennent plusieurs "areas", elles seront plus vite.
 

Pièces jointes

  • Range Functions Variations.xlsm
    84.9 KB · Affichages: 5

patricktoulon

XLDnaute Barbatruc
bonjour
perso je fais comme ça
VB:
Sub test()
    Dim rng As Range, rng2 As Range, rngf As Range, cel As Range
    Set rng = [a1:H20] 'range globale
    Set rng2 = [f5:h10] 'range a exclure
    For Each cel In rng.Cells
        If Intersect(rng2, cel) Is Nothing Then
            If rngf Is Nothing Then Set rngf = cel Else Set rngf = Union(rngf, cel)
        End If
    Next
    MsgBox rngf.Address
End Sub
 

Dudu2

XLDnaute Barbatruc
Bonjour,

Oui, ben justement c'est la méthode qu'on trouve dans tous les exemples et que je pratiquais.
Mais c'est ce qu'on veut éviter car ça peut durer des plombes selon les Ranges.
Surtout à cause de la fonction Union() qui rame comme c'est pas possible à partir d'un certain nombre d'Areas ou de cellules ajoutées l'une après l'autre.

C'est pour ça que j'ai fait les fonctions UnionOfRangeAddresses() et GetRangeFromAddress() pour minimiser les appels à la fonction Union().

D'ailleurs faudrait que je compare la méthode utilisée dans la ressource qui mappe un Range dans une table de Booléens avec cette méthode traditionnelle en remplaçant les Union() par des UnionOfRangeAddresses() et un GetRangeFromAddress() à la fin. De toutes façons sur des gros Ranges on va y gagner beaucoup mais autant que dans la ressource ? A voir selon l'efficacité de la fonction Intersect() que je n'utilise pas.
 

Dudu2

XLDnaute Barbatruc
Pour de "petits" Ranges, la fonction Union() est satisafaisante.
Mais dès que le nombre de Ranges augmente, les fonctions UnionOfRangeAddresses() et un GetRangeFromAddress() à la fin sont beaucoup plus rapides. 10 fois plus rapides dans l'exemple joint.

Er encore, je me suis arrêté à For i = 1 To 2000 pour créer les Ranges.
En passant à 5000, j'ai été obligé du tuer le processus Excel car avec Union() ça n'en finit plus.
 

Pièces jointes

  • Classeur1.xlsm
    31.6 KB · Affichages: 1

Discussions similaires

Statistiques des forums

Discussions
312 209
Messages
2 086 267
Membres
103 168
dernier inscrit
isidore33