Lorsque je crée une plage nommée via le gestionnaire de noms, je peux spécifier spécification Workbook ou [worksheet name]
. Mais si vous souhaitez ensuite changer de portée, la liste déroulante est grisée. Existe-t-il un moyen, dans le gestionnaire de noms ou, de préférence, dans VBA de modifier l'étendue d'une plage nommée existante?
Par exemple:
testName
fait référence à 'sheet1'!A1:B2
avec le classeur scope. Comment pourrais-je changer cela entestName
fait référence à 'sheet1'!A1:B2
avec la portée de 'sheet1'?Vous pouvez télécharger le complément gratuit du gestionnaire de noms développé par Jan Karel Pieterse et moi-même à partir de http://www.decisionmodels.com/downloads.htm Cela permet à de nombreuses opérations de nommer le gestionnaire de noms Excel 2007. ne peut pas gérer, y compris la modification de la portée des noms.
En VBA:
Sub TestName()
Application.Calculation = xlManual
Names("TestName").Delete
Range("Sheet1!$A$1:$B$2").Name = "Sheet1!TestName"
Application.Calculation = xlAutomatic
End Sub
J'ai trouvé la solution! Copiez simplement la feuille avec vos variables nommées. Puis supprimez la feuille d'origine. La feuille copiée aura désormais les mêmes variables nommées, mais avec une portée locale (portée = la feuille copiée).
Cependant, je ne sais pas comment passer des variables locales aux variables globales.
Vérifiez ces deux sous-fichiers qui s'inversent et inversez la portée (feuille de calcul en classeur ou inversement) de toutes les plages nommées qui font référence à une plage de la feuille active.
Option Explicit
'---------------------------------------------------------------------------------------
' Procedure : RescopeNamedRangesToWorkbook
' Author : JS20'07'11
' Date : 11/18/2013
' Purpose : Rescopes the parent of worksheet scoped named ranges to the active workbook
' for each named range with a scope equal to the active sheet in the active workbook.
'---------------------------------------------------------------------------------------
Public Sub RescopeNamedRangesToWorkbook()
Dim wb As Workbook
Dim ws As Worksheet
Dim objName As Name
Dim sWsName As String
Dim sWbName As String
Dim sRefersTo As String
Dim sObjName As String
Set wb = ActiveWorkbook
Set ws = ActiveSheet
sWsName = ws.Name
sWbName = wb.Name
'Loop through names in worksheet.
For Each objName In ws.Names
'Check name is visble.
If objName.Visible = True Then
'Check name refers to a range on the active sheet.
If InStr(1, objName.RefersTo, sWsName, vbTextCompare) Then
sRefersTo = objName.RefersTo
sObjName = objName.Name
'Check name is scoped to the worksheet.
If objName.Parent.Name <> sWbName Then
'Delete the current name scoped to worksheet replacing with workbook scoped name.
sObjName = Mid(sObjName, InStr(1, sObjName, "!") + 1, Len(sObjName))
objName.Delete
wb.Names.Add Name:=sObjName, RefersTo:=sRefersTo
End If
End If
End If
Next objName
End Sub
'---------------------------------------------------------------------------------------
' Procedure : RescopeNamedRangesToWorksheet
' Author : JS20'07'11
' Date : 11/18/2013
' Purpose : Rescopes each workbook scoped named range to the specific worksheet to
' which the range refers for each named range that refers to the active worksheet.
'---------------------------------------------------------------------------------------
Public Sub RescopeNamedRangesToWorksheet()
Dim wb As Workbook
Dim ws As Worksheet
Dim objName As Name
Dim sWsName As String
Dim sWbName As String
Dim sRefersTo As String
Dim sObjName As String
Set wb = ActiveWorkbook
Set ws = ActiveSheet
sWsName = ws.Name
sWbName = wb.Name
'Loop through names in worksheet.
For Each objName In wb.Names
'Check name is visble.
If objName.Visible = True Then
'Check name refers to a range on the active sheet.
If InStr(1, objName.RefersTo, sWsName, vbTextCompare) Then
sRefersTo = objName.RefersTo
sObjName = objName.Name
'Check name is scoped to the workbook.
If objName.Parent.Name = sWbName Then
'Delete the current name scoped to workbook replacing with worksheet scoped name.
objName.Delete
ws.Names.Add Name:=sObjName, RefersTo:=sRefersTo
End If
End If
End If
Next objName
End Sub
voici comment je fais la promotion de tous les noms de feuilles de calcul en noms globaux. YMMV
For Each wsh In ActiveWorkbook.Worksheets
For Each n In wsh.Names
' Get unqualified range name
Dim s As String
s = Split(n.Name, "!")(UBound(Split(n.Name, "!")))
' Add to "Workbook" scope
n.RefersToRange.Name = s
' Remove from "Worksheet" scope
Call n.Delete
Next n
Next wsh
créez le nouveau nom à partir de zéro et supprimez l'ancien.
Une autre méthode consiste à "pirater" le fichier Excel pour 2007 ou une version ultérieure, bien que vous fassiez attention à cela, et à conserver une copie de sauvegarde de l'original:
Commencez par enregistrer la feuille de calcul Excel en tant que fichier .xlsx ou .xlsm (non binaire). renommez le fichier en .Zip, puis décompressez. Accédez au dossier xl de la structure Zip et ouvrez le fichier workbook.xml dans Wordpad ou un éditeur de texte similaire. Les plages nommées se trouvent dans les balises defineName. La portée locale est définie par localSheetId = "x" (les ID de feuille peuvent être trouvés en appuyant sur Alt-F11 dans Excel, avec la feuille de calcul ouverte, pour accéder à la fenêtre VBA, puis en regardant dans le volet Projet). Les plages cachées sont définies par hidden = "1", il suffit donc de supprimer le hidden = "1" pour afficher, par exemple.
Tapez maintenant la structure du dossier en veillant à préserver son intégrité, puis renommez-la en .xlsx ou .xlsm.
Ce n'est probablement pas la meilleure solution si vous devez modifier l'étendue ou masquer/afficher un grand nombre de plages définies, bien que cela fonctionne correctement pour effectuer une ou deux petites modifications.
Cela doit encore être affiné, mais cela fonctionne avec toutes les références simples, sans tuer les noms locaux existants.
Type GlobalNamesToLocalNames_Type
Name As String
Sheet As String
Ref As String
End Type
Sub GlobalNamesToLocalNames(Optional Void As Variant)
Dim List() As GlobalNamesToLocalNames_Type
Dim Count As Long
Dim Name As Name
Dim Dat() As String
Dim X As Long
' count the size
For Each Name In ActiveWorkbook.Names
Count = Count + 1
Next
ReDim List(Count - 1)
Count = 0
' Collecect all name data
For Each Name In ActiveWorkbook.Names
With List(Count)
' Pick up only the name
If InStr(Name.Name, "!") > 0 Then
Dat = Split(Name.Name, "!")
.Name = Dat(1)
Else
.Name = Name.Name
End If
' pick up the sheet and refer
Dat = Split(Name.RefersTo, "!")
.Sheet = Mid(Dat(0), 2)
.Ref = Dat(1)
' make local sheet name
.Name = .Sheet & "!" & .Name
End With
Count = Count + 1
Next
' Delete all names
For Each Name In ActiveWorkbook.Names
Name.Delete
Next
'rebuild all the names
For X = 0 To Count - 1
With List(X)
If Left(.Ref, 1) <> "#" Then
ActiveWorkbook.Names.Add Name:=.Name, RefersToLocal:="=" & .Sheet & "!" & .Ref
End If
End With
Next
End Sub
Le code de JS20'07'11 est vraiment incroyable, simple et direct. Une suggestion que je voudrais donner est de mettre un point d'exclamation dans les conditions:
InStr(1, objName.RefersTo, sWsName+"!", vbTextCompare)
Cela empêcherait l'ajout d'un NamedRange dans une feuille incorrecte. Exemple: si le NamedRange fait référence à une feuille nommée Plan11 et que vous avez une autre feuille nommée Plan1, le code peut causer des dégâts lorsque vous ajoutez des plages si vous ne le faites pas t n’utilisez pas le point d’exclamation.
METTRE &AGRAVE; JOUR
Une correction: il est préférable d'utiliser une expression régulière pour évaluer le nom de la feuille. Une fonction simple que vous pouvez utiliser est la suivante (adaptée par http://blog.malcolmp.com/2010/express-expressions-Excel-add-in , activez Microsoft VBScript Regular Expressions 5.5):
Function xMatch(pattern As String, searchText As String, Optional matchIndex As Integer = 1, Optional ignoreCase As Boolean = True) As String
On Error Resume Next
Dim RegEx As New RegExp
RegEx.Global = True
RegEx.MultiLine = True
RegEx.pattern = pattern
RegEx.ignoreCase = ignoreCase
Dim matches As MatchCollection
Set matches = RegEx.Execute(searchText)
Dim i As Integer
i = 1
For Each Match In matches
If i = matchIndex Then
xMatch = Match.Value
End If
i = i + 1
Next
End Function
Donc, vous pouvez utiliser quelque chose comme ça:
xMatch("'?" +sWsName + "'?" + "!", objName.RefersTo, 1) <> ""
au lieu de
InStr(1, objName.RefersTo, sWsName+"!", vbTextCompare)
Cela couvrira les variations de {Plan1 _ et 'Plan1' (lorsque la plage se rapporte à plusieurs cellules).
CONSEIL: évitez les noms de feuille avec des guillemets simples ('), :).
Pour moi, cela fonctionne que lorsque je crée nouvelle étiquette de nom pour la même plage depuis le Gestionnaire de noms cela me donne la possibilité de changer de portée;) le classeur est fourni par défaut et peut être remplacé feuilles.
Ces réponses ont été utiles pour résoudre un problème similaire tout en essayant de définir une plage nommée avec une étendue Workbook
. Le "ah-ha!" pour moi, c’est utiliser la collection de noms qui est relative au classeur entier!partager pour d'autres avec des questions similaires.
' Local / Worksheet only scope
Worksheets("Sheet2").Names.Add Name:="a_test_rng1", RefersTo:=Range("A1:A4")
' Global / Workbook scope
ThisWorkbook.Names.Add Name:="a_test_rng2", RefersTo:=Range("B1:b4")
Si vous consultez votre liste de noms lorsque la Feuille2 est active, les deux plages sont présentes, mais passez à une autre feuille et "a_test_rng1"
n'est pas présent.
Maintenant, je peux créer avec plaisir une plage nommée dans mon code avec la portée que je juge appropriée. Pas besoin de perdre son temps avec le gestionnaire de noms ou un plug-in.
De plus, le gestionnaire de noms dans Excel Mac 2011 est un gâchis, mais j’ai découvert qu’il n’existait pas d’étiquettes de colonnes vous indiquant ce que vous regardiez lorsque vous consultez votre liste de plages nommées, s’il existe une feuille en regard du nom. , ce nom est limité à feuille de calcul/local. Voir la capture d'écran ci-jointe.
Crédit complet à cet article pour avoir assemblé les pièces.