Программно определить, находится ли именованный диапазон в рабочей книге

Я пытаюсь понять, что, по моему мнению, было бы довольно простым выражением vba, чтобы проверить, относится ли именованный диапазон к книге или конкретному листу.


В качестве теста я создал новый документ Excel и добавлен в 6 названных диапазонов. Вот как они выложены в Менеджере имен:

 Name         |   Refers To          |   Scope
 -------------+----------------------+-----------
 rng_Local01  |   =Sheet1!$A$2:$A$16 |   Sheet1
 rng_Local02  |   =Sheet1!$C$2:$C$16 |   Sheet1
 rng_Local03  |   =Sheet1!$E$2:$E$16 |   Sheet1
 rng_Global01 |   =Sheet1!$B$2:$B$16 |   Workbook
 rng_Global02 |   =Sheet1!$D$2:$D$16 |   Workbook
 rng_Global03 |   =Sheet1!$F$2:$F$16 |   Workbook

Я бы ожидал, что запуск:

For i = 1 To ThisWorkbook.Names.Count
    If ThisWorkbook.Names(i).WorkbookParameter Then Debug.Print ThisWorkbook.Names(i).Name
Next i

приведет к регистрации трех диапазонов с указанными диапазонами Workbook, однако ничего не происходит. Ошибок нет. .Names(i).WorkbookParameter оценивает False на ВСЕ названных диапазонов, и я не уверен, почему.


Просматривая объект Name в справке VBA, я наткнулся на ValidWorkbookParameter, который выглядит как кузен ReadOnly WorkbookParameter, однако использование этого метода НЕ имеет никакого значения.

Я также попытался явно установить ThisWorkbook.Names(i).WorkbookParameter = True, однако это приводит к ошибке:

"Неверный вызов или аргумент процедуры"

Несмотря на то, что WorkbookParameter указан как Read/Write


Может ли кто-нибудь пролить свет на то, почему это не работает, как я тоже этого ожидаю? Не понял ли я, как Name.WorkbookParameter должен работать? Кто-нибудь может заставить это успешно работать?

Ответ 1

Вы можете использовать свойство Parent:

Sub Global_Local_names()
    Dim oNm As Name
    For Each oNm In Names
        If TypeOf oNm.Parent Is Worksheet Then
            Debug.Print oNm.Name & " is local to " & oNm.Parent.Name
        Else
            Debug.Print oNm.Name & " is global to " & oNm.Parent.Name
        End If
    Next
End Sub

Ответ 2

Мне не удалось заставить WorkbookParameter работать, но я нашел обходное решение:

For i = 1 To ThisWorkbook.Names.Count
    If UBound(Split(ThisWorkbook.Names(i).Name, "!")) > 0 Then Debug.Print ThisWorkbook.Names(i).Name
Next i

Имя локального Named Range (т.е. область действия только для листа) форматируется следующим образом: Sheet1!NamedRange, тогда как имя глобального именованного диапазона отформатировано: NamedRange.

Таким образом, вы можете разделить на ! и проверить длину массива.