如何更改命名范围范围

时间:2009-06-29 08:31:51

标签: excel vba excel-vba

当我通过名称管理器创建命名范围时,我可以选择指定工作簿或[worksheet name]范围。但如果那时想要改变范围,那么下拉列表就会变灰。有没有办法,在名称管理器中,或者,优选地,VBA可以更改现有命名范围的范围?

例如:

  • testName指的是'sheet1'!A1:B2范围工作簿。我如何将其更改为
  • testName是指带有'sheet1'范围的'sheet1'!A1:B2

12 个答案:

答案 0 :(得分:13)

您可以从我自己和Jan Karel Pieterse下载免费的名称管理器插件 http://www.decisionmodels.com/downloads.htm 这将启用Excel 2007名称管理器无法处理的许多名称操作,包括更改名称范围。

在VBA中:

Sub TestName()
Application.Calculation = xlManual
Names("TestName").Delete
Range("Sheet1!$A$1:$B$2").Name = "Sheet1!TestName"
Application.Calculation = xlAutomatic
End Sub

答案 1 :(得分:9)

我找到了解决方案!只需使用命名变量复制工作表即可。然后删除原始工作表。复制的工作表现在将具有相同的命名变量,但具有本地范围(范围=复制的工作表)。

但是,我不知道如何从局部变量更改为全局..

答案 2 :(得分:8)

查看这两个相互反转的子项,并将所有命名范围的范围(工作表转换为工作簿或反向)翻转,这些范围指的是活动工作表上的范围。

 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

答案 3 :(得分:3)

这是我如何将所有工作表名称提升为全局名称。 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

答案 4 :(得分:2)

从头开始创建新名称并删除旧名称。

答案 5 :(得分:2)

另一种方法是“破解”2007年或更高版本的Excel文件,但如果你这样做是可取的,并保留原始文件的备份:

首先将Excel电子表格另存为.xlsx或.xlsm文件(非二进制文件)。将文件重命名为.zip,然后解压缩。转到zip结构中的xl文件夹,然后在Wordpad或类似的文本编辑器中打开workbook.xml。命名范围可在definedName标记中找到。本地范围由localSheetId =“x”定义(通过在Excel中按Alt-F11,打开电子表格,进入VBA窗口,然后查看“项目”窗格,可以找到工作表ID)。隐藏范围由hidden =“1”定义,因此只需删除隐藏=“1”即可取消隐藏,例如。

现在重新压缩文件夹结构,注意保持文件夹结构的完整性,并重命名回.xlsx或.xlsm。

如果您需要更改或隐藏/取消隐藏大量已定义的范围,这可能不是最佳解决方案,尽管它适用于进行一次或两次小调整。

答案 6 :(得分:1)

这仍然需要更多精炼,但是可以使用所有简单引用,而不会删除现有的本地名称。

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

答案 7 :(得分:1)

对我而言,当我从名称管理器创建相同范围的新名称标记时,它可以让我选择更改范围;)工作簿默认为并且可以更改为任何可用的工作表。

答案 8 :(得分:0)

JS20&#39; 07&#11的代码非常简单直接。我想提出的一个建议是在条件中加上感叹号:

InStr(1, objName.RefersTo, sWsName+"!", vbTextCompare)

因为这会阻止在错误的工作表中添加 NamedRange 。例如:如果 NamedRange 引用名为 Plan11 的工作表,并且您有另一个名为 Plan1 的工作表,则在添加范围时代码可能会造成一些混乱你不要使用感叹号。

<强>更新

更正:最好使用正则表达式来评估工作表的名称。您可以使用的一个简单函数(由http://blog.malcolmp.com/2010/regular-expressions-excel-add-in改编,启用Microsoft VBScript正则表达式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

所以,你可以使用类似的东西:

xMatch("'?" +sWsName + "'?" + "!", objName.RefersTo, 1) <> ""

而不是

InStr(1, objName.RefersTo, sWsName+"!", vbTextCompare)

这将涵盖 Plan1 &#39; Plan1&#39; (当范围指的是多个单元格时)变体

提示:使用单引号(&#39;)避免工作表名称。

答案 9 :(得分:0)

这些答案有助于在尝试使用Workbook范围定义命名范围时解决类似问题。 &#34;啊-HA!&#34;对我来说,使用与整个工作簿相关的名称集合这可能正在向许多人重申显而易见的事情,但在我的内容中并没有明确说明研究,所以我与其他人分享类似的问题。

' 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") 

如果您在Sheet2处于活动状态时查看名称列表,则两个范围都在那里,但切换到任何其他工作表,并且"a_test_rng1"不存在。

现在我可以愉快地在我的代码中生成一个命名范围,我认为适合的范围。不需要乱用名称管理器或插件。

除此之外,Excel Mac 2011中的名称管理器很乱,但我确实发现虽然没有列标签可以告诉您在查看命名范围列表时查看的内容,但是如果有的话名称旁边列出的工作表该名称的范围限定为工作表/本地。见附件截图。

Excel Mac 2011 Name Manager

this article完全归功于整理各个部分。

答案 10 :(得分:0)

我在JS20'07'11的以前的Makro中添加了一些其他代码行,以确保工作表的“命名范围”的名称尚未是工作簿的“命名范围”的名称。 没有这些行,将删除并替换已经定义好的工作簿中已命名的命名范围。

Public Sub RescopeNamedRangesToWorkbookV2()
Dim wb As Workbook
Dim ws As Worksheet
Dim objNameWs As Name
Dim objNameWb 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 objNameWs In ws.Names


'Check name is visble.
    If objNameWs.Visible = True Then
'Check name refers to a range on the active sheet.
        If InStr(1, objNameWs.RefersTo, sWsName, vbTextCompare) Then
            sRefersTo = objNameWs.RefersTo
            sObjName = objNameWs.Name
'Check name is scoped to the worksheet.
            If objNameWs.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))
'Check to see if there already is a Named Range with the same Name with the full workbook scope.
                For Each objNameWb In wb.Names
                    If sObjName = objNameWb.Name Then
                    MsgBox "There is already a Named range with ""Workbook scope"" named """ + sObjName + """. Change either Named Range names or delete one before running this Macro."
                    Exit Sub
                    End If
                Next objNameWb
                objNameWs.Delete
                wb.Names.Add Name:=sObjName, RefersTo:=sRefersTo
            End If
        End If
    End If
Next objNameWs
End Sub

答案 11 :(得分:-1)

在theexceladdict.com找到了这个

  • 在工作表上选择要更改其范围的命名范围;

  • 打开名称管理器(公式选项卡)并选择名称;

  • 单击“删除”并单击“确定”;

  • 单击“新建...”并在“名称”字段中键入原始名称;

  • 确保将Scope设置为Workbook,然后单击Close。

相关问题