2016-12-07 21 views
8

Mam trochę kodu, w którym po naciśnięciu przycisku wywołuje podpunktu, który doda nowy arkusz do skoroszytu, a następnie zmienić kodową nazwę Arkusz, aby ułatwić późniejszy odsyłacz w moim kodzie. Jest to w następujący sposób:Arkusz zmiany nazwy VBA nazwa kodowa Błąd wykonania 9: Indeks dolny poza zakresem

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" 

to nie wydają się działać - JEDNAK - tylko kiedy mam okno „Developer” otwarty lub wcześniej miał je otwarte.

Jeśli kliknę przycisk, gdy po raz pierwszy otworzę dokument programu Excel (nie otwierając okna "Programista"), to dodaje on arkusz, ale pojawia się następujący błąd i nie zmienia nazwy kodowej arkusza:

błąd Run-time „9”: Indeks poza zakresem

dopiero po naciśnięciu Debug, a następnie uruchomić kod po zamknięciu okna „Twórca” jest otwarty ponownie, że dodaje on kryptonim.

Czy jest jakiś sposób obejścia tego, aby użytkownik nie musiał otwierać okna programisty, aby działał poprawnie?

Dzięki

+1

Powinieneś 'Set wks = wbk.Sheets.Add', * a następnie * ustawić jego' .Name'. W ten sposób nie musiałbyś mieć literału napisanego dwa razy. –

+0

Możesz wypróbować wywołanie "DoEvents" lub dwa. Jeśli możesz, prawdopodobnie bezpieczniej byłoby użyć wywołania 'Application.Ontime', aby uruchomić kod w celu zmiany nazwy kodowej (i wszystkiego, co się dzieje). – Rory

+0

Aby wyjaśnić, czy błąd wykonania 9 został podniesiony na dostęp 'wks.Parent.VBProject.VBComponents (wks.CodeName)'? –

Odpowiedz

5

@Comintern już mam ci roztwór roboczy, ale ten kod nie zanieczyścić okienku bezpośrednim, a korzysta z ukrytej _CodeName właściwość zamiast zmienić nazwę arkusza z dostępu do kolekcji vbComponents.

wykorzystuje również wczesny związana Worksheet przyporządkowanie do wks, a następnie With bloku, ponieważ jest on z dostępem do ponad 1 członka wks.

Interesujące jest umieszczenie umieszczenia elementu członkowskiego 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

Nie sądzę, że to jest dziwne: "tworzysz" VBE * po * wszystkie VBomponents istnieją w projekcie. –

+0

@ Mat'sMug - Właściwie to w ogóle nie odwołuje się do VBE. Zastanawiam się, czy huśtałem się po płotkach i mogłem po prostu zatrzymać się na dereferencji 'wbk.Project'. @ThunderFrame - Czy musisz użyć ukrytej '_CodeName' po usunięciu referencji z projektu? Dobre wezwanie na ".Asert", BTW. – Comintern

+0

@Comintern eh, miałem na myśli "VBE" jak w "środowisku debugowania", lub cokolwiek to sprawia, że ​​środowisko wykonawcze VBA rozumie, co się dzieje. Dobre wywołanie w '[_CodeName]', IIRC nie używające tej ukrytej właściwości było błędem z funkcją Gumduck * refactor/rename * podczas zmiany nazwy arkusza w jednym punkcie. –

4

Jeśli potrzebujesz VBE zostały otwarte, można „trick” w kontekście debugowania robi to za Ciebie. Wydaje się to zrobić bez względu na projekt musi zaktualizować swoje indeksowanie przez zmuszając VBE.MainWindow do istnienia:

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:

Wydaje się, że po prostu uzyskania odwołanie do VBE.MainWindow jest wystarczająco (patrz komentarze). Działa to również:

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

Czy wystarczy odwołać się do 'wbk.VBProject.VBE.MainWindow.Caption' lub czy musi być jawnie użyty z obiektem Debug? (Wiem, że 'Debug.Print' jest lepszy dla kodu" wyrzucania "- po prostu ciekawy) –

+0

@MacroMan - Nie * całkowicie * pewnie. Zrobiłem test "Debug.Print" i nic nie zrobiłem. Drukowanie "Podpisu" było pierwszą rzeczą, o której myślałem, że otrzyma żądanie własności aż do "MainWindow". Ustawienie obiektu odniesienia również wydaje się działać. Zaktualizuję odpowiedź. – Comintern

0

Inna prosta metoda, aby wymusić odświeżanie VBComponents Kolekcja:

PropertyGetDiscard ThisWorkbook.VBProject.VBComponents.Count 

Private Sub PropertyGetDiscard(AnyPropertyGet): End Sub 

Procedura PropertyGetDiscard jest używany w celu uniknięcia zanieczyszczenia okienko bezpośrednie lub za pomocą zbędny zmienną

Powiązane problemy