I know this has been covered here and in the .public groups, but it
seems like it's been a while, especially around here, so I just thought
I'd ask again to see if anyone has figured out a new angle.
If I have a class MyClass--not a collection container but a
single-level class--that has a bunch of properties of different types,
I'd like to be able to reference them via the standard VBA syntax of
MyClass.Properties("MyProperty")
or
MyClass.Item("MyProperty")
so that I could use variables instead of having to say
MyClass.MyProperty
to get and let.
Of course, I could create a whole collection myself to loop using the
Item/IEnumerator trick, but seems to me that kind of squashes the
usefulness of properties in the first place.
Thanks in advance.
example (in a standard module called PseudoClass)
Dim mInput As Double
Public Property Let InputNumber(ByVal vInput As Double)
mInput = vInput
End Property
Public Property Get TwelfthRoot() As Double
TwelfthRoot = mInput ^ (1 / 12)
End Property
---------------------
somewhere else
PseudoClass.InputNumber = 29
MsgBox PseudoClass.TwelfthRoot
'Shows
'---------------------------
'Microsoft Office Access
'---------------------------
'1.32393450111241
'---------------------------
'OK
'---------------------------
That being said, one of the great values of Classes is that multiple
instances can be created. TTBOMK only one instance of a Standard module
can exist at one time.
As well, these properties seem to operate no differently than Subs and
Functions, (well maybe a bit slower).
MsgBox PseudoClass.Properties("TwelfthRoot")
So that I could potentially say
Dim strTest as string
strTest="ThirteenthRoot"
MsgBox PseudoClass.Properties(strTest)
That's a silly example, but if for example you want to return a bunch
of different properties with a single piece of code, you begin to see
how Class.Property is a limitation.
--
David Lloyd
MCSD .NET
http://LemingtonConsulting.com
This response is supplied "as is" without any representations or warranties.
"downwitch" <down...@gmail.com> wrote in message
news:1121952427....@g49g2000cwa.googlegroups.com...
I was curious, so I have verified that this works in AC97 as well.
--
Bri
I am intimately familiar with constructing classes and collections. I
am trying to find a workaround to the fact that VBA will let you build,
set, let, get, etc. a property, but does not expose the properties as a
native collection through which one can loop as one does through any
other native collection, such as a form's properties, or yes, as one
does through a collection object. I don't hold out much hope, but I
figured it was worth dashing the little bit I had for good, and this
would be the place to do it.
> That's a silly example, but if for example you want to return a
> bunch of different properties with a single piece of code, you
> begin to see how Class.Property is a limitation.
What you're asking for is a collection that you can walk to get the
properties.
There is no way to do this in Access class modules. THe only way to
implement it is either with a custom collection or an array stored
in class module, with an interface for allowing you to enumerate its
values. I don't believe an array can be a public member, but you
should be able to create a public property of type array.
I've only wanted to walk the properties collection of a class module
internally, never externally, so I've only implemented it with an
array.
But once you're at that point, you have to ask yourself:
1. will you allocate a variable for each property, then double enter
it into an array?
OR
2. will you use the array for storing all the properties, and then
have the property LET/GETs operate directly on the array, and
completely ignore internal variables.
I don't know if the latter slows things down.
The former is easy enough, and that was how I implemented it, but I
was adding functionality to a class that was already in list, so I
needed backward compatibility.
--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
> I am intimately familiar with constructing classes and
> collections. I am trying to find a workaround to the fact that
> VBA will let you build, set, let, get, etc. a property, but does
> not expose the properties as a native collection through which one
> can loop as one does through any other native collection, such as
> a form's properties, or yes, as one does through a collection
> object. I don't hold out much hope, but I figured it was worth
> dashing the little bit I had for good, and this would be the place
> to do it.
I posted in response to Lyle and explained one approach I've used.
It involves creating either your own internal custom collection or
an array to store the properties, then exposing that externally in
some fashion.
Having done it before, I immediately grasped the question -- you
want to be able to walk the properties collection of your class.
I use a class for storing the criteria for query-by-form interfaces,
and when writing the SQL, being able to walk a collection in order
to write the WHERE string would have been highly desirable. I
implemented an internal array, so I avoided the problems associated
with making the contents of an array in a class module public.
Hi
Is this problem special to custom classes?
I don't know how to do this for the Application object, for example.
If you were in VB you could examine the input file for the linker and see what code
is actually produced. You can also generate a map file if you paste
SetEnv "LINK", "/MAP"
into the immediate window.See
http://www.constantthought.com/yabbse/index.php?board=4;action=display;threadid=240
Debugging tip: Getting the name of the current and calling function at runtime
A post about this (1998) was
The form is tiny and has no recordsource and no controls, images or
whatever.
It does have a module. The module has four properties, viz. Application
(private), Copies, Document, and Status (which prints the document and
returns the status).
The first reference to the form is in code, something like
form_frmPrint.Copies = 5
whereupon the form open event creates an instance of Word.
Now the form slumbers, invisible.
I can let and get its public properties at will from anywhere. (The
properties are private actually, and I access them through Property Let
and
Set procedures.)
As far as I know, as long as I don't close the form, the word instance
remains on the alert ready to do the printing.
When the application closes, the form closes, running the close event
procedure that quits and releases the Word app.
Question: Is performance taking any significant hit by keeping this
form
open (but invisible), over and above what it might take keeping a
non-form
class instance open?
And for the Why? sayers ... the form is always in scope ... and the
closing
of it and therefore the quitting and release of Word are implicit in
the
closing of the database. In pertinent error routines, I'll close it as
well.
I think the following is a basic approach to what you are after.
<clsProperties>
Option Compare Database
Option Explicit
Private m_properties As VBA.Collection
Public Property Get properties(key As String) As String
properties = m_properties.item(key)
End Property
Public Property Let properties(key As String, value As String)
m_properties.Add value, key
End Property
Private Sub Class_Initialize()
Set m_properties = New VBA.Collection
End Sub
Private Sub Class_Terminate()
Set m_properties = Nothing
End Sub
</clsProperties>
<test>
Sub testPropertyCollection()
Dim pc As clsPropetyCollection
Set pc = New clsPropetyCollection
pc.properties("Horse") = "Mustang"
MsgBox pc.properties("Horse")
Set pc = Nothing
End Sub
</test>
<snip>
Yes, this is the idea, but it's still more wheel reinvention than I'm
after (of course ;)). The trick to a catch-all properties collection
is that what DFW is talking about still poses a problem. Normally when
you set variables and hold properties in a class, you've got a cogent
"object" that organizes your code. The hierarchy can be quite rigid,
which I've always found very useful--I use a full class hierarchy that
emulates some table data when the structure is very complex, because it
makes code manipulations easy to make, and virtually self-documenting.
Using collection-type classes and flat "single-object" classes as in
classFoot parent of classToes parent of classToe
makes things very nice and pretty, and while I suppose you could set a
generic objParent in your clsProperties collection, and then add that
"collection" to any other single-object class, but at that point you
have to *always* use
classToe.Properties("NailPolishColor") = "hot pink"
and you lose the self-documenting thing of storing strNailPolishColor
as a visible "member" of the class. Property Let/Set and Get are
strict, and that's very useful, I think, one of the things that makes
classes so powerful.
It'a shame that MS didn't take the (obvious, to me anyway) extra step
of exposing the set of properties one invents as a public collection,
since after all they *behave* like other similar exposed collections.
An instance of the above example that calls
MyFoot.Toes("BigToe")
is so easy to read and hard to miscode it's almost magical, and it's
not such a leap from there to see
MyFoot.Toes("BigToe")(strPropertyIWantRightNow)
_with the same class setup_ as a logical step. I would think it has to
be the same logical engine, but I'm only speculating.
Using a hidden form could work, I suppose, but I suspect at that point
the whole thing would run much faster using temporary tables, at which
point you're out of VBA and fake OOP anyway, so it's more like
abandoning custom classes than making them work.
I'm still up for any ideas. Worth pointing out that the
default-item-of-collection method of exporting a collection, pasting
some standard text into it, and reimporting it--which I first learned
from the developer's handbook a few years back--is totally undocumented
and works like a charm. Might there be other workarounds out there for
those of you who know pure VB classes better than I?
That still doesn't get you a collection that you can walk through to
pull out all the properties (or a specific subset of them).
The collection is there. A method to add or retrieve a single property
from the collection is there. If you want to iterate the collection
of course there is more to it. You write an iterator class or provide
methods in each class (which would would be redundant) to iterate the
collection.
How do you get a specific subset of properties from a dao.field object?
> David W. Fenton wrote:
>> rkc <r...@rochester.yabba.dabba.do.rr.bomb> wrote in
>> news:q0VDe.57577$0i3....@twister.nyroc.rr.com:
> The collection is there. A method to add or retrieve a single
> property from the collection is there. If you want to iterate the
> collection of course there is more to it. You write an iterator
> class or provide methods in each class (which would would be
> redundant) to iterate the collection.
>
> How do you get a specific subset of properties from a dao.field
> object?
Well, you can filter by name.
The custom class module allows you to create different
collections/arrays for different purposes. In the query-by-form
criteria class that I have there's an array for the individual
criteria that is used in the private method that writes WHERE
clause, which is called by the public property that returns the SQL
string.
There are other properties that are *not* part of that array.
Had there been a pre-existing Properties collection for my class, I
would have had to use naming conventions to get a walkable structure
for assembling the WHERE clause, as with the DAO collections.
> Yes, this is the idea, but it's still more wheel reinvention than I'm
> after (of course ;)). The trick to a catch-all properties collection
> is that what DFW is talking about still poses a problem. Normally when
> you set variables and hold properties in a class, you've got a cogent
> "object" that organizes your code. The hierarchy can be quite rigid,
> which I've always found very useful--I use a full class hierarchy that
> emulates some table data when the structure is very complex, because it
> makes code manipulations easy to make, and virtually self-documenting.
>
> Using collection-type classes and flat "single-object" classes as in
>
> classFoot parent of classToes parent of classToe
>
> makes things very nice and pretty, and while I suppose you could set a
> generic objParent in your clsProperties collection, and then add that
> "collection" to any other single-object class, but at that point you
> have to *always* use
>
> classToe.Properties("NailPolishColor") = "hot pink"
>
> and you lose the self-documenting thing of storing strNailPolishColor
> as a visible "member" of the class. Property Let/Set and Get are
> strict, and that's very useful, I think, one of the things that makes
> classes so powerful.
This is probably more than you're interested in since you want
magic as opposed to effort. But then taking care of that mule
team is probably time consuming.
<clsProperty>
Option Compare Database
Option Explicit
Private m_Name As String
Private m_Value As String
Private m_parent As Object
Public Property Let Name(ByVal nm As String)
m_Name = nm
End Property
Public Property Get Name() As String
Name = m_Name
End Property
Public Property Get Value() As Variant
Value = m_Value
End Property
Public Property Let Value(ByVal vlu As Variant)
'uses VB6 CallByName function to call the property's
'parent's Property Let method
m_Value = vlu
CallByName m_parent, Me.Name, VbLet, Me.Value
End Property
Public Property Set parent(prnt As Object)
Set m_parent = prnt
End Property
Private Sub Class_Terminate()
Set m_parent = Nothing
End Sub
</clsProperty>
<clsToe>
Option Compare Database
Option Explicit
Private m_nailPolishColor As String
Private m_hasFungus As Boolean
Private m_properties As VBA.Collection
Public Property Get properties(key As String) As String
Dim prop As clsProperty
Set prop = m_properties.Item(key)
properties = prop.Value
Set prop = Nothing
End Property
Public Property Let properties(key As String, Value As String)
Dim prop As clsProperty
Set prop = New clsProperty
Set prop.parent = Me
prop.Name = key
prop.Value = Value
m_properties.Add prop, key
Set prop = Nothing
End Property
Public Property Let NailPolishColor(clr As String)
m_nailPolishColor = clr
End Property
Public Property Get NailPolishColor() As String
NailPolishColor = m_nailPolishColor
End Property
Public Property Get HasFungus() As Boolean
HasFungus = m_hasFungus
End Property
Public Property Let HasFungus(ByVal bln As Boolean)
m_hasFungus = bln
End Property
Private Sub Class_Initialize()
Set m_properties = New VBA.Collection
End Sub
Private Sub Class_Terminate()
Set m_properties = Nothing
End Sub
</clsToe>
<sub test>
Sub Test()
Dim toe As clsToe
Set toe = New clsToe
toe.properties("NailPolishColor") = "Orange"
toe.properties("HasFungus") = True
'get property by name
MsgBox toe.properties("NailpolishColor")
'get property by method
MsgBox toe.NailPolishColor & _
vbCrLf & _
"has fungus: " & toe.HasFungus
Set toe = Nothing
End Sub
</sub test>
>>How do you get a specific subset of properties from a dao.field
>>object?
>
>
> Well, you can filter by name.
>
> The custom class module allows you to create different
> collections/arrays for different purposes. In the query-by-form
> criteria class that I have there's an array for the individual
> criteria that is used in the private method that writes WHERE
> clause, which is called by the public property that returns the SQL
> string.
How are you doing on the demo of your query-by-form implementation?
You've been threatening to publish it. I'd like to see it.
No, on the contrary, I find this pretty unspeakably awesome.
I'd venture to guess that this is the first time anywhere in the world
Access has tracked the lower phalanges, and I thank you for it.
So one last question--and I was really with you on this before you went
to all the trouble--how do you validate data? I think your clsProperty
needs a data type property... And so on. I see your point, but you
wind up reproducing, well, VBA in VBA. It's not the effort that's the
problem, it's the having-to-write-the-language-for-the-language that
gets me down.
I wish the MS Access development team was subjected to developing with
Access. They could probably work this through in an afternoon, and
then justify jacking up the price of MS Office Pro another fifty bucks
(and a team of mules).
Hmm. I don't remember ever promising that. A review of my Access
folder (where I keep these kinds of things) shows no QBF example
database. The Report Switchboard database is much further along,
though, and I should spend a weekend getting it put together.
But the QBF one, ho-boy, that would take a *lot* of work!
And, in fact, the last QBF interface I implemented was so simple I
didn't use my own QBF class module. But that was mostly because the
criteria were *very* simple (from only two tables).
>rkc <r...@rochester.yabba.dabba.do.rr.bomb> wrote i
>
...
>> How are you doing on the demo of your query-by-form
>> implementation? You've been threatening to publish it. I'd like to
>> see it.
>
>Hmm. I don't remember ever promising that. A review of my Access
>folder (where I keep these kinds of things) shows no QBF example
>database. The Report Switchboard database is much further along,
>though, and I should spend a weekend getting it put together.
>
>But the QBF one, ho-boy, that would take a *lot* of work!
>
>And, in fact, the last QBF interface I implemented was so simple I
>didn't use my own QBF class module. But that was mostly because the
>criteria were *very* simple (from only two tables).
>
I seem to remember that the licence agreement for using the ADT (run-time development
system - see how old I am) made you promise not to distribute runtimes which duplicate
the functions of Access itself. A really good QBF would do this for a lot of users!
???
I've never created a generic QBF interface. Indeed, writing one
would be extremely complex. The only way to do it would be to
duplicate the QBE design (since how else would you be able to define
which tables to query?).
I assume you were distinguishing QBF from QBE?
Sorry. That was from memory, which fails me at times these days.
Might be time to start responding to all the mail AARP sends me.
That was just a demonstration of how you could work both a properties
collection and let/get/set methods into a possible solution. I haven't
even attempted to add flesh to the bone. That'd be for someone who
actually wants a working solution bad enough to think it through.