【问题标题】:VBA excel Reference Userform as variable to get dataVBA excel参考用户表单作为变量来获取数据
【发布时间】:2020-11-29 02:30:32
【问题描述】:

我有几天时间来解决这个问题。我正在使用 excel VBA 填写 Word Doc。 我有多个包含文本框、组合框等的用户窗体,为了保持代码小而不是一遍又一遍地创建相同的模块,我只需要更改 FormName

此代码正在填写 Word Doc

wDoc.SelectContentControlsByTitle("#MonthBox").Item(1).Range.Text = Request_Form_1.MonthBox.Value

但我想使用变量来引用模块中的用户窗体,但我得到所有类型的错误

Dim FormName As String
FormName = "Request_Form_1"
wDoc.SelectContentControlsByTitle("#MonthBox").Item(1).Range.Text = FormName.MonthBox.Value

亲切的问候

感谢您的支持 我尝试过但不起作用

  1. 尝试过的用户表单(NumeForma) MsgBox UserForms(NumeForma).LunaBox.Value 表单可见但我得到 error 13 type mismatch
  2. 尝试插入包含ShowAnyForm() 调用MsgBox ShowAnyForm(NumeForma).LunaBox.Value 错误“预期函数或变量”的模块
  3. 模块 ShowAnyForm()Sub 更改为 Function 使用 MsgBox ShowAnyForm(NumeForma).LunaBox.Value 需要错误 424 对象

【问题讨论】:

  • 您搜索的是:“excel vba 用户表单名称作为变量”?
  • 是的,我尝试了多种方法,但都没有成功,因为我不理解它们。这就是我在这里问的原因。我现在搜索了几天
  • 你找到了ShowAnyForm的链接?你应该提到这一点。
  • 您在回答中看到了我的编辑。发现问题 ;) 另外ShowAnyForm不是函数(不返回任何内容),它只会使用户窗体可见!
  • 并且不要更改 ListBox 名称(MonthBox/LunaBox)。使用一个或另一个,而不是两个

标签: excel vba variables userform


【解决方案1】:

点前面或后面的所有内容(如FormName.)都不能(容易)被变量替换,因为它是一个对象或成员(但你可以CallByName它!)。

变量必须作为实参传递给参数,但由于集合可以访问许多对象,这就是我们通常采用的方式。

已加载用户表单可以在 UserForms 集合中找到。但它们只能通过它们的项目索引(0 到 UserForms.Count() -1)而不是它们的名字来访问。所以你需要某事。喜欢:

'code by http://www.cpearson.com/Excel/showanyform.htm
For Each Obj In VBA.UserForms
     If StrComp(FormName, Obj.Name, vbTextCompare) = 0 Then ' If Obj.Name matches FormName loop is exited and Obj contains the UserForm reference of FormName.
         Exit For
     End If
Next Obj

获取加载的用户表单引用。 示例代码可在Show Any Form 获得。

您的代码应如下所示:

wDoc.SelectContentControlsByTitle("#MonthBox").Item(1).Range.Text = ControlValueByName(FormName:=FormName, ControlName:="MonthBox", _
        ProcName:="Value", CallType:=vbGet)

我添加了一个函数来返回给定 FormName 的 UserForm 引用:

'Code inspired by http://www.cpearson.com/Excel/showanyform.htm
Public Function UserFormByName(ByVal FormName As String) As UserForm
Dim Obj As Variant
For Each Obj In VBA.UserForms
    If StrComp(FormName, Obj.Name, vbTextCompare) = 0 Then
        Exit For
    End If
Next Obj
If Obj Is Nothing Then ' UserForm not loaded
    Err.Clear
    Set Obj = VBA.UserForms.Add(FormName)
    If Err.Number <> 0 Then
        MsgBox "Error Calling Form: " & FormName
        Exit Function
    End If
End If
Set UserFormByName = Obj
End Function

现在你可以使用了:

wDoc.SelectContentControlsByTitle("#MonthBox").Item(1).Range.Text = UserFormByName(FormName).MonthBox.Value

如果您从用户窗体调用方法,事情会变得更容易,因为您可以简单地将引用传递给它。见 OP 的answer

在表格上:

Private Sub InregistreazaButtonActive2_Click()
    ToWord Me
End Sub

在模块中:

Sub ToWord(ByRef Caller As UserForm)
    MsgBox Caller.AnBox.Value
End Sub

您可以传递包含表单引用的列表框引用,而不是表单引用,因为它是表单的子对象,所以表单是ListBox.Parent

