Objectives of the Week
List and Combo Boxes
List Box and Combo Box controls are Visual Basic form of an array. Standalone BASIC supports array structures, but Visual Basic implements arrays using these controls.
Arrays are data structures used for holding a list of related information. Your program can maintain these lists by adding and removing the entries stored, but also use them to allow a restricted list of values from which to choose.
Select the List and Combo Boxes from the Toolbox and draw the controls on the form as you do with most all VB controls.
|
These controls share many of the same events, methods, and properties. But there are some significant differences between how they each function, depending on the style of their implementation.
List Box
When the Checked Property is selected, the List Box acts more like a
set of Option Buttons
as only one item can be selected at a time.
Combo Box
Remember that what you do with arrays or any temporary storage medium is to put data in, and then refer to the data stored in the structure. The List and Combo Boxes share many Methods and Properties that provide allow these functions.
AddItem | ctrl.AddItem [,Position] | Add an Item at the end of the list, or at the specified position. |
RemoveItem | ctrl.RemoveItem Position | Remove an Item from the specified position |
Clear | ctrl.Clear | Empty the List or Combo Box |
Visual Basic Arrays are Zero Based Arrays. This means that they are indexed starting with zero. If there are 5 entries in the array, they are numbered 0, 1, 2, 3, and 4.
So if I code: ListBox.AddItem "New
Item", 3
"New Item" will be placed in Position 3 (0, 1, 2, 3), or what we might think of
as the 4th entry
Coding: ListBox.RemoveItem 1
will remove the item in Position 1 (0,1), or what we might think of as the 2nd entry.
Here are a few List and Combo Box properties:
ListCount | Contains the actual number of entries in the control. If ctrl.ListCount contains a 5, there are 5 entries indexed 0, 1, 2, 3, 4 |
ListIndex | Contains the number of the currently selected entry If what we think of as the 3rd item has been selected, ListIndex will contain a 2 (0, 1, 2) This property contains -1 when nothing has been selected from the list. |
Text | Contains the content of the currently selected item |
Sorted | Boolean. Will maintain the list in Sorted Order when set to True |
MultiSelect | Allows the control to have more than one entry selected at a time. If this is the case, ListIndex contains the last entry selected, and Text contains the content of the last entry selected. |
The MultiSelect property can have three values. None, Simple and Extended.
List Property allows initialization of array items at design time and access to individual entries at run time.
To populate a List or Combo Box at design time, open the List Property and begin entering the content for each array element. Use CTRL-Enter to move to the next line.
At run time, any reference to an entry in the array requires that you specify what entry you want. You must supply an entry number. This number is often refereed to as an index or a subscript.
Both the List and Selected properties require an index.
List | strItem = ctrl.List(i) | Reference to a specific entry in the array |
Selected | If ctrl.Selected(i) Then .... | A Boolean value describing the selection state of a specific entry in the array |
The variable "i" is an Integer that contains the entry number.
The property ctrl.ListIndex contains the entry of the currently selected item so
will operate on the currently selected item, unless there is no item selected (ListIndex will be -1), and in that case, these instructions will fail with a run-time error.
More on processing the array entries after reviewing the Loop Controls
Looping
In general, we have three type of looping constructs available to us. These are implemented in various languages using a wide range of syntax that do not necessarily lend themselves to describing the actual loop construct.
While Loop | Test at the Top | 0 - N times |
Until Loop | Test at the Bottom | 1 - N times |
For Loop | Like a While Loop | Fixed Number of Times |
Here is how VB implements each type of loop:
While Loop (Test at the Top)
Do While condition ' Body of the Loop Loop |
Do Until condition ' Body of the Loop Loop |
Until Loop (Test at the Bottom)
Do ' Body of the Loop Loop While condition |
Do ' Body of the Loop Loop Until condition |
For Loop
For i = intStart to intLimit [Step intStep]
Next i
The integer variables i, j, and k are acceptable conventions for use with For Loops so when you declare them, you don't need to use the int prefix. These variables should always be local to the event handler or procedure.
Using Loops to Process List and Combos
In most situations, a List or Combo Box can be processed using this type of Loop construct:
For i = 0 to ctrl.ListCount - 1
Remember that the List and Combo Boxes are zero based.
When the ListCount property is 5, the entries are reference with index values from 0 to 4.
Referencing entry 5 will cause a run time error as there is no entry 5.
For i = 0 To List1.ListCount - 1
If List1.Selected(i) = True Then
Debug.Print "Item " & i &
" is " & List1.List(i)
End If
Next i
This example will display the contents and the index values for each selected item.
There are times when this method will not work. Specifically, when an item is removed
from the list.
When an item is removed, it changes the value of ListCount.
For i = 0 To List1.ListCount - 1
If List1.Selected(i) = True Then
List1.RemoveItem(i)
End If
Next i
This example will not function correctly when anything except the last item has been
selected and removed.
This is a "bug" or a feature in how VB implements the For Loop.
In Visual Basic, the limit if the For Loop is established during the initialization step. So if the ListCount is 5, the loop will repeat 5 times. When an item is removed from the array, the value if ListCount (the upper bound of the array) is changed. perhaps to 4, and when the 5th pass through the array takes place, the reference is "out of bounds" and the result is a run time error.
Here is one way around this feature:
For i = List1.ListCount - 1 to 0 Step -1
If List1.Selected(i) = True Then
List1.RemoveItem(i)
End If
Next i
Starting at the end and working back toward the top works around that problem.
Examples of List / Combo Box Operations
Message and Input Boxes
A Message Box is a fast and easy (and annoying) way to provide the user with immediate feedback from with your program. Often, this feedback is in response to data entry type errors. Up to this point, the response was to simply let them know there was a problem, and send them back to the program so they could correct the situation and retry. "OK" was the only practical response to these situations.
The MessageBox function allows you to examine the users response and take appropriate requested action.
intResponse = MsgBox("Message",Icon+Buttons,"Title")
If intResponse = vbCancel
' Take the appropriate action
The response codes are based on the button codes used in the MessageBox function.
Button Code: vbAbortRetryIgnore
Response Codes: vbAbort, vbRetry, vbIgnore
The InputBox functions much like the Message Box and is used to prompt the user for input
strItem = InputBox("Enter a new item", "New Item",
strDefault)
If the user clicks on cancel, the Null String is returned to the program,
otherwise, whatever is in the input area is assigned to strItem.
Important to take some care in verifying that what the user entered is correct.
Here is a very basic example checking for the Cancel button and determining if the default
value was changed.
This also includes an example of checking the return value from the MsgBox function.
strItem = InputBox("Enter a new item", "New Item", strDefault)
If strItem = strDefault Then
intResponse = MsgBox("Accept the default name?", _
vbQuestion + vbYesNo, _
"Just Double Checking")
If intResponse = vbNo Then
Exit Sub
End If
End IfIf strItem = "" Then ' User clicked on Cancel
Exit Sub
End If
String Manipulation Functions
Left | Left Substring | strTemp = Left(strSource,Number of Bytes) Left("ABCDEF",3) returns "ABC" |
Right | Right Substring | strTemp = Right(StrSource,Number of Bytes) Right("ABCDEF",4) returns "CDEF" |
Mid | Middle Substring | strTemp = Mid(StrSource,Begin Position, Number of Bytes) Mid("ABCDEF",2,3) returns BCD Mid("ABCDEF",2) returns BCDEF |
Len | Length of String | l = Len(String) Len("ABCDEF") returns 6 |
InStr | Search a String | p = InStr(Start Position (starts with 1), Search String, Target String (often a
literal)) InStr(2,"ABCDEF","D") returns a 4 |
The string functions are necessary to pick apart the pieces of a larger string. You can use InStr to look for occurrences of spaces or commas or other control/format characters used as delimiters in the larger string.
Here is an example of some code that pulls out City, State and Zip from a string. The
CSZ string must be in the format:
City - Comma - Space - State Abbreviation - Space - Zip Code.
It wouldn't take much to convert this code to use the comma between City and State as a delimiter. This would allow the full state name in the format and not just the abbreviation.
Private Sub cmdConvert_Click() Dim p As Integer Dim intSaveP As Integer Dim strTemp As String strTemp = txtCSZ.Text ' Look for the last space p = 1 Do intSaveP = p p = InStr(p + 1, strTemp, " ") Loop Until p = 0 lblZip.Caption = Mid(strTemp, intSaveP + 1) strTemp = Left(strTemp, intSaveP - 1) ' Look for the last space AGAIN p = 1 Do intSaveP = p p = InStr(p + 1, strTemp, " ") Loop Until p = 0 lblState.Caption = Mid(strTemp, intSaveP + 1) lblCity.Caption = Left(strTemp, intSaveP - 2) End Sub |
Printing
The Printer Object represents your workstation printer. In fact, you can set the Printer Object using the ShowPrinter Common Dialog method. Using the Print method and a number of formatting instructions, you can construct nicely formatted print reports from your Visual Basic application.
The Print command is the instruction that will write the output to the printer device. This instruction has a number of format and control characters associated with it.
A Comma tells Print to jump to the next tab setting
A SemiColon tells Print not to append any control character
A Print statement with no punctuation tells Print to generate a CR/LF
Printer.Print "Name",
Printer.Print "Address"
will print Name, followed by a Tab, followed by Address, followed by a CR/LF
Print "Name";"Address" will print NameAddress
where
Print "Name","Address" will print Name Address
Tab(n) | Absolute Column Position |
Spc(n) | Absolute Number of Spaces |
Printer.New Page | Send a FormFeed and Begin a new Page |
Printer.End Doc | Send a FormFeed. This will complete your print job |
You can also change the Font and Color properties of the Printer to suit your particular formatting needs.
Printing to a Form
Rather than route every summary or print request to a print device, a formatted report can be built on the form in much the same way a printed report is constructed.The Form Object shares many of the print related methods that the Printer Object supports.
The main form contains a "Print" button that will send a generated report to the printer. In class, you can provide a form that will provide the same function and not waste paper and tie up the printer.
In FormActivate you can code the same instructions for the Form Object that you would with the Printer Object and send a formatted report to a second form in the project. The Form and Printer Objects are not 100% compatible, but this is often a good method to get a majority of the formatting complete without waiting on the printer.
Here is a snippit of code that can be used to write to the "Background" of a form. This report can refer to the same controls on the main form as when you generate the report on the printer. There is no Printer.CLS method, but there is a NewPage and EndDoc method that controls the paging on the printer.
The Print Method is not listed with the other Methods and Properties in the AutoList feature of VB. It is available though as the Print instruction defaults to the From Object.
Me.Cls
Me.Print
Me.Font.Name = "Courier New"
Me.Font.Size = 24
Me.ForeColor = vbBlue
Me.Print Tab(3); "Shipment Summary"
Me.ForeColor = lngDefaultColor
Me.Font.Size = 12
Me.Print
Me.Print Tab(5); "Item List"
For This Class
Whenever a program says write a report to the printer
make sure that you write it to a form instead.
Review an Example
Download Example and walkthru the code
This example makes use of Combo Boxes, Adding and Removing items from these controls, but also makes use of Multiple Forms and passing a ComboBox as a function argument.
Look at the Change event in frmAdd
If txtAdd = "" Then
cmdAdd.Enabled = False
Else
cmdAdd.Enabled = True
End If
This code prevents the user from putting bad data in the ComboBox because the Add Function is disabled when the TextBox is empty. This is a better technique that simple editing the input and responding with an error message.
This code adds an entry to a ComboBox Object that refers to the selected "Real" control from the Main Form. This type of coding reduces the duplicate code that might be necessary to support all three Combo Boxes
' A control as a variable
' Use the Set command to refer to the object
Dim cComboBox As ComboBox
If optDDC.Value = True Then
Set cComboBox = frmMain.cboDropdown
ElseIf optSC.Value = True Then
Set cComboBox = frmMain.cboSimple
ElseIf optDDL.Value = True Then
Set cComboBox = frmMain.cboDropdownList
Else
Exit Sub
End If
cComboBox.AddItem txtAdd
txtAdd = ""
txtAdd.SetFocus
The Main Form uses the same type of code to initialize the ComboBoxes when the application starts.
Build the Example
Step by Step through the Example
Make sure that you:
Lab 1 -From the Text - Page 284, VB Mail Order
Step by Step through the First Lab
Let me know when you are done and I will check you off as Complete
Lab 2 - From the Text - Page 285, VB Auto Center
You are on your own.
Reading Assignment
Programming Assignment
As Always: The assignment is due before the start of class next week
Student Information Program
Page 280, Problem 7.1
There is one change to this assignment. You must "print" the form information to a second form, nicely formatted. Do not route the output to the printer.