Excel VBA:将'Target'变量从单击事件传递到用户窗体

Excel VBA:将'Target'变量从单击事件传递到用户窗体,excel,vba,Excel,Vba,我正在使用VBA构建Excel 2016用户表单,需要收集从中打开表单的单元格的行和列。我在单元格上打开表单,在双击之前用工作表双击,然后用Userform\u初始化初始化Userform。我想将双击事件的目标传递给UserForm\u Initialize,但不确定如何传递。解决了这个问题,但提供的解决方案对我不起作用 这是我的工作表\u,双击前: 和我的UserForm_初始化: 正如我在评论中所建议的,一种方法是只使用ActiveCell并将其分配给一个变量 或者,如果您确实希望将其作为变

我正在使用VBA构建Excel 2016用户表单,需要收集从中打开表单的单元格的行和列。我在单元格上打开表单,在双击之前用工作表双击,然后用Userform\u初始化初始化Userform。我想将双击事件的目标传递给UserForm\u Initialize,但不确定如何传递。解决了这个问题,但提供的解决方案对我不起作用

这是我的工作表\u,双击前:

和我的UserForm_初始化:


正如我在评论中所建议的,一种方法是只使用ActiveCell并将其分配给一个变量

或者,如果您确实希望将其作为变量传递,您可以通过一个全局变量临时保存该信息来解决这一问题:

在工作表代码中:

专用子工作表\u在双击“ByVal目标作为范围,取消作为布尔值”之前 '..... 使用UserForm1 Set.rngTarget=Target 显示 以 '..... 端接头 在您的用户表单中:

公共RNG目标As范围 私有子用户表单_激活 '.... 如果不是,那么rngTarget什么都不是 MsgBox行为&rngTarget。行和列为&rngTarget.Column 其他的 MsgBox分配rngTarget变量时出错 如果结束 '.... 端接头 编辑:我最初试图提出类似于@MathieuGuindon的建议,但由于我对初始化和激活之间的区别了解有限,所以失败了。谢谢Mathieu


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

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

或者,如果您确实希望将其作为变量传递,您可以通过一个全局变量临时保存该信息来解决这一问题:

在工作表代码中:

专用子工作表\u在双击“ByVal目标作为范围,取消作为布尔值”之前 '..... 使用UserForm1 Set.rngTarget=Target 显示 以 '..... 端接头 在您的用户表单中:

公共RNG目标As范围 私有子用户表单_激活 '.... 如果不是,那么rngTarget什么都不是 MsgBox行为&rngTarget。行和列为&rngTarget.Column 其他的 MsgBox分配rngTarget变量时出错 如果结束 '.... 端接头 编辑:我最初试图提出类似于@MathieuGuindon的建议,但由于我对初始化和激活之间的区别了解有限,所以失败了。谢谢Mathieu


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

表单是以模块方式显示的,因此ActiveCell不会在您身上更改,应该可以安全地在表单的代码中使用

问题是,您现在已经将表单绑定到ActiveSheet/ActiveCell,现在为了测试选择或激活单元格所需的任何内容

如果表单代码只需要知道单元格的地址,那么就不应该给它一个范围给它一个范围,它可以访问应用程序实例中任何工作簿中任何工作表中的任何单元格-这是最少知识的原则。但这显然是示例代码,所以让我们看一个范围:

现在您的表单代码可以使用WorkingCell或internalWorkingCell来完成它的工作,并且不需要全局变量浮动

With New UserForm1 ' Initialize handler runs here
    Set .WorkingCell = Target 
    .Show ' Activate handler runs here
End With
WorkingCell属于表单-它不在全局范围内

小心表单中的初始化处理程序-尤其是当您使用其默认实例时,即当您不新建它时:您不控制该处理程序何时运行,VBA运行时会控制它;UserForm_Initialize将在您的案例中第一次引用表单实例时运行,即.Show调用之前,然后再也不会运行,除非该实例被销毁,否则单击红色的X按钮将执行此操作


初始化处理程序中的MsgBox调用将在显示表单之前运行;您可能希望在导致问题之前将该代码移动到激活处理程序。

表单以模式显示,因此ActiveCell不会在您身上更改,并且应该可以安全地在表单的代码中使用

