使用对 Word VBA 中动态创建的控件的引用

发布于 2024-07-09 11:54:10 字数 1152 浏览 8 评论 0原文

我正在 Word 2003 中编写一个表单,以收集对单个问题的多个答复。 我在按钮上有一个宏,它复制了各种输入字段(下拉框、单选按钮等),准备新的响应。

但是,我需要更改单选按钮的文本,并在组合框上设置 OnChange 事件,但我找不到正确的语法来执行此操作。 这两个控件都来自“控件工具箱”工具栏。

我必须复制控件的宏代码如下。

Private Sub CommandButton11_Click() 
Set Doc = ActiveDocument
Response = MsgBox("Add another response?", vbYesNo, "Confirm action")
    If Response = vbYes Then
        If Doc.ProtectionType <> wdNoProtection Then
          Doc.Unprotect
        End If

        Selection.MoveRight
        Selection.MoveDown
        Selection.TypeParagraph
        ''# keep the reference to this control and set the OnChange event handler
        Selection.InlineShapes.AddOLEControl ClassType:="Forms.ComboBox.1"
        Selection.MoveRight Unit:=wdCharacter, Count:=1
        Selection.TypeText Text:=vbTab
        Selection.TypeText Text:=vbTab
        ''# keep the reference to this control and set text
        Selection.InlineShapes.AddOLEControl ClassType:="Forms.OptionButton.1"
        Selection.MoveRight Unit:=wdCharacter, Count:=1

        Doc.Protect Type:=wdAllowOnlyFormFields, NoReset:=True
    End If
End Sub

I am writing a form in Word 2003 to collect multiple responses to a single question. I have a macro on a button press which duplicates the various input fields (drop-down boxes, radio buttons etc.) ready for a new response.

However, I need to change the text of the radio buttons, and set the OnChange event on a combobox, and I can't find the correct syntax to do so. Both the controls are from the 'Control Toolbox' toolbar.

The macro code I have to duplicate the controls is below.

Private Sub CommandButton11_Click() 
Set Doc = ActiveDocument
Response = MsgBox("Add another response?", vbYesNo, "Confirm action")
    If Response = vbYes Then
        If Doc.ProtectionType <> wdNoProtection Then
          Doc.Unprotect
        End If

        Selection.MoveRight
        Selection.MoveDown
        Selection.TypeParagraph
        ''# keep the reference to this control and set the OnChange event handler
        Selection.InlineShapes.AddOLEControl ClassType:="Forms.ComboBox.1"
        Selection.MoveRight Unit:=wdCharacter, Count:=1
        Selection.TypeText Text:=vbTab
        Selection.TypeText Text:=vbTab
        ''# keep the reference to this control and set text
        Selection.InlineShapes.AddOLEControl ClassType:="Forms.OptionButton.1"
        Selection.MoveRight Unit:=wdCharacter, Count:=1

        Doc.Protect Type:=wdAllowOnlyFormFields, NoReset:=True
    End If
End Sub

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

五里雾 2024-07-16 11:54:10

动态添加事件处理程序有点棘手。

您可以将代码动态添加到 ThisDocument。 这是微软描述的方式: http ://support.microsoft.com/?scid=kb%3Ben-us%3B246299&x=14&y=10。 但是,当我尝试此操作时,Word 2007 崩溃了。

另一种方法是添加一个用于事件处理的类,并为每个控件创建该类的一个实例。 将以下代码放入模块中:

Option Explicit

Public objControls() As clsComboBox

Private Sub CommandButton11_Click()
    Dim objShape As InlineShape

    If ActiveDocument.ProtectionType <> wdNoProtection Then
        ActiveDocument.Unprotect
    End If

    Selection.MoveRight
    Selection.MoveDown
    Selection.TypeParagraph
    ' keep the reference to this control and set the OnChange event handler
    Set objShape = Selection.InlineShapes.AddOLEControl(ClassType:="Forms.ComboBox.1")
    With objShape.OLEFormat.Object
        .AddItem "Item 1"
        .AddItem "Item 2"
    End With

    Selection.MoveRight Unit:=wdCharacter, Count:=1
    Selection.TypeText Text:=vbTab
    Selection.TypeText Text:=vbTab
    ' keep the reference to this control and set text
    Set objShape = Selection.InlineShapes.AddOLEControl(ClassType:="Forms.OptionButton.1")
    With objShape.OLEFormat.Object
        .Caption = "My great option"
    End With
    Selection.MoveRight Unit:=wdCharacter, Count:=1

    ActiveDocument.Protect Type:=wdAllowOnlyFormFields, NoReset:=True

    ' we have to execute the creation of the event handlers with a delay
    ' to make it work (seems Word needs some time for object creation)
    Application.OnTime When:=Now + TimeValue("00:00:01"), Name:="prcCreateReference"

