Как изменить область именованного диапазона - PullRequest
17 голосов
/ 29 июня 2009

Когда я создаю именованный диапазон с помощью диспетчера имен, мне предоставляется возможность указать книгу или область действия [worksheet name]. Но если затем нужно изменить область действия, раскрывающийся список будет недоступен. Есть ли способ, в Name Manager или, предпочтительно, в VBA, изменить область существующего именованного диапазона?

Например:

  • testName относится к 'sheet1'!A1:B2 с областью Workbook. Как бы я изменил это на
  • testName относится к 'sheet1'!A1:B2 с областью действия 'sheet1'?

Ответы [ 11 ]

14 голосов
/ 29 июня 2009

Вы можете скачать бесплатную надстройку Name Manager, разработанную мной и Яном Карелом Питерсом из 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
9 голосов
/ 04 декабря 2013

Я нашел решение! Просто скопируйте лист с вашими именованными переменными. Затем удалите оригинальный лист. Скопированный лист теперь будет иметь те же именованные переменные, но с локальной областью действия (область действия = скопированный лист).

Однако я не знаю, как перейти от локальных переменных к глобальным ..

9 голосов
/ 18 ноября 2013

Проверьте эти две подпрограммы, которые обращают друг друга и переворачивают область (рабочий лист в рабочую книгу или наоборот) всех именованных диапазонов, которые относятся к диапазону на активном листе.

 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 голосов
/ 29 декабря 2011

Вот как я перевожу все имена листов в глобальные имена. 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
2 голосов
/ 13 декабря 2013

Альтернативным способом является «взлом» файла Excel на 2007 или более поздней версии, хотя желательно позаботиться о том, чтобы вы это делали, и сохранить резервную копию оригинала:

Сначала сохраните электронную таблицу Excel в виде файла .xlsx или .xlsm (не двоичного). переименуйте файл в .zip, затем разархивируйте. Перейдите в папку xl в структуре zip и откройте workbook.xml в Wordpad или аналогичном текстовом редакторе. Именованные диапазоны находятся в тегах defineName. Локальная область действия определяется с помощью localSheetId = "x" (идентификаторы листа можно найти, нажав Alt-F11 в Excel с открытой электронной таблицей, чтобы перейти в окно VBA, а затем посмотреть на панель проекта). Скрытые диапазоны определяются как hidden = "1", поэтому просто удалите скрытый = "1", чтобы показать, например.

Теперь распакуйте структуру папок, заботясь о сохранности целостности структуры папок, и переименуйте обратно в .xlsx или .xlsm.

Вероятно, это не лучшее решение, если вам нужно изменить область действия или скрыть / показать большое количество определенных диапазонов, хотя он отлично подходит для выполнения одной или двух небольших настроек.

2 голосов
/ 29 июня 2009

создайте новое имя с нуля и удалите старое.

1 голос
/ 02 марта 2017

Для меня это работает так: когда я создаю новый тег имени для того же диапазона из Диспетчер имен , это дает мне возможность изменить область;) книга по умолчанию поставляется и быть заменен на любой из доступных листов.

1 голос
/ 31 мая 2012

Это все еще требует доработки, однако работает со всеми простыми ссылками, без уничтожения существующих локальных имен.

0 голосов
/ 12 марта 2017

Эти ответы были полезны при решении аналогичной проблемы при попытке определить именованный диапазон с областью действия Workbook. "Ай-ха!" для меня это использование коллекции имен , относящейся к всей книге! Это может показаться очевидным для многих, но это не было четко указано в моем исследовании, поэтому я поделиться с другими похожими вопросами.

' 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

Полный кредит этой статье за сборку кусочков.

0 голосов
/ 26 января 2017

Код JS20'07'11 действительно невероятно простой и прямой. Одно из предложений, которое я хотел бы дать, - поставить восклицательный знак в следующих условиях:

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

Потому что это предотвратит добавление NamedRange в неправильный лист. Например: если NamedRange относится к листу с именем Plan11 и у вас есть другой лист с именем Plan1 , код может привести к путанице при добавлении диапазонов, если t используйте восклицательный знак.

UPDATE

Исправление: лучше использовать регулярное выражение для оценки названия листа. Простая функция, которую вы можете использовать: (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 и 'Plan1' (когда диапазон относится к более чем одной ячейке) вариаций

СОВЕТ: избегайте имен листов в одинарных кавычках ('), :).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...