Discussion:
What is a class?
(too old to reply)
Peter Nolan
2012-02-24 12:02:47 UTC
Permalink
Hello,

I have tried, trust me, to learn what a class is in VB and in spite of
many an attempt I remain baffled and I was wondering if you could help
me out. In addition to reading I have watched YouTube videos.
I know that fish is a class and so a trout is an instance of the class
fish. I also know that a class contains a function and data. I better
leave it at that because of how confused I am about the whole thing.
I just want to add that when I posted recently about the Beep Function
I went on to say a lot of things about M$ but I want you to understand
it was not my intention to upset but it was my motivation to
contribute to the life of this newsgroup. It was my rather camouflaged
effort to thank, believe it or not, MIke Willams for helping me out
with two great blocks of code. I realise you might not understand that
but I didn't want to pop up out of nowhere to then disappear back into
depths of cyberspace without making an effort to add something.

Regards,

Peter Nolan.
Dublin.
Auric__
2012-02-24 14:06:34 UTC
Permalink
Post by Peter Nolan
I have tried, trust me, to learn what a class is in VB and in spite of
many an attempt I remain baffled and I was wondering if you could help
me out. In addition to reading I have watched YouTube videos.
I know that fish is a class and so a trout is an instance of the class
fish. I also know that a class contains a function and data. I better
leave it at that because of how confused I am about the whole thing.
Have you read the Wikipedia entry?
http://en.wikipedia.org/wiki/Class_(computer_programming)

The very first sentence there might help you:
a class is a construct that is used as a blueprint

So, it might help to think of a class as a sort of blueprint. A class
describes something, and when you create a new instance of a class, you're
using the blueprint.

Say you're writing a game, and you have a class called "monster". When you
need a new monster, you could do (for example):
Dim duck As New monster
duck.Health = 1
duck.Strength = 1
'etc.
...rather than:
Dim duckHealth As Integer, duckStrength As Integer 'etc.
--
I'm not evil. I'm living up to my full potential!
Peter Nolan
2012-02-25 11:07:30 UTC
Permalink
Post by Auric__
Post by Peter Nolan
I have tried, trust me, to learn what a class is in VB and in spite of
many an attempt I remain baffled and I was wondering if you could help
me out. In addition to reading I have watched YouTube videos.
I know that fish is a class and so a trout is an instance of the class
fish. I also know that a class contains a function and data. I better
leave it at that because of how confused I am about the whole thing.
Have you read the Wikipedia entry?
 http://en.wikipedia.org/wiki/Class_(computer_programming)
  a class is a construct that is used as a blueprint
So, it might help to think of a class as a sort of blueprint. A class
describes something, and when you create a new instance of a class, you're
using the blueprint.
Say you're writing a game, and you have a class called "monster". When you
  Dim duck As New monster
  duck.Health = 1
  duck.Strength = 1
  'etc.
  Dim duckHealth As Integer, duckStrength As Integer 'etc.
--
I'm not evil. I'm living up to my full potential!
Hello Auric,

I haven't the faintest idea what the rest of the thread is about to do
with For Next loops and so on.
However can I ask you a question? Is New monster a user defined
datatype other than the default data types like Integer and Long that
has the values duck.Health = 1 and duck.Strength =1 It's like a more
sophisticated type of data that really could very detailed with many
more values. If I am making any sense here it doesn't actually mean I
know what is going on. What simple illustrative code would describe
monster in the first place?
Many thanks for taking the time to explain things to me.

Regards,

Peter.
Helmut_Meukel
2012-02-25 13:19:36 UTC
Permalink
Post by Peter Nolan
Post by Auric__
Post by Peter Nolan
I have tried, trust me, to learn what a class is in VB and in spite of
many an attempt I remain baffled and I was wondering if you could help
me out. In addition to reading I have watched YouTube videos.
I know that fish is a class and so a trout is an instance of the class
fish. I also know that a class contains a function and data. I better
leave it at that because of how confused I am about the whole thing.
Have you read the Wikipedia entry?
 http://en.wikipedia.org/wiki/Class_(computer_programming)
  a class is a construct that is used as a blueprint
So, it might help to think of a class as a sort of blueprint. A class
describes something, and when you create a new instance of a class, you're
using the blueprint.
Say you're writing a game, and you have a class called "monster". When you
  Dim duck As New monster
  duck.Health = 1
  duck.Strength = 1
  'etc.
  Dim duckHealth As Integer, duckStrength As Integer 'etc.
--
I'm not evil. I'm living up to my full potential!
Hello Auric,
I haven't the faintest idea what the rest of the thread is about to do
with For Next loops and so on.
However can I ask you a question? Is New monster a user defined
datatype other than the default data types like Integer and Long that
has the values duck.Health = 1 and duck.Strength =1 It's like a more
sophisticated type of data that really could very detailed with many
more values. If I am making any sense here it doesn't actually mean I
know what is going on. What simple illustrative code would describe
monster in the first place?
Many thanks for taking the time to explain things to me.
Regards,
Peter.
Hmm, I think you really should take a class in programming as Jim
suggested.

But I'll try to explain.
How would you program a library app? Just books in the library for
starters.
You could do it traditionally, store all data in arrays, e.g. Title,
Author, Publisher, date of copyright, publishing date, actual language,
original language, HC/Trade/MMPB/eBook, genre, subgenre, description, ...
or create only one UDT array named Books.

Or you could create a class named Book, with properties (Title, Author,...)
and a Books collection containing all books in the library.
To delete a book, you just remove it from the Books collection.
To add a new book you create a new instance of class Book, set the
properties to the appropriate values, e.g.
NewBook.Author = "Poul Anderson"
NewBook.Publisher = "Baen Books"
NewBook.Title = "Time Patrol"
NewBook.Genre = "SF"
NewBook.Subgenre = "time travel"
...
When done you add NewBook to the Books collection.

HTH,

Helmut.
Auric__
2012-02-25 21:26:29 UTC
Permalink
Post by Peter Nolan
Post by Auric__
Post by Peter Nolan
I have tried, trust me, to learn what a class is in VB and in spite
of many an attempt I remain baffled and I was wondering if you could
help me out. In addition to reading I have watched YouTube videos.
I know that fish is a class and so a trout is an instance of the
class fish. I also know that a class contains a function and data. I
better leave it at that because of how confused I am about the whole
thing.
Have you read the Wikipedia entry?
 http://en.wikipedia.org/wiki/Class_(computer_programming)
  a class is a construct that is used as a blueprint
So, it might help to think of a class as a sort of blueprint. A class
describes something, and when you create a new instance of a class,
you're using the blueprint.
Say you're writing a game, and you have a class called "monster". When
  Dim duck As New monster
  duck.Health = 1
  duck.Strength = 1
  'etc.
  Dim duckHealth As Integer, duckStrength As Integer 'etc.
I haven't the faintest idea what the rest of the thread is about to do
with For Next loops and so on.
Welcome to Usenet, where any thread about anything will quickly get twisted
into a thread about something only marginally related.
Post by Peter Nolan
However can I ask you a question? Is New monster a user defined
datatype other than the default data types like Integer and Long that
has the values duck.Health = 1 and duck.Strength =1 It's like a more
sophisticated type of data that really could very detailed with many
more values.
Eh... sorta. More like a super data type. If you've ever used the type
keyword, e.g.:
Type foo
a As Integer
b As Single
c As String
End Type
...then you can think of classes as types taken to the next level. Where
types are essentially collections of related variables, classes can also hold
subs and functions.

"New" is necessary because of the mechanics of creating a class. Doing this:
Dim duck As monster
tells the compiler that "duck" is a "monster", but doesn't actually create a
new "monster" in "duck's" memory space -- doesn't apply the "monster"
blueprint to "duck", so to speak. You would have to do this:
Dim duck As monster
Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above 2 lines.

Let's look at my previous example, "duck" as a type of "monster". I showed
what it might look like if we didn't use classes:
Dim duckHealth As Integer, duckStrength As Integer

If we were using Types, it might be like this:
Type monster
Health As Integer
Strength As Integer
End Type
Dim duck As monster

Simple enough, right? But with classes, in addition to keeping track of
things like the duck's health, strength, etc., we could also assign it
behaviors (in the form of Subs and Functions).

For example, we could add an "Attack" behavior to our monster:
Public Sub Attack (what As monster)
'whatever
End Sub

While this could go anywhere in the program, outside of the class, by putting
it *in* the class, we're making the "Attack" behavior specific to the
"monster". A Sub outside the class would have to be aware of what type of
"monster" is "Attack"ing, and would have to extract the relevant information
out of the class (or from wherever):
Sub Attack(attacker As monster, target As monster)
If attacker.ChanceToHit > target.ArmorClass Then
target.Health = target.Health - attacker.DamagePerHit
If target.Health < 1 Then target.Name = "dead " & target.Name
End If
'etc.
End Sub
...but by putting the Sub *inside* the class, the rest of the program doesn't
need to know any of that relevant info, and the pertinent details can be
handled inside the class, invisible to the rest of the program.

Here's a simple "monster" class:
-----monster.cls-----
Private myName As String
Private myHealth As Integer, myStrength As Integer, myXPvalue As Integer
Private myToHit As Integer, myArmorClass As Integer
Private myDamage As Integer, myDamageReduction As Integer

Private Sub Class_Initialize()
myHealth = 10: myStrength = 1: myXPvalue = 1: myToHit = 1: myDamage = 1
End Sub

Public Property Get mName() As String
mName = myName
End Property

Public Property Let mName(ByVal newName As String)
myName = newName
End Property

Public Property Get ToHit() As Integer
ToHit = myToHit
End Property

Public Sub Attack(target As monster)
target.Defend Me
End Sub

Friend Sub Defend(attacker As monster)
If attacker.ToHit > myArmorClass Then attacker.GiveDamage Me
End Sub

Friend Sub GiveDamage(defender As monster)
defender.TakeDamage myDamage
End Sub

Friend Sub TakeDamage(howMuch As Integer)
If howMuch > myDamageReduction Then
myHealth = myHealth - howMuch
If myHealth < 1 Then doDeath
End If
End Sub

Private Sub doDeath()
myName = "dead " & myName
End Sub
-----monster.cls-----

(Yes, that really is a *simple* class.)

To do combat between two "monsters", the written code could be as simple as
this:
Dim duck As New monster, dragon As New monster
'code here to set monsters' initial stats, then:
duck.Attack dragon

Behind the scenes (hidden from the calling code) would be somewhat like this,
if actually written out in VB:
duck.Attack dragon
-> dragon.Defend duck
-> If duck.ToHit > dragon.ArmorClass Then duck.GiveDamage dragon
-> dragon.TakeDamage duck.Damage
-> If duck.Damage > dragon.DamageReduction Then
dragon.Health = dragon.Health - duck.Damage
If dragon.Health < 1 Then dragon.doDeath
-> dragon.mName = "dead " & dragon.mName
End If

So by using classes, you can greatly simplify your code, making it easier to
read and (hopefully) easier to debug.

Other Wikipedia pages that might be worth reading are the entries on
information hiding and encapsulation:
http://en.wikipedia.org/wiki/Information_hiding
http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)
Post by Peter Nolan
If I am making any sense here it doesn't actually mean I
know what is going on. What simple illustrative code would describe
monster in the first place?
Many thanks for taking the time to explain things to me.
Np. I know that for some people it can be a difficult concept to grasp.

Let's look at the other messages you posted...

-----------------------------------------------------------------------------
Post by Peter Nolan
http://youtu.be/OuoytdFfyXs
Not going to watch that, but...
Post by Peter Nolan
I'm sure it contains everything I need to know but I still end up
confused. A dog ie this class can have a name or belong to some breed
of dog. Then a new dog or an instance of that class would have a new
name an say belong to another breed. Then the dog could bark or sit
say and they would be functions for all dogs. I kinda get this.
Do you have a very simple VB code snippet that would illustrate all
that?
"very simple"? No, but... well, see my monster.cls above.

-----------------------------------------------------------------------------
Post by Peter Nolan
Instead of saying monster you could have said bird. Duck with all it's
descriptors is a kind of bird just like crow is a bird with it's own
health and strength. I get all this now but what has all this got to
do with programming computers?
I should've said "creature". Shrug. The whole point was just meant to be an
example. I could've just as easily said a "vehicle" class, with "car" or
"airplane" instead of "duck". Or a "robot" class, with "factory robot" or
"cleaning robot".
--
Well, it's finally happened. I'm speechless.
Utterly, utterly speechless.
Jim Mack
2012-02-25 23:58:48 UTC
Permalink
Post by Auric__
Dim duck As monster
Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above 2 lines.
For the purpose of this discussion, maybe. But "Dim As New" is frowned
on because it adds an implicit 'is nothing' check on every reference to
the object, and you lose control over the object lifetime.
--
Jim
GS
2012-02-26 00:39:35 UTC
Permalink
Post by Auric__
Dim duck As monster
Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above 2 lines.
For the purpose of this discussion, maybe. But "Dim As New" is frowned on
because it adds an implicit 'is nothing' check on every reference to the
object, and you lose control over the object lifetime.
Interesting...!
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Auric__
2012-02-26 03:09:09 UTC
Permalink
Post by Jim Mack
Post by Auric__
Dim duck As monster
Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above 2 lines.
For the purpose of this discussion, maybe. But "Dim As New" is frowned
on because it adds an implicit 'is nothing' check on every reference to
the object, and you lose control over the object lifetime.
Interesting. First I've heard of it (but then, I don't use VB very much any
more, and can't recall having ever used VB for "serious" OOP).

Is this documented anywhere? Help file, MSDN, whatever?
--
Too late. Jamie got goatse'd.
Jim Mack
2012-02-26 03:35:11 UTC
Permalink
Post by Auric__
Post by Jim Mack
Post by Auric__
Dim duck As monster
Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above 2 lines.
For the purpose of this discussion, maybe. But "Dim As New" is frowned
on because it adds an implicit 'is nothing' check on every reference to
the object, and you lose control over the object lifetime.
Interesting. First I've heard of it (but then, I don't use VB very much
any more, and can't recall having ever used VB for "serious" OOP).
Is this documented anywhere? Help file, MSDN, whatever?
The help files do mention it, but obliquely. What is said (from memory)
is that when you 'Dim As New' the object is not immediately created, as
it would be if you did a Dim followed by a Set = New, but rather is
instantiated on first reference.

The obvious question is, how does it know which is the first reference?
It knows that because _every_ reference contains a check to see if it's
been created yet -- the implicit 'is nothing' check I mentioned.

What follows from that is that you can't then legitimately test "If x
Is Nothing" yourself, because doing so references X, and so creates
it... that's how you lose (some) control over object lifetime.
--
Jim
GS
2012-02-26 03:55:37 UTC
Permalink
Post by Auric__
Post by Jim Mack
Post by Auric__
Dim duck As monster
Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above 2 lines.
For the purpose of this discussion, maybe. But "Dim As New" is frowned
on because it adds an implicit 'is nothing' check on every reference to
the object, and you lose control over the object lifetime.
Interesting. First I've heard of it (but then, I don't use VB very much any
more, and can't recall having ever used VB for "serious" OOP).
Is this documented anywhere? Help file, MSDN, whatever?
The help files do mention it, but obliquely. What is said (from memory) is
that when you 'Dim As New' the object is not immediately created, as it would
be if you did a Dim followed by a Set = New, but rather is instantiated on
first reference.
The obvious question is, how does it know which is the first reference? It
knows that because _every_ reference contains a check to see if it's been
created yet -- the implicit 'is nothing' check I mentioned.
What follows from that is that you can't then legitimately test "If x Is
Nothing" yourself, because doing so references X, and so creates it... that's
how you lose (some) control over object lifetime.
I thought that the object created by "Dim As New" existed until the
exit from the scope they were created in. So...

In a procedure: (local scope)
Dim colItems As New Collection
..lives for the entire procedure if not explicitly destroyed beforhand.

In a module: (module scope)
Dim colItems As New Collection
..lives for the duration code executes within the module if not
explicitly destroyed beforhand.

Global scope:
Dim colItems As New Collection
..lives for the entire runtime if not explicitly destroyed beforhand.

