Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

XL 2013 VBA et plages nommées

sr94

XLDnaute Occasionnel
Bonjour

J'ai une macro qui me permet de supprimer et de refaire la mise en forme conditionnelle d'un fichier :

Code:
With Range("Y5").Select
Set plage3 = Range("Y5:Y" & Range("Y65536").End(xlUp).Row)

plage3.FormatConditions.Add Type:=xlExpression, Formula1:="=SI($O5<>"""";$Y5>=$O5;et($E5<>"""";$Y5>=$M5) )"
plage3.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.ColorIndex = 3
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
End With
plage3.FormatConditions(1).StopIfTrue = False

End With

Mon fichier est amené à être modifier et j'aimerais remplacer toute la référence à des cellules par les noms des colonnes ou les plages nommées, si je remplace ("Y5:Y") par ("FRI") par exemple j'ai une erreur

L'indice n'appartient pas à la selection

Comment dois je modifier ce code pour ne plus avoir de référence à des cellules ?

Je joins un fichier test

Merci
 

Pièces jointes

  • Classeur test.xlsm
    28.8 KB · Affichages: 57
  • Classeur test.xlsm
    28.8 KB · Affichages: 59
Dernière édition:

Dranreb

XLDnaute Barbatruc
Re : VBA et plages nommées

Bonjour.
Personnellement j'utilise beaucoup ces deux fonctions de service :
VB:
Function PlgUti(ByVal PlageDép As Range, Optional ByVal PlagExam As Range = Nothing, _
   Optional ByVal LMin As Long, Optional ByVal CMin As Long) As Range
Rem. Cherche la partie utilisée d'une plage, c'est à dire celle qui s'étend jusqu'à la dernière cellule renseignée de plus qu'une chaîne vide.
'    PlageDép: Plage de départ. Seule la 1ère cellule spécifiée est prise en compte pour la déterminer, et suffit donc pour une utilisation VBA.
'            Pour utilisation en formules, il est néanmoins nécessaire de spécifier la plage depuis celle ci jusqu'au reste des colonnes entières.
'    PlageExam: Plus grande plage susceptible de contenir la plage cherchée.
'            Facultatif: UsedRange assumé par défaut.
'    LMin: Mombre de lignes minimum à considérer même si tout est vide.
'    CMin: Mombre de colonnes minimum à considérer même si tout est vide.
Dim LMax As Long, CMax As Long, NbL As Long, NbC As Long
On Error GoTo RienTrouvé
If PlagExam Is Nothing Then Set PlagExam = PlageDép.Worksheet.UsedRange
LMax = PlagExam.Find("*", PlagExam.Cells(1, 1), xlValues, xlWhole, xlByRows, xlPrevious).Row
CMax = PlagExam.Find("*", PlagExam.Cells(1, 1), xlValues, xlWhole, xlByColumns, xlPrevious).Column
On Error GoTo 0
NbL = LMax - PlageDép.Row + 1: If NbL < LMin Then NbL = LMin
NbC = CMax - PlageDép.Column + 1: If NbC < CMin Then NbC = CMin
If NbL < 1 Or NbC < 1 Then GoTo CEstToutVide
Set PlgUti = PlageDép.Resize(NbL, NbC)
Exit Function
RienTrouvé: Resume CEstToutVide
CEstToutVide: Set PlgUti = Nothing
End Function
'

Function ColUti(ByVal PlageDép As Range, Optional ByVal LMin As Long, Optional ByVal CMin As Long) As Range
Rem. Comme PlgUti, mais la plage rendue se limitera aux colonnes couvertes par la plage de départ spécifiée.
Set ColUti = PlgUti(PlageDép, Intersect(PlageDép.Worksheet.UsedRange, PlageDép.EntireColumn), LMin, CMin)
End Function

Maintenant votre Sub commence par Range("Tableau2").Select
Ce qui me donne à subodorer que toutes vos colonnes sont dans un tableau Excel. Dans ce cas il faut plutôt utiliser le ListObject.

Oui ça se confirme. Vous pouvez utilser une structure comme ça :
VB:
Sub Mise_en_forme_conditionnelle()
Dim LO As ListObject
Set LO = Range("Tableau2").ListObject
LO.DataBodyRange.FormatConditions.Delete

With LO.ListColumns(1).DataBodyRange.FormatConditions.Add(Type:=xlExpression, Formula1:="=$AD5<>0")
   .Interior.ColorIndex = 35
   .Interior.Pattern = xlSolid
   .Interior.PatternColorIndex = xlAutomatic
   .StopIfTrue = False
   End With
Mais je vois que vous avez mis des noms qui renvoient au colonnes du tableau, alors il ont déjà toujours la bonne taille en nombre de lignes, non ?
 
Dernière édition:

sr94

