Classes / OCX (1 Viewer)

Mihail

Registered User.
Local time
Today, 13:39
Joined
Jan 22, 2011
Messages
2,373
Hello all !
This thread is intended to be a discussion.

There are many tutorials about how to create a class or an OCX.
So should not be a problem for me to do this.
But I never used this tools because (I think) I am not able to "see" the situations when a tool like this help me to design better programs.

So, be kind, please, and share with me from your experience.
Where this tools should be used ? Where you created a new class or an OCX ? Why you decided to do this ?

While I never used my own classes / OCXs I am sure that I don't know even what should I ask about this subject.
So feel free to answer me also to the questions that I can not formulate :)

Thank you !
 

MarkK

bit cruncher
Local time
Today, 03:39
Joined
Mar 17, 2004
Messages
8,179
I'll take a crack at this. Might take a few iterations, we'll see. For starters, take a look at this type. Have you ever used types in VBA? And if not, maybe experiment with/read about types.
Code:
Public Type AddressType
    AddressID As Long
    Street1   As String
    Street2   As String
    City      As String
    Province  As String
    Country   As String
    PostCode  As String
End Type
With that declaration, you can now declare variables of that type . . .
Code:
Dim MyAddressInstance As AddressType
. . . and assign values to that variable . . .
Code:
   Dim MyAddress As AddressType
   With MyAddress
      .Street1 = "The White House"
      .Street2 = "1600 Pennsylvania Avenue"
      .City = "Washington"
      .Province = "DC"
      .Country = "USA"
      .PostCode = "20500"
   End With
. . . and that's fairly powerful now because we can pass that variable around to other code, like, . . .
Code:
Sub PrintEnvelope(Address As AddressType)
[COLOR="Green"]'  This routine prints the given address to an envelope
   '. . . printing code[/COLOR]
End Sub
But it's tedious filling the type with data, so we can write code for that . . .
Code:
Function LoadAddress(AddressID As Long) As AddressType
[COLOR="Green"]'   Returns a structured AddressType variable loaded
'   with data from the table[/COLOR]
    Dim rst As DAO.Recordset
    
    Set rst = CurrentDb.OpenRecordset( _
        "SELECT * FROM tAddress " & _
        "WHERE AddressID = " & AddressID)
    With rst
        If Not .EOF Then
            LoadAddress.AddressID = !AddressID
            LoadAddress.Street1 = !Street1
            LoadAddress.Street2 = !Street2
            LoadAddress.City = !City
            LoadAddress.Province = !Province
            LoadAddress.Country = !Country
            LoadAddress.PostCode = !PostCode
        End If
        .Close
    End With
End Function
. . . and we can write code to save that data back to the table . . .
Code:
Sub SaveAddress(Address As AddressType)
[COLOR="Green"]'   Receives a structured AddressType variable
'   and attempts to save that data back to the table[/COLOR]
    Dim rst As DAO.Recordset
    
    Set rst = CurrentDb.OpenRecordset( _
        "SELECT * FROM tAddress " & _
        "WHERE AddressID = " & Address.AddressID)
    With rst
        If .EOF Then
            .AddNew
            !AddressID = Address.AddressID
        Else
            .Edit
        End If
        !Street1 = Address.Street1
[COLOR="Green"]        ' . . .
[/COLOR]        .Update
        .Close
    End With
    
End Sub
. . . and as our application grows we might write other functions that we can invoke using the data in our AddressType type, like maybe we open a browser, navigate to google, and show a map of the address . . .
Code:
Sub ShowGoogleMapOf(Address as AddressType)
[COLOR="Green"]'   This routine opens a browser, navigates to google maps, writes this address
'   into the search bar, and effectively shows a map of the address[/COLOR]

[COLOR="Green"]   ' code goes here[/COLOR]

End Sub
. . . so to keep all this related Address functionality together we write them all in a standard module called mAddress. Fine.


Now that's a fair bit of code, and at first glance makes it seem harder to work with address data, but wait. Now that that code is all written, we can get at, edit, and save address data very very quickly, like . .
Code:
[COLOR="Green"]'declare the variable[/COLOR]
Dim MyAddress as AddressType
[COLOR="Green"]'read the data from the table[/COLOR]
MyAddress = LoadAddress(51)
[COLOR="Green"]'make an edit[/COLOR]
MyAddress.PostCode = "26047"
[COLOR="Green"]'and save the changes[/COLOR]
SaveAddress MyAddress

So, I'm out of time, but here's an assignment if you're interested in more:
1) Copy all this code into a new database, into a standard module called mAddress.
2) Create the table described in LoadAddress, and put some sample data in there.
Then we'll use that database to take the step from Types in Standard modules (this post) to Classes (next post), and see the difference.
 

Mihail

