使用相对引用为控件重用宏

时间:2015-06-24 20:34:38

标签: excel vba excel-vba

我试图为同事编写Excel 2007宏,但我的VBA技能非常基本(请原谅双关语)。基本上,需要发生的是,当单击一个复选框时,右侧的相邻单元格将填入登录人员的用户名。

到目前为止,我提出的代码可以让我这样做:

Sub CheckBox1_Click()
    Range("J4").Activate
    If ActiveCell.Offset(0, 18).Value = True Then
        ActiveCell.Offset(0, 1).Value = Environ("UserName")
    Else
        ActiveCell.Offset(0, 1).Clear
    End If
End Sub

仅为了参考," ActiveCell.Offset(0,18)"是指链接到相关复选框并包含其真/假值的单元格。

(编辑:此外,单元格J4被激活的原因是因为在这种情况下,它是包含ActiveX复选框的单元格)

这很有效,但这不是我的问题。我的问题是:该行中还有49个复选框,此表上还有三个行,本书中还有45个表。我不想复制粘贴相同的代码到一个独特的宏只是为了更改活动单元格。更重要的是,作为一名优秀的程序员,我不应该重复这样的代码。我该如何写这个以便每次都不必引用一个不同的单元?

编辑2:圣洁的抽烟,兰斯刚刚帮我意识到我错了。工作表使用表单控件,而不是ActiveX控件。非常抱歉,大家。

2 个答案:

答案 0 :(得分:2)

虽然使用Sheet对象很容易,但使用ActiveX控件对象却很难。您不能在其事件中自引用ActiveX控件的名称,除非它已传递给它,并且您也无法引用事件子例程的名称来提取名称,并且你不能引用调用例程的例程的名称。

我还试图触发Worksheet Change和SelectionChange事件,但是那些不会触发复选框更改,即使它有一个更改的LinkedCell

我最终想到的是click事件的一些通用包装器,您必须修改字符串以匹配Checkbox名称:

Private Sub CheckBox1_Click()

  NameCopy Me, "CheckBox1"

End Sub

然后是Namecopy函数,它将LinkedCell左侧的单元格-7设置为名称值。

Public Sub NameCopy(wsheet As Worksheet, cname As String)

If wsheet.OLEObjects(cname).Object.Value = True Then
    Range(wsheet.OLEObjects(cname).LinkedCell).Offset(0, -7).Value = Environ("UserName")
End If

End Sub

使用“表单”复选框更容易,您可以将此宏用于所有复选框。只需记住将宏设置为:

Public Sub NameCopy()

Dim shp As Shape
Set shp = ActiveSheet.Shapes(Application.Caller)

If shp.ControlFormat.Value = xlOn Then
  ActiveSheet.Range(shp.ControlFormat.LinkedCell).Offset(0, -7).Value = Environ("UserName")
End If

End Sub

答案 1 :(得分:2)

由于您使用的是表单控件,因此非常简单。您可以使用Application.Caller让代码访问单击的复选框,然后使用它的TopLeftCell属性来获取复选框所在的位置,然后您就可以执行所需的任何操作。在你的情况下,像我这样猜测:

Sub Checkbox_Click()

    With ActiveSheet.CheckBoxes(Application.Caller)
        If .Value = 1 Then  'Checkbox is checked
            .TopLeftCell.Offset(, 1).Value = Environ("UserName")
        Else
            .TopLeftCell.Offset(, 1).ClearContents
        End If
    End With

End Sub