Also, I've created objects in this manner, tested them other than "If
colItems Is Nothing" via ways like "If colItems.Count > 0" so I know if
the created instance exists. Also, creating a new instance by using "If
colItems Is Nothing" doesn't cause any problems when you access its
items later, indicating VB is not at all confused about which
'instance' you're referring to.
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Farnsworth
2012-02-26 04:27:28 UTC
Permalink
What follows from that is that you can't then legitimately test "If x Is
Nothing" yourself, because doing so references X, and so creates it...
that's how you lose (some) control over object lifetime.
I thought that the object created by "Dim As New" existed until the exit
from the scope they were created in. So...
In a procedure: (local scope)
Dim colItems As New Collection
..lives for the entire procedure if not explicitly destroyed beforhand.
In a module: (module scope)
Dim colItems As New Collection
..lives for the duration code executes within the module if not explicitly
destroyed beforhand.
Dim colItems As New Collection
..lives for the entire runtime if not explicitly destroyed beforhand.
Correct, however, with "Dim As New", any checking to see if it's nothing
always creates the instance since you are referencing it. So "If o Is
Nothing" is always False in this case. Example:

Option Explicit

Private Sub Form_Load()
Dim o As New Collection

Debug.Print "o.Count = " & o.Count
Set o = Nothing

If o Is Nothing Then
Debug.Print "o Is Nothing"
Else
Debug.Print "o Is NOT Nothing"
End If
End Sub


Output:

o.Count = 0
o Is NOT Nothing



Case 2: No New keyword at Dim:

Option Explicit

Private Sub Form_Load()
Dim o As Collection

Set o = New Collection

Debug.Print "o.Count = " & o.Count
Set o = Nothing

If o Is Nothing Then
Debug.Print "o Is Nothing"
Else
Debug.Print "o Is NOT Nothing"
End If

End Sub


Output:

o.Count = 0
o Is Nothing
GS
2012-02-26 06:30:31 UTC
Permalink
Post by Farnsworth
What follows from that is that you can't then legitimately test "If x Is
Nothing" yourself, because doing so references X, and so creates it...
that's how you lose (some) control over object lifetime.
I thought that the object created by "Dim As New" existed until the exit
from the scope they were created in. So...
In a procedure: (local scope)
Dim colItems As New Collection
..lives for the entire procedure if not explicitly destroyed beforhand.
In a module: (module scope)
Dim colItems As New Collection
..lives for the duration code executes within the module if not explicitly
destroyed beforhand.
Dim colItems As New Collection
..lives for the entire runtime if not explicitly destroyed beforhand.
Correct, however, with "Dim As New", any checking to see if it's nothing
always creates the instance since you are referencing it. So "If o Is
Option Explicit
Private Sub Form_Load()
Dim o As New Collection
Debug.Print "o.Count = " & o.Count
Set o = Nothing
If o Is Nothing Then
Debug.Print "o Is Nothing"
Else
Debug.Print "o Is NOT Nothing"
End If
End Sub
o.Count = 0
o Is NOT Nothing
Option Explicit
Private Sub Form_Load()
Dim o As Collection
Set o = New Collection
Debug.Print "o.Count = " & o.Count
Set o = Nothing
If o Is Nothing Then
Debug.Print "o Is Nothing"
Else
Debug.Print "o Is NOT Nothing"
End If
End Sub
o.Count = 0
o Is Nothing
As I replied to Ralph, I've heard this arg before but you and he are
the first to demonstrate the facts behind the arg. I only use implicit
instantiation in local scope as a rule because it just doesn't sit
'right' with me to do this at module/global level.

Big thanks and appreciation for your persistence to get this across!
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Auric__
2012-02-26 04:41:09 UTC
Permalink
Post by GS
Post by Jim Mack
Post by Auric__
Post by Jim Mack
Post by Auric__
Dim duck As monster
Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above 2 lines.
For the purpose of this discussion, maybe. But "Dim As New" is
frowned on because it adds an implicit 'is nothing' check on every
reference to the object, and you lose control over the object
lifetime.
Interesting. First I've heard of it (but then, I don't use VB very
much any more, and can't recall having ever used VB for "serious" OOP).
Is this documented anywhere? Help file, MSDN, whatever?
The help files do mention it, but obliquely. What is said (from memory)
is that when you 'Dim As New' the object is not immediately created, as
it would be if you did a Dim followed by a Set = New, but rather is
instantiated on first reference.
The obvious question is, how does it know which is the first reference?
It knows that because _every_ reference contains a check to see if it's
been created yet -- the implicit 'is nothing' check I mentioned.
What follows from that is that you can't then legitimately test "If x
Is Nothing" yourself, because doing so references X, and so creates
it... that's how you lose (some) control over object lifetime.
I thought that the object created by "Dim As New" existed until the
exit from the scope they were created in. So...
[snip]

I read that as meaning you lose control over when the object is *created*,
i.e. initialized. I noticed this before Jim posted, while stepping through
my "monster" class -- the Class_Initialize code wasn't called until "duck"
attacked "dragon"...
Dim duck As New monster, dragon As New monster
duck.Attack dragon 'both get initialized right before .Attack
-----vs-----
Dim duck As monster, dragon As monster
Set duck = New monster 'duck gets initialized here
Set dragon = New monster 'dragon gets initialized here
duck.Attack dragon
but I didn't really give it any thought.
Post by GS
Also, I've created objects in this manner, tested them other than "If
colItems Is Nothing" via ways like "If colItems.Count > 0" so I know if
the created instance exists. Also, creating a new instance by using "If
colItems Is Nothing" doesn't cause any problems when you access its
items later, indicating VB is not at all confused about which
'instance' you're referring to.
Here's what the VB5CCE helpfile says about Dim As New:
Keyword that enables implicit creation of an object. If you use New when
declaring the object variable, a new instance of the object is created on
first reference to it, so you don't have to use the Set statement to
assign the object reference.

Based on *that*, I would use Dim As New, but based on what Jim says, Dim:
Set = New would probably give slightly better performance.

...okay, *very* slight. I just tried this code:
f! = Timer
For L0& = 1 To 1000000
Set duck = New monster 'duck gets initialized here
Set dragon = New monster 'dragon gets initialized here
duck.mName = "duck"
dragon.mName = "dragon"
duck.Attack dragon
Set duck = Nothing
Set dragon = Nothing
Next L0&
g! = Timer
...first using Dim As: Set = New, then using Dim As New. The total
difference between the two runs on my machine is only about .06 seconds
more for Dim As New (9.00... seconds vs 9.06... seconds), which is
negligible when averaged out over 1,000,000 iterations.

Of course, this is a trivial example, but in any project that doesn't
specifically need to check if an object Is Nothing, I see no reason not to
use Dim As New. The additional checks add such little overhead that I don't
think I'd be worried about it.
--
Unreal uses the Super Mario Bros. engine.
ralph
2012-02-26 05:05:24 UTC
Permalink
On Sun, 26 Feb 2012 04:41:09 +0000 (UTC), "Auric__"
Post by Auric__
Of course, this is a trivial example, but in any project that doesn't
specifically need to check if an object Is Nothing, I see no reason not to
use Dim As New. The additional checks add such little overhead that I don't
think I'd be worried about it.
You won't. Till you get burned.

-ralph
Henning
2012-02-26 10:24:30 UTC
Permalink
Post by ralph
On Sun, 26 Feb 2012 04:41:09 +0000 (UTC), "Auric__"
Post by Auric__
Of course, this is a trivial example, but in any project that doesn't
specifically need to check if an object Is Nothing, I see no reason not to
use Dim As New. The additional checks add such little overhead that I don't
think I'd be worried about it.
You won't. Till you get burned.
-ralph
I learnd the hard way that with a problem with the object:
Dim As New, does not rise an error until the object is used.
Set throws the error here.

/Henning
ralph
2012-02-26 05:03:16 UTC
Permalink
Post by GS
Post by Auric__
Post by Jim Mack
Post by Auric__
Dim duck As monster
Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above 2 lines.
For the purpose of this discussion, maybe. But "Dim As New" is frowned
on because it adds an implicit 'is nothing' check on every reference to
the object, and you lose control over the object lifetime.
Interesting. First I've heard of it (but then, I don't use VB very much any
more, and can't recall having ever used VB for "serious" OOP).
Is this documented anywhere? Help file, MSDN, whatever?
The help files do mention it, but obliquely. What is said (from memory) is
that when you 'Dim As New' the object is not immediately created, as it would
be if you did a Dim followed by a Set = New, but rather is instantiated on
first reference.
The obvious question is, how does it know which is the first reference? It
knows that because _every_ reference contains a check to see if it's been
created yet -- the implicit 'is nothing' check I mentioned.
What follows from that is that you can't then legitimately test "If x Is
Nothing" yourself, because doing so references X, and so creates it... that's
how you lose (some) control over object lifetime.
I thought that the object created by "Dim As New" existed until the
exit from the scope they were created in. So...
In a procedure: (local scope)
Dim colItems As New Collection
..lives for the entire procedure if not explicitly destroyed beforhand.
... But you can not "explicitly" destroy the collection object.
You can clear the contents but never get rid of the object until the
object reference goes out of scope.
Post by GS
In a module: (module scope)
Dim colItems As New Collection
..lives for the duration code executes within the module if not
explicitly destroyed beforhand.
... but you can not "explicitly" destroy the collection object.
You can clear the contents, but you'll never be shed of the object
inside the module.
Post by GS
Dim colItems As New Collection
..lives for the entire runtime if not explicitly destroyed beforhand.
... but (you guessed it <g>) you can not "explicity" destroy the
collection object for the life of the program.
Post by GS
Also, I've created objects in this manner, tested them other than "If
colItems Is Nothing" via ways like "If colItems.Count > 0" so I know if
the created instance exists. Also, creating a new instance by using "If
colItems Is Nothing" doesn't cause any problems when you access its
items later, indicating VB is not at all confused about which
'instance' you're referring to.
That is less an issue than all that extra code you have added to your
Application every single time you reference the object. Most of the
more serious consequences (e.g. memory leaks, circular references,
problems on Application exits, etc.) only present themselves in highly
specialized circumstances involving specific objects. Thus one can
probably program with the "As New" construct for years and never
notice a problem or bloat, however it only takes a few wasted hours on
tracking down a particular odd behavior of an object to appreciate it
is best not to go there in the first place. <g>

-ralph
GS
2012-02-26 06:26:10 UTC
Permalink
Post by ralph
Post by GS
Post by Auric__
Post by Jim Mack
Post by Auric__
Dim duck As monster
Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above 2 lines.
For the purpose of this discussion, maybe. But "Dim As New" is frowned
on because it adds an implicit 'is nothing' check on every reference to
the object, and you lose control over the object lifetime.
Interesting. First I've heard of it (but then, I don't use VB very much
any more, and can't recall having ever used VB for "serious" OOP).
Is this documented anywhere? Help file, MSDN, whatever?
The help files do mention it, but obliquely. What is said (from memory) is
that when you 'Dim As New' the object is not immediately created, as it
would be if you did a Dim followed by a Set = New, but rather is
instantiated on first reference.
The obvious question is, how does it know which is the first reference? It
knows that because _every_ reference contains a check to see if it's been
created yet -- the implicit 'is nothing' check I mentioned.
What follows from that is that you can't then legitimately test "If x Is
Nothing" yourself, because doing so references X, and so creates it...
that's how you lose (some) control over object lifetime.
I thought that the object created by "Dim As New" existed until the
exit from the scope they were created in. So...
In a procedure: (local scope)
Dim colItems As New Collection
..lives for the entire procedure if not explicitly destroyed beforhand.
... But you can not "explicitly" destroy the collection object.
You can clear the contents but never get rid of the object until the
object reference goes out of scope.
Post by GS
In a module: (module scope)
Dim colItems As New Collection
..lives for the duration code executes within the module if not
explicitly destroyed beforhand.
... but you can not "explicitly" destroy the collection object.
You can clear the contents, but you'll never be shed of the object
inside the module.
Post by GS
Dim colItems As New Collection
..lives for the entire runtime if not explicitly destroyed beforhand.
... but (you guessed it <g>) you can not "explicity" destroy the
collection object for the life of the program.
Post by GS
Also, I've created objects in this manner, tested them other than "If
colItems Is Nothing" via ways like "If colItems.Count > 0" so I know if
the created instance exists. Also, creating a new instance by using "If
colItems Is Nothing" doesn't cause any problems when you access its
items later, indicating VB is not at all confused about which
'instance' you're referring to.
That is less an issue than all that extra code you have added to your
Application every single time you reference the object. Most of the
more serious consequences (e.g. memory leaks, circular references,
problems on Application exits, etc.) only present themselves in highly
specialized circumstances involving specific objects. Thus one can
probably program with the "As New" construct for years and never
notice a problem or bloat, however it only takes a few wasted hours on
tracking down a particular odd behavior of an object to appreciate it
is best not to go there in the first place. <g>
-ralph
As usual, you persist to share your great (and much appreciated)
knowledge and wisdom. Fact is, I've heard this arg before but there was
never any convincing evidence presented to abondon implicit
instantiation in local scope. I actually don't practice this at
module/global levels because it just never sat 'right' with me to do
so. Thanks for sharing more details about the facts behind the args!
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Stuart McCall
2012-02-27 04:15:52 UTC
Permalink
Post by ralph
Post by Jim Mack
Post by Auric__
Post by Jim Mack
Post by Auric__
Dim duck As monster
Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above
2
lines.
For the purpose of this discussion, maybe. But "Dim As New" is frowned
on because it adds an implicit 'is nothing' check on every reference to
the object, and you lose control over the object lifetime.
Interesting. First I've heard of it (but then, I don't use VB very
much any more, and can't recall having ever used VB for "serious"
OOP).
Is this documented anywhere? Help file, MSDN, whatever?
The help files do mention it, but obliquely. What is said (from memory)
is that when you 'Dim As New' the object is not immediately created, as
it would be if you did a Dim followed by a Set = New, but rather is
instantiated on first reference.
The obvious question is, how does it know which is the first reference?
It knows that because _every_ reference contains a check to see if it's
been created yet -- the implicit 'is nothing' check I mentioned.
What follows from that is that you can't then legitimately test "If x
Is Nothing" yourself, because doing so references X, and so creates
it... that's how you lose (some) control over object lifetime.
I thought that the object created by "Dim As New" existed until the exit
from the scope they were created in. So...
In a procedure: (local scope)
Dim colItems As New Collection
..lives for the entire procedure if not explicitly destroyed beforhand.
... But you can not "explicitly" destroy the collection object.
You can clear the contents but never get rid of the object until the
object reference goes out of scope.
In a module: (module scope)
Dim colItems As New Collection
..lives for the duration code executes within the module if not
explicitly destroyed beforhand.
... but you can not "explicitly" destroy the collection object.
You can clear the contents, but you'll never be shed of the object
inside the module.
Dim colItems As New Collection
..lives for the entire runtime if not explicitly destroyed beforhand.
... but (you guessed it <g>) you can not "explicity" destroy the
collection object for the life of the program.
Also, I've created objects in this manner, tested them other than "If
colItems Is Nothing" via ways like "If colItems.Count > 0" so I know if
the created instance exists. Also, creating a new instance by using "If
colItems Is Nothing" doesn't cause any problems when you access its
items later, indicating VB is not at all confused about which 'instance'
you're referring to.
That is less an issue than all that extra code you have added to your
Application every single time you reference the object. Most of the
more serious consequences (e.g. memory leaks, circular references,
problems on Application exits, etc.) only present themselves in highly
specialized circumstances involving specific objects. Thus one can
probably program with the "As New" construct for years and never
notice a problem or bloat, however it only takes a few wasted hours on
tracking down a particular odd behavior of an object to appreciate it
is best not to go there in the first place. <g>
-ralph
As usual, you persist to share your great (and much appreciated) knowledge
and wisdom. Fact is, I've heard this arg before but there was never any
convincing evidence presented to abondon implicit instantiation in local
scope. I actually don't practice this at module/global levels because it
just never sat 'right' with me to do so. Thanks for sharing more details
about the facts behind the args!
--
Garry
Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
For instantiation in local scope, I tend to use the construct:

With New ClassName
.Property1 = <whatever>
.Method1
'etc
Variable = .Result
End With

No need for Dim, with or without As New.

