VB, Objects, and Collections

Justification

VB was designed in a simpler time.
It simply encapsulated the complexities of the Windows API
Now VB has a far more ambitious role.
It is used to manipulate all kinds of information - databases, applications, documents
It has evolved to a kind of universal macro language within the MS world
The older ways of looking at things are no longer relevant.
 

What is an object?

That's a good question
We will look at true Object oriented programming later
For now, lets go with some examples rather than a definition.
Each of the components you are used to is an object
Some of these contain their own objects.
(text box has a font object as one of its properties)
VB can also deal with other programs as objects
Databases and other entities count as well
 

New Variable Types

We can create object variables with the DIM statement, just as we create more traditional ones.
Example:
dim myText as TextBox
dim wordApp as Word.Application
There are some generic variable types, as well as some more specific types
Variant can contain ANYTHING... An object, a control, a traditional type, even an array
Object can contain any Object, including controls.
Control is an actual screen component (text box, timer, scroll bar, etc).
Collection is a special kind of array-like object designed to hold other objects.
(We'll see more about them later today).
You generally want the lowest - level you can get away with, as the higher level types take up LOTS of memory.

Using variables for components

You can dimension variables with all the component types you are familiar with.
You can then use the set command to bind a reference to that variable.
You will usually bind a variable to an existing component.
You can then manipulate the variable and the component will change dynamically.
It is good practice to release the object when you are finished by Setting it to Nothing
Study the following code for an example of this:

'Requires a form with txtTheRealTextBox on it
 

Private Sub Command1_Click()
  Dim varTextBox As TextBox
  Set varTextBox = txtTheRealTextbox
  varTextBox.Text = "I changed a variable!!!"
  Set varTextBox = Nothing    'reclaim the memory
End Sub
 

Collections

VB5 introduced a new concept called collections.  This actually existed earlier in VBA.
A collection is a type of object, designed to hold other objects.
There are a number of special collections already built-in to Office and VB.
Generally, these things will end in the letter 's'.
For example, the Excel object reference contains Worksheet and Worksheets
Worksheet is an object type, and worksheets is a special collection designed to work with
elements of the worksheet type.
Such special collections act a lot like normal collections, but not always!!!

Frequently we step through a collection with a special variant of the for loop called for each:

Private Sub Command1_Click()
  Dim theControl As Control
  For Each theControl In Form1.Controls
    MsgBox (theControl.Name)
    theControl.BackColor = QBColor(1)
  Next
End Sub

As you can see, this code would first generate a generic control variable
We then will step through the controls collection of the form
Each time through the loop, the current control will be in theControl
The number of iterations will be automatically calculated
We will then msgBox out the name of the control
Finally, we will manipulate the color of the control, if that is appropriate
Here you can see why it is nice to have references.

As another example, this code replicates Java's auto-resize behavior
 

Option Explicit
Dim XSize As Integer
Dim YSize As Integer
Dim XRatio As Single
Dim YRatio As Single
'resizer
'Andy Harris, 1/29/98
'Demos use of controls as objects and collections
'Note that this will work on pretty much ANY form!!!

Private Sub Form_Load()
  'set up initial values for Sizes
  XSize = theForm.Width
  YSize = theForm.Height
End Sub

Private Sub Form_Resize()
  'whenever the form is resized...
 
  'Get new ratio values
  XRatio = theForm.Width / XSize
  YRatio = theForm.Height / YSize

  'reset the values for X and Y sizes
  XSize = theForm.Width
  YSize = theForm.Height
 
  Dim thing As Control
 
  'step through each element in the built - in controls
  'collection
  For Each thing In Controls
    'We'll get an error for controls without width and height
    '(menus, timer, yada yada)
    On Error Resume Next
    'Use the ratios to find new values for size and placement
    'of each control
    thing.Width = thing.Width * XRatio
    thing.Left = thing.Left * XRatio
    thing.Height = thing.Height * YRatio
    thing.Top = thing.Top * YRatio
  Next
 
End Sub
 

Making your own collections

Collections are interesting little beasts.
They are something like arrays They also have distinct differences from arrays: A collection may be a better choice than an array when you want to take advantage of its features.
The indexing and multiple type capability are especially useful.

Example - the collection demo

Screen shot...

'CollDemo
'By Andy Harris
'Demonstrates use of simple collections
'

Dim People As New Collection
Private SearchType As String

Private Sub cmdGo_Click()
  If SearchType = "INDEX" Then
    MsgBox (People(scrIndex.Value))
  ElseIf SearchType = "KEY" Then
    MsgBox (People(lstKey.Text))
  End If
End Sub

Private Sub Form_Load()
  'general initialization
  Dim person As String
  SearchType = "INDEX"
 
  'add stuff to the collection
  'Note use of the with structure to simplify syntax
  With People
    person = "Bill"
    .Add person, "President"
    person = "Hillary"
    .Add person, "Wife"
    person = "Chelsea"
    .Add person, "Daughter"
    person = "Monica"
    .Add person, "That Woman"
    person = "Socks"
    .Add person, "Cat"
  End With
 
  'Initialize the scroll bar
  scrIndex.Max = People.Count
  'note that the min on a collection is 1,
  'but I'll leave this min to zero to test that assumption
 
  'Initialize the list box
  lstKey.AddItem ("President")
  lstKey.AddItem ("Wife")
  lstKey.AddItem ("Daughter")
  lstKey.AddItem ("That Woman")
  lstKey.AddItem ("Cat")
 
End Sub
 

Private Sub optIndex_Click()
  If optIndex.Value = True Then
    scrIndex.Enabled = True
    lstKey.Enabled = False
    SearchType = "INDEX"
  End If
End Sub
 

Private Sub optKey_Click()
  If optKey.Value = True Then
    scrIndex.Enabled = False
    lstKey.Enabled = True
    SearchType = "KEY"
  End If

End Sub
 

Private Sub scrIndex_Change()
  optIndex.Caption = "Index (" + Str$(scrIndex.Value) + ")"
End Sub
 

Using other object types

One of the most important uses of objects in vb is to use objects as a link to other libraries.
In other words, we can utilize other Windows programs, and objects exposed by these programs
This is especially useful as a tool to leverage Office programs.
The general strategy works like this

Example - the spell checker

Create a standard document with a text box and a command button
Add a reference on project - references menu to the word 8 object library.
All the action happens in the command button:

'Speller
'Demonstrates Use of Object variables
'Calling Word from VB
'expects cmdSpell, txtSpell
'Word must be installed and NOT CURRENTLY RUNNING
 

Private Sub cmdSpell_Click()
  Dim wordApp As Application
 
  'try to open a new version of word
  Set wordApp = CreateObject("Word.Application")
 
  'Check to see if this works!!
  'see if wordApp exists.  Nothing is a special null object
  'Note also that 'is' is a keyword for comparing objects
  If wordApp Is Nothing Then
    MsgBox "couldn't start word!!"
    End
  End If
 
  'Add a new document
  wordApp.Documents.Add
 
  'Activate the document
  wordApp.ActiveDocument.Activate
 
  'copy text from vb to word
  wordApp.ActiveDocument.Range.InsertAfter txtSpell.Text
 
  'run the spell checker
  wordApp.ActiveDocument.CheckSpelling
 
  'copy back to VB
  txtSpell.Text = wordApp.Selection.Text
 
  'Shut down word
  wordApp.Quit (True)
 
End Sub
 

Control Arrays and dynamic control creation

Control arrays fit somewhere here in this discussion.
As you know, they are generally built in design-time by copy and paste
Usually you build a prototype, then copy and paste it.
You cannot use code to build a control out of nothing
You can, however create a new element of a control array.
Here's an example:

Private Sub cmdClone_Click()
  Static counter
  counter = counter + 1
  Load cmdDolly(counter)
  cmdDolly(counter).Left = counter * cmdDolly(0).Width
  cmdDolly(counter).Caption = counter
  cmdDolly(counter).Visible = True
End Sub
 

Assignment

Create a program in VB that generates some kind of data through VB
(collects it from a user, file, or function)
Use the Excel Graph object library to display a graph of the data.
  or
Do a similar project incorporating the concepts we have learned this week
Be sure to incorporate some features of objects, controls, and collections.