【问题标题】:Use reference to dynamically created control in Word VBA在 Word VBA 中使用对动态创建的控件的引用
【发布时间】:2010-09-23 18:32:52
【问题描述】:

我正在 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

【问题讨论】:

    标签: vba ms-word


    【解决方案1】:

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

    您可以将代码动态添加到 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 对我不起作用(谁能解释原因???)。

    【讨论】:

    • 干得好。我发现Application.OnTime 呼叫的延迟要小得多。我用过:Application.OnTime VBA.Now + 0.000001, "prcCreateReference",略小于 1/10 秒。哦,我使用的是 Word 2007。
    猜你喜欢
    • 2014-02-24
    • 2012-07-12
    • 2021-12-15
    • 2014-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多