vba 用户定义类型 (UDT) 作为类模块 (VB6) 中 public Sub 中的参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/975982/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
User Defined Type (UDT) as parameter in public Sub in class module (VB6)
提问by cfischer
I've tried to solve this problem, but can't find any solution. I have a UDT defined in a normal module, and wanted to use it as parameter in a Public Subin a Class Module. I then get a compile error:
我试图解决这个问题,但找不到任何解决方案。我在普通模块中定义了一个 UDT,并希望将其用作Public Sub类模块中 a中的参数。然后我得到一个编译错误:
Only public user defined types defined in public object modules can be used as parameters or return type for public procedures of class modules or as fields of public user defined types
只有在公共对象模块中定义的公共用户定义类型才能用作类模块公共过程的参数或返回类型或公共用户定义类型的字段
I then try to move my UDT in the class, declared as Private. I get this compile error:
然后我尝试在类中移动我的 UDT,声明为Private. 我收到此编译错误:
Private Enum and user defined types cannot be used as parameters or return types for public procedures, public data members, or fields of public user defined types.
私有枚举和用户定义类型不能用作公共过程、公共数据成员或公共用户定义类型的字段的参数或返回类型。
I finaly try to declare it as Publicin the class, and get this compile error:
我最终尝试Public在类中声明它,并得到这个编译错误:
Cannot define a Public user-defined type within a private object module.
无法在私有对象模块中定义公共用户定义类型。
So is there any way to have a public UDT used as a parameter in a public sub in a class?
那么有没有办法让公共 UDT 用作类中公共子中的参数?
采纳答案by Karl E. Peterson
So is there any way to have a public UDT used as a parameter in a public sub in a class?
那么有没有办法让公共 UDT 用作类中公共子中的参数?
In a word, no. The closest you can come with just Classic VB code would be to create a class that replicates the UDT and use that instead. There are definitely advantages there, but you're hosed if you need to pass that to, say, an API as well.
一句话,没有。仅使用经典 VB 代码最接近的方法是创建一个复制 UDT 的类并使用它。那里肯定有优势,但是如果您还需要将其传递给 API,那么您就会感到沮丧。
Another option is to define the UDT in a typelib. If you do that, it can be used as a parameter for a public method.
另一种选择是在类型库中定义 UDT。如果这样做,它可以用作公共方法的参数。
回答by MarkJ
Just define the sub as Friendscope. This compiles fine for me in a VB6 class.
只需将子定义为Friend范围。这在 VB6 类中对我来说编译得很好。
Private Type testtype
x As String
End Type
Friend Sub testmethod(y As testtype)
End Sub
From your error messages it appears your class is private. If you do want your class to be public - i.e. you are making an ActiveX exe or DLL and you want clients to be able to access the sub - then just make both the type and the sub Public.
从您的错误消息看来,您的课程是私人课程。如果您确实希望您的类是公开的——即您正在制作一个 ActiveX exe 或 DLL,并且您希望客户端能够访问子类——那么只需将类型和子类都设为公开。
回答by Elroy
Ok, here's how to do it, if I can get my cat to leave me alone, that is.
好的,这是怎么做的,如果我能让我的猫让我一个人呆着,那就是。
In Form1 (with one command button on it):
在 Form1 中(上面有一个命令按钮):
Option Explicit
'
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal dst As Long, ByVal src As Long, ByVal nBytes As Long)
'
Private Sub Command1_Click()
' Okay, this is what won't work in VB6:
' Dim MyUdt1 As MyUdtType ' Declare a variable with a publicly defined UDT (no problem).
' Form2.Show ' We could have created some object with a class. This was just easier for the demo.
' INSIDE OF FORM2:
' Public Sub MySub(MyUdt2 As MyUdtType) ' It won't even let you compile this.
' Msgbox MyUdt2.l
' MyUdt2.l = 5
' End Sub
' Form2.MySub MyUdt1 ' You'll never get this far.
' Unload Form2
' Msgbox MyUdt1.l
'
' The following is a way to get it done:
'
Dim MyUdt1 As MyUdtType ' Declare a variable with a publicly defined UDT (no problem).
Dim ReturnUdtPtr As Long ' Declare a variable for a return pointer.
MyUdt1.l = 3 ' Give the variable of our UDT some value.
Form2.Show ' Create our other object.
'
' Now we're ready to call our procedure in the object.
' This is all we really wanted to do all along.
' Notice that the VarPtr of the UDT is passed and not the actual UDT.
' This allows us to circumvent the no passing of UDTs to objects.
ReturnUdtPtr = Form2.MyFunction(VarPtr(MyUdt1))
'
' If we don't want anything back, we could have just used a SUB procedure.
' However, I wanted to give an example of how to go both directions.
' All of this would be exactly the same even if we had started out in a module (BAS).
CopyMemory VarPtr(MyUdt1), ReturnUdtPtr, Len(MyUdt1)
'
' We can now kill our other object (Unload Form2).
' We probably shouldn't kill it until we've copied our UDT data
' because the lifetime of our UDT will be technically ended when we do.
Unload Form2 ' Kill the other object. We're done with it.
MsgBox MyUdt1.l ' Make sure we got the UDT data back.
End Sub
In form2 (no controls needed). (This could have just as easily been an object created with a class.):
在 form2 中(不需要控件)。(这可以很容易地成为用类创建的对象。):
Option Explicit
'
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal dst As Long, ByVal src As Long, ByVal nBytes As Long)
'
Public Function MyFunction(ArgUdtPtr As Long) As Long
' Ok, this is how we get it done.
' There are a couple of things to notice right off the bat.
' First, the POINTER to the UDT is passed (using VarPtr) rather than the actual UDT.
' This way, we can circumvent the restriction of UDT not passed into objects.
' Second, the following MyUdt2 is declared as STATIC.
' This second point is important because the lifetime of MyUdt2 technically ends
' when we return from this function if it is just DIMmed.
' If we want to pass changes back to our caller, we will want to have a slightly longer lifetime.
Static MyUdt2 As MyUdtType
' Ok, we're here, so now we move the argument's UDT's data into our local UDT.
CopyMemory VarPtr(MyUdt2), ArgUdtPtr, Len(MyUdt2)
' Let's see if we got it.
MsgBox MyUdt2.l
' Now we might want to change it, and then pass back our changes.
MyUdt2.l = 5
' Once again, we pass back the pointer, because we can't get the actual UDT back.
' This is where the MyUdt2 being declared as Static becomes important.
MyFunction = VarPtr(MyUdt2)
End Function
And Finally, this goes in a module (BAS) file.
最后,这进入一个模块 (BAS) 文件。
Option Explicit
'
' This is just the UDT that is used for the example.
Public Type MyUdtType
l As Long
End Type
'
回答by Nithin K V
Just Pass the UDT as Reference parametre and it will work. :)
只需将 UDT 作为参考参数传递,它就会起作用。:)
'method in the class
Public Sub CreateFile(ByRef udt1 As UdtTest)
End Sub
回答by Vic Fanberg
I had the same error message and after checking the application, I found that in the property window for the class, the "Instancing" setting was set to "1 - Private" for the referenced object. I changed it to "5 - MultiUse" and got the same error message. I then went back to a version of the project module prior to when I added that referenced object and added it again the project - it defaulted to "1 - Private". I changed it to "5 - MultiUse" before doing anything else and closed the project to for it to update before compiling. I re-opened the project, verified it was still set to "5 - MultiUse", then compiled the project and it compiled cleanly without the error message.
我有同样的错误消息,在检查应用程序后,我发现在类的属性窗口中,引用对象的“实例化”设置被设置为“1 - 私有”。我将其更改为“5 - MultiUse”并收到相同的错误消息。然后我返回到项目模块的一个版本之前,当我添加该引用的对象并再次将其添加到项目时 - 它默认为“1 - 私有”。在执行任何其他操作之前,我将其更改为“5 - MultiUse”并关闭项目以在编译之前进行更新。我重新打开了该项目,验证它仍然设置为“5 - MultiUse”,然后编译该项目并且它编译干净,没有错误消息。
When the error message was saying it didn't allow referencing a private object, the object really was private. Once I declared it not private, and the project module accepted that new setting, it compiled cleanly.
当错误消息说它不允许引用私有对象时,该对象确实是私有的。一旦我声明它不是私有的,并且项目模块接受了这个新设置,它就会干净利落地编译。
回答by user2276227
Define UDF (public type) in a module:
在模块中定义 UDF(公共类型):
Public Type TPVArticulo
Referencia As String
Descripcion As String
PVP As Double
Dto As Double
End Type
and use Friendin class, module o frm:
并Friend在课堂上使用,模块 o frm:
Friend Function GetArticulo() As TPVArticulo
回答by Paulo Santos
The UDT must be declared in a Public Object, like:
UDT 必须在公共对象中声明,例如:
Public Class Sample
Public Strucutre UDT
Dim Value As Object
End Structure
End Class