Private Sub InregistreazaButtonActive2_Click()
    ToWord Me.AnBox
End Sub

Sub ToWord(ByRef CallerListBox As ListBox)
    MsgBox CallerListBox.Value
    Debug.Print CallerListBox.Parent.Name ' shows form name of listbox 
End Sub

通过传递引用,您不必担心多个实例(名称相同),因为每个实例都有自己的引用。

【讨论】:

  • 没有其他简单的方法来引用表格吗?类似Controls("Check" &amp; x)
  • 正如我所说的集合是UserForms(所以UserForms(FormName)会在表单被加载的情况下这样做),但只包含加载的表单。这就是为什么你需要来自最后一个链接的ShowAnyForm
  • 请相信我,表单已加载/可见但在线 MsgBox UserForms(NumeForma).LunaBox.Value 我得到运行时间错误''13'类型不匹配
  • 现在无法测试,但请尝试ControlValueByName 函数,来自ShowAnyForm 的链接。它使用提到的 CallByName 函数,因为用户窗体可能不返回对象引用。我会调整我的答案。
  • 刚刚测试了我的代码 -> 适用于 ControlValueByName ,b 但在 UserForms(FormName) 时失败,因为与 Ms Access 表单集合不同,您只能按索引而不是名称获取值。这就是为什么ControlValueByName 使用 for 循环来获取表单名称的索引!
【解决方案2】:

首先我想说谢谢@ComputerVersteher 二会粘贴孔代码

  1. 在 excel 工作表中我有一个形状,点击会调用表单
Sub Start_Cerere_De_Autentificare_1_Click()
    Cerere_De_Autentificare_2.Show False
End Sub
  1. 在表单上我有 3 个文本框(ZiBox、LunaBox、AnBox)
Public Sub UserForm_Activate()
     ZiBox = Day(Date)
     LunaBox = Month(Date)
     AnBox = Year(Date)
End Sub
Private Sub InregistreazaButtonActive2_Click()
    Call ToWord_CerereDeAutentificare2
End Sub
  1. 按下注册按钮时会调用
Sub ToWord_CerereDeAutentificare2()

    Dim NumeForma As String
    NumeForma = "Cerere_De_Autentificare_2"

    Dim AllName As Object
    Set AllName = UserFormByName(NumeForma)

    MsgBox AllName.AnBox.Value
End Sub
  1. 这将调用您的代码,该代码将返回表单名称,最后可以通过一行轻松访问存储在文本框中的值 MsgBox AllName.AnBox.Value
Public Function UserFormByName(FormName As String) As UserForm
Dim Obj As Variant
For Each Obj In VBA.UserForms
    If StrComp(FormName, Obj.Name, vbTextCompare) = 0 Then
        Exit For
    End If
Next Obj
If Obj Is Nothing Then ' UserForm not loaded
    Err.Clear
    Set Obj = VBA.UserForms.Add(FormName)
    If Err.Number <> 0 Then
        MsgBox "Error Calling Form: " & FormName
        Exit Function
    End If
End If
Set UserFormByName = Obj
End Function

再次感谢您

【讨论】:

  • 正如我假设的那样,表单调用 sub,但我不明白为什么您使用表单名称来获取列表框值而不是 Cerere_De_Autentificare_2。如果这只是一个简单的例子,ToWord_CerereDeAutentificare2被更多的表单使用,你怎么知道调用的是什么表单。要仅访问列表框,您可以将其引用作为参数传递给ToWord_CerereDeAutentificare2 中的参数。这比通过名称获取表单引用更容易(顺便说一句,UserFormByName 不能用于多个表单实例!)。
  • 我想这样做,因为我需要创建 50 个表单和 50 个ToWord_ 模块和 50 个 Word 模板。表单和单词模板的最新版本存储在 Excel 表中(用于可追溯性),为了方便更改,我在 Excel 表中搜索表单名称并在 VBA 代码中使用它。关于UserFormByName,我将对此进行深入研究。非常感谢!
  • 知道您可以在运行时通过代码操作表单(例如创建、编辑、删除控件)吗?您也可以同时打开一个用户窗体的多个独立实例。结合将对象引用传递给方法,这可能使您能够对所有人使用 ine 形式。我将扩展我的答案,向您展示如何使用ToWord 显示任何表单上任何列表框的值。
  • 请给我看一个小例子,不要占用你的时间,我会做我的研究。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-29
相关资源
最近更新 更多