在私有子节点中引用公共变量时遇到问题

问题描述

我有一个非常基本的问题让我发疯,我这辈子都想不通。

我有一个工作簿,其中有几张工作表,其中包含打开要填写的相同用户表单的单元格。目前,该代码关闭表单,特别是将工作簿返回到一页。我试图让工作簿返回到之前正在处理的页面;这样做时,我设置了一个公共工作表变量 (wsWorking),该变量将设置为打开用户窗体之前最后单击的工作表。但是,这样做时,我总是收到“运行时错误 '9':下标超出范围”消息,并且调试消息显示我的 wsWorking 变量为空。

如果我输入工作表的名称而不是尝试使用该变量,我可以将其打开到我想要的页面,但是由于此页面将根据正在工作的内容动态变化,这不是所需的结果。

声明:'(在我的 ThisWorkbook 模块中,(一般)(描述)

Public wsWorking As Worksheet 

尝试设置:'(在私有模块中,删除了无关代码

Sub Worksheet_BeforeDoubleClick(ByVal Target As Range,Cancel As Boolean)
    Set wsWorking = ThisWorkbook.Worksheets("MRL 1")
    Dim clickRow As Integer
    Dim ClickCol As Integer

尝试使用:(在不同的私有模块中)

Private Sub CloseForm_Click()
    Call SaveFormToscorecard_Click
    Unload Me
    ActiveWorkbook.Sheets(wsWorking).Activate
End Sub

任何想法或建议将不胜感激 - 我已经尝试在模块的一般声明中设置 wsWorking,当工作表被激活时,并在模块中创建一个公共子,仅用于设置该变量,但没有一个有效。

EDIT 更改 ActiveWorkbook.Sheets(wsWorking).Activate

线到

wsWorking.Activate

只给我一个错误“运行时错误‘424’:需要对象”。我不相信一个模块中的变量设置会转移到另一个模块。

解决方法

ThisWorkbook 是一个具有 PredeclaredId 属性的类模块,可以从任何地方访问它,但它的成员仍然是它的成员。通过使用预先声明的 ThisWorkbook 对象对其进行限定,您可以从代码中的任何位置访问 ThisWorkbook 的任何公共成员:

Debug.Print ThisWorkbook.wsWorking.Name

如果你想要一个 global 变量,那么你不能使用对象模块,因为对象需要一个实例(ThisWorkbook 实例被自动创建并不会使它成为对象实例)。改为在标准模块中声明一个公共变量,然后您就可以从代码中的任何地方不加限定地访问它,无论是读取它还是写入它。

等等。大声说出来。

然后您可以从代码中的任何地方无限制地访问它,无论是阅读它还是编写它。

这可能不是一个好主意。考虑将其声明为 Private,并且仅将其公开为 Public Property Get,以便不能随时随地被任何内容覆盖。

如果它是 Public 中的 ThisWorkbook,这应该可以工作:

Sub Worksheet_BeforeDoubleClick(ByVal Target As Range,Cancel As Boolean)
    Set ThisWorkbook.wsWorking = ThisWorkbook.Worksheets("MRL 1")
    Dim clickRow As Integer '<~ this will explode at row 32,768. Use a Long!
    Dim ClickCol As Integer '<~ should still be a Long

这里有几个严重的问题:

    Call SaveFormToScorecard_Click '<~ event handlers aren't supposed to be invoked like this
    Unload Me '<~ self-destructing object,danger!
    ActiveWorkbook.Sheets(wsWorking).Activate '<~ will throw error 1004 End Sub ```

ActiveWorkbook任何当时处于活动状态的工作簿,虽然这可能 ThisWorkbook,但很有可能不是。只要不是,这个就会爆炸。 wsWorking 是一个 Worksheet 引用,从 Sheets 集合中取消引用它(按名称,隐式!)是多余的 - 只需 ThisWorkbook.wsWorking.Activate 即可。

请注意,如果 wsWorking 在编译时存在于 ThisWorkbook 中,您可能最好只使用它自己的预先声明的实例。

每个 Worksheet 模块都有一个 (Name) 属性,它是 VB 项目组件的名称;这个值成为一个全局对象的名称,就像 ThisWorkbook 一样。有关详细信息,请参阅 implicit containing workbook reference Rubberduck 检查。