MFC sur ligne visible
Bonsoir à tous,
Je lance ce sujet pour lequel je cherche une solution logique et rapide.
Dans un tableau structuré, je souhaite ajouter de façon dynamique une bordure épaisse (via MFC) qui servira à faciliter/délimiter la lecture de ce tableau.
Un bout de code devra forcément intervenir car :
→ cette bordure doit être visible quelque soit l'état du filtrage (inactif ou actif)
Illustration (ouiiii j'ai fait un zoli dessin ^^
A ce stade je réfléchi à la meilleure manière d'opérer ...
Pouvez-vous m'orienter/m'aider svp ?
Bonne nuit
bonjour tomato,
une réponse rapide, épais n'est pas possible en MFC
une bordure épaisse (via MFC)
avec un fichier, ma réponse serait plus lent ...
Bonsoir Bart,
Merci pour ta réponse.
Je me satisferais donc d'une bordure simple
A première vue ma stratégie consistera via VBA à boucle for sur les lignes du databodyrange de 1 à ListRow.count :
1) si ligne visible relever valeur de semaine A
2) si ligne visible et valeur de semaine <> de semaine A : relever row position et exit for
3) ajout dans workbook.name de la row position
4) MFC pour bordure supérieure sur row position
5) choix de l'évènement déclencheur "le moins pire" (si seulement les events existaient sur les changements de filtres ... un jour surement ... ) pour actualisation de ma row position
Que penses tu de la logique ? Surtout as tu une autre idée ?
Bonne soirée
re,
un tableau avec 2 colonnes auxiliaires G:H,
si la ligne est visible, la colonne G montre le numéro de la ligne (relatif à l'entête), si elle n'est pas visible = 0
la colonne H verifie si la semaine de la derniere ligne visible avant cette ligne <> la semaine de cette ligne
Maintenant utiliser le filtre pour colonne C, choississez le 1 ou le 0
Bonsoir et merci Bart,
Elégante façon de faire avec une formule. J'ai découvert la fonction AGREGAT très intéressante ! Merci.
Pour mon cas mon tableau structuré de donnée est composé de dizaines de milliers de lignes, et des utilisateurs pourraient être amenés à "perdre" les formules par une erreur de saisie, et puis je ne souhaite pas qu'ils soient perturbés par une colonne qui ne soit pas directement liée à leur travail. Bref je vais coder rapidement une petite macro telle que je l'ai décrite, je pourrais d'ailleurs même m'épargner une MFC et mettre ma fameuse ligne épaisse
Encore merci
re,
de dizaines de milliers de lignes,
votre macro durera 1 ou plusieurs secondes (dépendant du nombre de lignes), n'est-ce pas un inconvéniant ?
Pour 10.000 lignes effectives = 1.2 sec, pour 10 lignes effectives 0.1 sec
Sub Souligner()
Application.ScreenUpdating = False
t = Timer
For i = 1 To 100000 Step 10
s = s & "," & Cells(i, 3).Resize(, 10).Address(0, 0)
cnt = cnt + 1
Next
s = Mid(s, 2)
Range("C:L").Borders.LineStyle = xlNone
Do
i = Len(s)
If i <= 255 Then i = i + 1 Else i = InStrRev(s, ",", 256)
If i > 0 Then
With Range(Left(s, i - 1)).Borders(xlEdgeBottom) 'pas 2 lignes consécutives
.LineStyle = xlContinuous
.Weight = xlMedium
End With
With Range(Left(s, i - 1)).Borders(xlInsideHorizontal) '2 lignes consécutives
.LineStyle = xlContinuous
.Weight = xlMedium
End With
End If
s = Mid(s, i + 1)
Loop While s <> ""
MsgBox Timer - t & vbLf & cnt & " lignes"
End SubSalut à tous,
En optimisant un peu, avec la macro ci-dessous pour 2000 lignes j'ai un résultat instantané :
Voir fichier ci-joint, feuille "Sheet1"
Sub BordureSem()
Dim visibleCells As Range
With Sheet1.Range("B2")
Set visibleCells = Range(.Cells, .End(xlDown)).SpecialCells(xlCellTypeVisible)
End With
' tableau de correspondance : [num sem, row num]
Dim tbl() As Variant
ReDim tbl(0 To visibleCells.Count - 1, 0 To 1)
Dim i As Long, cel As Range
For Each cel In visibleCells
tbl(i, 0) = cel.Value2
tbl(i, 1) = cel.Row
i = i + 1
Next cel
' correspondances : [num sem: derniere ligne]
Dim lastRows As Object: Set lastRows = CreateObject("Scripting.Dictionary")
For i = LBound(tbl, 1) To UBound(tbl, 1)
lastRows(tbl(i, 0)) = tbl(i, 1)
Next i
' Definition des cellules a colorier
Dim toUpdate As Range
With Sheet1
Set toUpdate = .Range("A1:C1")
For i = 1 To lastRows.Count - 1
Set toUpdate = Union(toUpdate, .Cells(lastRows.Items()(i), 1).Resize(1, 3))
Next i
End With
' nettoyage du coloriage precedent
With Sheet1.Range("A1:C1")
Range(.Cells, .End(xlDown)).Borders.LineStyle = xlNone
End With
' coloriage
With toUpdate.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlMedium
End With
With toUpdate.Borders(xlInsideHorizontal)
.LineStyle = xlContinuous
.Weight = xlMedium
End With
End Subre,
salut Saboh12617,
je me rappèle que "Union" a ces inconveniants quand il devient trop grand, je ne sais plus mais je pense après 100 cellules ou 100 "areas" la vitesse ralentit enormément. Essayez votre macro avec 50.000 lignes et (????) je suppose 10.000-15.000 bordures !!! Puis faites la même chose mais après 100 union's (=300 cellules), vous actualisez les bordures et vous resettez "toUpdate". Et puis faites la même chose avec 33 unions ou 100 cellules.
Un pari, tout en une fois sera X, avec 100 unions << X/10, avec 33 unions ???
Salut @BsAlv,
Je n'étais pas au courant du ralentissement, il faut dire que je ne travaille pas souvent avec d'aussi grandes plages. Après je me suis basé sur le screenshot de l'OP. Ça m'étonnerait qu'il analyse manuellement +10k lignes, et si c'est le cas… 🥶
Il y a d'autres limitations dans la macro que j'ai postée :
Semaines dans l'ordre, au moins une ligne visible, pas de doublons…
Après tout cela s'adapte, et si on travaille vraiment avec +100 séparateurs à ajouter, oui il faudrait revoir le code en splittant la range, mais je pense qu'il faudrait aussi s'interroger sur pourquoi on a autant de lignes !
Bonsoir Bart et Saboh12617,
Merci de vous être penchés à nouveau sur mon sujet.
J'aime particulièrement la solution de Saboh qui est proche de ce que je pensais faire, deux remarques cependant :
- Saboh, nous sommes d'accords que tu passes par un Union qui te permet d'appliquer en masse les bordures et un énorme gain de performance/temps par rapport à boucler sur chaque ligne du dictionnaire ?
- Bart, merci pour ta précision concernant les limitations de taille de Union. Je ne savais pas non plus.
A propos des contraintes suivantes :
Semaines dans l'ordre
→ pas de souci de ce côté
Au moins une ligne visible
→ un test simple assorti d'une sortie de sub ira
Pas de doublons
→ tel que tu l'as codé je ne vois pas là où tu veux en venir, a fortiori si l'on concatene année & semaine comme clé de dictionnaire, non ?
Bonsoir @tomato,
Oui l'union est exactement là pour ça. Ce qui ralentit le code c'est de faire des aller-retour VBA/Excel. Faire un aller simple permet de considérablement réduire ce temps. Après comme l'indique @BsAlv ces méthodes ont aussi leurs limites.
Pour la suite tu as tout bon c'est ça, avec les solutions qui vont bien.
Pour les doublons, tu as aussi la solution en ajoutant l'année. Je disais ça car sur 1 an on a 52 semaines, donc si tu as > 1 an de registre, et que tes numéros de semaine se chevauchent (on reprend à 1 à chaque année), alors le dictionnaire va zapper toutes les années sauf la dernière. Mais la solution d'ajouter l'année dans la clé évite cela.
Pour contourner la lenteur de l'union on peut concaténer les adresses des cellules dans une string, et utiliser Range(laString) pour accéder au classeur. @BsAlv l'avait fait ici https://forum.excel-pratique.com/excel/largeur-de-colonnes-non-consecutives-197201
Après il faut faire attention aux autres limitations que ça implique (longeur de string maxi, etc) mais sur de très grandes plages c'est le plus opti je pense.
Bonsoir à tous !
Juste en passant pour ceux qui veulent des bordures épaisses en MFC !
L'astuce : c'est de mettre toutes les bordures épaisses, puis par MFC dans format, soit choisir de les mettre en fin, ou bien de les retirer.
Fichier joint pour l'exemple :
@ bientôt
LouReeD
le génie dans sa simplicitéBonsoir,
Merci LouReed pour ton intervention très astucieuse.
Un petit up et clin d'oeil à BsAlv. Juste à signaler que j'ai détourné plusieurs fois ton code sur d'autres procédures qui étaient jusque là chronophage et je ne m'en lasse pas de ce petit bijou !! Merci beaucoup
Bonsoir,
il est vrai qu'il m'arrive d'avoir des lueurs d'esprit !
Merci de votre retour !
Et je suis d'accord avec vous BsAlv est très rapide ! Enfin ses codes
@ bientôt
LouReeD