Icône de la ressource

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

Dudu2

XLDnaute Barbatruc
Je code la représentation mémoire du Range avec le Type que j'ai cité plus haut. Plus de problème de Range Global limité. Mais je me prends la tête, faut pas se tromper dans les algorithmes qui sont pas simples.
Il me reste à faire la mapping mémoire vers le Range avec recherche des Areas. Ça viendra en son temps.
 

Dudu2

XLDnaute Barbatruc
Alors c'est la cata. Ça fonctionne mais ça prend un temps fou dans une séquence particulière. Faut que j'essaie de trouver une alternative mais c'est pas gagné.
 

patricktoulon

XLDnaute Barbatruc
j'ai essayé moi aussi un tableau de 1 million
c'est pire
mais je pensait que c'était moi qui m'y prenait mal
je suis rassuré
je pense que justement la méthode des multiple redim de tableau vides seraient une alternative intéressantes

voila un depart de l'idée
VB:
Sub testQ()

    Dim R(1 To 4) As Range
    Dim tblarea() As Variant
    Dim T, A&, I&, Texte$
    Dim Texte As String
    Dim rng As Range
    
    Cells.Interior.Color = xlNone

    'for the example 4 ranges which intersect somewhere
    Set R(1) = [D3:J9]
    Set R(2) = [E1:E15]
    Set R(3) = [B7:E7]
    Set R(4) = [G1:G5]

    'for the demo I put the ranges in color
    R(1).Interior.Color = RGB(0, 200, 255)
    R(2).Interior.Color = RGB(0, 255, 200)
    R(3).Interior.Color = RGB(255, 200, 0)
    R(4).Interior.Color = RGB(200, 255, 0)

    'we group them all together with union function
    Set rng = Union(R(1), R(2), R(3), R(4))
    ReDim tblarea(1 To rng.Areas.Count)
    For Each area In rng.Areas
        A = A + 1
        ReDim T(area.Row To area.Row + area.Rows.Count - 1, area.Column To area.Column + area.Columns.Count - 1)
        tblarea(A) = T
    Next

'lecture
For I = 1 To UBound(tblarea)
Texte = Texte & rng.Areas(I).Address & vbCrLf & " ligne " & LBound(tblarea(I)) & " à " & UBound(tblarea(I)) & vbCrLf & _
"les colonnes " & LBound(tblarea(I), 2) & " à " & UBound(tblarea(I), 2) & vbCrLf & "*******************************" & vbCrLf
Next

MsgBox Texte

 'reste plus qu'a boucler sur les items tableaux vides
 'et les comparer entre eux
 'les index seront les mêmes puisqu'il ont été dimentionner avec les vrai index de ligne et colonne des areas
End Sub
 

Dudu2

XLDnaute Barbatruc
J'ai réussi à améliorer certaines partie pour être assez performant mais loin de la méthode de Mapping booléen. Je vais continuer à essayer d'améliorer les algorithmes.
Ou alors je ferai un mix des 2 méthodes selon le nombre de cellules du Range Réservoir.
Mais plut tard, là je sors.
 

patricktoulon

XLDnaute Barbatruc
je sais pas je te laisse faire
ta facon de coder avec passerelle et tout le toutim m'est pas intelligible pour moi
alors j'attends que tu ai fini
le jour ou tu saura faire sans artifice peut être ce jour là on pourra se comprendre

juste une sub avec l'essentiel du moteur avec juste 3 ou 4 ranges et qui se croisent
 

Dudu2

XLDnaute Barbatruc
La méthode Map Range To Table avec un structure:
VB:
Private Type Row
    RowNumber As Long
    TabColumnNumbers() As Integer
End Type
est évidemment moins performante que la Map Range To Table avec un tableau de booléens.

Elle est aussi performante que la méthode traditionnelle améliorée pour un nombre de Range jusqu'à 250 (dans l'exemple) et devient comparativement de plus en plus performante au fur et à mesure qu'on augmente le nombre de Ranges. Et contrairement à la méthode utilisant un tableau de booléens elle n'a que faire de la localisation proche ou espacée des Areas du Range Réservoir.
 

Dudu2

XLDnaute Barbatruc
Au final, je vais mixer les 2 méthodes Map Range To Table (tableau de booléen et tableau de structures) en prenant la première quand c'est possible et la 2ème dans le cas contraire.
Le plus difficile étant de déterminer à partir que quand il faut basculer. Pas facile à déterminer sauf à multiplier les tests.
 

Dudu2

XLDnaute Barbatruc
Fichier corrigé.

Après j'ai pensé à une autre méthode pour l'Exclusion puisque c'est le mapping booléen qui est le plus efficace. Au lieu de représenter le Range Réservoir de manière globale, je vais faire le mapping booléen de chaque Area du Range Réservoir.
Il restera la limite de dimensionnement en tableau d'une Area faisant plus de 2 ^ 31 - 1 (2.147.483.647) de cellules. Dans ce cas il faudra accepter de ne pas retourner une valeur de Range d'Exclusion, à supposer que le parcours d'un tableau d'un tel nombre d'items soit réaliste en temps, sinon il faudra descendre cette limite.
 

Pièces jointes

  • Range Exclusion Test Performance TabRows.xlsm
    112.5 KB · Affichages: 0
Dernière édition:

Dudu2

XLDnaute Barbatruc
Voici cette autre méthode qui consiste à mapper les Areas du Range Réservoir en tables de Booléens représentant les cellules présentes (quand False) dans l'Area. L'exclusion ou le retrait des "Overlaps" consiste à les mettre à True. Ensuite la reconstruction du Range reprends les tables des Areas restés à False.

Sur 100 Ranges de 100 lignes x 15 colonnes ça va 100 fois plus vite que la méthode traditionnelle améliorée.

Inconvénient: si une Area fait plus de 100 millions de cellules, je génère une erreur pour garder les calculs dans des temps raisonnables. De toutes façons, je ne pourrais pas dimensionner le tableau de Booléens au delà de 2 ^ 31 - 1.

La méthode initiale par comparaison des adresses des Areas était la meilleure idée. Je ne sais pas pourquoi c'était très lent. Je vais revisiter cette méthode aussi, comme ça j'aurai fait le tour.
 

Pièces jointes

  • Range Exclusion Test Performance TabBool Area.xlsm
    104.6 KB · Affichages: 0
Dernière édition:

Dudu2

XLDnaute Barbatruc
Bonjour à tous,
Sub simple ? Je sais pas si cette dernière version est simple mais elle est très performante.
Sur 100 Ranges de 100 lignes x 15 colonnes ça va 360 fois plus vite que la méthode traditionnelle améliorée.

Plus aucune représentation des Ranges ou des Areas dans des tableaux.
J'utilise uniquement les adresses des Areas pour faire les Exclusions, donc plus de limites.

J'aurais dû me focaliser là-dessus, qui était l'option initiale que j'avais prise, au lieu de passer des heures et des heures de programmation sur les 3 versions avec les tableaux dont l'idée était de copier la méthode de @bsalv en mémoire plutôt qu'en feuille.

Je vais devoir modifier les ressources sur cette nouvelle base de fonctions de Ranges.
Fichier -> Voir Post suivant.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Encore un bug sur le test d'un Intersect() dont l'un des Ranges est Nothing !
 

Pièces jointes

  • Range Exclusion Test Performance Adresses.xlsm
    105.9 KB · Affichages: 0

Discussions similaires

Statistiques des forums

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