Registered User.
Local time
Today, 13:39
Joined
Jan 22, 2011
Messages
2,373
@lagbolt
Thank you very much for your time and help.

I created the DB, I filled it with very general data (you will see) and I attached it.
The compiler was "happy" so seems that all is OK until now.

Have you ever used types in VBA?
Yes and I know how to use types of data.

I "know" even about classes/OCXs: what they are and how are used but, please, continue what you started: the tutorial. I'm sure that this will give me a better understanding. Thank you again
 

Attachments

  • UsingClasses.mdb
    216 KB · Views: 86

MarkK

bit cruncher
Local time
Today, 03:39
Joined
Mar 17, 2004
Messages
8,179
A Class is like a Type in that it can contain structured data, but inside a Class you actually run code, which is a very interesting capability. With a Type you have to pass a variable of that Type to a Sub or Function to get a result, but a class carries all it's functions around with it, so a class can offer a result immediately, and you don't have to remember how to use it.

The enclosed database opens showing a Customer form, and displays that customer's address. What's important in my mind is how light the code is on the customer form. There is a cCustomer object, and apart from that all the form code ever does is run methods of the classes.

The reason this is awesome is that in general, adding new features in a program with rich classes is easy. You've already solved the problems once that the classes need to perform, and you simply invoke them as required with very little code. Or, if you need to add a feature you add it once, to the class, not to the many forms and/or reports where it might be invoked. And, if I want to open a form to edit a customers address I can run code as simple as . . .
Code:
[COLOR="Green"]'create a new class object[/COLOR]
Dim cus As New cCustomer
[COLOR="Green"]'load CustomerID = 4 and show their address[/COLOR]
cus.Load(4).Address.Show
. . . and all the classes in the chain already know how to do all that stuff. This also makes it way easier to make stuff work with ribbons.

And we haven't even started talking about objects raising their own events . . .

Here's the db . . .
 

Attachments

  • UsingClasses.zip
    28.4 KB · Views: 84

CJ_London

Super Moderator
Staff member
Local time
Today, 11:39
Joined
Feb 19, 2013
Messages
16,605
Thanks Lagbolt, I'm enjoying the lesson as well!

Interesting to note that in this example there is an addressID in the customer record whereas the usual advice would be to have a customerID in the address record.

Like Mihail I haven't used classes much so this is a learning curve for me - so is the above a requirement for using classes in this way or is it just the way you happen to have put the lesson together?

Hoping your answer will be quicker than me experimenting!
 

MarkK

bit cruncher
Local time
Today, 03:39
Joined
Mar 17, 2004
Messages
8,179
No, the address needs to exist independent of any strongly typed object so a Customer might have a BillingAddressID and a ShippingAddressID, but a Contact object needs addresses too, and Suppliers need addresses. It wouldn't make sense to have an address table with a CustomerID, SupplierID, ContactID, and whatever else. Really the pattern we're implementing here is more of a many-to-many, where we could have a CustomerAddress table, like, . . .
tCustomerAddress
CustomerAddressID
CustomerID
AddressID
AddressType (Billing, shipping, and so on)

Like Mihail I haven't used classes much so this is a learning curve for me - so is the above a requirement for using classes in this way or is it just the way you happen to have put the lesson together

I'm not sure what you mean by "the above requirement." This code, including that in the posted database, looks a lot like what I write in a normal database. There are rules the language requires, like, you need to create a new instance using the New keyword . . .
Code:
dim csr as new cCustomer
. . . but exposing classes as properties is a pretty common pattern. Is that what you mean?

Mark
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 06:39
Joined
Feb 19, 2002
Messages
43,213
I think we're about to loose the OCX model with O2013. Or, maybe it is just if the 64-bit version is installed.
 

CJ_London

Super Moderator
Staff member
Local time
Today, 11:39
Joined
Feb 19, 2013
Messages
16,605
@Mark
I actually said "the above a requirement":) which you answered in your first paragraph - I was referring to the 'requirement' of having the addressID in the customer record and not having the customerID in the address record which is the way it is usually presented -as a family key.
 

MarkK

bit cruncher
Local time
Today, 03:39
Joined
Mar 17, 2004
Messages
8,179
Oh, got it now. Yeah.

And @Pat, what does that mean, "loose the OCX model?" No more ActiveX controls?
 

Mihail

Registered User.
Local time
Today, 13:39
Joined
Jan 22, 2011
Messages
2,373
Thank you all for your comments.
On my side I need time to "compile" the information.
As I can see the thread become more interesting with any new post.
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 06:39
Joined
Feb 19, 2002
Messages
43,213
Before committing to using an OCX, make sure there is a 64-bit version available and that it will work with Access 2013.
 

Users who are viewing this thread

Top Bottom