(just thought I'd throw this into the mix to see what the group make of it)
ralph
2012-02-27 06:48:02 UTC
Permalink
On Mon, 27 Feb 2012 04:15:52 -0000, "Stuart McCall"
Post by Stuart McCall
With New ClassName
.Property1 = <whatever>
.Method1
'etc
Variable = .Result
End With
No need for Dim, with or without As New.
(just thought I'd throw this into the mix to see what the group make of it)
lol
Haven't seen that around here for a very long time.

I like the construct.

It is ideal for small business classes that do a simple conversion,
format, etc., then 'exit'. For it 'wraps' up all the 'required' setup
in one nice block. Makes it very clear what you are doing, and helps
to avoid accidental deletion during later code maintence.

I also like to use it as a kind of 'constructor' where you preferred
an initial setup/state for some attributes you already had properties
for, but not necessarily for all or any every time.

For example ...

' in one case
With New ClassName
.Property1 = <whatever>
.Property2 = <whatever>
End With
' in another ...
With New ClassName
.Property1 = value
.Property3 = value2
End With

... removed the need to write a separate multiple argument constructor
method that provided for optional arguments.

[Also occasionally providing a .ObjectReference method to the class in
case I needed to pass it out of the procedure it was created in.]

Unfortunately, I quickly discovered that not everyone shares my
opinion on the beauty of auto-instantiation. It seemed that no matter
what shop I went to there was always someone who, or in some cases an
entire team, that would rise up in horror. <g>

Forget the auto-instantiation for the moment, some shops absolutely
refuse to accept With statements.

So after getting tired of debating the subject, I sort of let the
habit just side by. <bg>

-ralph
Mayayana
2012-02-27 13:57:02 UTC
Permalink
| Unfortunately, I quickly discovered that not everyone shares my
| opinion on the beauty of auto-instantiation. It seemed that no matter
| what shop I went to there was always someone who, or in some cases an
| entire team, that would rise up in horror. <g>
|
It's a popular device in the VBScript group. A lot
of people like to do things like:

With CreateObject("Scripting.FileSystemObject").OpenTextFile

The appeal is that it's compact, which makes
it *seem* efficient. But by skipping the variable
there's no way to set to Nothing. So the technique
enforces the idea that one shouldn't bother to
pay atention to resources. The object creation is
just a time-consuming hassle that has to be squeezed
in there somewhere. It also makes code
difficult to read (and impossible for newcomers to
understand) when two or three separate operations
have been smashed together that way.
Stuart McCall
2012-02-27 19:19:45 UTC
Permalink
Post by Mayayana
| Unfortunately, I quickly discovered that not everyone shares my
| opinion on the beauty of auto-instantiation. It seemed that no matter
| what shop I went to there was always someone who, or in some cases an
| entire team, that would rise up in horror. <g>
|
It's a popular device in the VBScript group. A lot
With CreateObject("Scripting.FileSystemObject").OpenTextFile
Ugh. I could never bring myself to do that, especially not with the fso.
Post by Mayayana
The appeal is that it's compact, which makes
it *seem* efficient. But by skipping the variable
there's no way to set to Nothing. So the technique
enforces the idea that one shouldn't bother to
pay atention to resources. The object creation is
just a time-consuming hassle that has to be squeezed
in there somewhere. It also makes code
difficult to read (and impossible for newcomers to
understand) when two or three separate operations
have been smashed together that way.
I agree. However, the use I mentioned can be far _more_ readable IMO. I
wouldn't recommend it's use to anyone, but it suits me perfectly under
certain circumstances.

Thanks for your comments.
Stuart McCall
2012-02-27 19:12:21 UTC
Permalink
Post by ralph
On Mon, 27 Feb 2012 04:15:52 -0000, "Stuart McCall"
Post by Stuart McCall
With New ClassName
.Property1 = <whatever>
.Method1
'etc
Variable = .Result
End With
No need for Dim, with or without As New.
(just thought I'd throw this into the mix to see what the group make of it)
lol
Haven't seen that around here for a very long time.
I like the construct.
It is ideal for small business classes that do a simple conversion,
format, etc., then 'exit'. For it 'wraps' up all the 'required' setup
in one nice block. Makes it very clear what you are doing, and helps
to avoid accidental deletion during later code maintence.
I only use it for specific purposes, such as avoiding long lists of
parameters in a function call, and only when I'm sure no errors will be
thrown (jumping out of a with block isn't such a good idea). I didn't
consider the code maintenance angle, but it's worth bearing in mind.
Post by ralph
I also like to use it as a kind of 'constructor' where you preferred
an initial setup/state for some attributes you already had properties
for, but not necessarily for all or any every time.
For example ...
' in one case
With New ClassName
.Property1 = <whatever>
.Property2 = <whatever>
End With
' in another ...
With New ClassName
.Property1 = value
.Property3 = value2
End With
... removed the need to write a separate multiple argument constructor
method that provided for optional arguments.
[Also occasionally providing a .ObjectReference method to the class in
case I needed to pass it out of the procedure it was created in.]
Unfortunately, I quickly discovered that not everyone shares my
opinion on the beauty of auto-instantiation. It seemed that no matter
what shop I went to there was always someone who, or in some cases an
entire team, that would rise up in horror. <g>
Forget the auto-instantiation for the moment, some shops absolutely
refuse to accept With statements.
So after getting tired of debating the subject, I sort of let the
habit just side by. <bg>
I never worked that way. Always coded alone (I retired in '06 - purely a
hobbyist now)

Thanks for your comments.
Post by ralph
-ralph
Bob Butler
2012-02-27 14:06:04 UTC
Permalink
Post by Stuart McCall
With New ClassName
.Property1 = <whatever>
.Method1
'etc
Variable = .Result
End With
No need for Dim, with or without As New.
(just thought I'd throw this into the mix to see what the group make of it)
I use it in some limited cases. The only caution I have is that you have to
be careful of issues that can leave you with orphaned objects.

In Class1:
Private Sub Class_Initialize()
MsgBox "init class"
End Sub

Private Sub Class_Terminate()
MsgBox "term class"
End Sub

Public Sub DoSomething()
Dim x As Long
x = 1 / 0
End Sub

In Module1:
Sub Main()
On Error GoTo eh
With New Class1
.DoSomething
End With
eh:
MsgBox "at error handler"
End Sub

The error handler jumps over the 'End With' without releasing the object.
It has local scope so it goes away when the procedure ends but depending on
your logic that might not happen right away. The same thing can happen in
other ways:

Sub Main()
Dim x As Long
For x = 1 To 10
With New Class1
Exit For
End With
Next
MsgBox "post loop"
End Sub

If code like the above is inside another loop you could end up with multiple
orphans and if the logic doesn't allow the procedure to end they will live
until it does. As long as you are sure that nothing will prevent the code
from hitting the 'End With' statement it can be a useful consruct. On the
other hand it doesn't really save anything over declaring an object variable
and setting it explicitly since that's what happens implicitly anyway.
Stuart McCall
2012-02-27 19:24:15 UTC
Permalink
Post by Bob Butler
Post by Stuart McCall
With New ClassName
.Property1 = <whatever>
.Method1
'etc
Variable = .Result
End With
No need for Dim, with or without As New.
(just thought I'd throw this into the mix to see what the group make of it)
I use it in some limited cases. The only caution I have is that you have
to be careful of issues that can leave you with orphaned objects.
Private Sub Class_Initialize()
MsgBox "init class"
End Sub
Private Sub Class_Terminate()
MsgBox "term class"
End Sub
Public Sub DoSomething()
Dim x As Long
x = 1 / 0
End Sub
Sub Main()
On Error GoTo eh
With New Class1
.DoSomething
End With
MsgBox "at error handler"
End Sub
The error handler jumps over the 'End With' without releasing the object.
It has local scope so it goes away when the procedure ends but depending
on your logic that might not happen right away. The same thing can happen
Sub Main()
Dim x As Long
For x = 1 To 10
With New Class1
Exit For
End With
Next
MsgBox "post loop"
End Sub
If code like the above is inside another loop you could end up with
multiple orphans and if the logic doesn't allow the procedure to end they
will live until it does. As long as you are sure that nothing will
prevent the code from hitting the 'End With' statement it can be a useful
consruct. On the other hand it doesn't really save anything over
declaring an object variable and setting it explicitly since that's what
happens implicitly anyway.
I agree with all of the above. As I mentioned elsewhere, I only use it when
I'm reasonably sure no errors will occur. The main attraction for me is
readability.

Thanks for your comments.
GS
2012-02-27 16:01:34 UTC
Permalink
Post by Stuart McCall
With New ClassName
.Property1 = <whatever>
.Method1
'etc
Variable = .Result
End With
No need for Dim, with or without As New.
(just thought I'd throw this into the mix to see what the group make of it)
Interesting that you should post this now! I was just thinking to
revise my FilterMatches function to do similar so it avoids multiple
refs to a collection inside a loop. After reading the replies on your
post from others I'm incline to forge ahead. I use implicit
instantiation for 2 collections outside a loop and was thinking it
would be better to eliminate the multiple refs as follows...

Existing code:

Dim cItemsToCheck As New Collection: On Error Resume Next
For i = LBound(vCheckRng) To UBound(vCheckRng)
cItemsToCheck.Add key:=CStr(vCheckRng(i, 1)), Item:=vbNullString
Next 'i
Err.Clear
'Check the Collection for matches
On Error GoTo MatchFound
For i = LBound(vFilterRng) To UBound(vFilterRng)
bMatch = False '..reset
cItemsToCheck.Add key:=CStr(vFilterRng(i, 1)), Item:=vbNullString
If bMatch Then
If bReturnMatches Then vaMatches(j) = vFilterRng(i, 1)
j = j + 1
Else
vaNoMatches(j) = vFilterRng(i, 1): j = j + 1
cItemsToCheck.Remove CStr(vFilterRng(i, 1)) '..don't count
dupes
End If 'bMatch
Next 'i

Intended change:

On Error Resume Next
With New Collection
For i = LBound(vCheckRng) To UBound(vCheckRng)
.Add key:=CStr(vCheckRng(i, 1)), Item:=vbNullString
Next 'i
Err.Clear

'Check the Collection for matches
On Error GoTo MatchFound
For i = LBound(vFilterRng) To UBound(vFilterRng)
bMatch = False '..reset
.Add key:=CStr(vFilterRng(i, 1)), Item:=vbNullString
If bMatch Then
If bReturnMatches Then vaMatches(j) = vFilterRng(i, 1)
j = j + 1
Else
vaNoMatches(j) = vFilterRng(i, 1): j = j + 1
.Remove CStr(vFilterRng(i, 1)) '..so dupes don't get counted
End If 'bMatch
Next 'i
End With 'New Collection

Unfortunately, there was no apparent performance improvement as the
function took the same amount of time to process for each of the 4
possible results. I invite comments...
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
ralph
2012-02-27 17:07:52 UTC
Permalink
Post by GS
Post by Stuart McCall
With New ClassName
.Property1 = <whatever>
.Method1
'etc
Variable = .Result
End With
No need for Dim, with or without As New.
(just thought I'd throw this into the mix to see what the group make of it)
Interesting that you should post this now! I was just thinking to
revise my FilterMatches function to do similar so it avoids multiple
refs to a collection inside a loop. After reading the replies on your
post from others I'm incline to forge ahead. I use implicit
instantiation for 2 collections outside a loop and was thinking it
would be better to eliminate the multiple refs as follows...
/snip
Unfortunately, there was no apparent performance improvement as the
function took the same amount of time to process for each of the 4
possible results. I invite comments...
The "With ... End With" statement doesn't "eliminate" much of anything
except extra typing, and to provide a code 'block' to improve, IMHO,
clarity and readability.

-ralph
GS
2012-02-27 18:10:31 UTC
Permalink
Post by ralph
Post by GS
Post by Stuart McCall
With New ClassName
.Property1 = <whatever>
.Method1
'etc
Variable = .Result
End With
No need for Dim, with or without As New.
(just thought I'd throw this into the mix to see what the group make of it)
Interesting that you should post this now! I was just thinking to
revise my FilterMatches function to do similar so it avoids multiple
refs to a collection inside a loop. After reading the replies on your
post from others I'm incline to forge ahead. I use implicit
instantiation for 2 collections outside a loop and was thinking it
would be better to eliminate the multiple refs as follows...
/snip
Unfortunately, there was no apparent performance improvement as the
function took the same amount of time to process for each of the 4
possible results. I invite comments...
The "With ... End With" statement doesn't "eliminate" much of anything
except extra typing, and to provide a code 'block' to improve, IMHO,
clarity and readability.
-ralph
It was my hope to eliminate the 500,000 refs to cItemsToCheck but
apparently the refs are made in this case anyway. I'll see if using
'explicit' declaration makes any diff...
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Schmidt
2012-02-27 18:09:34 UTC
Permalink
Post by GS
Unfortunately, there was no apparent performance improvement as the
function took the same amount of time to process for each of the 4
possible results. I invite comments...
I think the routine as it is (based on VB(A).Collections)
cannot be improved much more (maybe by 10-15% or so ...).

And since you're running in PCode whilst working in VBA,
there's also not much to improve, by implementing your
own "lightweight, specialized Array-BinarySort-stuff",
which only makes sense when you can native compile in VB6.
With your own, selfimplemented fast "Exists-Checks-Hash-
Class" (in a VB6-Dll) you could go a bit faster
(at the cost of a Dll-dependency in the VBA-environment).


Since I know, that you make use of the RichClient-stuff -
(and if the Dll-dependency topic is a "no-issue" on your
end) then you could also make use of an already implemented
"fast, Keyed-Access-Container" from this lib (cSortedDictionary).

Here's some Code, which works about 3 times as fast
as your code (I have only XL-2000 with a 65536-Row-Limit)
and this ratio should get better with more Items in the Compare-
List, since I know, that the cSortedDictionary scales nearly
linearly with higher ItemCounts - whereas the VB.Collection
does not (it get's "overproportionally slower with more items
to hash within).

To be able to test this also in VB6, I've changed the
Param-Structure to my needs - but maybe you find my
changes useful too (I give VArr() params directly
into the Procedure - as well as two new Enum-Params.

This is my "Excel-Button"-click Event, which triggers
the whole thing here on my VM (just that you see, that
everything is "yet there" <g>...

Private Sub cmdCompare2_Click()
Dim T!, Matches As Long
Dim vFiltrRange(): vFiltrRange = Range("A1:A50000")
Dim vCheckRange(): vCheckRange = Range("B1:B50000")
T = Timer

Matches = FilterMatches2(vFiltrRange, vCheckRange, "D", _
Abs(Not chkReturnMatches), chkDupesAllowed)

txtTiming.Text = Timer - T
txtReport.Text = Matches
End Sub


Ok - here the Code - please let me know how it performs with
500000 items on your end - and if everything was understood
correctly by me (regarding your intentions with the generated OutPut).


'***** Into a normal VB(A)-Module *****
Option Explicit

Public Enum FilterMode
fltReturnMatches
fltReturnNonMatches
End Enum

Public Enum ExpectedTypes
UseStringComparison
UseIntegerComparisons
UseDoubleComparisons
End Enum

'Returns Count of found Matches or NonMatches (accord. to the Mode-Enum)
'One can achieve additional speedup, when the "Types are known" - e.g.
'when both Compare-Ranges consist "only of Doubles" - or alternatively
'are made up completely from LongInt or Currency-Types - then the
'Default-Method (UseStringComparison, see last Param) can be overridden
Function FilterMatches2&(vFilterRng(), vCheckRng(), _
Optional OutColName As String, _
Optional ByVal Mode As FilterMode, _
Optional ByVal DupesAllowed As Boolean, _
Optional ByVal TypeComparison As ExpectedTypes)

Dim DCheck As cSortedDictionary, DDupes As cSortedDictionary
Dim i As Long, Key, Match As Boolean, Results(), ResCount As Long, Out()

Set DCheck = New cSortedDictionary
DCheck.StringCompareMode = TextCompare
Set DDupes = New cSortedDictionary
DDupes.StringCompareMode = TextCompare

For i = LBound(vCheckRng) To UBound(vCheckRng)
Select Case TypeComparison
Case UseStringComparison: Key = CStr(vCheckRng(i, 1))
Case UseIntegerComparisons: Key = CCur(vCheckRng(i, 1))
Case UseDoubleComparisons: Key = CDbl(vCheckRng(i, 1))
End Select
If Not DCheck.Exists(Key) Then DCheck.Add Key
Next i

If DCheck.Count = 0 Then Exit Function

ReDim Results(1 To DCheck.Count)

For i = LBound(vFilterRng) To UBound(vFilterRng)
Select Case TypeComparison
Case UseStringComparison: Key = CStr(vFilterRng(i, 1))
Case UseIntegerComparisons: Key = CCur(vFilterRng(i, 1))
Case UseDoubleComparisons: Key = CDbl(vFilterRng(i, 1))
End Select
Match = DCheck.Exists(Key)

If Match And Mode = fltReturnMatches Then
If Not DupesAllowed Then DCheck.Remove Key
ResCount = ResCount + 1: Results(ResCount) = vFilterRng(i, 1)
ElseIf Not Match And Mode = fltReturnNonMatches Then
If DupesAllowed Then
ResCount = ResCount + 1: Results(ResCount)=vFilterRng(i, 1)
ElseIf Not DDupes.Exists(Key) Then
DDupes.Add Key
ResCount = ResCount + 1: Results(ResCount)=vFilterRng(i, 1)
End If
End If
Next i

If ResCount = 0 Or Len(OutColName) = 0 Then Exit Function

ReDim Out(1 To ResCount, 1 To 1)
For i = 1 To ResCount: Out(i, 1) = Results(i): Next i 'copy over

'**only the following block needs to be commed out to test in VB6**
Columns(OutColName).ClearContents
With Range(OutColName & "1").Resize(ResCount, 1)
.Value = Out
.NumberFormat = "0000000000000" '..optional
.EntireColumn.AutoFit '..optional
End With
'************ End of the Excel/VBA-related code-block *************

FilterMatches2 = ResCount
End Function

Olaf
GS
2012-02-27 18:29:06 UTC
Permalink
Wow! Thanks, Olaf!!!

I will try your code and let you know the results. Note that I do not
exit the function if OutColName = 0 because I default to using the
column being filtered for where the results go because this is a
typical requirement when filtering dupes in a list. (Occasionally, a
user may want to retain the original list and put the results
elsewhere)
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
GS
2012-02-27 19:43:53 UTC
Permalink
Ok, Olaf:
Your code does the job considerably faster (25% to 33%) but tested on
the same lists it returns different results. Here's my criteria...

Option1:
Return a unique list of matches found (no dupes)

Option2:
Return a list of all matches found

Option3:
Return a unique list of non-matches (no dupes)

Option4:
Return a list of all non-matches

I will run both functions in xl2003 so I can pass you a file that you
can test drive yourself...
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Schmidt
2012-02-27 21:14:53 UTC
Permalink
Post by GS
Your code does the job considerably faster (25% to 33%) but tested on
the same lists it returns different results. Here's my criteria...
Return a unique list of matches found (no dupes)
Return a list of all matches found
Return a unique list of non-matches (no dupes)
Return a list of all non-matches
I will run both functions in xl2003 so I can pass you a file that you
can test drive yourself...
Better to test that with a small dataset, which is
able to show the differences already:

Here's my two lists (only 10 Rows in each XL-Column):
A and B (as FilterList and CheckList)
---------------------------------------
a 1
b 2
a 3
b 4
x 5
1 a
2 a
3 c
4 d
6 x
---------------------------------------

---------------------------------------
Option 1: Return a unique list of matches found (no dupes)
(the left result-column is yours, the right one mine respectively):
a a
x x
1 1
2 2
3
4
Our Reported Matchcount for Option1:
11 6
---------------------------------------

---------------------------------------
Option2: (Matches incl. Dupes) is identically
a
a
x
1
2
3
4
Also the reported MatchCount is the same: 7
---------------------------------------


---------------------------------------
Option3: Return a unique list of non-matches (no dupes)
Our listing is identically:
b
6
But your MatchCount seems incorrect
(I reported the NonMatch-Count - maybe I should report it as (10-2)?)
15 2
---------------------------------------


---------------------------------------
Option4: Return a list of all non-matches
Listings are identically again:
b
b
6
But the MatchCount seems screwed once more:
7 3
---------------------------------------


Maybe I've copied the wrong version of your code -
but it was the one, which you said, you already
placed a fix in.

Oh - and there's also a bug to fix in my routine <g>...
(although not affecting the results - it only ran
out of indexes due to a too optimistic ArrResult-Redim
in case of huge empty-cell-areas.

It's in the Redim Results(...) line, which needs to be changed to:
ReDim Results(1 To IIf(DupesAllowed, UBound(vCheckRng), DCheck.Count))


Just for completeness, I post the entire fixed routine again now
(followed by the version of your routine I've made my comparison with):

Option Explicit

Public Enum FilterMode
fltReturnMatches
fltReturnNonMatches
End Enum

Public Enum ExpectedTypes
UseStringComparison
UseIntegerComparisons
UseDoubleComparisons
End Enum

'Returns the Count of found Matches or NonMatches (dep. on the Mode-Enum)
Function FilterMatches2&(vFilterRng(), vCheckRng(), _
Optional OutColName As String, _
Optional ByVal Mode As FilterMode, _
Optional ByVal DupesAllowed As Boolean, _
Optional ByVal TypeComparison As ExpectedTypes)

Dim DCheck As cSortedDictionary, DDupes As cSortedDictionary
Dim i As Long, Key, Match As Boolean, Results(), ResCount As Long, Out()

Set DCheck = New cSortedDictionary
DCheck.StringCompareMode = TextCompare
Set DDupes = New cSortedDictionary
DDupes.StringCompareMode = TextCompare

For i = LBound(vCheckRng) To UBound(vCheckRng)
Select Case TypeComparison
Case UseStringComparison: Key = CStr(vCheckRng(i, 1))
Case UseIntegerComparisons: Key = CCur(vCheckRng(i, 1))
Case UseDoubleComparisons: Key = CDbl(vCheckRng(i, 1))
End Select
If Not DCheck.Exists(Key) Then DCheck.Add Key
Next i

If DCheck.Count = 0 Then Exit Function

ReDim Results(1To IIf(DupesAllowed,UBound(vCheckRng),DCheck.Count))

For i = LBound(vFilterRng) To UBound(vFilterRng)
Select Case TypeComparison
Case UseStringComparison: Key = CStr(vFilterRng(i, 1))
Case UseIntegerComparisons: Key = CCur(vFilterRng(i, 1))
Case UseDoubleComparisons: Key = CDbl(vFilterRng(i, 1))
End Select
Match = DCheck.Exists(Key)

If Match And Mode = fltReturnMatches Then
If Not DupesAllowed Then DCheck.Remove Key
ResCount = ResCount + 1: Results(ResCount) = vFilterRng(i, 1)
ElseIf Not Match And Mode = fltReturnNonMatches Then
If DupesAllowed Then
ResCount = ResCount + 1:Results(ResCount) = vFilterRng(i, 1)
ElseIf Not DDupes.Exists(Key) Then
DDupes.Add Key
ResCount = ResCount + 1:Results(ResCount) = vFilterRng(i, 1)
End If
End If
Next i

If ResCount = 0 Or Len(OutColName) = 0 Then Exit Function

ReDim Out(1 To ResCount, 1 To 1)
For i = 1 To ResCount: Out(i, 1) = Results(i): Next i 'copy over

'**only the following block needs to be commed out to test in VB6**
Columns(OutColName).ClearContents
With Range(OutColName & "1").Resize(ResCount, 1)
.Value = Out
.NumberFormat = "0000000000000" '..optional
.EntireColumn.AutoFit '..optional
End With
'************ End of the Excel/VBA-related code-block *************

FilterMatches2 = ResCount
End Function





Function FilterMatches(Matches As Long,Criteria() As Variant) As Boolean
' Compares 2 user-specified cols and filters matches found.
' User can also specific target col to receive resulting list.
' Optionally supports returning a unique list or allow duplicates.
' Optionally supports returning matches or non-matches.
'
' Args In: Matches: ByRef var to return number of matches found
'to the caller.
'
' vCriteria(): A variant array containing the filtering
' parameters.
' Criteria(0) - Address of the values to be filtered
' Criteria(1) - Address of the values to check
' Criteria(2) - Label of the column to put the filtered
' list
' Criteria(3) - Numeric value to determine if we return
' matches or non-matches
' Criteria(4) - Numeric value to determine if we return
' a unique list or allow dupes
'
' Returns: True if matches found and no error occurs;
' False if a: matches not found --OR-- error occurs;

Dim i&, j& 'as long
Dim vFilterRng, vCheckRng, vResult, vaMatches(), vaNoMatches()
Dim vaDataOut() 'as variant
Dim bReturnMatches As Boolean, bMatch As Boolean
Dim bDupesAllowed As Boolean
Dim sMsg$, sRngOut$ 'as string

'Load the filtering criteria
vFilterRng = Range(Criteria(0)):
vCheckRng = Range(Criteria(1)): sRngOut = Criteria(2)
bReturnMatches = (Criteria(3) = 1): bDupesAllowed = (Criteria(4) = 1)
ReDim vaMatches(UBound(vFilterRng)):
ReDim vaNoMatches(UBound(vFilterRng)):j = 0

'Load the Collection with the values to be checked.
'Collections only allow unique keys so use OERN (no need to check
'if they already exist)
Dim cItemsToCheck As New Collection: On Error Resume Next
For i = LBound(vCheckRng) To UBound(vCheckRng)
cItemsToCheck.Add Key:=CStr(vCheckRng(i, 1)), Item:=vbNullString
Next 'i
Err.Clear

'Check the Collection for matches
On Error GoTo MatchFound
For i = LBound(vFilterRng) To UBound(vFilterRng)
bMatch = False '..reset
cItemsToCheck.Add Key:=CStr(vFilterRng(i, 1)), Item:=vbNullString
If bMatch Then
If bReturnMatches Then vaMatches(j) = vFilterRng(i, 1): j = j + 1
Else
vaNoMatches(j) = vFilterRng(i, 1): j = j + 1
cItemsToCheck.Remove CStr(vFilterRng(i,1)) '..so dupes of it
'don't get counted
End If 'bMatch
Next 'i

'Initialize the return list
If bReturnMatches Then vResult = vaMatches Else vResult = vaNoMatches

'Return a list of unique values?
If Not bDupesAllowed Then
On Error GoTo UniqueList
Dim cUniqueList As New Collection
For i = LBound(vResult) To UBound(vResult)
cUniqueList.Add Key:=CStr(vResult(i)), Item:=vbNullString
Next 'i
ReDim vaDataOut(cUniqueList.Count - 1, 0): j = 0
Else
ReDim vaDataOut(UBound(vResult), 0): j = 0
End If 'Not bDupesAllowed
Err.Clear: On Error GoTo ErrExit

'Make the list to return contiguous.
For i = LBound(vaDataOut) To UBound(vaDataOut)
If Not vResult(i) = Empty Then vaDataOut(j, 0) = vResult(i):j = j + 1
Next 'i

If Matches > 0 Then '..only write if Matches > 0
Columns(sRngOut).ClearContents
With Range(sRngOut & "1").Resize(UBound(vaDataOut) + 1, 1)
.Value = vaDataOut
.NumberFormat = "0000000000000" '..optional
.EntireColumn.AutoFit '..optional
End With
End If 'Matches > 0


ErrExit:
' If bReturnMatches Then Matches = UBound(vResult) ' + 1
FilterMatches = (Err = 0): Exit Function

MatchFound:
bMatch = True: Matches = Matches + 1: Resume Next

UniqueList:
vResult(i) = Empty: Matches = Matches + 1: Resume Next

End Function 'FilterMatches()


Olaf
GS
2012-02-27 21:45:34 UTC
Permalink
Olaf,
Yes, you have the correct version of my function.

I don't think a smaller list is going to reveal anything more clearly,
but it would certainly make results more immediately obvious.

Where I'm getting different results from your version is in grabbing
the unique values. I'm coming up short of your lists for unique [non-]
matches. Looking further into this I found unique items in your
returned lists that my unique lists did not include. Examining the
difference between your IF constructs inside the 2nd loop reveals why
my function is in error and so I will try to fix it before sending you
a file.

At the end of the day your cSortedDictionary is much faster! Is there a
way to use the class outside of dhRichClient so there's no dependancy?
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
GS
2012-02-27 23:23:58 UTC
Permalink
Ok, my Option1 isn't returning a correct list. All the others return
same results as your function with the exception of the match counts as
you noted.

My function counts dupes when reporting matches found for both no dupes
Options.

Your 2nd loop includes matches, non-matches, dupes, no-dupes. I broke
this out into a [non]matches loop, and a [no]dupes loop purely for
understanding the processes. I'm thinking my error is in the [no]dupes
loop matches calc.

Looking back in history, a previous version used Dictionary and it took
considerably more time than using Collection. I'm curious as to how you
get Dictionary to work so fast!
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
GS
2012-02-28 04:26:25 UTC
Permalink
Ok, Olaf!
I fixed my Option1/3 so it now returns identical to your function in
all 4 cases. I simply reverted back to using vResult() for building
vaDataOut().

It's still much slower than your function and so I'm really hoping your
cSortedDictionary can be used separately from dhRichClient!<bg><g><rbg>
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Schmidt
2012-02-28 12:54:40 UTC
Permalink
Post by GS
Ok, Olaf!
I fixed my Option1/3 so it now returns identical to your function in all
4 cases. I simply reverted back to using vResult() for building
vaDataOut().
It's still much slower than your function and so I'm really hoping your
cSortedDictionary can be used separately from dhRichClient!<bg><g><rbg>
Do you mean, in "pure code" or as a standalone-Dll?

As already mentioned - in pure code (for easier, dependency-free
usage in a VBA-class) it would surely be slower than the
VB.Collection (it needs to be compiled to native code to be fast).

About providing the cSortedDictionary in a standalone-Dll we
could talk - but there already *is* one (though a bit older)
version of the cSortedDictionary, downloadable here:
http://www.datenhaus.de/Downloads/dhSortedDictionary.zip
which can be used as a direct replacement for the
Class in the RichClient (no need to change any code
in the comparison-routine - running at the same (if not
a bit better) performance then.


Olaf
GS
2012-02-28 13:37:22 UTC
Permalink
Post by Schmidt
Post by GS
Ok, Olaf!
I fixed my Option1/3 so it now returns identical to your function in all
4 cases. I simply reverted back to using vResult() for building
vaDataOut().
It's still much slower than your function and so I'm really hoping your
cSortedDictionary can be used separately from dhRichClient!<bg><g><rbg>
Do you mean, in "pure code" or as a standalone-Dll?
As already mentioned - in pure code (for easier, dependency-free
usage in a VBA-class) it would surely be slower than the
VB.Collection (it needs to be compiled to native code to be fast).
About providing the cSortedDictionary in a standalone-Dll we
could talk - but there already *is* one (though a bit older)
http://www.datenhaus.de/Downloads/dhSortedDictionary.zip
which can be used as a direct replacement for the
Class in the RichClient (no need to change any code
in the comparison-routine - running at the same (if not
a bit better) performance then.
Olaf
Thanks, Olaf! I can live with the speed of my function 'as is', but for
larger amounts of data it would be nice to use your code with a DLL.
The wrench in the works is that this will commonly be used with VBA,
and so is why I went with a Collection. If I had a DLL then I could
carry it around on a memstick and use it wherever. Of course, on my
main machine I have dhRichClient and so no need for a separate DLL.
It's unfortunate that VBA requires external COMs be registered!

BTW, I changed my counting strategy from 'found matches' to 'items
returned' and it now matches your in every way except speed. Hands
down, yours is 2-3 times faster.

Thanks so much for your time and effort! Very appreciated...
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
ralph
2012-02-28 15:19:34 UTC
Permalink
Post by GS
Post by Schmidt
Post by GS
Ok, Olaf!
I fixed my Option1/3 so it now returns identical to your function in all
4 cases. I simply reverted back to using vResult() for building
vaDataOut().
It's still much slower than your function and so I'm really hoping your
cSortedDictionary can be used separately from dhRichClient!<bg><g><rbg>
Do you mean, in "pure code" or as a standalone-Dll?
As already mentioned - in pure code (for easier, dependency-free
usage in a VBA-class) it would surely be slower than the
VB.Collection (it needs to be compiled to native code to be fast).
About providing the cSortedDictionary in a standalone-Dll we
could talk - but there already *is* one (though a bit older)
http://www.datenhaus.de/Downloads/dhSortedDictionary.zip
which can be used as a direct replacement for the
Class in the RichClient (no need to change any code
in the comparison-routine - running at the same (if not
a bit better) performance then.
Olaf
Thanks, Olaf! I can live with the speed of my function 'as is', but for
larger amounts of data it would be nice to use your code with a DLL.
The wrench in the works is that this will commonly be used with VBA,
and so is why I went with a Collection. If I had a DLL then I could
carry it around on a memstick and use it wherever. Of course, on my
main machine I have dhRichClient and so no need for a separate DLL.
It's unfortunate that VBA requires external COMs be registered!
BTW, I changed my counting strategy from 'found matches' to 'items
returned' and it now matches your in every way except speed. Hands
down, yours is 2-3 times faster.
Thanks so much for your time and effort! Very appreciated...
Probably not as fast as Olaf's, but consider that the Scripting
Library Dictionary is usually much faster than the VB/VBA Collection.

-ralph
GS
2012-02-28 15:42:26 UTC
Permalink
Post by ralph
Post by GS
Post by Schmidt
Post by GS
Ok, Olaf!
I fixed my Option1/3 so it now returns identical to your function in all
4 cases. I simply reverted back to using vResult() for building
vaDataOut().
It's still much slower than your function and so I'm really hoping your
cSortedDictionary can be used separately from dhRichClient!<bg><g><rbg>
Do you mean, in "pure code" or as a standalone-Dll?
As already mentioned - in pure code (for easier, dependency-free
usage in a VBA-class) it would surely be slower than the
VB.Collection (it needs to be compiled to native code to be fast).
About providing the cSortedDictionary in a standalone-Dll we
could talk - but there already *is* one (though a bit older)
http://www.datenhaus.de/Downloads/dhSortedDictionary.zip
which can be used as a direct replacement for the
Class in the RichClient (no need to change any code
in the comparison-routine - running at the same (if not
a bit better) performance then.
Olaf
Thanks, Olaf! I can live with the speed of my function 'as is', but for
larger amounts of data it would be nice to use your code with a DLL.
The wrench in the works is that this will commonly be used with VBA,
and so is why I went with a Collection. If I had a DLL then I could
carry it around on a memstick and use it wherever. Of course, on my
main machine I have dhRichClient and so no need for a separate DLL.
It's unfortunate that VBA requires external COMs be registered!
BTW, I changed my counting strategy from 'found matches' to 'items
returned' and it now matches your in every way except speed. Hands
down, yours is 2-3 times faster.
Thanks so much for your time and effort! Very appreciated...
Probably not as fast as Olaf's, but consider that the Scripting
Library Dictionary is usually much faster than the VB/VBA Collection.
-ralph
Actually, the early VBA versions of my function used that approach and
was discarded because the VB.Collection performed almost 25% better.

Olaf's dhSortDictionary.dll is a tad faster than dhRichClient, or so it
seems looking at elapsed times for processing 4 return options!<g>
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Schmidt
2012-02-29 05:47:15 UTC
Permalink
Post by GS
I can live with the speed of my function 'as is', but for
larger amounts of data it would be nice to use your code with a DLL.
The wrench in the works is that this will commonly be used with VBA,
and so is why I went with a Collection. If I had a DLL then I could
carry it around on a memstick and use it wherever. Of course, on my
main machine I have dhRichClient and so no need for a separate DLL.
It's unfortunate that VBA requires external COMs be registered!
Hah - and so we finally found a good use-case for DirectCOM.dll
on your side <g>.

Please check the following out - it is using a "two-step-approach"
(sounds already complicated, but is not... ;-))

First, we have to move everything that needs speed - into
a separate VB-Dll-Project - in practise that means:
The compare-routine (without the XL-Range-stuff which
writes the results into the OutColumn - instead a vOut()
VariantArray is returned "ByRef")...

Then, only there, within this small ActiveX-Dll (which I named
MyWrapper.dll, having only a small Class, named: cMyClass),
there's a reference to dhSortedDictionary (the smaller,
a bit faster version of the RC-based cSortedDictionary).

Within this new VB6-Dll we now only need to ensure, that
the externally referenced Class (cSortedDictionary
from dhSortedDictionary.dll) is created regfree per
DirectCOM (one normal Dll-Declare - one Call with the
correct Path and we're done).

That's it already on the VB6-end (the VB6-Code for
MyWrapper.dll is included in the Zip).

So now we have an ActiveX-Dll, which creates its
external Helper (cSortedDictionary) already regfree
and also contains the fast Compare-Routine, which
we now were able to compile even to native code.

Now XL comes into play - which will work only with
your new Wrapper cMyClass and will not know anything
about any sorting Dictionaries - these are already
"encapsulated out of the way".

So what remains is (to complete the regfree-hierarchy,
and my above mentioned "two steps"), to create your
cMyClass regfree also in XL ... *and* latebound (As Object),
so that XL not even knows (and gets confused by) the
Interface-Reference of your cMyWrapper.dll.

Here's the DirectCOM related code-part which ensures
the regfree Loading/Instancing:

'*** In a VBA-Module
Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" _
(ByVal lpLibFileName As String) As Long
Declare Function GetInstance Lib "DirectCom" Alias "GETINSTANCE" _
(FName As String, ClassName As String) As Object

Function CreateWrapperInstanceRegFree(ByVal WorkBookPath As String)
Static hLib As Long
If Right$(WorkBookPath, 1) <> "\" Then WorkBookPath = WorkBookPath & "\"

'preload DirectCOM.Dll (only once) into the Excel-Process
If hLib = 0 Then hLib = LoadLibrary(WorkBookPath & "DirectCOM.dll")

Set CreateWrapperInstanceRegFree = GetInstance(WorkBookPath & _
"MyWrapper.dll", "cMyClass")
End Function


And this is the hollowed out Original VBA-Function, which
now delegates the main-task to your Wrapper-Class:

Function FilterMatches2&(vFilterRng(), vCheckRng(), _
OutColumnName As String, _
Optional ByVal Mode As FilterMode, _
Optional ByVal DupesAllowed As Boolean, _
Optional ByVal TypeComparison As ExpectedTypes)

Dim Wrp As Object, vOut()
'this instantiates cMyClass (a VB6-Compiled Wrapper)
Set Wrp = CreateWrapperInstanceRegFree(Application.ActiveWorkbook.Path)

FilterMatches2=Wrp.FilterMatches2(vFilterRng,vCheckRng,vOut, Mode, _
DupesAllowed, TypeComparison)

Columns(OutColumnName).ClearContents

If FilterMatches2 > 0 Then
With Range(OutColumnName & "1").Resize(FilterMatches2, 1)
.Value = vOut
.NumberFormat = "0000000000000" '..optional
.EntireColumn.AutoFit '..optional
End With
End If
End Function

Please check it out - here's a complete example
including a MatchTest.xls with a 50000er test-set.
www.datenhaus.de/Downloads/XLRegFreeCOM.zip

Olaf
GS
2012-02-29 14:39:15 UTC
Permalink
Wow! This is awesome.., thanks sooo much!

I will check it out and get back to you later today. (Just so you know
time diff, I'm located in Ontario Canada)
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
GS
2012-02-29 18:33:39 UTC
Permalink
Hah - and so you finally proved a good use-case for using DirectCOM.dll
for reg-free VBA!<g> Well done. I have yet to check out the vbp source
but I'm going to do that later today.

Olaf, this changes my entire approach in several ways. Thank you, thank
you, thank you...
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
GS
2012-02-29 19:43:42 UTC
Permalink
OT:
Olaf,
It now occurs to me why I erroneously referred to DirectCOM.dll as
"CommonCOM.dll". Before getting involved with your dhRichClient I was
using the name "DirectCOM.dll" for my Excel COMAddins, and so I renamed
them "CommonCOM" to avoid problems. Thus, the erroneous association to
your dhRichClient component.<g>
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Schmidt
2012-02-29 20:39:45 UTC
Permalink
Am 29.02.2012 19:33, schrieb GS:

[regfree usage of COM-Dlls in VBA using DirectCOM.dll]
Post by GS
Olaf, this changes my entire approach in several ways.
Yep, I know that there's already many XL-VBA-users, which do
use (mostly) the SQLite-wrapper from the RichClient-lib
(some of them also doing that regfree).

...often for InMemory-DBs, to massage Data per SQL - and
then they use the SQLite-Recordsets Rs.GetRows(...) to
put the Results of "Selects" out in a fast and convenient
way, back into XL-Ranges.


If you want to try that out, you will have to put the
RichClient-Dll as well as its companion-SQLite-Dll into
the same WorkBookPath (for example into the path which
already contains the example I've posted a link to before).

Then please change the modDirectCOM-Modules content
to a more "sophisticated" version which now should
contain this code here:

Option Explicit

Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" _
(ByVal lpLibFileName As String) As Long
Declare Function GetInstanceEx Lib "DirectCom" _
(StrPtr_FName As Long, StrPtr_ClassName As Long, _
ByVal UseAlteredSearchPath As Boolean) As Object
Declare Function GETINSTANCELASTERROR Lib "DirectCom" () As String


Private Sub EnsureDirectComDllPreLoadingAndCheckPath(Path As String)
Static hLib As Long
If Right(Path, 1) <> "\" Then Path = Path & "\"
'preload DirectCOM.Dll (only once) into the Excel-Process
If hLib = 0 Then hLib = LoadLibrary(Path & "DirectCOM.dll")
End Sub

Function CreateWrapperInstanceRegFree(ByVal WorkBookPath As String)
EnsureDirectComDllPreLoadingAndCheckPath WorkBookPath

Set CreateWrapperInstanceRegFree = GetInstance(WorkBookPath & _
"MyWrapper.dll", "cMyClass")
End Function

Function CreateSQLiteCnnRegFree(ByVal WorkBookPath As String)
EnsureDirectComDllPreLoadingAndCheckPath WorkBookPath

Set CreateSQLiteCnnRegFree = GetInstance(WorkBookPath & _
"vbRichClient4.dll", "cConnection")
End Function

Function GetInstance(DllFileName As String, ClassName As String)
On Error Resume Next
Set GetInstance = GetInstanceEx(StrPtr(DllFileName), _
StrPtr(ClassName), True)
If GetInstance Is Nothing Then
On Error GoTo 0: Err.Raise vbObjectError, , GETINSTANCELASTERROR
End If
End Function


Then you can already try out SQLite-InMemory-DBHandling inside your
XL-Sheet (when you add an additional Button CommandButton1 there):

Here's the Button-EventHandler which demonstrates SQLite-stuff:

Private Sub CommandButton1_Click()
Dim Cnn As Object '<- we use the regfree created Objects LateBound
Set Cnn = CreateSQLiteCnnRegFree(ActiveWorkbook.Path)
Cnn.CreateNewDB '<- without params creates a yet empty InMemory-DB

'so we create a DemoTable now
Dim SQL$
SQL = "Create Table T(ID Integer Primary Key, Txt Text, Dbl Double)"
Cnn.Execute SQL

'and now we add a few Records into it
Dim i As Long, Rs As Object '<- LateBound-usage here as well
Set Rs = Cnn.OpenRecordset("Select * From T Where 0")
For i = 1 To 20
Rs.AddNew
Rs!ID = i
Rs!Txt = "SomeText_" & i
Rs!Dbl = 20 / i
Next i
Rs.UpdateBatch

'finally we perform a Select on the just added InMemory-Table-Data
'(thereby filtering for "uneven IDs" per SQLs Mod-Operator '%')
Set Rs = Cnn.OpenRecordset("Select * From T Where (ID % 2)")

'and now with one command, we beam the result into an XL-range
'(from a given "TopLeft-Cell")
With Range("F7").Resize(Rs.RecordCount, Rs.Fields.Count)
.Value = Rs.GetRows(, , , True)
End With

'or also with RowHeaders (with a few formattings on the 1st Row)
With Range("J7").Resize(1, Rs.Fields.Count)
.Font.Bold = True
.HorizontalAlignment = xlCenter
End With
With Range("J7").Resize(Rs.RecordCount + 1, Rs.Fields.Count)
.Value = Rs.GetRowsWithHeaders(, , , True)
End With
End Sub


Olaf
GS
2012-02-29 21:15:49 UTC
Permalink
Olaf,
I can't tell you enough how much I appreciate you! This is awesome
stuff now that I know it's doable reg-free. I see in this sample that
that it can work in VB6 via Excel automation with only minor
modification.

Now you've got me all worked up! I've been not using the SQLite wrapper
because of the dependancy, using plain text files instead. Now I'm
going to re-examine my projects for using this. Do you have a help file
for the SQLite wrapper? Most of my DB experience revolves around using
ADODB with Excel workbooks and text files. I bought a book on VB6
Database Programming by John Smiley so I could learn this aspect of
programming. Otherwise, I'm as green as can be about working with
databases even though it's not all that different than what I'm
familiar with. It just seems there's a lot more complexity involve when
working with databases, so I usually opt out for the easiest approach.
You just opened up a way for me to make my projects more robust for
their data management.

Looks like I need to revisit www.datenhaus.de and spend a bit more time
there...
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Schmidt
2012-02-29 22:20:18 UTC
Permalink
I see in this sample that that it can work in VB6 via Excel
automation with only minor modification.
Yes, this direction is also possible
(E.g. in a VB-Host-Executable, which is able to fill XL-Ranges
directly from Recordsets in "only one call", which is
important, to not stress the OutOfProcess COM-communication
channel too much).
Now you've got me all worked up! I've been not using the SQLite wrapper
because of the dependancy, using plain text files instead. Now I'm going
to re-examine my projects for using this. Do you have a help file for
the SQLite wrapper?
No, not yet - but the Objects are widely ADO-compatible.
Most of my DB experience revolves around using ADODB
That's good ... if you already have some ADODB-Background
(and "a book for it"), then using the SQLite-WrapperObjects is
not all that much different - the Recordsets behave similar and
are (on the most methods) calling-compatible to ADO.Rs:
- Rs.AbsolutePosition
- Rs.BOF/EOF
- Rs.MoveFirst/Next/Previous/Last
- Rs.Fields("SomeField").Value (Read-Direction as in ADO-Rs)

And the Write-Direction is pretty similar as well:
- Rs.AddNew (for Inserts)
- Rs.Delete (for Deletes)
- Rs.Fields("SomeField").Value = NewValue (for Updates)
- Rs.UpdateBatch (to write the accumulated changes back into the DB)

The Cnn-Object (cConnection) works a bit more "File-oriented" -
meaning that it doesn't use any Connection-String-setups,
but a "naked FileName instead" for its Cnn.OpenDB or
Cnn.CreateNewDB commands.

There's more useful stuff of course, which ADO/JET doesn't
offer (InMem-DBs and UserDefined SQL-Functions for example) -
or the possibility to create entire Tables dynamically, directly
from already existing Rs - but maybe ask for that later on,
after you became more familiar with "the Basics".

Just try to use F2 (VBs ObjectExplorer) when you want to take a
look at (or search for) the exposed Methods on certain RichClient-
Objects - you can look up the cRecordset.GetRows-Function
for eaxmple there, to take a look at the Parameter-List.

Happy Coding! ;-)

Olaf

GS
2012-02-28 05:16:49 UTC
Permalink
Olaf, I think we should move this to a new thread because it's very OT
and getting rather numerous posts.
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Jim Mack
2012-02-27 18:26:23 UTC
Permalink
Post by Stuart McCall
With New ClassName
.Property1 = <whatever>
.Method1
'etc
Variable = .Result
End With
No need for Dim, with or without As New.
(just thought I'd throw this into the mix to see what the group make of it)
There's nothing actually wrong with it as long as you're sure to stay
within the block, but I don't use it because I tend to avoid VB's
implicit helpfulness. (-:

I admit to being a little outside the mainstream in this regard. In
addition to explicit typing, and never using default properties, I also
always specify both array bounds, and use a lot of explicit type
conversions like CLng() etc. If I can specify it, I do.

I spend so little time typing compared to time debugging that I don't
see how, in the long run, there's any pain attached to being explicit,
whether with "Dim" or in those other areas. It makes the intent clear,
shows that you know what's happening under the hood, and adds no
runtime overhead.
--
Jim
Stuart McCall
2012-02-27 19:33:02 UTC
Permalink
Post by Jim Mack
Post by Stuart McCall
With New ClassName
.Property1 = <whatever>
.Method1
'etc
Variable = .Result
End With
No need for Dim, with or without As New.
(just thought I'd throw this into the mix to see what the group make of it)
There's nothing actually wrong with it as long as you're sure to stay
within the block, but I don't use it because I tend to avoid VB's implicit
I admit to being a little outside the mainstream in this regard. In
addition to explicit typing, and never using default properties, I also
always specify both array bounds, and use a lot of explicit type
conversions like CLng() etc. If I can specify it, I do.
We're definitely on the same page. I do all of the above, too.
Post by Jim Mack
I spend so little time typing compared to time debugging that I don't see
how, in the long run, there's any pain attached to being explicit, whether
with "Dim" or in those other areas. It makes the intent clear, shows that
you know what's happening under the hood, and adds no runtime overhead.
Is there some runtime overhead? I seem to recall reading (probably somewhere
on MSDN) that MS reserved pre-allocated space for some implicit vars, in
which case that just leaves instantiation, which has to occur at runtime
anyway.

Thanks for your comments.
Post by Jim Mack
--
Jim
Jim Mack
2012-02-27 20:50:54 UTC
Permalink
Post by Stuart McCall
Post by Jim Mack
I spend so little time typing compared to time debugging that I don't
see how, in the long run, there's any pain attached to being explicit,
whether with "Dim" or in those other areas. It makes the intent clear,
shows that you know what's happening under the hood, and adds no
runtime overhead.
Is there some runtime overhead? I seem to recall reading (probably
somewhere on MSDN) that MS reserved pre-allocated space for some implicit
vars, in which case that just leaves instantiation, which has to occur at
runtime anyway.
Referring specifically to the "Dim As New" scenario, which does carry
some runtime baggage. Not much, but my instinct (I'm originally an ASM
programmer) is always: why use _any_ processor time you can avoid?

I do temper that in these days of 4GHz and 8 cores, and I'm certainly
willing to trade development time for runtime when it doesn't really
matter, but by training I always take free optimizations as early as I
can in the process. (-:
--
Jim
Helmut_Meukel
2012-02-26 10:02:55 UTC
Permalink
Post by ralph
Post by GS
I thought that the object created by "Dim As New" existed until the
exit from the scope they were created in. So...
In a procedure: (local scope)
Dim colItems As New Collection
..lives for the entire procedure if not explicitly destroyed beforhand.
... But you can not "explicitly" destroy the collection object.
You can clear the contents but never get rid of the object until the
object reference goes out of scope.
Hmm, I thought even if you created an object using
Dim Duck As New Monster
you can explicitely destroy that object, e.g.
Set Duck = Nothing
But *any* explicitely or implicitely reference - not only the test
"Is Nothing" will create a new instance of the object if it doesn't
exist.
This will look like you only cleared the contents, but it was destroyed
actually.

You can't always have an object locally to the subroutine and if the
object is explicitely destroyed in another subroutine, then any further
reference e.g.
if Duck.Weight > 2000 then 'weight in gramms
will automagically recreate a new instance of Duck with its default
values. Your program will be unaware of this and happily work with the
new Duck.

In small routines, creating local objects using
Dim MyObject As New AnObject
will work without problems, but if you get the habit of using this
construct, chances are you'll use it everywhere and finally it will
bite you.

Helmut.
GS
2012-02-26 19:23:59 UTC
Permalink
Post by Helmut_Meukel
Post by ralph
Post by GS
I thought that the object created by "Dim As New" existed until the
exit from the scope they were created in. So...
In a procedure: (local scope)
Dim colItems As New Collection
..lives for the entire procedure if not explicitly destroyed beforhand.
... But you can not "explicitly" destroy the collection object.
You can clear the contents but never get rid of the object until the
object reference goes out of scope.
Hmm, I thought even if you created an object using
Dim Duck As New Monster
you can explicitely destroy that object, e.g.
Set Duck = Nothing
But *any* explicitely or implicitely reference - not only the test
"Is Nothing" will create a new instance of the object if it doesn't
exist.
This will look like you only cleared the contents, but it was destroyed
actually.
You can't always have an object locally to the subroutine and if the
object is explicitely destroyed in another subroutine, then any further
reference e.g.
if Duck.Weight > 2000 then 'weight in gramms
will automagically recreate a new instance of Duck with its default
values. Your program will be unaware of this and happily work with the
new Duck.
In small routines, creating local objects using
Dim MyObject As New AnObject
will work without problems, but if you get the habit of using this
construct, chances are you'll use it everywhere and finally it will
bite you.
Helmut.
Normally, I practice the follow self-made programming rules:

"Anything we leave to VB to do by 'implicity' will ALWAYS require
extra processing on VB's part"

"Any object 'implicity' created should be 'implicitly' destroyed"

"Any object 'explicitly' created should be 'explicitly' destroyed"

"Any object that needs to be reused should ALWAYS be 'explicitly'
created AND 'explicitly' destroyed when done with each usage"

Adhering to these has never got me into trouble. I do use "Dim As New"
on occasion in local scope only. I'm not an advocate of not using this
VB feature because it exists for a reason and it certainly is useful in
appropriate circumstances. Since I'm a 'creature of habit' to an
obssesive degree, there's not likely a chance I would use "Dim As New"
in unappropriate circumstances.<g>
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
GS
2012-02-26 22:09:35 UTC
Permalink
Adhering to these has never got me into trouble. I do use "Dim As New" on
occasion in local scope only. I'm not an advocate of not using this VB
feature because it exists for a reason and it certainly is useful in
appropriate circumstances. Since I'm a 'creature of habit' to an obssesive
degree, there's not likely a chance I would use "Dim As New" in unappropriate
circumstances.<g>
Well, if you read my reply to my own post "For..Each vs For..Next with
Collections" you'll see egg in my face about the last line of my above
statement.
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
ralph
2012-02-26 04:21:32 UTC
Permalink
On Sun, 26 Feb 2012 03:09:09 +0000 (UTC), "Auric__"
Post by Auric__
Post by Jim Mack
Post by Auric__
Dim duck As monster
Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above 2 lines.
For the purpose of this discussion, maybe. But "Dim As New" is frowned
on because it adds an implicit 'is nothing' check on every reference to
the object, and you lose control over the object lifetime.
Interesting. First I've heard of it (but then, I don't use VB very much any
more, and can't recall having ever used VB for "serious" OOP).
Is this documented anywhere? Help file, MSDN, whatever?
Yes.

Do a search online, the MSDN, any major book, ... and you will find
plenty of references to the problems associated with the "As New"
construct.

In the same vein, there are similar problems associated with using the
inherent Form name to manage Form objects.

Casual VB programmers are often not aware of the problems because the
majority of code snippets and examples use both constructs to save
typing an 'extra' line of code, and the consequences are largely
invisible. One usually has to get burned a couple of times to learn
about them.

Your comment about VB and "serious" Object-Oriented programming is a
little bizarre - since the VB development platform is about as pure an
OOP environment as they come. It does lack two features, constructors
and implementation inheritance, found in many OOPLs, but neither
construct defines or delimits an OOPL.

-ralph
Auric__
2012-02-26 04:51:34 UTC
Permalink
Post by ralph
Your comment about VB and "serious" Object-Oriented programming is a
little bizarre - since the VB development platform is about as pure an
OOP environment as they come. It does lack two features, constructors
and implementation inheritance, found in many OOPLs, but neither
construct defines or delimits an OOPL.
Let me rephrase, then: I've never used VB for OOP in any of my projects.
"Serious" or not being my opinion of what I'm working on, not the language
features. (Although I've always been kinda iffy about the lack of
inheritance... but if I *really* needed it, I could always bull my way
through C++ or Java or whatever.)
--
On the one hand, it still works. On the other hand, IT STILL WORKS?!
ralph
2012-02-26 05:10:52 UTC
Permalink
On Sun, 26 Feb 2012 04:51:34 +0000 (UTC), "Auric__"
Post by Auric__
Post by ralph
Your comment about VB and "serious" Object-Oriented programming is a
little bizarre - since the VB development platform is about as pure an
OOP environment as they come. It does lack two features, constructors
and implementation inheritance, found in many OOPLs, but neither
construct defines or delimits an OOPL.
Let me rephrase, then: I've never used VB for OOP in any of my projects.
"Serious" or not being my opinion of what I'm working on, not the language
features. (Although I've always been kinda iffy about the lack of
inheritance... but if I *really* needed it, I could always bull my way
through C++ or Java or whatever.)
It might be interesting to note that Java and C++* does 'Interface
Inheritance' awkwardly.

-ralph
[*except for some vendor's extensions to the language.]
Peter Nolan
2012-02-26 12:11:28 UTC
Permalink
Post by Auric__
Post by Peter Nolan
Post by Auric__
Post by Peter Nolan
I have tried, trust me, to learn what a class is in VB and in spite
of many an attempt I remain baffled and I was wondering if you could
help me out. In addition to reading I have watched YouTube videos.
I know that fish is a class and so a trout is an instance of the
class fish. I also know that a class contains a function and data. I
better leave it at that because of how confused I am about the whole
thing.
Have you read the Wikipedia entry?
 http://en.wikipedia.org/wiki/Class_(computer_programming)
  a class is a construct that is used as a blueprint
So, it might help to think of a class as a sort of blueprint. A class
describes something, and when you create a new instance of a class,
you're using the blueprint.
Say you're writing a game, and you have a class called "monster". When
  Dim duck As New monster
  duck.Health = 1
  duck.Strength = 1
  'etc.
  Dim duckHealth As Integer, duckStrength As Integer 'etc.
I haven't the faintest idea what the rest of the thread is about to do
with For Next loops and so on.
Welcome to Usenet, where any thread about anything will quickly get twisted
into a thread about something only marginally related.
Post by Peter Nolan
However can I ask you a question? Is New monster a user defined
datatype other than the default data types like Integer and Long that
has the values duck.Health = 1 and duck.Strength =1 It's like a more
sophisticated type of data that really could very detailed with many
more values.
Eh... sorta. More like a super data type. If you've ever used the type
  Type foo
    a As Integer
    b As Single
    c As String
  End Type
...then you can think of classes as types taken to the next level. Where
types are essentially collections of related variables, classes can also hold
subs and functions.
  Dim duck As monster
tells the compiler that "duck" is a "monster", but doesn't actually create a
new "monster" in "duck's" memory space -- doesn't apply the "monster"
  Dim duck As monster
  Set duck = New monster
"Dim duck As New monster" is essentially the same thing as the above 2 lines.
Let's look at my previous example, "duck" as a type of "monster". I showed
  Dim duckHealth As Integer, duckStrength As Integer
  Type monster
    Health As Integer
    Strength As Integer
  End Type
  Dim duck As monster
Simple enough, right? But with classes, in addition to keeping track of
things like the duck's health, strength, etc., we could also assign it
behaviors (in the form of Subs and Functions).
  Public Sub Attack (what As monster)
    'whatever
  End Sub
While this could go anywhere in the program, outside of the class, by putting
it *in* the class, we're making the "Attack" behavior specific to the
"monster". A Sub outside the class would have to be aware of what type of
"monster" is "Attack"ing, and would have to extract the relevant information
  Sub Attack(attacker As monster, target As monster)
    If attacker.ChanceToHit > target.ArmorClass Then
      target.Health = target.Health - attacker.DamagePerHit
      If target.Health < 1 Then target.Name = "dead " & target.Name
    End If
    'etc.
  End Sub
...but by putting the Sub *inside* the class, the rest of the program doesn't
need to know any of that relevant info, and the pertinent details can be
handled inside the class, invisible to the rest of the program.
-----monster.cls-----
  Private myName As String
  Private myHealth As Integer, myStrength As Integer, myXPvalue As Integer
  Private myToHit As Integer, myArmorClass As Integer
  Private myDamage As Integer, myDamageReduction As Integer
  Private Sub Class_Initialize()
    myHealth = 10: myStrength = 1: myXPvalue = 1: myToHit = 1: myDamage = 1
  End Sub
  Public Property Get mName() As String
    mName = myName
  End Property
  Public Property Let mName(ByVal newName As String)
    myName = newName
  End Property
  Public Property Get ToHit() As Integer
    ToHit = myToHit
  End Property
  Public Sub Attack(target As monster)
    target.Defend Me
  End Sub
  Friend Sub Defend(attacker As monster)
    If attacker.ToHit > myArmorClass Then attacker.GiveDamage Me
  End Sub
  Friend Sub GiveDamage(defender As monster)
    defender.TakeDamage myDamage
  End Sub
  Friend Sub TakeDamage(howMuch As Integer)
    If howMuch > myDamageReduction Then
      myHealth = myHealth - howMuch
      If myHealth < 1 Then doDeath
    End If
  End Sub
  Private Sub doDeath()
    myName = "dead " & myName
  End Sub
-----monster.cls-----
(Yes, that really is a *simple* class.)
To do combat between two "monsters", the written code could be as simple as
  Dim duck As New monster, dragon As New monster
  duck.Attack dragon
Behind the scenes (hidden from the calling code) would be somewhat like this,
  duck.Attack dragon
  -> dragon.Defend duck
     -> If duck.ToHit > dragon.ArmorClass Then duck.GiveDamage dragon
        -> dragon.TakeDamage duck.Damage
           -> If duck.Damage > dragon.DamageReduction Then
                dragon.Health = dragon.Health - duck.Damage
                If dragon.Health < 1 Then dragon.doDeath
                 -> dragon.mName = "dead " & dragon.mName
              End If
So by using classes, you can greatly simplify your code, making it easier to
read and (hopefully) easier to debug.
Other Wikipedia pages that might be worth reading are the entries on
 http://en.wikipedia.org/wiki/Information_hiding
 http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)
Post by Peter Nolan
If I am making any sense here it doesn't actually mean I
know what is going on. What simple illustrative code would describe
monster in the first place?
Many thanks for taking the time to explain things to me.
Np. I know that for some people it can be a difficult concept to grasp.
Let's look at the other messages you posted...
--------------------------------------------------------------------------- --
Post by Peter Nolan
http://youtu.be/OuoytdFfyXs
Not going to watch that, but...
Post by Peter Nolan
I'm sure it contains everything I need to know but I still end up
confused. A dog ie this class can have a name or belong to some breed
of dog. Then a new dog or an instance of that class would have a new
name an say belong to another breed. Then the dog could bark or sit
say and they would be functions for all dogs. I kinda get this.
Do you have a very simple VB code snippet that would illustrate all
that?
"very simple"? No, but... well, see my monster.cls above.
--------------------------------------------------------------------------- --
Post by Peter Nolan
Instead of saying monster you could have said bird. Duck with all it's
descriptors is a kind of bird just like crow is a bird with it's own
health and strength. I get all this now but what has all this got to
do with programming computers?
I should've said "creature". Shrug. The whole point was just meant to be an
example. I could've just as easily said a "vehicle" class, with "car" or
"airplane" instead of "duck". Or a "robot" class, with "factory robot" or
"cleaning robot".
--
Well, it's finally happened. I'm speechless.
Utterly, utterly speechless.
Hello Auric,

I am very grateful to you for the comprehensive account you have given
of a simple class. I know everything I need to know is right there in
what you have written above. I was a teacher of physics, chemistry and
applied maths in St. Mary's School, Nairobi, Kenya 1975/1979 and my
reward was knowing that I had imparted understanding. All I can offer
you is saying that your reward in this case will be my having an
understanding of what a class is. You write:

Public Property Get mName() As String
Post by Auric__
mName = myName
End Property
Public Property Let mName(ByVal newName As String)
myName = newName
End Property
Public Property Get ToHit() As Integer
ToHit = myToHit
End Property
Can I just ask what I'm certain is a really dumb question? What is a
property?
I can google for this info so if you feel exasperated by the question
just ignore it. In the meantime I will study what you have written
because on a first reading I'm still at a loss to understand.

Many thanks,

Peter.
Helmut_Meukel
2012-02-26 15:37:08 UTC
Permalink
Post by Auric__
Public Property Get mName() As String
Post by Auric__
mName = myName
End Property
Public Property Let mName(ByVal newName As String)
myName = newName
End Property
Public Property Get ToHit() As Integer
ToHit = myToHit
End Property
Can I just ask what I'm certain is a really dumb question? What is a
property?
I can google for this info so if you feel exasperated by the question
just ignore it. In the meantime I will study what you have written
because on a first reading I'm still at a loss to understand.
From outside, the Property Get/Let pair looks like a public variable,
but because it's split in two parts, you (the programmer of the class)
can make it read-only or write-only. And you can place code in those
routines so the class can act when the property is accessed from outside.

HTH,

Helmut.
Auric__
2012-02-26 18:36:43 UTC
Permalink
Post by Peter Nolan
I am very grateful to you for the comprehensive account you have given
of a simple class. I know everything I need to know is right there in
what you have written above.
Not *everything*, no. You should read Jim Mack's reply to me, and that
branch of the discussion. Turns out that "Dim x As New whatever" adds
behind-the-scenes stuff to the program that could be undesirable, and it is
probably a good idea to instead use "Dim x As whatever: Set x = New
whatever".
Post by Peter Nolan
I was a teacher of physics, chemistry and
applied maths in St. Mary's School, Nairobi, Kenya 1975/1979 and my
reward was knowing that I had imparted understanding. All I can offer
you is saying that your reward in this case will be my having an
understanding of what a class is.
That's all anyone could ask for.
Post by Peter Nolan
Post by Auric__
Public Property Get mName() As String
mName = myName
End Property
Public Property Let mName(ByVal newName As String)
myName = newName
End Property
Public Property Get ToHit() As Integer
ToHit = myToHit
End Property
Can I just ask what I'm certain is a really dumb question? What is a
property?
Adding to what Helmut wrote (looks like a public variable; can make it
read-only or write-only; the class can act when the property is
accessed)...

While a class can have "normal" public variables (Public x As whatever), by
using properties instead of public variables, you can make the class do
something if a property gets changed. Looking back at my "monster" class,
we see this property:

Public Property Get ToHit() As Integer
ToHit = myToHit
End Property

Rather than just parroting out the local variable, this could've accessed
multiple internal variables, returning just a single number:

Public Property Get ToHit() As Integer
Private tmp As Integer
tmp = baseToHit + strengthToHitMod + armorToHitMod + weaponToHitMod
ToHit = tmp
End Property

Or perhaps the Attack sub could handle dealing out damage, rather than the
multi-step method I used, and the Health property could deal with things
like the monster dying (instead of calling another sub to do it):

Public Sub Attack(target As monster)
If myToHit > target.ArmorClass Then
target.Health = target.Health - myDamage
End If
End Sub

Public Property Let Health(ByVal newHealth As Integer)
If newHealth < 1 Then
myHealth = 0
myName = "dead " & myName
Else
myHealth = newHealth
End If
End Property

(I didn't mention it before, but with properties, "Property Get" is how you
retreive the property's value, while "Property Let" is how you assign a
value to the property. There's also "Property Set", but you shouldn't worry
about that just yet...)
Post by Peter Nolan
I can google for this info so if you feel exasperated by the question
just ignore it. In the meantime I will study what you have written
because on a first reading I'm still at a loss to understand.
Here's some more reading for you:
http://en.wikibooks.org/wiki/Object_Oriented_Programming
Especially read the section "Classes, Types, and Classic OOP".
--
They say nothing good happens at 3am, they're right, *I* happen at 3am.
ralph
2012-02-26 20:11:32 UTC
Permalink
On Sun, 26 Feb 2012 18:36:43 +0000 (UTC), "Auric__"
Post by Auric__
While a class can have "normal" public variables (Public x As whatever), by
using properties instead of public variables, you can make the class do
something if a property gets changed. ...
A so called "normal public variable" in a VB class needs a bit of
amplification. Basically to point out there actually is no such thing.
<g>

A VB Class exposes only Properties and Methods. When you declare a
Public variable in your code it looks like a single "normal" variable,
but in fact behind the scenes VB generates a default Get and Let
Property for the variable. (or Set if needed)

So if you had a class that looked like this ...

' MyClass
Public MySize As Long

What you really get is this ...
' MyClass
Private InvisibleMySize As Long

Public Property Let MySize( NewValue As Long)
InvisibleMySize = NewValue As Long
End Property

Public Property Get MySize() As Long
MySize = InvisibleMySize
End Property

Most of the time this fact is trivial, but the consequence does have
an impact in three minor areas.

1) Programmers often feel they are saving keystrokes and bloat by
using a "normal" variable instead of creating Properties, however not
as much as they think because VB is creating them anyway.

Having your own 'coded' Properties is often useful during development.
For example while stepping through your code, if you have provided
your own Property the debugger will stop inside the class. You can
easily place stops inside the Property to catch changes from anywhere
in your Application, etc.

2) When you attempt Interface Inheritance (through Implements) you
will notice that you will have to provide a Get and Let property for
any "normal" variable to fully support the Implementation.

3) VB Types can not be exposed through a "normal" public variable
because a default property generator for a VB Type doesn't exist.
(Only part of the issues surrounding the passing VB Types but serves
as a basic reminder of why not to try and go there in the first place.
<g>)

-ralph
Peter Nolan
2012-02-27 11:11:54 UTC
Permalink
Post by Auric__
Post by Peter Nolan
I am very grateful to you for the comprehensive account you have given
of a simple class. I know everything I need to know is right there in
what you have written above.
Not *everything*, no. You should read Jim Mack's reply to me, and that
branch of the discussion. Turns out that "Dim x As New whatever" adds
behind-the-scenes stuff to the program that could be undesirable, and it is
probably a good idea to instead use "Dim x As whatever: Set x = New
whatever".
Post by Peter Nolan
I was a teacher of physics, chemistry and
applied maths in St. Mary's School, Nairobi, Kenya 1975/1979 and my
reward was knowing that I had imparted understanding. All I can offer
you is saying that your reward in this case will be my having an
understanding of what a class is.
That's all anyone could ask for.
Post by Peter Nolan
Post by Auric__
  Public Property Get mName() As String
    mName = myName
  End Property
  Public Property Let mName(ByVal newName As String)
    myName = newName
  End Property
  Public Property Get ToHit() As Integer
    ToHit = myToHit
  End Property
Can I just ask what I'm certain is a really dumb question? What is a
property?
Adding to what Helmut wrote (looks like a public variable; can make it
read-only or write-only; the class can act when the property is
accessed)...
While a class can have "normal" public variables (Public x As whatever), by
using properties instead of public variables, you can make the class do
something if a property gets changed. Looking back at my "monster" class,
  Public Property Get ToHit() As Integer
    ToHit = myToHit
  End Property
Rather than just parroting out the local variable, this could've accessed
  Public Property Get ToHit() As Integer
    Private tmp As Integer
    tmp = baseToHit + strengthToHitMod + armorToHitMod + weaponToHitMod
    ToHit = tmp
  End Property
Or perhaps the Attack sub could handle dealing out damage, rather than the
multi-step method I used, and the Health property could deal with things
  Public Sub Attack(target As monster)
    If myToHit > target.ArmorClass Then
      target.Health = target.Health - myDamage
    End If
  End Sub
  Public Property Let Health(ByVal newHealth As Integer)
    If newHealth < 1 Then
      myHealth = 0
      myName = "dead " & myName
    Else
      myHealth = newHealth
    End If
  End Property
(I didn't mention it before, but with properties, "Property Get" is how you
retreive the property's value, while "Property Let" is how you assign a
value to the property. There's also "Property Set", but you shouldn't worry
about that just yet...)
Post by Peter Nolan
I can google for this info so if you feel exasperated by the question
just ignore it. In the meantime I will study what you have written
because on a first reading I'm still at a loss to understand.
 http://en.wikibooks.org/wiki/Object_Oriented_Programming
Especially read the section "Classes, Types, and Classic OOP".
--
They say nothing good happens at 3am, they're right, *I* happen at 3am.
Hello Auric,

Again many thanks. The bottom line is that I have probably reached the
limits of my own capacity to understand. I'm a humble physicist but
many of my crew are quite at home in the land of programming. I always
thought I could just keep going keeping up but this is not so. I'm
almost sure I read the Wiki you cite but got lost in all the words.
I will return again to this thread for as often it takes to study what
you have written but I'm afraid to ask another stupid question or a
question that I already should know the answer to before asking what a
class is in the first place like my asking what a property is. I now
have a feel for how much more powerful the Dim statement is that I
gather sets up the whole thing.
I've learned a whole lot this time round about the dazzling
intelligence you have. Dazzling!
I have always noted my own limitations but I now understand more about
those very limitations.

Regards,

Peter.
Auric__
2012-02-27 16:33:41 UTC
Permalink
Post by Peter Nolan
Again many thanks. The bottom line is that I have probably reached the
limits of my own capacity to understand. I'm a humble physicist but
many of my crew are quite at home in the land of programming.
Unless you're writing in a strictly OOP language like Java, using classes
isn't necessary to modern programming -- they're a convenience. (As I noted
elsewhere in this thread, I don't have any VB projects that use classes.)
Using classes can simplify your code *if you know what you're doing*; if
you don't, your code will be a mess.

For that matter, most of my projects are no longer in VB at all. I've moved
most of my code to either FreeBASIC (which is very similar to QuickBASIC)
or PowerBASIC (which is only vaguely similar to MS BASICs).
Post by Peter Nolan
I always
thought I could just keep going keeping up but this is not so. I'm
almost sure I read the Wiki you cite but got lost in all the words.
I will return again to this thread for as often it takes to study what
you have written but I'm afraid to ask another stupid question
"There's no such thing as a stupid question, just stupid people." Being
unable to wrap your brain around a thing doesn't make you stupid, nor does
asking questions about it. (I'm having problems with lambda functions in
Lisp. That doesn't make me stupid; it makes me unable to deal with lambda
functions. (So far... but I haven't asked for help, yet.) Although, believe
it or not, I think that part of this very thread will help that...)
Post by Peter Nolan
or a
question that I already should know the answer to before asking what a
class is in the first place like my asking what a property is.
If you look through Usenet, you'll see that kind of question all the time.
If you don't know the answer, then how could it be that you "should" know
it?
Post by Peter Nolan
I now
have a feel for how much more powerful the Dim statement is that I
gather sets up the whole thing.
I've learned a whole lot this time round about the dazzling
intelligence you have. Dazzling!
Intelligence has much less practical application than you'd think.
-- Dilbert

Trust me, while my intelligence may be higher than average, I don't put it
to good use, "dazzling" or otherwise. ;-)
Post by Peter Nolan
I have always noted my own limitations but I now understand more about
those very limitations.
If you were "a teacher of physics, chemistry and applied maths", your
intelligence likely isn't the problem.
--
oooh, flashback!
Jim Mack
2012-02-27 18:33:35 UTC
Permalink
Post by Auric__
Unless you're writing in a strictly OOP language like Java, using classes
isn't necessary to modern programming -- they're a convenience. (As I
noted elsewhere in this thread, I don't have any VB projects that use
classes.) Using classes can simplify your code *if you know what you're
doing*; if you don't, your code will be a mess.
I recently went looking for some anti-aliasing code in VB because I
didn't want to reinvent that wheel, and I found a useful library that
someone had adapted from old Delphi code. While it works, it's
(bizarrely) implemented as a class, rather than as straight procedural
code, as I'm sure it existed in Delphi.

It makes no sense as a class, it has none of the attributes that would
cry out for a class -- the only thing I can imagine is that the author
had grown up with classes and just didn't know how to implement a
module with callable functions, instead of methods in a class.
--
Jim
Peter Nolan
2012-02-28 12:07:25 UTC
Permalink
Post by Auric__
Post by Peter Nolan
Again many thanks. The bottom line is that I have probably reached the
limits of my own capacity to understand. I'm a humble physicist but
many of my crew are quite at home in the land of programming.
Unless you're writing in a strictly OOP language like Java, using classes
isn't necessary to modern programming -- they're a convenience. (As I noted
elsewhere in this thread, I don't have any VB projects that use classes.)
Using classes can simplify your code *if you know what you're doing*; if
you don't, your code will be a mess.
For that matter, most of my projects are no longer in VB at all. I've moved
most of my code to either FreeBASIC (which is very similar to QuickBASIC)
or PowerBASIC (which is only vaguely similar to MS BASICs).
Post by Peter Nolan
I always
thought I could just keep going keeping up but this is not so. I'm
almost sure I read the Wiki you cite but got lost in all the words.
I will return again to this thread for as often it takes to study what
you have written but I'm afraid to ask another stupid question
"There's no such thing as a stupid question, just stupid people." Being
unable to wrap your brain around a thing doesn't make you stupid, nor does
asking questions about it. (I'm having problems with lambda functions in
Lisp. That doesn't make me stupid; it makes me unable to deal with lambda
functions. (So far... but I haven't asked for help, yet.) Although, believe
it or not, I think that part of this very thread will help that...)
Post by Peter Nolan
or a
question that I already should know the answer to before asking what a
class is in the first place like my asking what a property is.
If you look through Usenet, you'll see that kind of question all the time.
If you don't know the answer, then how could it be that you "should" know
it?
Post by Peter Nolan
I now
have a feel for how much more powerful the Dim statement is that I
gather sets up the whole thing.
I've learned a whole lot this time round about the dazzling
intelligence you have. Dazzling!
Intelligence has much less practical application than you'd think.
 -- Dilbert
Trust me, while my intelligence may be higher than average, I don't put it
to good use, "dazzling" or otherwise. ;-)
Post by Peter Nolan
I have always noted my own limitations but I now understand more about
those very limitations.
If you were "a teacher of physics, chemistry and applied maths", your
intelligence likely isn't the problem.
--
oooh, flashback!
Hello Auric,

At the risk once again of saying something silly I tell you that I
find it awful hard to think using words. That is why I came to
comp.lang.basic.visual.misc to ask the question what a class is having
read wiki's and online books and so on about classes. I thought if I
saw actual code just like the code you wrote I could then invent my
own way of looking at the whole thing and write my own book! Only
joking. Imagine a rock in a field that the farmer of long ago wanted
to move aside to continue to clear space for planting. He with his
friends if needed would use say crowbars or if you go back far enough
logs of a fitting size to gradually lever the rock over to the side.
That's the kind of thing I easily understand that is in this case the
lever. I call it mechanical horse sense. However when I have to think
using words I am pretty much lost.
This comprehensive thread is now in place and there to study from now
on and who knows others will find what you have written most excellent
to read. You write:

Trust me, while my intelligence may be higher than average, I don't
put it
Post by Auric__
to good use, "dazzling" or otherwise. ;-)
You have just put your intelligence to good use in this thread but I'm
sure you are talking about putting your intelligence to work for you
in life. I don't know if you watch the American Idol or Xfactor on TV
that are TV shows to select exceptional singers like for example Kelly
Clarkson in the States but it's becoming more clear to me now that the
truly great exponents of the art of singing like Kelly Clarkson in the
States or Leona Lewis or Alexandra Burke in the UK are really small
or very small in number percentage wise with respect to the population
as a whole. Why is this so? I think that to be a great singer and that
is to be liked by more and more people one has to have a wide array of
talent to just produce that great exceptional sound. I believe so many
components are involved. Now take your case. I can assure you me now
speaking as a teacher of years ago, Auric, that you are exceedingly
gifted but you may just not feel like achieving this or that. One of
my first cousins, Maureen, has a beautiful daughter called Amy. They
paid me a visit not too long ago when it became clear that Amy is
actually a natural born runner who without doing any training prior to
the event just set off to complete a mini marathon. Does she now want
to dedicate her life to becoming a running superstar? The answer is
no. You could be become a superstar but you just don't have that
hungry feeling to let us say compete and if there were more peaceful
less competitive people in the world like you and Amy we would all be
much happier. Why is Kelly Clarkson now a superstar? Because she is
motivated to be so. You can take it from me that if you too had that
raw feeling that's needs satisfying you too would be what we call over
here a high flyer. It's easy for you to be just happy and trust me
again me speaking as an unfortunate who has felt pain you should be
very thankful for being the happy guy I know you are even if you are a
little annoyed that you haven't capitalised on the stunning talents
you have above others and that you know you have above others.
You write:

For that matter, most of my projects are no longer in VB at all. I've
moved
Post by Auric__
most of my code to either FreeBASIC (which is very similar to QuickBASIC)
or PowerBASIC (which is only vaguely similar to MS BASICs).
I'm gobsmacked. I'm not entirely sure what gobsmacked actually means
but it's probably fitting and that I now read that most of your
projects are no longer in VB I can see that VB is like a hobby to you.
Amazing!
I may just startle you at some point in the future by popping back in
to proclaim I now get what a class is. Hope springs eternal but you
know all about that.

Many thanks,

Peter.
Peter Nolan
2012-02-25 11:33:11 UTC
Permalink
Post by Auric__
Post by Peter Nolan
I have tried, trust me, to learn what a class is in VB and in spite of
many an attempt I remain baffled and I was wondering if you could help
me out. In addition to reading I have watched YouTube videos.
I know that fish is a class and so a trout is an instance of the class
fish. I also know that a class contains a function and data. I better
leave it at that because of how confused I am about the whole thing.
Have you read the Wikipedia entry?
 http://en.wikipedia.org/wiki/Class_(computer_programming)
  a class is a construct that is used as a blueprint
So, it might help to think of a class as a sort of blueprint. A class
describes something, and when you create a new instance of a class, you're
using the blueprint.
Say you're writing a game, and you have a class called "monster". When you
  Dim duck As New monster
  duck.Health = 1
  duck.Strength = 1
  'etc.
  Dim duckHealth As Integer, duckStrength As Integer 'etc.
--
I'm not evil. I'm living up to my full potential!
Hello Auric,

I just found this YouTube video:



I'm sure it contains everything I need to know but I still end up
confused. A dog ie this class can have a name or belong to some breed
of dog. Then a new dog or an instance of that class would have a new
name an say belong to another breed. Then the dog could bark or sit
say and they would be functions for all dogs. I kinda get this.
Do you have a very simple VB code snippet that would illustrate all
that?

Regards,

Peter.
Peter Nolan
2012-02-25 12:19:29 UTC
Permalink
Post by Auric__
Post by Peter Nolan
I have tried, trust me, to learn what a class is in VB and in spite of
many an attempt I remain baffled and I was wondering if you could help
me out. In addition to reading I have watched YouTube videos.
I know that fish is a class and so a trout is an instance of the class
fish. I also know that a class contains a function and data. I better
leave it at that because of how confused I am about the whole thing.
Have you read the Wikipedia entry?
 http://en.wikipedia.org/wiki/Class_(computer_programming)
  a class is a construct that is used as a blueprint
So, it might help to think of a class as a sort of blueprint. A class
describes something, and when you create a new instance of a class, you're
using the blueprint.
Say you're writing a game, and you have a class called "monster". When you
  Dim duck As New monster
  duck.Health = 1
  duck.Strength = 1
  'etc.
  Dim duckHealth As Integer, duckStrength As Integer 'etc.
--
I'm not evil. I'm living up to my full potential!
Hello Auric,

Instead of saying monster you could have said bird. Duck with all it's
descriptors is a kind of bird just like crow is a bird with it's own
health and strength. I get all this now but what has all this got to
do with programming computers?

Regards,

Peter.
Ivar
2012-02-24 15:15:56 UTC
Permalink
The real good thing about a Class is you can have a collection of em.

The Collection can have properties, methods and events just like a class
(because it is a class)
And even better! You can have a collection of classes where each class in
the collection can have a collection of classes

imagine you have some big boxes, and inside each big box is some medium
boxes, and inside each medium box is some little boxes.
you could have a collection of big boxes, each with their own properties,
methods and events
each big box class has it's own collection of medium boxes, each with their
own properties, methods and events
each Medium box class has it's own collection of little boxes, each with
their own properties, methods and events.

If you have it, the best way to gain understanding of the power of
collections of classes is to play with the VB6 Class Builder utility.

People say collections are slow to iterate. Yes if you use For Next loops,
Very Fast if you use For Each Next Loops

Hope This Helps A Bit

Ivar
GS
2012-02-24 19:52:36 UTC
Permalink
Post by Ivar
People say collections are slow to iterate. Yes if you use For Next loops,
Very Fast if you use For Each Next Loops
To add to your final statement...

Using a collection to add 500,000 members and check another 500,000
item list (in an array) to find duplicates in the collection, and
return a list of either matches found OR non-matches found (with or
without duplicates):

Using a For...Next loop took less than 8 seconds. Every other method I
tried took *considerably* longer. I did not try looping the collection
with a For Each...Next loop, though, because my experience with For
Each loops is they tend to be somewhat slower than incremental
For...Next loops. (I'm basing this on my rather extensive VBA
programming experience in MS Excel)

I'm not meaning to raise controversy with you, Ivar, but rather to just
point out iterating a collection is not always the optimum approach
depending on the task at hand. You've managed to spark my curiosity,
though, enough to try your suggestion in my 'FilterMatches' utility.
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Ivar
2012-02-24 23:10:39 UTC
Permalink
Gone from what is a class to Looping.
I've Written a rough bit of code below to demo the time diff between For
Next and For Each Next when iterating Collections

My Results. About 7 seconds total time
4914 For Next
0 For Each Next
1950 Find By Index In Collection
30 Find By Key in Collection
0 Find By Index in Array



Option Explicit
Private Declare Function GetTickCount& Lib "kernel32" ()

Private Sub Command1_Click()
Dim SomeVar As Variant
Dim L As Long
Dim TheCol As New Collection
Dim TheArray(50000) As Long
Dim TickNow As Long
Dim I As Integer
Dim Time1 As Long
Dim Time2 As Long
Dim Time3 As Long
Dim Time4 As Long
Dim Time5 As Long
Dim S As String

'Add 50,000 Items to a collection
For L = 1 To 50000
TheCol.Add L, "S" & L
Next

'Use For Next to Load Array Values (Time 1)
TickNow = GetTickCount
For L = 1 To 50000
TheArray(L) = TheCol(L)
Next

Time1 = GetTickCount - TickNow
TickNow = GetTickCount

'Use For Each Next Loop To Load Array Values (Time 2)
L = 0
For Each SomeVar In TheCol
L = L + 1
TheArray(L) = SomeVar
Next

Time2 = GetTickCount - TickNow

'Find 10000 items by index in Collection (Time 3)
TickNow = GetTickCount
For I = 1 To 10000
L = TheCol.Item(40000 + I)
Next
Time3 = GetTickCount - TickNow

'Find 10000 items by Key in Collection(Time 4)
TickNow = GetTickCount
For I = 1 To 10000
L = TheCol.Item("S" & 40000 + 1)
Next
Time4 = GetTickCount - TickNow

'Find 10000 items in the Array (Time 5)
TickNow = GetTickCount
For I = 1 To 10000
L = TheArray(40000 + I)
Next
Time5 = GetTickCount - TickNow

S = "For Next Loop Took " & Time1 & vbCrLf
S = S & "For Each Next Took " & Time2 & vbCrLf
S = S & "Find 10000 By Index Took " & Time3 & vbCrLf
S = S & "Find 10000 By Key Took " & Time4 & vbCrLf
S = S & "Find 10000 Items In Array Took " & Time5 & vbCrLf
MsgBox S
End Sub
GS
2012-02-25 00:46:37 UTC
Permalink
Ivar,
I appreciate your efforts. After reviewing your example I see that it
doesn't really do anything except iteration without processing results.
In this case I'm not going to contest your findings.

In the case of my utility, it's designed to compare two lists of data
contained in two columns of a spreadsheet. The average length of the
lists is 500,000 rows. These are processed as follows:

Both columns are loaded into arrays, the column being checked for
matches being inserted into a collection by iterating its array same as
you added to TheCol so the collection contains unique list items.

The list items to check for matches is then added to the collection in
the same manner. Depending on the args passed to the function, results
of this process are handled as follows:
Function options:
1. Return a list of all matches found.
2. Return a unique list of matches found.
3. Return a list of all non-matches found.
4. Return a unique list of non-matches found.

If option1 then put item into Matches()
If option3 then put item into NoMatches() and remove it from the
collection

If option2 then remove duplicates from Matches()
If option4 then remove duplicates from NoMatches()

Put the resulting list into the specified column of the spreadsheet

That's considerably more work than your example. Processing less than
50,000 items takes less than 1 second. That's as fast as any one (or
faster than all) your tests! Processing 500,000 items takes less than 8
seconds. Note that your time for the For..Each loop and the time for
Find by Index in Array are the same. (although I didn't get the point
of the reduced iterations <50k vs 10k>) The fact is that iterating a
collection is much faster than say a Dictionary, a data table, or a
worksheet range. I'd be really happy if you could produce a more
efficient function that does what my FilterMatches function does! I
will make a new function that iterates the collection and compares to
the array out of curiosity, though, just because I never tried doing it
that way.<g>

I think if this discussion continues it should have its own thread...
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Ivar
2012-02-25 02:20:25 UTC
Permalink
Hi GS
(although I didn't get the point of the reduced iterations <50k vs 10k>)
Just to save waiting time when running the code.

The comment to the OP was to say that classes can become really useful when
multiple instances of Classes (objects (I Used Boxes as an example)) are
being used, but many have said that using collections are slow, and they can
be if using indexes instead of Keys

In reply to your last post
I knock up a quickie bit of code that finds matches of two sets of 500K
number and puts then to a new collection
Is this comparable to what you have?

On my fairly new laptop average results are
Finds about 400 matches in 1.9 seconds

Ivar

Option Explicit

Private Declare Function GetTickCount& Lib "kernel32" ()

Private Sub Command_Click()
On Error GoTo ErrorChk

Randomize
Dim CollectA As New Collection
Dim CollecB As New Collection
Dim MatchedColl As New Collection
Dim L As Long
Dim RndNum As Long
Dim TheVar As Variant
Dim TickNow As Long

For L = 1 To 500000
CollectA.Add L ', "S" & L
Next

For L = 1 To 500000
RndNum = (500000000 * Rnd) + 1
CollecB.Add RndNum, "S" & RndNum
Next

TickNow = GetTickCount
For Each TheVar In CollectA
MatchedColl.Add CollecB("S" & TheVar)
Next

MsgBox "Found " & Format(MatchedColl.Count, "###,##0") & " Matches In " _
& Format((GetTickCount - TickNow) / 1000) & " Seconds"

'Don't bother un commenting the next part. Takes Forever

'TickNow = GetTickCount
'For L = 1 To 500000
'MatchedColl.Add CollecB(L)
'Next
'
'MsgBox "Found " & Format(MatchedColl.Count, "###,##0") & " Matches In " _
'& Format((GetTickCount - TickNow) / 1000) & " Seconds"

Exit Sub
ErrorChk:
If Err.Number = 5 Then 'Duplicate Random Number
Resume Next
Else
MsgBox "Oops"
End If
End Sub
GS
2012-02-25 21:57:59 UTC
Permalink
That's way too slow IMO! I can process 50,000 items in under 1 second
(times based on using Now() function).

See my new post "For..Each vs For..Next with Collections"
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
Helmut_Meukel
2012-02-25 10:36:28 UTC
Permalink
Post by Ivar
Gone from what is a class to Looping.
I've Written a rough bit of code below to demo the time diff between For Next
and For Each Next when iterating Collections
My Results. About 7 seconds total time
4914 For Next
0 For Each Next
1950 Find By Index In Collection
30 Find By Key in Collection
0 Find By Index in Array
There's a principle flaw in your approach, you are timing computations
in some of the loops which /might/ increase access time unnecessarily.
See my changes in your code below.
Post by Ivar
Option Explicit
Private Declare Function GetTickCount& Lib "kernel32" ()
Private Sub Command1_Click()
Dim SomeVar As Variant
Dim L As Long
Dim TheCol As New Collection
Dim TheArray(50000) As Long
Dim TickNow As Long
Dim I As Integer
Dim Time1 As Long
Dim Time2 As Long
Dim Time3 As Long
Dim Time4 As Long
Dim Time5 As Long
Dim S As String
'Add 50,000 Items to a collection
For L = 1 To 50000
TheCol.Add L, "S" & L
Next
'Use For Next to Load Array Values (Time 1)
TickNow = GetTickCount
For L = 1 To 50000
TheArray(L) = TheCol(L)
Next
Time1 = GetTickCount - TickNow
TickNow = GetTickCount
'Use For Each Next Loop To Load Array Values (Time 2)
L = 0
For Each SomeVar In TheCol
L = L + 1
TheArray(L) = SomeVar
Next
Time2 = GetTickCount - TickNow
In the next three loops you are computing the index within the loop.
Why? Depending on your version of VB and probably the OS and CPU,
Post by Ivar
'Find 10000 items by index in Collection (Time 3)
TickNow = GetTickCount
For I = 1 To 10000
L = TheCol.Item(40000 + I)
Next
better to use a long for I:
For I = 40001 To 50000
L = TheCol.Item(I)
Next
Post by Ivar
Time3 = GetTickCount - TickNow
'Find 10000 items by Key in Collection(Time 4)
TickNow = GetTickCount
For I = 1 To 10000
L = TheCol.Item("S" & 40000 + 1)
Next
better to use a long for I:
For I = 40001 To 50000
L = TheCol.Item("S" & I)
Next
In many real world apps the string key isn't computed only to access the
collection, thus the concatination adds unnecessary time to the loop.
Storing the strings in an array (done outside of the loop) and accessing
the items by
L = TheCol.Item(StringArray(I))
should be faster.
Post by Ivar
Time4 = GetTickCount - TickNow
'Find 10000 items in the Array (Time 5)
TickNow = GetTickCount
For I = 1 To 10000
L = TheArray(40000 + I)
Next
again better to use a long for I:
For I = 40001 To 50000
L = TheArray(I)
Next
Post by Ivar
Time5 = GetTickCount - TickNow
S = "For Next Loop Took " & Time1 & vbCrLf
S = S & "For Each Next Took " & Time2 & vbCrLf
S = S & "Find 10000 By Index Took " & Time3 & vbCrLf
S = S & "Find 10000 By Key Took " & Time4 & vbCrLf
S = S & "Find 10000 Items In Array Took " & Time5 & vbCrLf
MsgBox S
End Sub
One could argue, because the 40000 + I is within all loops, it doesn't
matter, but it will change the ratio.
Say 100 ticks to 50 ticks compared to (100 + 20) ticks to (50 + 20) ticks.

OTOH, there are situations where you should include lengthy computations
into your test loop; e.g. if the items are stored to a remote database,
the speed differences of the internal storage (array vs. collection) may
be unnoticeable. :-)

Helmut.
Peter Nolan
2012-02-25 11:35:53 UTC
Permalink
Post by Ivar
The real good thing about a Class is you can have a collection of em.
The Collection can have properties, methods and events just like a class
(because it is a class)
And even better! You can have a collection of classes where each class in
the collection can have a collection of classes
imagine you have some big boxes, and inside each big box is some medium
boxes, and inside each medium box is some little boxes.
you could have a collection of big boxes, each with their own properties,
methods and events
each big box class has it's own collection of medium boxes, each with their
own properties, methods and events
each Medium box class has it's own collection of little boxes, each with
their own properties, methods and events.
If you have it, the best way to gain understanding of the power of
collections of classes is to play with the VB6 Class Builder utility.
People say collections are slow to iterate. Yes if you use For Next loops,
Very Fast if you use For Each Next Loops
Hope This Helps A Bit
Ivar
Hello Ivar,

My poor head needs to see illustrative examples. I have done all the
reading and it makes no sense to me. For example I read the wiki and I
can't make head or tail of it!

Regards,

Peter.
Jim Mack
2012-02-24 20:23:43 UTC
Permalink
A class is what you should take to learn a bit about programming. (-:
--
Jim
Auric__
2012-02-25 01:33:23 UTC
Permalink
Ouch. :-)
--
- Haven't you forgotten something?
- No, I remembered the whipped cream.
Peter Nolan
2012-02-25 11:09:09 UTC
Permalink
--
        Jim
Hello Jim,

I may indeed have to get a few face to face lessons,

Regards,

Peter.
Mayayana
2012-02-25 01:05:05 UTC
Permalink
Reuse has been mentioned, but I'm not sure anyone
mentioned encapsulation. What makes it a class is that
the scoping renders it an object. I often use classes
in VBScript, where their role is more clear due to the
simplicity. It just involves adding the class at the end
of a script:

Class Something

End Something

The public scope is visible from inside the class. The
class's private scope is not visible from outside. So
you can design an interface of your choice by creating
public methods in the class. And it's self-contained, so
you can reuse it without needing to adapt the rest of
the project. For instance, I can add a class to
encapsulate Registry operations, then create that
as an object in my script, then call very simple and
sensible functions of my own design from the script
code.
--
--
"Peter Nolan" <***@gmail.com> wrote in message news:e20a08e0-5d12-4ec8-bb47-***@hs8g2000vbb.googlegroups.com...
| Hello,
|
| I have tried, trust me, to learn what a class is in VB and in spite of
| many an attempt I remain baffled and I was wondering if you could help
| me out. In addition to reading I have watched YouTube videos.
| I know that fish is a class and so a trout is an instance of the class
| fish. I also know that a class contains a function and data. I better
| leave it at that because of how confused I am about the whole thing.
| I just want to add that when I posted recently about the Beep Function
| I went on to say a lot of things about M$ but I want you to understand
| it was not my intention to upset but it was my motivation to
| contribute to the life of this newsgroup. It was my rather camouflaged
| effort to thank, believe it or not, MIke Willams for helping me out
| with two great blocks of code. I realise you might not understand that
| but I didn't want to pop up out of nowhere to then disappear back into
| depths of cyberspace without making an effort to add something.
|
| Regards,
|
| Peter Nolan.
| Dublin.
|
|
Loading...