更改sheet代号运行-时间错误9:下标超出范围

Changing sheet codename Run-Time Error 9: Subscript out of range

我编写了代码,当我按下一个按钮时,它将向工作簿添加一个新的 sheet 并更改 sheet 的代号,以便以后在我的工作簿中更容易参考代码。

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" window 或之前已经打开它时。

如果我在第一次打开 Excel 文档(没有打开 "Developer" window)时单击按钮,它会添加 sheet,但是它会出现出现以下错误,并且不会更改 sheet:

的代号

Run-time error '9': Subscript out of range

只有当我按调试然后运行 "Developer" window 之后的代码再次打开时,它才会添加代号。

有没有什么办法可以让用户不必打开开发人员 window 即可正确 运行?

如果您需要打开 VBE,您可以 "trick" 调试上下文为您完成。这似乎通过强制 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"

编辑:

似乎只获取对VBE.MainWindow的引用就足够了(见评论)。这也有效:

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

@Comintern 已经为您提供了一个可行的解决方案,但此代码不会污染您的即时 Window,并使用隐藏的 _CodeName 属性 来更改 sheet 名称而不是访问 vbComponents 集合。

它还使用早期绑定 Worksheet 赋值给 wks,然后使用 With 块,因为它正在访问 wks 的 1 个以上成员。

有趣的是,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

另一种强制刷新 VBComponents 集合的简单方法:

PropertyGetDiscard ThisWorkbook.VBProject.VBComponents.Count

Private Sub PropertyGetDiscard(AnyPropertyGet): End Sub

过程PropertyGetDiscard用于避免污染立即数window或使用多余的变量

解决此类 VBComponent 相关代码问题的一般方法是使用灵活的 为每个可能尚未“VBComponent-initialized”的新打开的工作簿调用多次。