Ошибка VBA 400 при попытке удалить именованный диапазон

Я хочу удалить все глобальные именованные диапазоны в книге. У меня есть этот код:

Dim xName As Name
For Each xName In Application.ActiveWorkbook.Names
    If InStr(xName.Name, "!") = 0 Then xName.Delete
Next

Даже когда я изменяю код, чтобы удалить ВСЕ именованные диапазоны, я все равно получаю ту же ошибку.

Dim xName As Name
For Each xName In Application.ActiveWorkbook.Names
    xName.Delete
Next

Когда я запускаю его, удаляется только первый именованный диапазон, а затем выдается ошибка 400. Он не переходит к следующему.

Есть ли какое-то дополнение или настройка, которую мне не хватает? Этот код кажется довольно простым, но я не могу заставить его работать.


person narfie    schedule 31.03.2018    source источник
comment
Я не думаю, что это незаконно, потому что, если я заменю xName.Delete на msgbox, он отобразит все мои глобальные именованные диапазоны, как и ожидалось. Проблема НЕ в бите Instr(), а в xName.Delete. Как я уже говорил, даже без функции InStr() он ведет себя так же.   -  person narfie    schedule 31.03.2018
comment
Вряд ли дело в этом.   -  person narfie    schedule 31.03.2018
comment
Что вы на самом деле пытаетесь удалить? Есть другой узор?   -  person QHarr    schedule 31.03.2018
comment
Пожалуйста, не зацикливайтесь на !. Я удалил его, и проблема сохраняется. Итак, ясно, что проблема НЕ в этом. ! на самом деле не в названии. Это просто помогает мне найти глобальные именованные диапазоны. Ни в одном из моих именованных диапазонов нет ! в самом имени. Я откуда-то скопировал этот скрипт, и он работает, чтобы найти все глобальные именованные диапазоны.   -  person narfie    schedule 31.03.2018
comment
поставьте точку останова в If InStr(xName.Name, "!") = 0 Then xName.Delete и после этого введите ?xName.Name, xname.RefersTo в Immediate Window и нажмите return .   -  person DisplayName    schedule 31.03.2018
comment
оказавшись в VBA IDE, нажмите CTRL-G, чтобы открыть его.   -  person DisplayName    schedule 31.03.2018
comment
Если вы возьмете один случай и используете фактическое имя, оно будет удалено с помощью ActiveWorkbook.Names(THE NAME).Delete ?   -  person QHarr    schedule 31.03.2018
comment
@DisplayName, спасибо :) Нашел. Ошибка выполнения «424»: требуется объект   -  person narfie    schedule 31.03.2018
comment
@QHarr, я тоже пробовал. Я все еще получаю тот же результат. 400 Ошибка.   -  person narfie    schedule 31.03.2018
comment
затем попробуйте ввести ?ActiveWorkbook.Name и нажмите клавишу возврата   -  person DisplayName    schedule 31.03.2018
comment
@DisplayName — возвращает имя книги: Book57 — Может ли проблема быть связана с тем, что книга еще не сохранена?   -  person narfie    schedule 31.03.2018
comment
попробуйте ввести ActiveWorkbook.Names.Count и нажмите клавишу возврата   -  person DisplayName    schedule 31.03.2018
comment
@DisplayName ?ActiveWorkbook.Names.Count возвращает 48   -  person narfie    schedule 31.03.2018
comment
и все, что выводится в Immediate Window, пока вы все еще находитесь в For Each xName In Application.ActiveWorkbook.Names строке нарушения?   -  person DisplayName    schedule 31.03.2018
comment
О нет... Я был на xName.Delete :( Позвольте мне переместить разрыв строки и повторить все это для вас. ?xName.Name, xname.RefersTo возвращает ошибку: Ошибка времени выполнения '91': переменная объекта или переменная блока не установлена   -  person narfie    schedule 31.03.2018
comment
Давайте продолжим обсуждение в чате.   -  person narfie    schedule 31.03.2018


Ответы (2)


Хорошо, после долгого разговора и проб и ошибок я нашел проблему. Это на самом деле в два раза.

Причина, по которой этот код не работал, по-видимому, заключается в том, что первый найденный им именованный диапазон был встроенным диапазоном Excel, который, очевидно, нельзя было удалить. Это относится к обоим фрагментам кода

Dim xName As Name
For Each xName In Application.ActiveWorkbook.Names
    xName.Delete
Next

И

Dim xName As Name
For Each xName In Application.ActiveWorkbook.Names
    If InStr(xName.Name, "!") = 0 Then xName.Delete
Next

Потому что оба они находят этот встроенный именованный диапазон «_xlfn.CONCAT» и пытаются его удалить.

Наконец я прислушался к совету @QHarr и использовал другой квалификатор. К счастью, у всех моих именованных диапазонов в области рабочей книги есть «Мастер» в названии, так что это было достаточно просто.

Итак, окончательное решение:

Dim xName As Name
For Each xName In Application.ActiveWorkbook.Names
    If InStr(xName.Name, "Master") > 0 Then xName.Delete
Next

Спасибо, ребята!

person narfie    schedule 31.03.2018

Простое решение - проверить первый символ именованного диапазона. Специальные диапазоны начинаются с «_» (подчеркивание).

Я решил это простой проверкой. И работать в обратном направлении.

Dim xName As Name
Dim xNum as Long
For XNum = Application.ActiveWorkbook.Names.Count To 1 Step -1
    Set XName = Application.ActiveWorkbook.Names(XNum)
    If InStr(xName.Name, "!") = 0 And Left(XName.Name <> "_", 1) Then xName.Delete
Next

В моем случае я удалял все имена, поэтому InStr(xName.Name, "!") = 0 And не понадобилось, но это очень похоже.

person AJD    schedule 31.03.2018
comment
Спасибо за предложение, но, к сожалению, оно мне не подходит. Кроме того... в вашем коде есть небольшая ошибка - вы пропустили параметр в функции Left. Left(xName.Name <> "_", 1) - person narfie; 01.04.2018
comment
@narfie: исправил эту опечатку. - person AJD; 01.04.2018
comment
@narfie: должно работать. Вы изменили свой код, чтобы он работал в обратном направлении? Итерация вперед по коллекции и удаление элементов, как правило, не будут работать должным образом, потому что после удаления первого элемента все остальные элементы перенумеровываются, и в конечном итоге вы пропускаете элементы. - person AJD; 01.04.2018