将 33 个复选框代码子改进为几个? (书签中的自动日期复选框)

Improve 33 checkbox code subs to few? (Checkbox for auto-date in bookmarks)

:) 我是 VBA 的新手! 我有一个工作代码,用于在使用复选框 (ActiveX) 时在我有书签的地方插入日期。问题是我有 33 个复选框(我实际上希望 33x2。一个表示是,一个表示否)。所以我最终得到了 33 个订阅和 33 个书签。我敢打赌这段代码可以更有效地将其减少到几个子。任何人都知道是否可以完成? 下面的代码是 33 个重复 sub 中的第一个,其中 Sub 和书签名称是 agi1, agi2 agi3.....

Private Sub agi1_Click()

Dim rngFormat As Range
 Set rngFormat = ActiveDocument.Range( _
 Start:=ActiveDocument.Bookmarks("agi1").Range.Start, _
 End:=ActiveDocument.Bookmarks("agi1").Range.End)
 With rngFormat
 .Font.Size = 8
 End With

   Dim v
   Dim BMRange As Range
   v = ThisDocument.agi1.Value

'Sjekke om boks er sjekket eller ikke
   If v = True Then

'Sett inn dato i bokmerke
Set BMRange = ActiveDocument.Bookmarks("agi1").Range
With Selection.Font
 .Size = 9
End With
BMRange.Text = (Format(Date, "dd.mm.yyyy"))

Else

'Erstatte dato med tom tekst hvis boks ikke er sjekket
Set BMRange = ActiveDocument.Bookmarks("agi1").Range
BMRange.Text = " "

End If
'Sett inn bokmerke på nytt
ActiveDocument.Bookmarks.Add "agi1", BMRange

End Sub

ActiveX 控件总是像这样注册它们的事件处理程序:

Private Sub NameOfTheControl_NameOfTheEvent({args})

如果重命名处理程序,控件将停止工作 - 因为处理程序 name 必须 的格式如上,带有下划线分隔控件的名称和处理的事件的名称。

因此,如果您的控件必须存在于 compile-time,则无法绕过它:对于 33 个控件,您需要 33 个处理程序。

这并不意味着您需要将这个庞大的过程重复 33 次!

提取程序。 Select 该处理程序的整个 body,将其删除。

现在制作一个新的程序原型:

Private Sub HandleCheckBoxClick(ByVal controlName As String)

End Sub

并在其中粘贴 body。然后用对这个 controlName 参数的引用替换所有你有 hard-coded "agi1" 的地方:

Dim rngFormat As Range
Set rngFormat = ActiveDocument.Range( _
    Start:=ActiveDocument.Bookmarks(controlName).Range.Start, _
    End:=ActiveDocument.Bookmarks(controlName).Range.End)
With rngFormat
    .Font.Size = 8
End With

'...

您使用编程名称引用控件的地方会有点困难:

v = ThisDocument.agi1.Value

你可以通过ThisDocument.InlineShapescollection获取MSForms.CheckBox控件,但是that won't let you find a checkbox by its name,所以你需要一个可以为你做的函数:

Private Function FindCheckBoxByName(ByVal controlName As String) As MSForms.CheckBox
    Dim sh As InlineShape
    For Each sh In ThisDocument.InlineShapes
        If TypeOf sh.OLEFormat.Object Is MSForms.CheckBox Then
            If sh.OLEFormat.Object.Name = controlName Then
                'return the MSForms control:
                Set FindControlByName = sh.OLEFormat.Object
            End If
        End If
    Next

现在您可以这样做了:

Dim cb As MSForms.ChecBox
Set cb = FindCheckBoxByName(controlName)
If cb Is Nothing Then
    MsgBox "No ActiveX CheckBox control named '" & controlName & "' was found in ThisDocument."
    Exit Sub
End If
v = cb.Value

一旦所有对 ActiveX 控件的引用都被参数化,您的 33 个处理程序现在看起来像这样:

Private Sub agi1_Click()
    HandleCheckBoxClick "agi1"
End Sub

Private Sub agi2_Click()
    HandleCheckBoxClick "agi2"
End Sub

'...

Private Sub agi33_Click()
    HandleCheckBoxClick "agi33"
End Sub

或者,您可以在 run-time 处创建复选框,然后在专用的 class 模块中处理它们的 Click 事件,但这有点复杂;- )

您可以使用事件接收器,也许可以。

在普通模块中,创建一个集合并填充它以保存将控制复选框事件的 classes。

这里有代码,这需要在打开文档时 运行,在它生命周期的早期填充集合。

Public col As Collection

Public Sub SETUP()

Dim o As InlineShape
Dim c As MSForms.CheckBox
Dim cust As clsCustomCheckBox

Set col = New Collection

For Each o In ActiveDocument.InlineShapes

    Set c = o.OLEFormat.Object
    Set cust = New clsCustomCheckBox
    cust.INIT c
    col.Add cust

Next o

End Sub

然后有一个名为 clsCustomCheckBox 的 class 模块,其代码为

Private WithEvents c As MSForms.CheckBox

Public Function INIT(cmdIN As MSForms.CheckBox)
    Set c = cmdIN
End Function

Private Sub c_Click()
    MsgBox "Here you can get the name " & c.Name
End Sub

这会将每个复选框的点击转移到 classes c_click 而不是它自己的。

所以对你来说

Dim rngFormat As Range
 Set rngFormat = ActiveDocument.Range( _
 Start:=ActiveDocument.Bookmarks(c.name).Range.Start, _
 End:=ActiveDocument.Bookmarks(c.name).Range.End)
 With rngFormat
 .Font.Size = 8
 End With
.......