2016-12-07 8 views
8
.

. У меня есть немного кода, где, когда я нажимаю кнопку, он вызывает подраздел, который добавит новый лист в книгу, а затем изменит кодовое имя лист, чтобы упростить обращение к нему в моем коде. Это выглядит следующим образом:Изменение кодового имени VBA. Ошибка во время выполнения. 9: Подстрочный код за пределами диапазона.

Dim wbk As Workbook 
Dim wks As Worksheet 

Set wbk = ThisWorkbook 

wbk.Sheets.Add.Name = "Admin - Save Log" 
Set wks = wbk.Worksheets("Admin - Save Log") 
wks.Parent.VBProject.VBComponents(wks.CodeName).Name = "wksAdminSaveLog" 

Это похоже на работу - ОДНАКО - только тогда, когда у меня есть окно «Developer» открытого или ранее был его открытым.

Если я нажму кнопку, когда я впервые открою документ Excel (не открыв окно «Разработчик»), то он добавляет лист, однако появляется следующая ошибка и не изменяет кодовое имя листа:

ошибка времени выполнения «9»: Подстрочная из диапазона

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

Есть ли способ обойти это, чтобы пользователю не нужно открывать окно разработчика, чтобы он работал правильно?

Благодаря

+1

Вы должны «Установить wks = wbk.Sheets.Add', *, а затем * установить его' .Name'. Таким образом, вам не нужно будет иметь строковый литерал, прописанный дважды. –

+0

Вы можете попробовать «DoEvents» или два. Однако, если вы можете, было бы безопаснее использовать вызов «Application.Ontime» для запуска кода для изменения кодового имени (и всего остального). – Rory

+0

Как раз пояснить, является ли ошибка времени выполнения 9 поднятой на 'wks.Parent.VBProject.VBComponents (wks.CodeName)' доступ? –

ответ

5

@Comintern уже получил вам рабочее решение, но этот код не загрязнить Immediate Window и использует скрытую _CodeName свойства, чтобы изменить имя листа вместо доступа к vbComponents коллекции.

Он также использует ранний переплете Worksheet присвоение wks, а затем With блок, так как он с доступом к более чем на 1 члена wks.

Адрес электронной почты: Адрес пользователя использования VBProject.

Dim wbk As Workbook 
Dim wks As Worksheet 

Set wbk = ThisWorkbook 
Set wks = wbk.Worksheets.Add 

'Oddly, this statement MUST appear AFTER the Worksheets.add 
Debug.Assert wbk.VBProject.Name <> vbNullString 'Don't pollute the Immediate window 

With wks 
    .Name = "Admin - Save Log" 
    .[_CodeName] = "wksAdminSaveLog" 
End With 
+0

Я не думаю, что это странно: вы «создаете» VBE * после того, как все VBComponents существуют в проекте. –

+0

@ Mat'sMug - На самом деле это вообще не отменяет VBE. Интересно, качался ли я за ограждениями и мог просто остановиться при разыменовании 'wbk.Project'. @ThunderFrame. Вам нужно использовать скрытое '_CodeName' после того, как вы разыменовали проект? Хороший звонок на '.Assert', BTW. – Comintern

+0

@Comintern eh, я имел в виду «VBE», как в «среде отладки», или что бы то ни было, что позволяет среде VBA понять, что происходит. Хороший вызов '[_CodeName]', IIRC, не использующий это скрытое свойство, был ошибкой с функциями Rubarduck * refactor/rename * при переименовании рабочих листов в один момент. –

4

Если вам нужна VBE, были открыты, вы можете «обмануть» контекст отладки в делать это для вас. Это, кажется, делает все, что проект должен обновить свою индексацию, заставляя VBE.MainWindow в существование:

Dim wbk As Workbook 
Dim wks As Worksheet 

Set wbk = ThisWorkbook 

Set wks = wbk.Sheets.Add 
wks.Name = "Admin - Save Log" 
Debug.Print wbk.VBProject.VBE.MainWindow.Caption '<--Force the VBE to exist. 
wbk.VBProject.VBComponents(wks.CodeName).Name = "wksAdminSaveLog" 

Edit:

кажется, что просто получить ссылку на VBE.MainWindow достаточно (см комментарии). Это также работает:

Dim editor As Object 
Set editor = wbk.VBProject.VBE.MainWindow '<--Force the VBE to exist. 
+1

Просто ссылается на 'wbk.VBProject.VBE.MainWindow.Caption' достаточно или он должен быть явно использован с объектом Debug? (Я знаю, что «Debug.Print» лучше для «выбросить» код - просто любопытно) –

+0

@MacroMan - Не * полностью * уверен. Я тестировал только «Debug.Print» и ничего не делал. Печать 'Caption' была первым, что я подумал об этом, чтобы получить запрос свойства до конца в MainWindow. Установка ссылки на объект также работает. Я обновлю ответ. – Comintern

0

Другой простой способ заставить освежения VBComponents Collection:

PropertyGetDiscard ThisWorkbook.VBProject.VBComponents.Count 

Private Sub PropertyGetDiscard(AnyPropertyGet): End Sub 

Процедура PropertyGetDiscard используется, чтобы избежать загрязнения Немедленное окно или с помощью лишнюю переменную