问题是,您现在已经将表单绑定到ActiveSheet/ActiveCell,现在为了测试选择或激活单元格所需的任何内容

如果表单代码只需要知道单元格的地址,那么就不应该给它一个范围给它一个范围,它可以访问应用程序实例中任何工作簿中任何工作表中的任何单元格-这是最少知识的原则。但这显然是示例代码,所以让我们看一个范围:

现在您的表单代码可以使用WorkingCell或internalWorkingCell来完成它的工作,并且不需要全局变量浮动

With New UserForm1 ' Initialize handler runs here
    Set .WorkingCell = Target 
    .Show ' Activate handler runs here
End With
工作单元属于fo rm-it不在全球范围内开展业务

小心表单中的初始化处理程序-尤其是当您使用其默认实例时,即当您不新建它时:您不控制该处理程序何时运行,VBA运行时会控制它;UserForm_Initialize将在您的案例中第一次引用表单实例时运行,即.Show调用之前,然后再也不会运行,除非该实例被销毁,否则单击红色的X按钮将执行此操作



初始化处理程序中的MsgBox调用将在显示表单之前运行;您可能希望在代码出现问题之前将其移动到Activate处理程序。

如果双击,您可以使用ActiveCell。。。不需要通过目标。类似于:MsgBox行是&ActiveCell。行和列是&ActiveCell。Column@FAB这是我之前实现的,但我收到的反馈是,应该避免使用ActiveCell,因为如果用户在窗体打开时单击另一个单元格,它可能会导致错误。这是真的,但您可以将其分配给一个变量,Dim rngActCell as range:设置rngActCell=ActiveCell,这应该会在打开用户窗体时立即发生。。。因此,无论用户之后点击什么,都不重要。哦,太好了。非常感谢你。请随意提交您的代码作为答案。@FAB+1了解变量用法。我认识的大多数开发人员都充分利用了这一点!您可以使用ActiveCell,因为您正在双击。。。不需要通过目标。类似于:MsgBox行是&ActiveCell。行和列是&ActiveCell。Column@FAB这是我之前实现的,但我收到的反馈是,应该避免使用ActiveCell,因为如果用户在窗体打开时单击另一个单元格,它可能会导致错误。这是真的,但您可以将其分配给一个变量,Dim rngActCell as range:设置rngActCell=ActiveCell,这应该会在打开用户窗体时立即发生。。。因此,无论用户之后点击什么,都不重要。哦,太好了。非常感谢你。请随意提交您的代码作为答案。@FAB+1了解变量用法。我认识的大多数开发人员都充分利用了这一点!我喜欢你的解决方案。。。我一定会记住这一点,以备将来使用。在他的例子中,使用双击事件意味着必须激活一个工作表/单元格。@FAB表单本身不应该关心或假设它从何处显示。一个设计良好的表单或任何模块都是独立存在的,它的依赖关系是从外部传递的,而不是去接触和获取它们。谢谢Mathieu,我每天都在努力帮助他人,这就是其中的一个时刻。我从你的答案中获得了一些灵感来编辑我的答案,但如果这是个问题,请告诉我,我很乐意将其恢复到原来的状态。@FAB没问题!重要的是,当数十人从Google Searchs登陆时,页面包含正确的信息=我喜欢你的解决方案。。。我一定会记住这一点,以备将来使用。在他的例子中,使用双击事件意味着必须激活一个工作表/单元格。@FAB表单本身不应该关心或假设它从何处显示。一个设计良好的表单或任何模块都是独立存在的,它的依赖关系是从外部传递的,而不是去接触和获取它们。谢谢Mathieu,我每天都在努力帮助他人,这就是其中的一个时刻。我从你的答案中获得了一些灵感来编辑我的答案,但如果这是个问题,请告诉我,我很乐意将其恢复到原来的状态。@FAB没问题!重要的是,当数十人从Google Searchs登陆时,页面包含正确的信息=必须将字段/变量移到表单后面的代码中!向上投票=必须将字段/变量移动到表单的代码中!向上投票=
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
With New UserForm1 ' Initialize handler runs here
    Set .WorkingCell = Target 
    .Show ' Activate handler runs here
End With