我一直在努力解决这个问题并找到了一些相关的问题,但似乎没有解决我的问题所以它可能只是我的编码。目标是从用户定义的数据类型(Customer)填充表单,然后在用户更新表单后将表单中的信息检索回数据对象。当我使用IOType =" O"运行此代码时它工作正常,数据元素都被放入表单中。当我使用IOType =" I"它将表单中的文本读入DataObjectOrType变量,但我发送的客户对象未更新(即CurCustomer.name和CurCustomer.territory都是="")。如果重要的话,CurCustomer的基础数据元素都是字符串。我已经尝试过这个作为一个子函数和一个函数,有和没有括号,有和没有byref但似乎没有任何区别。
更新 - 我简化了一些事情并在下面添加了一些代码。 Madgui,你是对的,它适用于数据类型(子CustomerFormIO2)。它也适用于几个字符串(sub CustomerFormIO3)。我也将下面的Customer类模块中的代码放在一起,以防万一。我觉得这不会起作用。它可能与使用中间变量的Get和Let属性有关吗?有没有办法让这个工作?
感谢。
Private Type structCustomer
Name As String
Territory As String
Rep As String
End Type
Public Sub CustomerFormIO1()
Dim CurCustomer As Customer
Dim IOType As String
Set CurCustomer = New Customer
IOType = "I"
Call ObjectIO("X", CurCustomer.Name, IOType)
Call ObjectIO("Y", CurCustomer.Territory, IOType)
ObjectIO "Z", CurCustomer.Rep, IOType
End Sub
Public Sub CustomerFormIO2()
Dim CurCustomer As structCustomer
Dim IOType As String
IOType = "I"
Call ObjectIO("X", CurCustomer.Name, IOType)
Call ObjectIO("Y", CurCustomer.Territory, IOType)
ObjectIO "Z", CurCustomer.Rep, IOType
End Sub
Public Sub CustomerFormIO3()
Dim CurCustomerName As String
Dim CurCustomerTerritory As String
Dim CurCustomerRep As String
Dim IOType As String
IOType = "I"
Call ObjectIO("X", CurCustomerName, IOType)
Call ObjectIO("Y", CurCustomerTerritory, IOType)
ObjectIO "Z", CurCustomerRep, IOType
End Sub
Public Function ObjectIO(FormObject As String, ByRef DataObjectOrValue As Variant, Optional IOType As String) As Variant
If IOType = "I" Then
DataObjectOrValue = FormObject
Else '"O"
FormObject = DataObjectOrValue
End If
ObjectIO = True
End Function
客户类模块:
Private c_CustName As String
Private c_Rep As String
Private c_Territory As String
Public Property Get Name() As String
Name = c_CustName
End Property
Public Property Let Name(CName As String)
c_CustName = CName
End Property
Public Property Get Rep() As String
Rep = c_Rep
End Property
Public Property Let Rep(CRep As String)
c_Rep = CRep
End Property
Public Property Get Territory() As String
Territory = c_Territory
End Property
Public Property Let Territory(CTerritory As String)
c_Territory = CTerritory
End Property
Private Sub Class_Initialize()
c_CustName = ""
c_Rep = ""
c_Territory = ""
End Sub
答案 0 :(得分:0)
奇怪的是,如果您将Customer类定义为Type(=静态结构):
Private Type structCustomer Name As String Territory As String Rep As String End Type
在您的代码更改中
Dim CurCustomer As Customer
通过
Dim CurCustomer As structCustomer
并评论该行:
'设置CurCustomer =新客户
答案 1 :(得分:0)
(旧帖子,但是添加了这个,因为这里没有确定的答案。)
这可以通过将引用传递给完整对象CurCustomer
来完成,但不能直接传递属性。无论是否指定ByRef
,都会评估属性并将其作为值传递。
传递Customer
对象时,可以直接在接收函数(DataObjectOrValue.Name
)中添加属性,但这样做需要额外的逻辑来处理同一函数中的多个属性。
您还可以传递属性名称并使用CallByName
来保持功能灵活。
请参阅下面的示例。
Public Sub CustomerFormIO4()
Dim CurCustomer As Customer
Dim IOType As String
Set CurCustomer = New Customer
IOType = "I"
Call ObjectIO("X", CurCustomer, "Name", IOType)
Call ObjectIO("Y", CurCustomer, "Territory", IOType)
ObjectIO "Z", CurCustomer, "Rep", IOType
End Sub
Public Function ObjectIO(FormObject As String, _
ByRef DataObjectOrValue As Variant, PropName As String, _
Optional IOType As String) As Variant
If IOType = "I" Then
CallByName DataObjectOrValue, PropName, VbLet, FormObject
Else '"O"
CallByName DataObjectOrValue, PropName, VbGet, FormObject
End If
ObjectIO = True
End Function
您可以通过对工作表对象尝试相同的方法来验证问题不是用户定义的类所特有的:
Sub wsNameByRefTest()
Dim ws As Object
Set ws = Sheets.Add
ws.Name = "It failed!"
changeNameByRef ws.Name
End Sub
Sub changeNameByRef(ByRef wsName As String)
wsName = "It worked!"
End Sub
供参考,请参阅此MSDN Article。它是关于VBScript的官方文档,但我已经在VBA中进行了测试,并且本文中的所有要点都适用。 (例如,ByRef是两者中参数的默认值。)我找不到具体的VBA类似参考。
按值传递的ByRef参数
如果参数指定为 ByRef ,则参数仍可按值传递。如果满足以下条件之一,则会发生这种情况:
参数位于括号中,括号不适用于参数列表。
作为参数发送的变量位于类中。
传递的参数不是变量,例如12。