J'ai un tableau dans Excel avec des en-têtes de colonne qui correspondent à une partie d'une plage nommée dynamique ailleurs dans mon classeur. Par exemple, j'ai ces en-têtes de colonne: "10", "20", etc., et ces plages nommées dynamiques: "ExampleRange10", "ExampleRange2", etc. J'aimerais entrer une formule VLookup qui référence ExampleRange10 en concaténant la chaîne "ExampleRange" et l'en-tête de colonne "10". Cela me permettrait simplement d'étendre la formule à toutes les colonnes du tableau, au lieu de saisir manuellement "ExampleRange10", "ExampleRange20", etc. dans la formule de chaque colonne.
Je connais la fonction INDIRECT et je l’utilise avec succès dans le passé avec des plages nommées, mais cela ne semble pas fonctionner avec la plage dynamic named dans ce cas. Je suppose que c'est une nuance qui a quelque chose à voir avec la façon dont les plages nommées dynamiques sont définies par Excel (elles n'apparaissent pas dans la liste déroulante des plages nommées située à gauche de la barre de formule et possèdent des propriétés intéressantes dans VBA. , par exemple). Est-il possible d'utiliser la formule INDIRECT conjointement avec une plage nommée dynamique ou existe-t-il un autre moyen de résoudre ce problème?
Edit : Voici les formules exactes utilisées.
Ceci est la formule principale: =VLOOKUP(B2,INDIRECT("ExampleRange"&C1),2,FALSE)
où C1 contient "10" et la formule de ma plage dynamique nommée appelée "ExampleRange10" est la suivante: =OFFSET(Sheet1!$F$2,0,0,COUNTA(Sheet1!$F$2:$F$25),2)
. La formule principale renvoie "#REF!", Mais cela fonctionne correctement lorsque je supprime la formule de plage dynamique nommée et que je définis simplement "ExampleRange10" en tant que plage statique.
Autant que je puisse le dire après avoir fait d'autres recherches, la fonction INDIRECT
d'Excel ne fonctionne tout simplement pas avec les plages dynamiques. Il existe peut-être un moyen astucieux de contourner INDIRECT
tout en restant fidèle au monde Excel non-VBA, mais je ne suis pas au courant. Au lieu de cela, j'ai fini par créer une fonction définie par l'utilisateur très similaire à celle décrite ici . J'ai modifié ma formule principale pour lire =VLOOKUP(B2,DINDIRECT("ExampleRange"&C1),2,FALSE)
, où DINDIRECT
est le nom de la fonction VBA que j'ai créée.
Le seul inconvénient (qui peut être ou ne pas être un inconvénient, selon votre perception) de cette alternative est que le classeur doit être enregistré en tant que classeur prenant en charge les macros et que l'utilisation d'une fonction personnalisée n'est pas très auto-documentée et nécessite une petite explication aux autres utilisateurs. Tout bien considéré, cependant, c’était une solution acceptable pour moi.
Pour le link-averse, voici le code:
Public Function DINDIRECT(sName As String) As Range
Dim nName As Name
On Error Resume Next
Set nName = ActiveWorkbook.Names(sName)
Set nName = ActiveSheet.Names(sName)
On Error GoTo 0
If Not nName Is Nothing Then
Set DINDIRECT = nName.RefersToRange
Else
DINDIRECT = CVErr(xlErrName)
End Function
Remarque: Bien que cette solution ait fonctionné, je ne vais pas accepter ma réponse car je ne veux pas décourager les autres de proposer de meilleures solutions. De plus, je suis nouveau sur le site, donc désolé si je casse un code d'étiquette en répondant à ma propre question ... Je pensais juste partager la solution exacte que j'avais utilisée au cas où d'autres le trouveraient utile.
J'ai récemment touché ce mur de briques exact et la réponse, comme vous l'avez déjà deviné, est simplement que vous ne pouvez pas référencer des plages nommées dynamiques avec INDIRECT.
Vous pouvez cependant utiliser la formule de la dynamique elle-même comme argument de INDIRECT, mais cela ne sert à rien. Un peu comme un PITA car c'est le genre de fonctionnalité qui serait très utile.
Si vos données comportent des en-têtes tels que 10, 20, etc., vous n'avez pas besoin d'utiliser Indirect. Pourquoi ne pas simplement utiliser Index/Match pour sélectionner les données dont vous avez besoin?
Nommez votre table entière ExampleRanges par exemple et utilisez cette formule:
Index(ExampleRanges, match(B2, index(ExampleRanges, , 1), 0), match(C1, index(ExampleRanges, 1,), 0))
Non testé, mais je pense que cela fonctionnerait:
fonction définie par l'utilisateur pour renvoyer l'adresse de votre plage nommée dynamiquement:
Function Named_Range_Address(Range_Name As Range, _
Optional SheetName As Boolean) As String
Dim strName As String
Application.Volatile
If SheetName = True Then
strName = "'" & Range_Name.Parent.Name & "'!" & Range_Name.Address
Else
strName = Range_Name.Address
End If
Named_Range_Address = strName
End Function
alors vous devriez pouvoir utiliser votre formule vlookup:
=VLOOKUP(B2,INDIRECT(named_range_address("ExampleRange"&C1,TRUE)),2,FALSE)
Je sais que c'est un très vieux fil, mais j'avais le même problème, alors peut-être que ma solution pourra aider les gens à l'avenir.
Fondamentalement, j'ai créé une macro qui supprime et redéfinit la plage lors de l'enregistrement et lui donne un nom. Par conséquent, la fonction INDIRECT fonctionnerait car la plage n'était pas dynamique. Tout ce que vous avez à faire est d’enregistrer le classeur après avoir ajouté des valeurs aux plages nommées.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim a, b, c, d, e, f As Integer
Dim data As Worksheet
Set data = ThisWorkbook.Worksheets("Data")
a = data.Range("A" & Rows.count).End(xlUp).row
b = data.Range("B" & Rows.count).End(xlUp).row
c = data.Range("C" & Rows.count).End(xlUp).row
d = data.Range("D" & Rows.count).End(xlUp).row
e = data.Range("E" & Rows.count).End(xlUp).row
f = data.Range("F" & Rows.count).End(xlUp).row
ActiveWorkbook.Names("KP").Delete
ActiveWorkbook.Names("KPT").Delete
ActiveWorkbook.Names("AP").Delete
ActiveWorkbook.Names("APT").Delete
ActiveWorkbook.Names("DISC").Delete
ActiveWorkbook.Names("SEATS").Delete
ActiveWorkbook.Names.Add Name:="KP", RefersTo:="=Data!$A$2:$A$" & a
ActiveWorkbook.Names.Add Name:="KPT", RefersTo:="=Data!$B$2:$B$" & b
ActiveWorkbook.Names.Add Name:="AP", RefersTo:="=Data!$C$2:$C$" & c
ActiveWorkbook.Names.Add Name:="APT", RefersTo:="=Data!$D$2:$D$" & d
ActiveWorkbook.Names.Add Name:="DISC", RefersTo:="=Data!$E$2:$E$" & e
ActiveWorkbook.Names.Add Name:="SEATS", RefersTo:="=Data!$F$2:$F$" & f
End Sub
Je sais que c'est assez ancien, mais je viens juste de le comprendre et de penser que j'ajouterais une solution qui évite tout codage VBA au cas où cela aiderait quelqu'un d'autre qui tombe par hasard sur ceci:
=VLOOKUP(B2,CHOOSE(C1/10,example10,example20,example30,example40),2,0)
Ceci suppose que la convention de dénomination est 10,20,30, etc. et ne sera pas idéal pour des centaines de plages.
En ajoutant une nouvelle torsion, il est possible d’utiliser une plage nommée avec les fonctions Address et Indirect. J'ai un cas où je configure des plages nommées pour une série de tables et j'utilise les éléments suivants:
Named Range: WWDH-FF-PI which points to Linear!$A$19 (first cell in table)
pour obtenir l'adresse: $ T 56 $: = ADRESSE (MATCH (S56, Linéaire! A: A, 0), 1,1,1, "Linéaire")
Ensuite, en utilisant la fonction offset copiée plusieurs fois pour créer un tableau croisé dynamique:
=OFFSET(INDIRECT($T$56),C5,$T$57-1)
Ainsi, la fonction Address peut être incorporée (ou encapsulée) dans la fonction Indirect pour créer une adresse de cellule dynamique.
Aujourd’hui, j’étais en train de bricoler avec des plages nommées Excel, et j’ai découvert que, s’il est vrai que vous ne pouvez pas calculer le nom de la plage dans l’appel INDIRECT()
lui-même, vous pouvez toujours l’obtenir de manière purement "Excel-way" en ajoutant un étape: créez simplement une cellule cachée dans laquelle vous calculez la plage nommée.
Par exemple, supposons que A1
contienne la "partie dynamique" du nom de la plage, puis dans A2
, utilisez la formule = "ExampleRange" & A1
et vous avez maintenant le nom complet de la plage, que vous pouvez utiliser comme = INDIRECT(A2)
.