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 ^^

image

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

16totmato.xlsx (14.35 Ko)

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 Sub

Salut à 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"

7totmato.xlsm (98.31 Ko)
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 Sub

re,

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

Rechercher des sujets similaires à "mfc ligne visible"