XLDnaute Occasionnel
Re : VBA et plages nommées

Merci mais ... il n'y a pas quelque chose de plus simple ?

Dans les formules comment faire pour que la référence à la plage nommée prenne uniquement la ligne de la cellule et non pas toute la plage nommée ? par exemple si je remplace $AD5 par ETA, dès lors qu'une cellule est >0, la mise en forme conditionnelle s'applique à toutes les lignes et non pas seulement à la ligne. [@ETA] me fait une erreur.

Merci
 

Dranreb

XLDnaute Barbatruc
Re : VBA et plages nommées

With [FRI].FormatConditions.Add(Type:=xlExpression, Formula1:= etc.
Vous voulez bien les mêmes Mises en forme à toutes les lignes du tableau pour chaque colonne, non ?
En tout cas vous n'avez certainement plus besoin de faire des End(xlUp).Row
 
Dernière édition:

sr94

XLDnaute Occasionnel
Re : VBA et plages nommées

le soucis se situe au niveau de la formule
J'arrive à définir que la MFC s'applique à toute une plage, mais le hic c'est que s'applique uniquement à a ligne en question

Voici le code modifié pour le début de la macro qui est dans le fichier :
Code:
With Range("Tableau2").Select
Set plage2 = Range("Tableau2")
plage2.FormatConditions.Add Type:=xlExpression, Formula1:="=ETA<>0"
plage2.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.ColorIndex = 35
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
End With
plage2.FormatConditions(1).StopIfTrue = False

End With

la formule "=ETA<>0" s'applique à toutes les lignes si n'importe où dans le tableau ETA<>0 alors que seule la ligne où ETA<>0 doit appliquer le format demandé
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Re : VBA et plages nommées

Alors si vous tenez à mettre une mise en formes différentes à une ligne particulière vous pouvez utiliser Intersect([FRI], Rows(5)).FormatConditions.Add etc.
Mais moi je trouve ça tout à fait anormal. À partir du moment ou dans la formule il n'y a pas de dollar devant le numéro de ligne 5 spécifié, ça s'appliquera à la ligne 5 pour la 5, d'accord, mais à la 6 pour la 6 etc.
 
Dernière édition:

sr94

XLDnaute Occasionnel
Re : VBA et plages nommées

non ce n'est pas une ligne particulière c'est juste que la mise en forme conditionnelle s'applique à chaque ligne séparemment
si première ligne la formule n'est pas remplie il n'y a rien
si deuxième ligne la formule est remplie, la MFC est appliquée
etc ...

actuellement si la condition est remplie sur la ligne 5 c'est tout le tableau qui a le format de la MFC
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Re : VBA et plages nommées

Elle s'applique toujours à chaque cellule séparément, en s'appuyant sur des lignes et colonnes différentes quand il n'y a pas de "$" devant leur spécification dans la formule. Vous vous trompez certainement en cryant que la condition seulement remplie sur la ligne 5 s'applique à tout le tableau.
 
Dernière édition:

sr94

XLDnaute Occasionnel
Re : VBA et plages nommées

je sais je connais le $ mais je veux mettre le nom des colonnes au lieu des références aux cellules, car ce tableau est appelé à évoluer et ça éviterait de mettre à jour les macros à chaque fois.
Si je mets FRI tout court il considère toute les valeurs de la colonne et à partir du moment où il trouve la condition une fois il l'applique à toutes les lignes, évidemment si je mets $FRI... j'ai une erreur... comment contourner ça ?
 

Dranreb

XLDnaute Barbatruc
Re : VBA et plages nommées

Alors si c'est dans la formule que vous voudriez pouvoir utiliser le nom, je doute que ce soit possible.
Mas vous pourriez toujours l'utiliser pour mettre
Formula1:="=" & [ETA].Rows(1).Address(False, True) & "<>0"

Ne pourriez vous utiliser les titres du tableau plutôt ?
VB:
Option Explicit
Dim LO As ListObject

Function A1Tit(ByVal TitCol As String) As String
Dim Plg As Range
Set Plg = LO.ListColumns(TitCol).DataBodyRange.Rows(1)
A1Tit = Plg.Address(False, True)
End Function
Ça permettrait de faire des :
VB:
                       … Formula1:="=" & A1Tit("ETA") & "<>0"
Enfin si "ETA" était le titre d'une colonne du tableau.
 
Dernière édition:

sr94

XLDnaute Occasionnel
Re : VBA et plages nommées

J'ai essayé avec la fonction mais j'ai une erreur de "with" sur la fonction, c'est dommage ça aurait peut être plus simple que la formule

En revanche la formule donc marche très bien avec
Code:
Formula1:="=" & [ETA].Rows(2).Address(False, True) & "<>0"

Par contre je vais devoir appliquer ce code sur toutes les mises en forme conditionnelles de la macro, peux tu m'expliquer le code ? je vois notament que la $ est bien présent dans la formule
Code:
[ETA].Rows(2).Address(False, True)

Je joins le fichier test avec la fonction qui me ressort une erreur

La macro est utilisée dans 2 contextes : le premier c'est que je ne suis pas seule à utiliser mon fichier de 5000 lignes et que j'ai en permanence les MFC en multiple avec des plages différentes, la macro permet de tout défaire et refaire proprement. Et le deuxième c'est que mon fichier est scindé en plusieurs morceaux par macro et implanter la macro de MFC à l'intérieur de cette macro permet de récupérer les MFC dans les fichiers générés.

Merci !
 

Pièces jointes

  • Classeur test 2.xlsm
    24.9 KB · Affichages: 50
  • Classeur test 2.xlsm
    24.9 KB · Affichages: 57

Dranreb

XLDnaute Barbatruc
Re : VBA et plages nommées

Ne marchait pas parce que LO n'était pas défini.
J'ai réussi à faire marcher ça, en mettant tout dans le même module :
VB:
Option Explicit
Private LO As ListObject
'

Sub Mise_en_forme_conditionnelle()
Dim FC As FormatCondition
Set LO = ActiveSheet.ListObjects(1)
LO.DataBodyRange.FormatConditions.Delete

Set FC = LO.ListColumns("Colonne2").DataBodyRange.FormatConditions.Add _
   (Type:=xlExpression, Formula1:="=" & A1Tit("ETA") & "<>0")
With FC.Interior: .ColorIndex = 35: .Pattern = xlSolid
   .PatternColorIndex = xlAutomatic: End With
FC.StopIfTrue = False
End Sub
'

Function A1Tit(ByVal TitCol As String) As String
Dim Plg As Range
Set Plg = LO.ListColumns(TitCol).DataBodyRange.Rows(1)
A1Tit = Plg.Address(False, True) ' Adresse 1ère cellule avec référence ligne relative.
End Function
Function AColTit(ByVal TitCol As String) As String
Dim Plg As Range
Set Plg = LO.ListColumns(TitCol).DataBodyRange
AColTit = Plg.Address(True, True) ' Adresse colonne pour NB.SI, EQUIV etc.
End Function
Le "$" bien présent mais seulement pour la colonne vient du Address(RowAbsolute:=False, ColumnAbsolute:=True)
 
Dernière édition:

sr94

XLDnaute Occasionnel
Re : VBA et plages nommées

Bonjour,

Ca marche presque ! La fonction est ok mais toute la ligne prend le format pour cette MFC, pas uniquement "Colonne2", comment dois je adapter pour indiquer toutes les colonnes de tableau2 ?

Merci !
 

Dranreb

XLDnaute Barbatruc
Re : VBA et plages nommées

Bonjour.

J'avais fait l'essai sous mon Excel 16 dans le classeur que j'avais, ça ne m'avait coloré en vert pâle qu'une des deux cellules de la colonne A. Remarque, je n'ai pas fait l'essai avec un titre fantaisiste. Qui sait, plutôt que de stopper l'exécution en signalant une erreur comme quoi il ne trouve pas de colonne particulière portant exactement ce titre, il préfère l'appliquer à toutes les colonnes. Ce serait assez intelligent, pour une fois, après tout.
Sinon il serait possible de préciser le numéro d'ordre de la colonne au lieu du titre, mais ça ne règlerait qu'en partie le problème parce que ma fonction utilise aussi les titres, et absolument pas des noms de plages indépendamment définis par dessus.
Joindre le classeur, avec quelques séquences supplémentaires de Set FC = LO.ListCol… … FC.StopIfTrue = False

Ah non, c'est l'inverse: tu voudrait que ça s'applique à tout LO.DataBodyRange en fait ? Eh Ben c'est LO.DataBodyRange.FormatConditions.Add
Pour un groupe de colonnes ne couvrant pas entièrement, plusieurs façon de l'exprimer. Le plus 'simple' à mon avis :
LO.ListColumns(x).DataBodyRange.Resize(, NbCol).FormatConditions.Add
À moins qu'il n'y ait une autre syntaxe (je ne découvre les ListObject que depuis peu de temps). Il y a peut être aussi des possibilités plus courtes avec Evaluate ou les […]. Mais pas sûr. Je trouve la syntaxe de ces références assez lourde. Mais je songe à écrire une Function qui les convertis en références classiques, puisqu'elles ne sont pas acceptées dans les MeFC, lesquelles sont toujours très en retard sur le reste (impossibilité de préciser déjà des FormulaR1C1, Formula1 ne reconnaissant que du local). Et la conversion inverse aussi.
 
Dernière édition:
Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…