Question

Passing a UDT Variable to a Sub Argument Typed as Variant

Asked by: Rodr

I want to develop a generic, reusable Sub procedure to accept any user-defined type (UDT) as a variant argument. I plan to call this Sub procedure from Form modules. I want the Sub procedure to accept any UDT as the variant argument. I envision the Sub procedure to be defined as

   Public MySub(ByVal varUDT as Variant)

I'm getting all confused as to (1) where (what kind of module) do I define the UDT? .BAS module? Class module? Can I define a single variable as a UDT type and have this variable be used anywhere in an application? If so, where do I place the statement

   Public pubVar as MyUDT

where pubVar is the name of the variable and MyUDT is defined by a Type statement somewhere.

I'm getting all twisted up with what kind of modules to place various statements so that I can have a Public Sub Procedure and public variables of UDT type.

The above text is a simplified version of my problem. In actuality, I'm trying to write a generic procedure to add, change, delete and insert fixed-length records into any binary file (specified by an argument). In my struggles with this problem I've gotten the following error message several times:
 
    Compile error.

    Only public user defined types defined in public object   modules can be used as parameters or return types for public procedures of class modules or as fields of public user defined types.

I need a more elementary explanation than this authentic Visual Basic gibberish.



This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2004-08-20 at 16:20:18ID21101836
Tags

udt

,

passing

Topic

Visual Basic Programming

