J
JGPatrick
Objects created by invoking methods do not seem to behave like normal objects
in VBA.
Consider that in other programming languages, once you set an equality, you
can use either side of the expression interchangeably.
For instance:
A = B
C = sqrt(A)
will give you the same thing as
A = B
C = sqrt(B)
But consider two examples where this interchangeability is not true in VBA.
You can say:
Set Ws = DBEngine.CreateWorkspace( Arguments ) (ie, A = B)
and then you can say: Workspaces.Append Ws (similar to C = sqrt(A))
but you cannot do: Workspaces.Append DBEngine.CreateWorkspace( Arguments ),
(like saying you can't do C = sqrt(B)). If you try to do this, you will run
into
later problems when you try to use the last item in the Workspaces collection.
In a second example, you can say
Set Dbs = CurrentDb() (ie, A = B)
And then you can: debug.print Dbs.TableDefs(0).Name (like you evaluate
sqrt(A) )
But you cannot Set Tbs = CurrentDB().TableDefs(0) and work with THAT
directly (Like saying you can't do sqrt(B)).
So clearly I need to understand what is going on when you create an object
by executing a method in VBA.
Now in the second example, after reading responses to my earlier posting
called "a fundamental difference between object variables and other
variables", here's my understanding of what the issue is. Let's say the
current default database is the Northwind databse, whose first table is
Customers.
Set Tbs = CurrentDb().TableDefs(0) does NOT say
"Tbs is the Customers table in the Northwind database."
Instead, it says
"Tbs is the first table in the database whose name is written on the
blackboard in
the room marked 'CurrentDb'. "
The problem is that this blackboard gets erased, so that VBA cannot define
Tbs in later statements.
However, I have to say that this is still not that satisfying. Extending the
analogy, the statement
Set Dbs = CurrentDb()
should say
"Dbs is the database whose name is written on the blackboard in the room
marked 'CurrentDb'."
so later references to Dbs should also fail when that blackboard gets erased.
But they do not.
So instead of trying to understand what the difference is between
method-created objects and other objects, I think I will be satisfied with
simply
using the following rule:
Never invoke a method that creates an object, except on the right hand side
of a Set statement.
ie, for any object O that has a method M that creates an object, the only
place you should ever see O.M is in statements of the form
Set obj = O.M( Arguments ).
And if you have a function F() that has been defined via
Function F( Arguments ) As some kind of object
the only place you should ever see F( Arguments ) is in
statements of the form
Set obj = F( Arguments )
I would appreciate it if someone would be able to supply an alternative rule
which is less conservative but is also guaranteed to always work.
in VBA.
Consider that in other programming languages, once you set an equality, you
can use either side of the expression interchangeably.
For instance:
A = B
C = sqrt(A)
will give you the same thing as
A = B
C = sqrt(B)
But consider two examples where this interchangeability is not true in VBA.
You can say:
Set Ws = DBEngine.CreateWorkspace( Arguments ) (ie, A = B)
and then you can say: Workspaces.Append Ws (similar to C = sqrt(A))
but you cannot do: Workspaces.Append DBEngine.CreateWorkspace( Arguments ),
(like saying you can't do C = sqrt(B)). If you try to do this, you will run
into
later problems when you try to use the last item in the Workspaces collection.
In a second example, you can say
Set Dbs = CurrentDb() (ie, A = B)
And then you can: debug.print Dbs.TableDefs(0).Name (like you evaluate
sqrt(A) )
But you cannot Set Tbs = CurrentDB().TableDefs(0) and work with THAT
directly (Like saying you can't do sqrt(B)).
So clearly I need to understand what is going on when you create an object
by executing a method in VBA.
Now in the second example, after reading responses to my earlier posting
called "a fundamental difference between object variables and other
variables", here's my understanding of what the issue is. Let's say the
current default database is the Northwind databse, whose first table is
Customers.
Set Tbs = CurrentDb().TableDefs(0) does NOT say
"Tbs is the Customers table in the Northwind database."
Instead, it says
"Tbs is the first table in the database whose name is written on the
blackboard in
the room marked 'CurrentDb'. "
The problem is that this blackboard gets erased, so that VBA cannot define
Tbs in later statements.
However, I have to say that this is still not that satisfying. Extending the
analogy, the statement
Set Dbs = CurrentDb()
should say
"Dbs is the database whose name is written on the blackboard in the room
marked 'CurrentDb'."
so later references to Dbs should also fail when that blackboard gets erased.
But they do not.
So instead of trying to understand what the difference is between
method-created objects and other objects, I think I will be satisfied with
simply
using the following rule:
Never invoke a method that creates an object, except on the right hand side
of a Set statement.
ie, for any object O that has a method M that creates an object, the only
place you should ever see O.M is in statements of the form
Set obj = O.M( Arguments ).
And if you have a function F() that has been defined via
Function F( Arguments ) As some kind of object
the only place you should ever see F( Arguments ) is in
statements of the form
Set obj = F( Arguments )
I would appreciate it if someone would be able to supply an alternative rule
which is less conservative but is also guaranteed to always work.