Chapter 14 Input boxes
14.1 Basic input boxes
We have seen in lectures that Input Boxes are a useful tool for collecting user inputs. Here we will consider in more detail some of their features, and how to avoid errors if the user inputs an unexpected piece of data.
First, it is worth noting that Input Boxes are very commonly used with only the prompt given as one of the arguments. This defaults to producing an Input Box with no default entry (and a generic title) which is often sufficient if we are just looking for a simple piece of data.
We saw in lectures that we need to be able to deal with the
possibility that nothing is entered by the user. We used the Len
command to detect this, and GoTo
statements to make the Input Box
repeat. We also mentioned how to detect a different kind of error,
where the user does not enter the right kind of data, but did not
consider this in much detail.
Recall that anything entered into an Input Box is regarded as a string when we refer to it in our VBA code. Often we will want to interpret it as a number or a date, or some other kind of data. If we try to convert it into the appropriate type immediately and it is not of the right type then this will produce an error. Instead we have a number of commands which we can use to test whether the data is of the appropriate form.
The function IsNumeric
takes a
variable as argument and returns True
if the variable is of one of the various numerical types, or if it can
be interpreted as a number. Otherwise it returns False
. There are
similar functions called IsArray
(which checks whether the variable
can be interpreted as an array) and IsDate
(which checks whether the
variable can be interpreted as a date). We have already used the
similar IsError
function earlier in the course.
Once we know our variable is of the desired type, the next step is to convert it from a string to the form we wish to work with it as. If we do not do this then VBA will complain and give an error. There are many conversion functions, corresponding to most of the different data types which we have seen:
Conversion function | Data type converted to |
---|---|
CBool |
Boolean |
CDate |
Date |
CDbl |
Double |
CInt |
Integer |
CLng |
Long |
CSng |
Single |
CStr |
String |
In lectures we saw an example of the use of CInt
; the other functions
are similar.
14.2 Advanced input boxes: the Application.InputBox method
For most applications, basic Input Boxes are fine (although it is
slightly tiresome to have to convert the string into other data
types). But they do not allow us to easily collect certain kinds of
data from the user, such as a Range of cells. For this reason we have
an alternative method, using the Application.InputBox
method, which
allows us to tell VBA what kind of input we are expecting.
The syntax for Application.InputBox
is similar to that for the
ordinary InputBox
, but with extra options:
InputBox(Prompt[,Title][ ,Default][ ,Left][ ,Top][ ,HelpFile][ ,HelpContextId][ ,Type])
We have seen all of these before except Left
and Top
(which are just
like xpos
and ypos
and will be ignored in this module) and the final
option Type
.
The option Type
is an integer (or sum of integers) which indicates
what type or types of input are allowed:
Type | Allowed input types |
---|---|
0 | Formula |
1 | Number |
2 | String |
4 | Boolean |
8 | Range |
16 | Error value |
64 | Array |
If we want to allow more than one data type we set Type
to be the sum
of the corresponding values, so type 3 would allow a number or a
string.
There are two features which are useful to note when using
Application.InputBox
. First, it is rather inconvenient that the type
option occurs at the end of a long list of options which we will
hardly ever use. If we try to enter commands in the usual way we will
end up with statements like
x=Application.InputBox("Enter a number", , , , , , , 1)
which is irritating to type, hard to read, and likely to be entered incorrectly. This is thus a good time to introduce a second way to refer to arguments in a function.
So far when we have used functions we have given the arguments by
entering them in the specified order. For example, the Prompt
was
always the first argument in a MsgBox. This method uses what are called
positional arguments. There is a second way of specifying arguments,
using what are called named arguments.
You will have noticed that each argument in our functions has had a
name (such as Prompt
, or Title
). We can enter the arguments in a
function in any order we like if we use the syntax ArgumentName:=value
Thus for example we can specify an InputBox
with prompt "Enter number"
and allowed type number
by entering
Application.InputBox(Prompt:="Enter number", Type:=1)
This works for all functions with arguments, and is well worth remembering if you only need to use a few arguments in a function with many optional arguments available.
The second feature of Application.InputBox
is a more serious issue. If
the user does not enter the right kind of data (or presses Cancel
)
then this method will generate an error straight away, so we are not
able to use our earlier method of detecting and preventing the wrong
data type being processed.
To avoid this we can use a couple of commands which we do not want to explain in detail. For the purposes of this module they can be regarded as fixed commands which make VBA handle errors sensibly. If you wish to know more about how these commands work, you will need to consult a more advanced reference on VBA.
Before we use our Application.InputBox
command we will enter the lines
On Error Resume Next
and
Application.DisplayAlerts = False
In essence these “turn off” the error checking function in
VBA. Once we have used the command Application.InputBox
we enter the
lines
On Error GoTo 0
and
Application.DisplayAlerts = True
which “switch on” the error checking function again.
This is all best understood with an example. Consider the following simple macro.
Sub MarkEntry()
Dim entry As Double
EnterScore:
On Error Resume Next
Application.DisplayAlerts = False
entry = Application.InputBox(Prompt:="Enter your score", Type:=1)
On Error GoTo 0
Application.DisplayAlerts = True
If entry = 0 Then
MsgBox("Please enter a mark")
GoTo EnterScore
End If
output = MsgBox(Prompt:="You scored " & entry)
End Sub
This asks the user to input a mark, and if
they do it displays a message box stating their score. However, if
they enter something which is not a number, then the Input Box
reappears with their input highlighted. If they enter nothing and
press Cancel
or Escape
, then it displays a Message Box asking them to
enter a mark and re-displays the Input Box.
Note that we have used the four special lines described above before
and after the Input command, and have used a GoTo
command to deal with
the case of the empty entry.
Our next example is very similar, and illustrates how we can ask the user for a range of cells. Consider the following macro.
Sub RangeEntry()
Dim entry As Range
EnterRange:
On Error Resume Next
Application.DisplayAlerts = False
Set entry = Application.InputBox(Prompt:="Enter a range with your mouse", Type:=8)
On Error GoTo 0
Application.DisplayAlerts = True
If entry Is Nothing Then
MsgBox("Please enter a range")
GoTo EnterRange
End If
' rest of code does something to that range
output = MsgBox("Success")
End Sub
This asks the user to enter a range, and if they do
then it does something (which we have not included here) and prints
Success. If they do not enter a range then it returns to the Input
Box, and if they press Cancel
or Escape
it displays a message and
returns to the Input Box. To enter a range the user can either use the
mouse to highlight some cells, or enter a range directly in the Input Box.
There are some small but important differences compared to the
previous example. Obviously, entry
is now of type Range. Unfortunately
we cannot just write entry=....
in such circumstances, but must
instead write Set entry=....
. Also, to test whether the entry is empty
we use the line
If entry Is Nothing Then
which is a little different from our earlier examples.
We will not make much use of the ability to ask for ranges in this
module, so you can if you wish ignore the use of Application.InputBox
to select a range. But it is useful to know that such an operation is possible.