End Sub

Public Sub prcCreateReference()
    Dim objShape As InlineShape
    Dim intCount As Integer

    On Error Resume Next
    For Each objShape In ThisDocument.InlineShapes
        intCount = intCount + 1
        ReDim Preserve objControls(1 To intCount)
        If TypeOf objShape.OLEFormat.Object Is ComboBox Then
            Set objControls(intCount) = New clsComboBox
            Set objControls(intCount).ComboBox = objShape.OLEFormat.Object
        ElseIf TypeOf objShape.OLEFormat.Object Is OptionButton Then
            ' add event handlers for option buttons
        End If
    Next
End Sub

该代码应放入名为 clsComboBox 的类模块中:

Option Explicit

Private WithEvents mobjComboBox As MSForms.ComboBox

Friend Property Set ComboBox(objComboBox As MSForms.ComboBox)
    Set mobjComboBox = objComboBox
End Property

Private Sub mobjComboBox_Change()
    MsgBox "Selection changed."
End Sub

Private Sub mobjComboBox_Click()
    MsgBox "Clicked."
End Sub

请注意,变量 objControls 的类型必须为 clsComboBox。 将此变量声明为 Object 或 Variant 对我来说不起作用(有人能解释为什么吗???)。

adding the event handlers dynamically is a bit tricky.

You could add the code dynamically to ThisDocument. This is the way described by Microsoft: http://support.microsoft.com/?scid=kb%3Ben-us%3B246299&x=14&y=10. However, when I tried this Word 2007 crashed.

Another way is to add a class for event handling and create an instance of this class for each control. Place the following code into a module:

Option Explicit

Public objControls() As clsComboBox

Private Sub CommandButton11_Click()
    Dim objShape As InlineShape

    If ActiveDocument.ProtectionType <> wdNoProtection Then
        ActiveDocument.Unprotect
    End If

    Selection.MoveRight
    Selection.MoveDown
    Selection.TypeParagraph
    ' keep the reference to this control and set the OnChange event handler
    Set objShape = Selection.InlineShapes.AddOLEControl(ClassType:="Forms.ComboBox.1")
    With objShape.OLEFormat.Object
        .AddItem "Item 1"
        .AddItem "Item 2"
    End With

    Selection.MoveRight Unit:=wdCharacter, Count:=1
    Selection.TypeText Text:=vbTab
    Selection.TypeText Text:=vbTab
    ' keep the reference to this control and set text
    Set objShape = Selection.InlineShapes.AddOLEControl(ClassType:="Forms.OptionButton.1")
    With objShape.OLEFormat.Object
        .Caption = "My great option"
    End With
    Selection.MoveRight Unit:=wdCharacter, Count:=1

    ActiveDocument.Protect Type:=wdAllowOnlyFormFields, NoReset:=True

    ' we have to execute the creation of the event handlers with a delay
    ' to make it work (seems Word needs some time for object creation)
    Application.OnTime When:=Now + TimeValue("00:00:01"), Name:="prcCreateReference"

End Sub

Public Sub prcCreateReference()
    Dim objShape As InlineShape
    Dim intCount As Integer

    On Error Resume Next
    For Each objShape In ThisDocument.InlineShapes
        intCount = intCount + 1
        ReDim Preserve objControls(1 To intCount)
        If TypeOf objShape.OLEFormat.Object Is ComboBox Then
            Set objControls(intCount) = New clsComboBox
            Set objControls(intCount).ComboBox = objShape.OLEFormat.Object
        ElseIf TypeOf objShape.OLEFormat.Object Is OptionButton Then
            ' add event handlers for option buttons
        End If
    Next
End Sub

This code should go into a class module named clsComboBox:

Option Explicit

Private WithEvents mobjComboBox As MSForms.ComboBox

Friend Property Set ComboBox(objComboBox As MSForms.ComboBox)
    Set mobjComboBox = objComboBox
End Property

Private Sub mobjComboBox_Change()
    MsgBox "Selection changed."
End Sub

Private Sub mobjComboBox_Click()
    MsgBox "Clicked."
End Sub

Note that the variable objControls must be of type clsComboBox. Declaring this variable as Object or Variant didn't work for me (could anyone explain why???).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文