excel VBA byref参数传递给函数未被更改

时间:2015-02-01 18:51:07

标签: excel vba excel-vba

我一直在努力解决这个问题并找到了一些相关的问题,但似乎没有解决我的问题所以它可能只是我的编码。目标是从用户定义的数据类型(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

2 个答案:

答案 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。

  •