Professional Documents
Culture Documents
or
A Beginners Guide to using a Subform control in place of a Standard List Box control
Introduction
The standard List Box control that comes with all versions of Access is very useful for providing a
list of items on a form and is generally easy and quick to set up. It also has the facilities to
select/deselect items on the list, select multiple rows, read which row/s are currently highlighted
and so on. However, it has very limited formatting facilities for text alignment, color coding,
graphics images, etc which tends to make it look a bit plain and boring in modern applications.
The accompanying (Access 2003) demo database shows a method of providing a better looking
alternative to the normal List Box control by using a standard Subform control instead. Using this
method is a little bit more complicated to set up but the resultant Graphical User Interface (GUI)
provides a better experience for the application users and can also provide more facilities than the
normal list box.
The demo database is based on the ‘Northwind’ example database from Microsoft (the table names
and some field names have been changed slightly although the data itself is unchanged) and
consists of several forms that each use a subform control to emulate a list box with various
different facilities and formatting options. The standard list box also has a number of facilities
which can be used with some VBA code to read data from the control, set/clear the highlighting on
one or more rows, count the total number of rows or the number of highlighted rows, etc, etc. To
provide all these facilities with a subform control is a little more complicated so a set of VBA
procedures has been provided in a separate code module which can be called with (usually) one
line of code that can perform the same functions as the list box equivalent (see below for more
details).
To try out the demo database just run it is normal and select each option in turn on the main
Switchboard. The function of the various fields and buttons are described in more detail below.
When you have created the form and saved it you should set up various properties as described in
the next section and save it again, these basic changes will be much the same for all the examples
shown below. Where additional changes are required they are specified in the appropriate section.
Page 1 of 17
To make the basic changes open the form in Design mode and set up the properties as follows :-
1. Record Source. Set this property to the table or query or SQL string that will supply the
data for the list. A query is preferred to a table here because it gives you a bit more control
over the listed data such as sorting, criteria, etc.
2. Default View. Change this property to ‘Continuous Forms’.
3. Allow Datasheet View, Allow PivotTable View and Allow PivotChart View. Change
these three properties to ‘No’. If you don’t change these, the user could right-click on the
list box and change the form view to a different type (which you would not normally want).
4. Allow Edits, Allow Deletions and Allow Additions. Change these three properties to
‘No’. Normally you cannot edit records in a list box but if you do want to allow this then
you will need to leave these as ‘Yes’ (but then it just becomes a normal subform which
rather defeats the object of this exercise).
5. Scroll Bars. Change this property to ‘Vertical Only’. Depending on how you want the list
box to work, you could also use ‘Neither’ or ‘Both’ but generally a list box only has a
vertical scroll bar.
6. Record Selectors and Navigation Buttons. Change these properties to ‘No’. A list box
does not need these.
7. Dividing Lines. Change this property to ‘No’. You could leave this one as ‘Yes’ which
will then show a line below every row but the list generally looks tidier without those lines
(especially as you cannot change the line color to anything but black).
8. Cycle. Leave this property as ‘All Records’. By doing this (and adding one line of code to
the form’s Form_Current event) the user can use the Arrow keys to move the highlighted
row up and down the list. If you do not require this option then change the property to
‘Current Record’.
9. Tag. Leave this property blank or change it to 0, 1 or 2 (see below for more details).
In addition to the above form properties you should also enable the Form Header/Footer option
on the menu or ribbon to display those form sections. The Header section of the form would
normally hold the column headings (unless you don’t need them) and the Footer section may or
may not be required, depending on how you want the list to look. On the first example the Footer
section is used to display the grand sales total but on the other examples the Footer section is
hidden. If you don’t need either section just click on the Form Header or Form Footer bar and
set the Visible property to ‘No’. You should also click on the Detail bar and change the Back
Color property to white, if you don’t the default form back color will show at the end of the list
which looks kind of messy.
At this point you should add the fields and controls to the Detail section of the form but since these
can vary considerably, depending on the fields and layout, this procedure is covered in more detail
below. Assuming that you have the subform set up with the required fields, etc you can now add
the subform to the main form. To do this open the main form in Design mode and drag the
subform onto it in roughly the required position. Delete the subform label and change the height of
the subform to roughly the size required (the width is usually the right size anyway).
You can now change some properties of the subform control itself. Click on the control and change
the Border Width property to ‘2 pt’, you can use different values but this setting looks the best
(but it depends on what sort of look you want for your form, of course). Now position the subform
in the required position on the main form and adjust the height, as required. Next, double-click on
one of the ‘sizing’ boxes around the edge of the subform which will automatically set the size of
the form to fit the controls within the form (you may need to re-adjust the height again).
Page 2 of 17
Basic (Non-interactive) List Box
The standard List box control can be set up in a number of different ways, it can be used to just
display a single list of items or it can display multiple columns or the user can click on items to
highlight one or more rows, etc, etc. The first example on the Switchboard menu is the simplest
type, a list of employee sales figures for each year where the user does not need to interact with the
list items.
When you have set up the basic subform (as described above) and set up the query with the
required fields you should drag them onto the form and position them horizontally in the required
order (open the form frmYearSalesSub in Design mode to see how it works). The Detail section
height should be made the same as the height of the Text box controls so that there is no gap
between rows. You would also set up the Text box control properties for the fields like this :-
1. Enabled = ‘No’.
2. Locked = ‘Yes’.
3. Border Style = ‘Transparent’. You could also make this ‘Solid’ if you want boxes around
the controls but this does not look much like a standard List box then.
4. Back Style = ‘Transparent’. In this example this option does not really matter but for the
later examples, where a row is to be highlighted in a different color, it is necessary.
5. The Text box formatting properties can be set up, as required. In this example the first field
is shown as Bold and Center Aligned, the second field is Left Aligned and the third field
is Right Aligned. You would obviously set up your own fields to suit the data used.
6. Name. The Text box names have been changed to Column0, Column1 and Column2 in this
example. Again, this is not necessary for this list box because there is no user interaction
with the controls but in the later forms the names are used to identify the various columns.
7. Conditional Formatting. If you want to change the formatting of some fields depending
on the data in the field (or another field) you can use the standard built-in Conditional
Formatting facilities (although not used in this example).
On a standard List box control a vertical line is displayed between each column (where there are
multiple columns). The first two examples on the Switchboard menu also show these lines which
is done by adding a small vertical grey line between the three Text box controls. However, this is
quite fiddly to set up so on the last two examples they are not provided and the display still looks
pretty good and is much easier to design. You will have to decide which option you prefer.
As you can see in this example, the Header and Footer sections of the subform have been made
visible and the BackColor changed to pale blue, the Header holds the column labels and the
Footer holds a Text box control to display the total sales figures. The Combo Box control on the
main form is used to select all years or a specific year and some VBA code in the AfterUpdate
event of the Combo box is used to refresh the subform control data like this :-
The procedure for setting up the subform controls for the remaining examples is very similar to the
above, except where otherwise stated.
Page 3 of 17
create your own if you prefer). The group of controls at the right of the form are just there so that
you can test the various facilities and see the VBA code required to perform those tests, see below
for more details).
To provide these extra facilities you will need to add three more Text box controls and one button
to the subform and you will need to use the control names shown below (assuming you want to use
the VBA functions provided).
To set up a subform to be used as a list box that can have items selected or processed you should
first create a new form and add the query and fields to the form, as described in the previous
sections. Where you have multiple columns the Text box names, from left to right, should be
changed to Column0 to ColumnX (where X is the last column number). As before, you can add the
column labels to the Header section and, for this example, make the Footer section invisible.
Important Note: In order to be able select an individual row in the list you must have one unique
numeric field in the query, i.e. a field that has a different value in each row (although it does not
necessarily need to be visible in the list). Usually you would have an AutoNumber type field in a
table which could be used, although it depends on the data format. In this example, the data being
displayed is a list of orders for each customer so the unique value here is the Order No field
(OrderID in the query) and so this field is used as the row identifier field (see below for details).
In addition to that you need to also do the following :-
1. Add two Text box controls to the Footer section and name them txtSelect and txtIndex.
You can delete the associated labels if you wish although it will not affect the operation
either way. If you need to have some of your own controls in the Footer section you should
keep the Footer section visible and make these two new Text box controls invisible. Set
the Default property of the txtIndex control to 0.
2. Add another Text box control to the Detail section, change the Name property to txtRef
and delete its associated label, this control which will act as the highlight control. If you
have already added the main data fields to the form then the easiest way to do this is to
make the height of the Detail section of the form bigger (by dragging the Form Footer bar
down a centimetre or so) and then temporarily placing the new txtRef control below the
others. Now make the width of this control the same width as the form (or however wide
you want the highlight area to be) and make the height of the control the same as the height
of the other controls. Change the ForeColor and BackColor properties to white (or
whatever background color you are using) so that any text in the field will not show up in
the list. Make the Border Style property ‘Transparent’ and make sure the Back Style
property is ‘Normal’. Next, set the Control Source property to the name of the unique
numeric field (OrderID in this example), note that you can also use this field in one of the
displayed fields if you wish, as it is in this example. (Note: This unique field could be set
up as a text type field but if the database has several List box controls that use this method
it would get very complicated to write common functions that could handle Text and
Numeric values so it is simpler to only use Numeric values as the unique identifier field).
Now click on the Conditional Formatting icon on the menu or ribbon and set up the
format parameters as shown in Fig 1 below. When that is done, move the Text box control
up to the top of the Detail section so that it covers the other existing controls and then click
the Send to Back icon on the Format Menu or Ribbon to place it behind the existing
controls. Provided the Back Style property of the other fields is ‘Transparent’, the color in
this control will show through the other controls.
3. Add a new button to the Detail section and make the width the same as the width of the
subform and the height the same as the Text box controls. Change the Name property to
‘cmdSelect’ (without the quotes, of course) and change the Transparent property to ‘Yes’.
Now move the button up to cover the existing Text boxes and then click the Bring to
Front icon on the menu or ribbon to ensure that it is placed above those controls. The
Page 4 of 17
reason for this button is that the user will need to be able to click on a row in the list box in
order to select and highlight it and if the various Text box click events were used for this
we would need to repeat the same event code several times. Also, the mouse cursor would
change to the I cursor (instead of the standard arrow icon) which does not look right for a
list box control and so a transparent button gives a better effect and makes it easier to write
the necessary VBA code. In the cmdSelect_MouseDown event for this button add this
line of code - SelectRow Me, Shift 'highlight selected row
See below for more details on adding VBA code for the list boxes. With all the controls
now added to the Detail section you can set the height back to the original size so that there
is no gap between the rows (unless you really need a gap, of course).
4. Change the subform’s Tag property to 0 (note that this is the Tag property for the form
itself and not the subform control, see the example forms if there is any doubt). The
standard list box control has three ‘modes’ which are defined by the Multi Select property
and these are ‘None’, ‘Simple’ and ‘Extended’ (which equate to 0, 1 and 2 in VBA coding).
In order to simulate these three modes the subform’s Tag property is used here to act as the
list box Multi Select property and the associated code functions check this property when
called from the main form and perform the necessary actions. This makes it very easy for
the programmer to switch from one mode to another just by changing the value in the Tag
property. Since this example does not require multiple selections the Tag property should
be set to 0 (note that on the first example described above, the form did not have any user
selection facilities which meant that as the code functions were not used, the Tag property
was not used there).
Select Expression Is for the condition and enter the following into the parameter field :-
Select the color you want on the highlighted line/s for the BackColor and ForeColor icons (in this
case it is yellow but you can, of course, choose any other color). By making the background and
text colors the same, any text in the txtRef field will not show when a row is selected. Click OK to
save the settings and close the form. Note that the ‘comparison’ parameter could be simplified a bit
for this situation (where only one row at a time is highlighted) but the following examples that
require multiple rows to be selected together will need this code so it is simpler and more flexible
to just use the same code on all examples.
Page 5 of 17
How Does It Work?
When you open the second example form (Order Totals by Customer) you can see that by clicking
on a row in the list, the background for that row changes to yellow and you can click on any other
row so that only one row at a time is selected. Also (as mentioned above) you can use the UP and
DOWN arrow keys to move the highlighted row up and down the list.
When the user clicks on a row in the list the VBA code in the MouseDown event for the hidden
button (cmdSelect) calls the SelectRow sub-routine in the code module (see below for more
details) which simply copies the unique numeric value from the txtRef field for that row to the
txtSelect control in the Footer section of the subform. The reason that the MouseDown event is
used here, rather than the normal Click event, is because the MouseDown event triggers when the
button is pressed which then moves the highlighting from the current row to the new row
immediately whereas the Click event only triggers when the mouse button is released which does
not look quite so good. Also, using the MouseDown event, has the added advantage that you have
access to the x co-ordinate of the mouse which you could use to determine which column the user
clicked on and then take some action based on the column number.
The Conditional Formatting code for the txtRef field on the row compares the contents of the
txtRef field with the contents of the txtSelect control in the Footer section and if they match the
txtRef field colors are changed to yellow (or whatever color you chose) which then shows through
the other fields for that row. To see this code working you can temporarily unhide the form’s
Footer section and you can see the contents of the txtSelect control change as you click on
different records. The Index control should also change to show the current index value of the row
although this data is not actually used for this type of list, see below for more information. Note
also that the value in the txtSelect control is wrapped in brackets, while not strictly necessary for
this type of list it is required for the multiple selection list types as described later.
To update the txtSelect and txtIndex controls in the Footer section when the user clicks a row you
need to add just one line of code to the MouseDown event for the hidden button (cmdSelect) which
will look something like this :-
The SelectRow sub-routine in the imported code module has code which updates the two control
fields with the data from selected row and the value in the Tag property is used to determine which
type of list is being used. The identity of the subform is passed to the sub-routine as the Me
parameter so that you could have several list boxes on different main forms that all use the same
sub-routine. The Shift parameter from the MouseDown event is also passed to the sub-routine
which is not actually used for this particular list box type but is used for one of the multiple
selection types (see below).
This is basically all the code you need to highlight a row when the row is clicked on. However, if
you need the facility to move up and down the list using the keyboard arrow keys you should also
add the same line of code to the subform’s Form_Current event like this :-
SelectRow Me, 0
Page 6 of 17
Note that the only difference here is that the second parameter is set to 0 since there is no Shift
value to send to the sub-routine (and this parameter is not required for this type of list anyway).
In addition to the above code you could, of course, add further code to provide other facilities for
the users. For example, if you double click on a row a form will pop up to show the current Order
No of the row and in your own project you could easily extend this to do other things. Have a look
at the subform (frmOrdersListSub) VBA code to see how this works.
One other item to note is that when a Continuous type form is displayed the first row normally gets
the focus which in this example would highlight the first row (because of the code in the subform’s
Form_Current event). If you do not want this to happen (and it would not normally happen with
a standard list box control) then you should also add a line of code to the Form_Open event of the
main form which will disable this option, something like this :-
You will need to replace the subform name above with your own subform name, of course.
The functions listed here are for the second example form (Order Totals by Customer), the
examples below for multiple row selection have some others which are described in the following
sections. In all the code examples below a reference to the subform being used as the list box must
be passed to the sub-routine or function as an in-line parameter. In the descriptions below these are
just shown as Me.SubformName which you would replace with the name of your subform. See
the VBA code in the main forms to see how it works in practice.
On the example form you can click the Get List Count button to display the total number of
records in the list in the associated Text box.
On the example form click the Get List Index button with no records selected which will then
display -1 in the associated Text box and then select a row and try again to show the Index number
for that row (which is zero based, of course).
Page 7 of 17
Select / Deselect Row Procedure
To select a row and make it the current row you can use the RowSelected procedure (the
standard list box equivalent to this function is lstbox.Selected(n) = True (or False to
deselect a row) where n is the row index number. For the subform version the procedure call is
something like this :-
where RowNumber is the number of the row to be highlighted (and remember that the row
numbering starts at 0) and the third parameter is set to True to select the specified row or set to
False to de-select the specified row.
To try this out on the example form you can enter a row number (between 0 and 829 for this list) in
the Row field and click the Set Selected button to highlight the selected row. If the selected row is
not already visible on the form the list will be moved so that the new selected row is at the top of
the subform (or within the subform if the row number is less than the number of visible rows).
Note that if you try and select a row number that is not valid (i.e. higher than the number of rows
in the list) the command is just ignored.
As mentioned above, you can also de-select an already selected row by using False as the last
parameter and you can also test if a particular row is selected or not (see the next form example
below for more details).
where n is the number of the column you want to read (between 0 and the highest number
column). Note that the returned data is a Variant type (since the column data could be any type)
and so you may need to format the data before copying it into a Text box or whatever.
To try this out on the example form first enter a number between 0 and 6 in the Col field, click on
a row and then click the Get Column Data button. The contents of the selected column for the
highlighted row will be displayed in the Data field below the button, if a row is not selected or the
column number is not valid, a Zero Length String will be returned. Note that you can format the
returned data in the normal way, for example, if you click on columns 5 or 6 the currency fields
will return just the numbers so if they are being displayed on a form or report you may need to
format them first, i.e. something like this :-
x = Format(GetColumnData(Me.SubformName, n),”Currency”)
Page 8 of 17
Get Column / Row Data Function
The previous function can be used to return the data for a column in the currently selected row but
the standard list box control also has the option to fetch the data from any column in any row and,
for the subform version, this facility is provided by the GetColRowData function. It is similar to
the previous function except that you can specify the column and row numbers and it does not
matter if a row is selected or not. The function call would look something like this :-
where Col is the column number and Row is the row index number.
As in the previous function, a Variant type data is returned and the Column and Row numbers
must be valid, a Zero Length String is returned if they are not valid numbers. On the example form
you can test this out by entering valid column and row numbers in the Col and Row fields and
clicking the Get Col Row Data button to display the field data in the Data field below the button.
For the subform list box the unique numeric value that is used in the txtRef control acts like the
‘bound’ column on a standard list box control and this is the value that you would pass to the
procedure in order to select that row. In other words, if the reference field for the subform list is
the OrderID field (as it is in the example form) then you would pass the required OrderID value
to the sub-routine to highlight that row in the list.
You can test this facility on the example form by entering a valid Order No into the Value field
(10682 for example), pressing the TAB key and then clicking the Set Row Value button to
highlight row 15 in the list which is the row for Order No 10682. If you enter an invalid value
then any existing selections are removed.
You can test this facility by selecting a row and then clicking the Clear Current Selection button.
Note that on the multiple selections forms described below this operation will clear all selected
rows.
Page 9 of 17
Fetching Data from Multiple Rows
With the standard list box control you can easily scan through each row in the list and read the
current data or set/clear the selection, etc, etc. It is not easy to provide a simple procedure or
function to do this since there are so many variations that could be used but it is easy enough to
execute the same sort of procedure using the Access RecordsetClone function. The code snippet
below shows a method of scanning every record in the subform list and reading the data from one
of the columns or fields.
vControl = Me.SubformName.Form("Column3").ControlSource
Set rst = Me.SubformName.Form.RecordsetClone
rst.MoveFirst
Do Until rst.EOF
vResult = rst(vControl) ‘fetch Column3 data for current row
rst.MoveNext
Loop
rst.Close
Set rst = Nothing
End Sub
In this example the data from column 3 for each row is copied into variable vResult, in your own
code this data would then be processed in some way, of course.
The first line of the code fetches the name of the field from the Control Source property of Text
box ‘Column3’ and copies it to variable vControl. Then the rst recordset object is set to a copy of
all records in the subform and each record is processed within the Do…Loop. If you know the
name of the field that you want to process you could simplify the code a bit, for example you could
remove the first line of code (where the variable vControl is set) and replace the vResult line with
something like this which copies the current OrderID value into vResult :-
vResult = rst!OrderID
You can try this out on the example form by opening the VBA code window for the Click event
of the button cmdTest and setting a break point on the rst.MoveNext line, click the Test button
on the form and the vResult variable will show the order date (i.e. column 3) for each record in
turn when the code hits the break point.
This code snippet is just an example of reading data from a recordset clone and in your own
database project you would need to design your own code depending on the requirements of the
program. If you need to design some code which uses a similar subform list format you could
modify this code to try it out before you implement it in your own database.
Page 10 of 17
Multiple Row Selection (“Simple”) List Box
The standard list box control can also be set up to allow multiple rows to be selected at the same
time by setting its Multi Select property to ‘Simple’ and, as discussed above, this can also be
simulated on the subform list system but with more flexibility in that the highlight color can be any
color. To see an example of how the form could look you can open the third option on the main
menu called “Product Sales by Supplier”. Clicking on one or more rows will highlight them in
pink and clicking on a highlighted row will change it back to white. Also, in this example, the Cat
Icon column is displayed as a simple image and the Dis column as a standad Check box, see below
for more details.
To set up a multi selection subform list like this you should create a new form in the same way as
the previous ‘single selection’ form but with the following changes :-
1. Set the Tag property of the subform to 1 (to identify the subform as a ‘Simple’ multi
selection type list) which then allows the various procedures to use the appropriate code.
2. This is basically all you need to do to make the list into a multi select list but there is one
other minor change that makes the form look better. When you create the txtRef Text box
(which is the control that shows the highlight color) you should change the height of the
control so that it is 1 pixel shorter than the other controls and then move it down by 1 pixel.
The easiest way to do this is to change the control’s Height property on the Properties
sheet by trial and error (for an 8 point font one pixel is approximately 0.023 cm) and then
move the control down one pixel with the CTRL + DOWN arrow key. Doing this provides
a 1 pixel gap between lines where adjacent rows have been highlighted and looks a bit
better than having a large block of rows colored together.
Also, the ‘Discontinued’ (Dis) column shows a standard Check box control instead of a Text box
control which looks better for this type of field. Note that, as with the other columns, the Check
box control Name property is set to ‘Column6’ so that it can be used with the various procedures
provided and that it will return 0 (False) or -1 (True) if you use the function to read its status.
Page 11 of 17
The Conditional Formatting code that you entered for the txtRef control in the previous form
checks whether the ProductID value for each row is present in the txtSelect Text box control and
if it is, then the color of the txtRef field is changed to whatever color you chose.
To update the form display you need to add just one line of code, as before, to the MouseDown
event for the hidden button (cmdSelect) which will look something like this :-
The SelectRow sub-routine, in the imported code module, reads the value of the Tag property of
the form and changes the way the field value is copied to the txtSelect control, as described above.
Note that the value of the CONTROL and SHIFT keys are not used for this type of list box so the
Shift parameter is ignored here.
On the demo form there is no button to use this option but the No of Items Selected field shows
the current number of selected rows, which you can see if you select and deselect different rows.
This field is updated in ‘real time’ because the function has been added to the Text box control’s
Control Source property (in the same way as you can do for the standard list box) like this :-
=ItemsSelected([frmSuppliersSub])
where RowNumber is the number of the row to be highlighted and the third parameter is set to
True to select the specified row or set to False to de-select the specified row (note that using this
Page 12 of 17
procedure also sets the Index to the specified row and that the No of Items Selected field is
updated automatically each time).
To test this on the demo form just enter a valid row number into the Row field and click the Set
Selected button to highlight that row or click the Clear Selected button to un-highlight the same
row.
where RowNumber is the index number of the row to be tested. The function returns a Boolean
data type of True if the row is currently selected and False if it is not selected.
You can test this with the demo form by first entering a valid row number in the Row field and
then clicking the Get Selected button. If the specified row is highlighted the Selected field will
show ‘True’ and will show ‘False’ if it is not highlighted.
vControl = Me.SubformName.Form("Column2").ControlSource
Set rst = Me.SubformName.Form.RecordsetClone
rst.MoveFirst
Do Until rst.EOF
If GetSelected(Me.SubformName, rst.AbsolutePosition) = True Then
vResult = rst(vControl) 'process collected data here
End If
rst.MoveNext
Loop
rst.Close
Set rst = Nothing
This code is basically the same as the routine in the previous section except that before the data is
read from the specified column, the status of the row is checked to see if it is a ‘selected’ row or
not. The GetSelected function is called and the current row index number (a numeric value in
rst.AbsolutePosition) is passed to the function which then returns True if the row is
selected or False if not. The data in variable vResult would then be processed as appropriate.
As described in the previous section, you can try this out on the example form by opening the
VBA code window for the Click event of the button cmdTest and setting a break point on the
vResult = rst(vControl)line, click the Test button on the form and the vResult variable
will show the contents of column 2 for each selected record in turn when the code hits the break
point (note that in this case you will first need to execute the code on this line with the F8 key to
get the data into the variable).
Page 13 of 17
Multiple Row Selection (“Extended”) List Box
The standard list box control can also be set up to allow multiple rows to be selected in different
modes by setting its Multi Select property to ‘Extended and using the SHIFT and CTRL keys on
the keyboard. To see an example of how the form could look you can open the fourth option on the
main menu called “Supplier Products” which shows a list of all products along with the supplier
name, category, country and total sales. The last column displays a bitmap image which is
associated with the Category column, see below for more information.
This subform is slightly different in that the Text box controls use the Calibri font and a font size
of 10 pts (which is the default font for A2007 and later) and the Tag property is set to 2 to
designate it as an ‘Extended’ type list box. Apart from the Tag property value the form would be
set up in exactly the same way as the previous example.
1. If a row is clicked then that row is highlighted and any other row/s are un-highlighted
(which is basically the same as the second example form). Note however, that you cannot
use the UP and DOWN arrow keys to move the highlighted row because if you add the
SelectRow procedure to the form’s Current event (as in the earlier example) it interferes
with the facilities described below.
2. If a row is clicked while the CTRL key is held down then that row is highlighted (or un-
highlighted if it is already highlighted) and any other highlighted rows are not changed
(this is the same as the third example form).
3. If a row is clicked while the SHIFT key is held down then all the rows between that row
and the previous row that was clicked on are highlighted including the current and last
selected rows. Any other selected rows that are outside this range are not changed.
Note. The method used to highlight the rows with the SHIFT key is slightly different than the
standard list box control which appears to maintain a separate list of items that have been selected
using the SHIFT-Click method. You can test out this difference with the standard list box control
on the fifth menu option (see below for more information) which has been set up as a Multi-Select
Extended List box for test purposes. To see how the standard list box control works, try this :–
If you now try the same operation on the subform list example, this does not happen in quite the
same way. It would probably be possible to provide the exact same facility but would make the
code and form a lot more complicated because you would need to have extra fields on the subform
to hold a list of previously selected rows and copy them back into the txtSelect control at the right
time to ensure the rows are highlighted with the Conditional Formatting facilities and for a fairly
obscure facility like this it does not seem worth the extra complication.
Page 14 of 17
Adding Graphic Images to a List Box
Yet another advantage of using a subform instead of a standard list box is that you can also have
images displayed on each row. In the example form, the last column is displayed as an image
which is associated with each product category (the images themselves in this example don’t really
mean anything, they were just picked at random from a selection of same size images). To provide
an image on a list you should add a Bound Object Frame control to the form, change the name to
‘Column5’ (or whatever number is appropriate) and set the Control Source to the name of the
field in the bound query (i.e. CatPicture in this example). You will need to decide which option to
use for the Size Mode property (Clip, Stretch or Zoom) by trial and error which will depend on the
size and nature of the images. The various other properties such as Border Style, Border Color
etc should be set up depending how you want the image to look. Note that if you leave the
Enabled property as ‘Yes’ and the hidden button (cmdSelect) does not cover the image control
then the user could double-click on it and change the image (probably not a good idea but the
option is there). There are a number of properties that are specific to this type of control which
would not normally be required for this type of application but if you need them you should be
able to find more information in the Access Help file or on the Internet.
Now you also need to add the image itself to the appropriate table, in this case it is table
tblCategories. If you double-click on the table in the Database window you can see that the
CatPicture field (which is an OLE Object type field) shows ‘Bitmap Image’ for each record and
if you double-click on one of those the Windows Paint program should open and display the
image. You can edit it using this program or you can change it to a different image with Paint by
clicking on Paste –> Paste from .. and choose a different image in the File Selector pop up form.
There are several ways of manipulating images with this type of OLE field which are not covered
here so if you need more information on this you should look for it in Access Help or the Internet.
Page 15 of 17
an error occurs, otherwise the database will appear to ‘lock up’ because screen updates will still be
disabled.
Conclusion
The examples described above are only basic guidelines on using a Continuous type form in place
of a List box control, there are obviously hundreds of different ways of using a List box and some
may not be suitable for use with a Continuous form.
Also, the group of VBA functions and sub-routines provided in the code module provided may not
work as you want in certain circumstances so you may need to modify the code to work in your
own particular database application but they should provide enough information to allow you to do
that easily.
If any bugs are found in the code or errors in this document then please contact me at :-
peter.hibbs@btinternet.com
History
Version 1.0 January 2014.
Page 16 of 17
SUMMARY OF VBA PROCEDURES
Select and highlight current row.
SelectRow Me, Shift
The Shift parameter defines the
value of the SHIFT or CONTROL
key.
In the procedures below the Me.SubformName parameter defines the name of the subform
control being used to show the list.
x = GetListCount(Me.SubformName) Fetch total number of rows in list.
Fetch the row index of the
currently selected row (0 based) or
x = GetListIndex(Me.SubformName) -1 if no row is selected. (Only
relevant for ‘single row selection’
type list).
Select or de-select row defined in
RowNumber, third parameter is set
RowSelected Me.SubformName, RowNumber, True
to True to select row or False to
de-select row.
Fetch data from a column for the
currently selected row, parameter
x = GetColumnData(Me.SubformName, n)
n defines the column number
(starts at 0).
Fetch data from any column and
row, Col defines the column
x = GetColRowData(Me.SubformName, Col, Row)
number and Row defines the row
number (both start at 0).
Select a row based on ‘bound’
SetValue Me.SubformName, n
column data, parameter n is set to
the value of the ‘bound’ column
(i.e. values in txtRef).
ClrCurrent Me.SubformName
De-select all currently selected
rows on subform.
x = ItemsSelected(Me.SubformName)
Fetch the number of rows that are
currently selected.
Fetch the status of a specified row,
the RowNumber parameter
x = GetSelected(Me.SubformName, RowNumber) specifies the row number, returns
True if row selected or False if
not selected.
Page 17 of 17