Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba 将对象链接到用户界面_Vba_Userform - Fatal编程技术网

Vba 将对象链接到用户界面

Vba 将对象链接到用户界面,vba,userform,Vba,Userform,将类链接到用户表单的最佳方法是什么 很抱歉,这是假设性的,但使用实际的代码将导致一个页面长的问题 假设我有一个类,它保存关于一个人的数据 <<class Person>> Public FirstName as String Public LastName as String Public PhoneNumber as String <<end class>> 从上述代码中的项到实际对象的最佳方式是什么?我应该为每个对象添加一个GUID,并将其放

将类链接到用户表单的最佳方法是什么

很抱歉,这是假设性的,但使用实际的代码将导致一个页面长的问题

假设我有一个类,它保存关于一个人的数据

<<class Person>>
Public FirstName as String
Public LastName as String
Public PhoneNumber as String
<<end class>>

从上述代码中的项到实际对象的最佳方式是什么?我应该为每个对象添加一个GUID,并将其放在listitem的标记中,然后查找它吗?我是否应该将listview中的listitem添加到类中,这样我就可以遍历所有人,然后查看来自_ItemClick的项目是否等于来自对象的项目?

最简单的方法是使用listitem的Index属性(如果没有唯一标识符),或者使用Key属性(如果有)

如果选择使用Index属性,则无法(或者至少会使其变得非常复杂)添加任何功能来重新排列列表项的顺序

您可以通过ListView.ListItems.Add方法基于集合/记录集中的对象填充ListView。可以使用Index属性根据ListItems中的项目顺序返回到原始对象,ListItems中的项目顺序对应于原始对象集合中的项目顺序

或者,如果您更喜欢使用唯一键的更大灵活性,但不希望修改底层对象,那么您可以在将每个对象添加到ListItems时构造一个唯一键(最简单的是CStr(一些递增的数字)),将键存储在对象旁边

然后可以使用ListItem的.Key属性。这里的好处是,用户可以修改其中的项目、删除内容等,而无需使控件无效并重新添加所有对象,以保持源中的索引和列表中的索引之间的链接

例如:

最后,如果在DB返回的记录集中有它们,另一种方法是添加一个新字段(我假设您有一个现有的对象字段),并对记录运行更新查询,并用递增的数字填充它(这只会影响本地记录集(当然,首先检查记录集设置!)。用这个作为钥匙


您在对问题的评论中提到,您从SQL获取数据。对于列表框的所有正常用途,可能仍然最容易通过集合对象运行它们,如上所述,但是如果记录集中的记录有SQL中的4个字段,那么就没有能够调用其属性的“对象”。如果您这样做,请在您的问题或对此的评论中指定,因为可能有更好的方法来回答您的问题,或者实际的更新操作可能需要不同的语法或语义(特别是如果您需要将任何更新传播回源):

我将使用事件驱动的方法

Person
将具有属性而不是变量,分配这些属性将引发事件

用户表单将有
with events Person
,因此相关人员的更改将触发用户表单代码

人员类别:

Public Event Changed()
Private pFirstName As String
Private pLastName As String
Private pPhoneNumber As String

Public Property Get FirstName() As String
    FirstName = pFirstName
End Property

Public Property Let FirstName(ByVal v As String)
    pFirstName = v
    RaiseEvent Changed
End Property

Public Property Get LastName() As String
    LastName = pLastName
End Property

Public Property Let LastName(ByVal v As String)
    pLastName = v
    RaiseEvent Changed
End Property

Public Property Get PhoneNumber() As String
    PhoneNumber = pPhoneNumber
End Property

Public Property Let PhoneNumber(ByVal v As String)
    pPhoneNumber = v
    RaiseEvent Changed
End Property
以用户形式捕获事件:

Public WithEvents ThisPerson As Person

Private Sub ThisPerson_Changed()
    'Update user form
End Sub

因此,无论何时分配
YourForm.RelatedObject=SomePerson
,对
SomePerson
所做的任何更改都将触发
YourForm
中的代码,因为您无法更改返回的
ListItem
,我有另一个解决方案:

将相关的
列表项
添加到您的
人员
类:

Public FirstName as String
Public LastName as String
Public PhoneNumber as String
Public RelatedObject As Object
填充
TreeView
时,为其分配:

Set SomeListItem = SomeTreeView.ListItems.Add(...)
Set SomePerson.RelatedObject = SomeListItems
因此,每当您在
列表项中进行更改时:

Private Sub SomeListView_ItemClick(ByVal Item As MSComctlLib.ListItem)
    Dim p As Person
    For Each p In (...)
        If p.RelatedObject Is Item Then
            'Found, p is your person!
            p.PhoneNumber = ...
        End If
    Next
End Sub
或者,如果您不想更改
Person
类,可以将其封装在另一个类中,例如PersonToObject:

Public Person As Person
Public RelatedObject As Object

并将
PersonToObject
用作链接对象。

添加GUID或任何其他ID都是唯一标识个人对象的好方法,在您的示例中,电话号码可能对每个人都是唯一的,并且可以用作ID。如果您希望每个人都有一个以上的电话号码,那么这将不起作用,或多人拨打一个电话号码。您的数据存储在Excel工作表、Access数据库或Word中的列表中吗?人员信息来自何处?本例中的数据是从SQL加载的。我真的在寻找一种通用方法来识别/链接UI元素到对象。这不会有帮助吗?@mehow,我同意这个问题很广泛,但这是有目的的,我想问是否有最好的方法来做某事。对于如何改进这个问题,我非常感谢任何建设性的批评。重要的是,你是如何拥有“人”的?我假设你有适当的“对象”,因为你提到了一个类的人,所以这是有帮助的,我想更新数据库超出了问题的范围。不管怎样,我的建议有帮助吗?如果没有,请说明原因,供我参考。Thanks@lfrandom嗯,任何答案都将主要基于观点。没有<代码>最佳方式,因为它总是依赖于代码设计、实现和VBA技能等。你的问题太宽泛,难以回答,因为任何回答者都必须考虑其解决方案的利弊。一个会同意,另一个会不同意,所以你的问题没有完美的解决方案。你的问题也有点不清楚,所以努力理解你想要达到的目标是至关重要的
Private Sub SomeListView_ItemClick(ByVal Item As MSComctlLib.ListItem)
    Dim p As Person
    For Each p In (...)
        If p.RelatedObject Is Item Then
            'Found, p is your person!
            p.PhoneNumber = ...
        End If
    Next
End Sub
Public Person As Person
Public RelatedObject As Object