Participating Experts
3
Points
200
Comments
20

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. UDT TYPES!!!
    Can anyone tell me the how i can do the following:- I want to write a general piece of code that will be using UDT's. Something like this - projectA.bas Type udtTestA strA1dummy as String * 5 strA2dummy as String * 6 end type Type udtTestB strB1dummy as String *...
  2. UDT TYPES AGAIN!!!!!!!
    Hi, I have a problem with UDT's. The problem is mainly trying to pass them around functions as parameters, when the functions receiving them as parameters need to be generic. The UDTs are required because they represent C Structures on another UNIX type platform. Some Code....
  3. Classes vs. UDTs
    Hi there, a couple of small ones : 1. Is it possible to have collections of UDT's (User-Defined-Types) 2. Which is 'better' to use, Collections of Classes, or Arrays of UDT's. (or collections of UDT's if possible) Can anyone point me towards a white paper, or a VB standa...
  4. UDT property
    I would like to return a udt as a property for a class. Is it possible? I dont want to make another class because this class has many properties that must be this type.

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: ImbuePosted on 2004-08-20 at 17:07:55ID: 11857077

Try this.

File > Add project > ActiveX DLL

In this new project put your UDT in the class module. Make sure you make it public. (Public Type udtWhatever)

Now go back to your first project (Standard EXE) and go to Project > References. Check the name of the second project. Now you should be able to pass those UDTs back and forth all over the place.

 

by: EnladePosted on 2004-08-21 at 08:58:54ID: 11859393


I don't think he is using more then one processes.  That is I don't think he is having trouble passing data from one of his processes to another.

Basically, you define all your "user defined types" in a .BAS module.  Or, you create a Class that will contain the data.  Most likely you are not dealing with Classes in your program.  So, just create a module called modTypes and put them in there as Public types.  I normally create a few modules ever time I start a new program (whether I end up using them or not).

modTypes  -  Contains all my global types
modGlobs  -  Contains all my global variables
modConst  -  Contains all my Constants
modGenFuncs  -  Contains any general functions that I might use (not specific to this application).
modResource -  Contains all the defines I might need to address my resource data.

In any case, put all your Public Type definitions inside of modTypes.  Then put your Public global variables inside of modGlobs.  Remember you can't pass a user defined type between forms, so sometimes you need to have temporary global locations to store your data (kind of simulate passing types between forms by useing a global variable).  I am not sure why Microsoft doesn't allow such a useful thing, but they don't.

Hope that helps.

 

by: EnladePosted on 2004-08-21 at 09:02:12ID: 11859409


Oh, I mentioned the alternitive, which is to encapsulate your data inside of a class.  In that case you will just define a class for each data type and give access to each field through the class methods and properties.  We can talk about that if you want, but from what you are saying I think you just need to define the types as public in a .BAS module.

 

by: ImbuePosted on 2004-08-21 at 09:45:56ID: 11859676

Enlade, you say that it is not possible to pass UDTs between forms. Actually, using my first answer it is possible to have a public function of a form that takes and returns a UDT. Also, no one is talking about having more than one process.

To pass around UDTs you must put them in a "public object modules," according to your error message. If you make a class in your project it cannot be totally public, so you have to add an ActiveX DLL project and create a public class module in that, and you are doing what the error message says to fix your problem.

 

by: EnladePosted on 2004-08-21 at 11:21:26ID: 11860088


Remember I am saying between "Forms".  Clearly you can pass a type structure to a module function, but you cannot pass a structure to a form even if the forms function is public.  For example, try passing this to a function on a form:

Public Type MyType
  Field1 As Long
  Field2 As Long
End Type

I think that you might be giving him a much larger answer then he is looking for (though I'm not sure).  It seems to me that he wants to define some types and he is having trouble passing variables of those types between forms.  Though, maybe he is talking about creating class objects and passing them....and/or creating his own ActiveX object and linking it into his project.  So he will need to clearify that for us.

In any case, I'm not sure what you mean by "if you make a class in your project it cannot be totally public"?  It is totally public to your process.  Its just not totally public to some other process that your application may spawn.  But clearly I can create a class within my project that is totally public to my entire project and even create an object of that class that is also entirely public to all the code in my project.  Maybe I just don't understand what you are trying to suggest.  It seems like you are suggesting that he should create some ActiveX object to encapulate his data and that seems like an overkill.  Though maybe that is what he wants and I'm just not understanding him.  I'll wait for him to clearify his question for me.

 

by: RodrPosted on 2004-08-21 at 11:49:42ID: 11860242

Imbue--

I tried your suggestions (File > Add project > ActiveX DLL, etc.)

I put the following UDT in a Class Module in Project2:

    Public Type BinaryFileUtilityType
        PostDateTime as Variant
        Amount as Single
        Bool as Boolean
        LongInteg as Long
        Integ as Integer
        Desc as String * 25
    End Type


When I try to run the application I get the following error message:

   Compile error:

   Fixed-length strings and use of the 'new' qualifier are not allowed for fields in public user defined type defined in an object module.

and the 'Desc as String *' is highlighted by the error.

My problem is simple. Please don't read any complexity into it. All I want to do is create a generic binary file update procedure to add, change, delete and insert records into any binary file. Any such record will be defined by its own UDT. By "generic...procedure" I mean a procedure in some kind of module that I can develop once and reuse it over and over again for any record (UDT) structure in any application. Naturally, each record (UDT) structure will be unique, which is why I want to type the record parameter as a Variant in the generic procedure's Sub statement.

 

by: EnladePosted on 2004-08-21 at 12:37:30ID: 11860439


The problem is that you are using the term UDT and a lot of people simple understand that to mean "Class".  Well, a Class is a UDT, but so is a simple type structure like you are showing above.  Just don't use a Class module at all.  Just create your public type in a regular old module.

 

by: EnladePosted on 2004-08-21 at 12:49:00ID: 11860494


Oh, I think I see what you want to do.  You want to make this a generic function that takes any such type structure and writes it to a record in the file.  This is not a simple task.  I think you might have trouble with the fact that a Variant has additional information that is beyond that contained in the strucuture that you are passing.  Right now you are having trouble passing the structure, but you might end up with a larger problem when you try to write the variant (that contains the structure) into the file (thinking that it is just a file containing your original structures).  I'll need to think about this a bit.

 

by: EnladePosted on 2004-08-21 at 12:57:00ID: 11860532


I now understand what Imbue meant by "totally public".  I'll need to rethink this problem a bit to see if there is an easier solution.

 

by: EnladePosted on 2004-08-21 at 13:15:29ID: 11860606


Nope, no easier way that I can think of (short of copying the structure into a byte array or something).  So, I'll defer to Imbue on this one.  Still, I think you might end up with another problem when you try to write the variant to disk.

 

by: ImbuePosted on 2004-08-21 at 13:16:21ID: 11860612

Ok, unless I am missing something (and I could very well be), you will need to have an ActiveX DLL project. If you only have the EXE project then you cannot get UDT data into the type library for that program (that means you cannot make it public enough to do cool stuff with it).

Anyway, to make it simple the fixed length string is causing your problem now. I don't know of an really slick ways to deal with that, though. You could make it variable length, or use a byte array. Why does it need to be fixed length?


Enlade, when you said "you cannot pass a structure to a form even if the forms function is public" I don't think you could be more wrong. If the UDT is in the type library you can do just about anything with it, including passing it to and from classes (forms).

 

by: ImbuePosted on 2004-08-21 at 13:26:35ID: 11860642

You will not have any problems writing a variant (vs a real UDT) to a file. The variable length string shouln't cause any problems either, VB is really flexible and handles this stuff very well.

 

by: EnladePosted on 2004-08-21 at 13:30:38ID: 11860651


It was my missunderstanding.  I over simplfied the problem.

As far as not being able to pass type structures to a form.  You will have to explain to me how to do that.  Tell me how to pass this public type structure to a form without first making the structure into a Class.

Public Type MyType
  Field1 As Long
  Field2 As Long
End Type

In any case, you are on the right path with what you are suggesting.  I was way off.  Sorry.

 

by: ImbuePosted on 2004-08-21 at 13:38:21ID: 11860670

Enlade, all you need to do to pass that structure to a form is get it into a public type library. The easiest way to do that is plop it into an ActiveX DLL's class. Please understand that this is not making it into a class. It is not a class, it is a user defined type.

Anyway, then once you have the project references set up you just make your public sub in your form like Public Sub Test (TestUDT as MyType).

The difference from being a class and being in a class is.


Public Type MyType 'A UDT defined in a class.
  Field1 As Long
  Field2 As Long
End Type


Public Field1 As Long 'Using a class to act like a UDT (not a real UDT)
Public Field2 As Long

 

by: PocketLintPPCPosted on 2004-08-21 at 19:02:00ID: 11862089

You can pass a UDT as a param to a form, just make sure you use FRIEND and not PUBLIC as the scope identifier..


in a public module...
Public Type MyType
  Field1 As Long
  Field2 As Long
End Type


on a form..
Friend Sub Test(m As MyType)
   msgbox "Madeit"
End Sub

 

by: PocketLintPPCPosted on 2004-08-21 at 19:24:57ID: 11862162

As for making a generic method,
Remember that passing a UDT requires early binding. This means that the structure of the UDT MUST be know at compile time. So a true generic way is not really possible. Well It is if you use some balck belt thing to actually pass along the address of the UDT then inside the SUB you use a few API calls to copy the data at that loction into a local udt. But in the end, again the UDT must be known if you plan on manipulating the UDT contents.

A similar and much safer way might to use the following as a jumping off point to do what you want...
Make a master UDT that contains all the sub UDT's and include a TYPE field to let the reciever know which sub UDT to work with..


Public Type MasterType
   UDT1 as UDT1_Type
   UDT2 as UDT2_Type
   MType as TypeEnum
End type

Also include the following before all else...
Public Enum TypeEnum
   eUDT1
   eUDT2
End Enum

Public Type UDT1_Type
        PostDateTime as Variant
        Amount as Single
        Bool as Boolean
        LongInteg as Long
        Integ as Integer
        Desc as String * 25
End Type

Public Type UDT2_Type
        PostDateTime as Variant
        Total as Single
        Bool as Boolean
        LongInteg as Long
        Integ as Integer
End Type


Then dim it with something like..
Public M as MasterType

then use it like...

' Set the UDT to use
M.MType = eUDT1  

' Set some Data        
With M.UDT1
   .PostDateTime = Now
   .Amount = 100
End With


'Call the function
call Form1.NewSub(M)


And the prototype of the sub is
Friend Sub NewSub(M as MasterType)
   If M.MType = eUDT1 then
      Msgbox "PostDate = " & M.UDT1.PostDateTime
   Else
      Msgbox "PostDate = " & M.UDT2.PostDateTime
   End If
End Sub


Hope this helps some

 

by: ImbuePosted on 2004-08-21 at 19:33:28ID: 11862186

Passing a UDT does not require early binding. You can pass a UDT as a variant. You can pass a UDT to a form's public methods. The UDT just must be written in the type library.

 

by: PocketLintPPCPosted on 2004-08-21 at 19:55:25ID: 11862239

I was offer an alternate example. In a sense they have to be considered early bound unless one uses the ActiveX DLL method.
I'm right with you though that the ActiveX DLL method should work here.






 

by: RodrPosted on 2004-08-27 at 13:15:43ID: 11917253

Imbue and others:

Sorry I've taken so long to respond. I've been away.

Here's what I have so far in my application:
    Project1
         Form1
         Module1
    Project2
         Class1 (ActiveX DLL type)

I have my UDT ("myUDT") defined in Class1. I have my generic Sub procedure defined in Class1.

I use Module1 to declare a Public variable of type myUDT. (Apparently, I must declare the variable in Module1. Declaring a Public variable of type myUDT in any of my other modules doesn't work.)

I've softened my requirements to surrender to the ridiculous complexity of trying to solve my problem: I've replaced the fixed-length string in myUDT with a variable length string. In my generic procedure in Class1 I'm using the statement(s)
      If TypeOf myVariant is myUDT then
         ....
      Else
         (error)
      End If

This softening of requirements means I must change my "generic Class1" to include any new UDT types and test for these new UDT types specifically with the "If TypeOf" tests. So much for the concept of "generic".

I now have new problems:

   1. A Binary file that I opened in Form1 is not recognized in the Class1 module. I pass the file number to the Sub procedure as a parameter. But the statement x = LOF(BinFileNo) generates an error (Error 52 - bad file name or number). I would like to open the file in Form1 and update the file in Class1.

  2. I take it I must instantiate a new object of Class1 in my Form1 procedure(s) in order to use the one and only Sub procedure in Class1 as a "method". Can't I just Call the procedure (e.g., Call Project2.Class1.SubProcedure...) without instantiating an object?

  3. How do I specify "early binding" for my Class1 stuff? So much documentation talks about early and late binding but I haven't found a clear description about how to achieve either binding in my IDE environment.

My original problem seemed so straightfoward. I must be missing an understanding of relevant basic concepts. It seems to me the solution is ridiculously complex.

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...