Excel VBA:将Click事件中的Target变量传递给用户窗体

时间:2019-06-10 14:07:32

标签: excel vba

我正在使用VBA构建Excel 2016用户窗体,需要收集从中打开窗体的单元格的行和列。我用Worksheet_BeforeDoubleClick双击单元格打开窗体,然后用UserForm_Initialize()初始化用户窗体。我想将双击事件的Target传递给UserForm_Initialize(),但不确定如何传递。 This forum thread解决了这个问题,但是提供的解决方案对我不起作用。

这是我的Worksheet_BeforeDoubleClick

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    Column = Target.Column
    Row = Target.Row

    'Find the last non-blank cell in column B(2)
    lRow = Cells(Rows.Count, 2).End(xlDown).Row

    'Find the last non-blank cell in row 2
    lCol = Cells(2, Columns.Count).End(xlToRight).Column
     If Not Intersect(Target, Range(Cells(3, 3), Cells(lRow, lCol))) Is Nothing Then
        Cancel = True
        EdgeEntryForm.Show
    End If

End Sub

还有我的UserForm_Initialize()

Private Sub UserForm_Initialize()
    Dim Column As Long, Row As Long 'I would like to fill these with the Target values
    MsgBox ("Row is " & Row & " Column is " & Column)
     'Description.Caption = "Fill out this form to define a network edge from " & Cells(2, Row).Value & " to " & Cells(Column, 2).Value
End Sub

2 个答案:

答案 0 :(得分:3)

如我的评论所建议,一种方法是仅使用ActiveCell并将其分配给变量。

或者,如果您确实希望将其作为变量传递,则可以通过一个全局变量临时保存该信息来进行一些变通:

在您的工作表代码中:

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'.....
    With UserForm1
        Set .rngTarget = Target
        .Show
    End With
'.....
End Sub

在您的用户表单中:

Public rngTarget As Range
Private Sub UserForm_Activate()
'....
    If Not rngTarget Is Nothing Then
        MsgBox ("Row is " & rngTarget.Row & " Column is " & rngTarget.Column)
    Else
        MsgBox "something went wrong with assigning rngTarget variable"
    End If
'....
End Sub

编辑:我起初试图提出类似于@MathieuGuindon的answer的内容,但是由于我对初始化和激活之间的区别的了解有限,所以失败了。(感谢Mathieu)。 / p>

我已经更新了答案,以便在用户窗体级别使用全局变量,而不是使用模块中的全局变量。

答案 1 :(得分:2)

该表单以模态显示,因此ActiveCell不会对您造成任何影响,应该可以安全地用于表单的代码隐藏中。

问题在于,您现在已经将表单绑定到ActiveSheet / ActiveCell,并且现在为了测试任何内容,您需要Select或{{1} }一个单元格。

如果表单代码仅需要知道单元格的Activate,则不应为其提供Address(给它一个Range,它可以访问任何一个单元格中的任何单元格Range实例中任何工作簿中的工作表)-这是知识最少的原则。但这显然是示例代码,所以让我们来看一个Application

Range

现在您的表单代码可以使用Option Explicit Private internalWorkingCell As Range Public Property Get WorkingCell() As Range Set WorkingCell = internalWorkingCell End Property Public Property Set WorkingCell(ByVal value As Range) Set internalWorkingCell = value End Property WorkingCell来完成它的工作,并且不需要全局变量

internalWorkingCell

With New UserForm1 ' Initialize handler runs here Set .WorkingCell = Target .Show ' Activate handler runs here End With 属于形式-它与全球范围无关。

请谨慎对待WorkingCell形式的处理程序-特别是在使用默认实例时(特别是当您不Initialize使用它时) ):您无法控制该处理程序何时运行,VBA运行时可以控制; New将在表单实例第一次被引用(在您的情况下,紧接UserForm_Initialize调用之前)运行,然后再运行一次,除非实例被销毁(单击红色的X按钮可以做到这一点。

.Show处理程序中的MsgBox调用将在显示表单之前 运行;您可能想要在导致问题之前将代码移至Initialize处理程序。