将 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.InlineShapes
collection获取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
.......
:) 我是 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.InlineShapes
collection获取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
.......