If Then ElseIf the solution to this bug?
Author Message
If Then ElseIf the solution to this bug?

Hi, folks,

With some kind help from some of the members here, I've been able to
get my compound interest program running.  I'm putting the code for it
at the end of this post (or you may download the current code and GUI
at http://www.*-*-*.com/ ).

The little program calculates interest fine, but it has one bug I
haven't been able to fix.  If the user forgets to type in an amount of
money to deposit (aka the principal) into the txtAmount field, I get
the following error:

Run-time error '13':
type mismatch

I need to remindl the user to enter the principal if he forgets to.
According to the de{*filter*}, my code should go somewhere in this part of
the prog:

years = txtYears.Text
principal = txtAmount.Text
interestRate = txtInterest.Text / 100

I'm thinking some kind of an "If Then ElseIf" statement would do the
trick, but am not sure how to make it work.    Here is what I'm trying
to do in code and pseudocode mixed together:

principal = txtAmount.Text
If the user forgets to type in a txtAmount Then
MsgBox "You forgot to enter a deposit amount (the principal)",
vbExclamation, "Principal"
ElseIf
Continue running the program.

Am I on the right track here?  If so, how do I make an "If Then
ElseIf" statement work here?  Or would some approach other than "If
Then ElseIf" be more appropriate?

The entire code is cut and pasted below, or you may download both the
code and GUI at http://www.*-*-*.com/ ;

__________________________________________________
' Calculating compound interest.
Option Explicit           ' General Declaration

Private Sub cmdCalculate_Click()
Dim years As Integer
Dim yearsCount As Integer
Dim interestRate As Double
Dim amount As Currency
Dim principal As Currency

lstDisplay.Clear       ' Clear list box
'Command below remmed out in favor of replacing it with code that
will
'let the user choose how many years.
'years = 10             ' Initialize variable

' Get information from text boxes
years = txtYears.Text
principal = txtAmount.Text
interestRate = txtInterest.Text / 100

' Display header in list box
lstDisplay.AddItem "Year" & vbTab & "Amount On Deposit"

'For years = 1 To 10
'   amount = principal * (1 + interestRate) ^ years

'                      Format\$(Format\$(amount, "Currency"), _

'   Next years

For yearsCount = 1 To years
amount = principal * (1 + interestRate) ^ yearsCount

Format\$(Format\$(amount, "Currency"), _

Next yearsCount

End Sub

Private Sub cmdExit_Click()
End
End Sub

Sun, 20 Jun 2004 12:37:21 GMT
If Then ElseIf the solution to this bug?

Quote:
> The little program calculates interest fine, but it has one bug I
> haven't been able to fix.  If the user forgets to type in an amount of
> money to deposit (aka the principal) into the txtAmount field, I get
> the following error:

> Run-time error '13':
> type mismatch

[snip]

> principal = txtAmount.Text
> If the user forgets to type in a txtAmount Then
> MsgBox "You forgot to enter a deposit amount (the principal)",
> vbExclamation, "Principal"
> ElseIf
> Continue running the program.

Maybe something like:

If Len(txtAmount.Text) = 0 Then
MsgBox "You forgot to enter a deposit amount (the principal)",
vbCritical
Exit Sub
ElseIf Not IsNumeric(txtAmount.Text) Then
MsgBox "You must enter a numeric value for the deposit amount (the
principal)", vbCritical
Exit Sub
End If
principal = CCur(txtAmount.Text)

?

Jason

Sun, 20 Jun 2004 12:45:08 GMT
If Then ElseIf the solution to this bug?
Jason's code below is perfectly fine.  However, I suggest you put that code
into the VALIDATE event of the text box, so that you have to make the
required fixes before leaving the text box.  You want the user to get
validation messages while they are still working in that field, not later,
after they've already moved on to other things.

--
Cordially;
E. DALE FRANKS JR. MCP MOUS

Dissent is morally neutral. You can correctly call yourself a dissident
because you like to kick puppies, but at the end of the day, you're just a
jerk who likes to kick puppies.
--Jonah Goldberg

Quote:
> > The little program calculates interest fine, but it has one bug I
> > haven't been able to fix.  If the user forgets to type in an amount of
> > money to deposit (aka the principal) into the txtAmount field, I get
> > the following error:

> > Run-time error '13':
> > type mismatch

> [snip]

> > principal = txtAmount.Text
> > If the user forgets to type in a txtAmount Then
> > MsgBox "You forgot to enter a deposit amount (the principal)",
> > vbExclamation, "Principal"
> > ElseIf
> > Continue running the program.

> Maybe something like:

> If Len(txtAmount.Text) = 0 Then
>     MsgBox "You forgot to enter a deposit amount (the principal)",
> vbCritical
>     Exit Sub
> ElseIf Not IsNumeric(txtAmount.Text) Then
>     MsgBox "You must enter a numeric value for the deposit amount (the
> principal)", vbCritical
>     Exit Sub
> End If
> principal = CCur(txtAmount.Text)

> ?

> Jason

Sun, 20 Jun 2004 13:25:12 GMT
If Then ElseIf the solution to this bug?

Quote:
> Jason's code below is perfectly fine.  However, I suggest you put that
code
> into the VALIDATE event of the text box, so that you have to make the
> required fixes before leaving the text box.  You want the user to get
> validation messages while they are still working in that field, not later,
> after they've already moved on to other things.

I hate apps that force you to fix changes there and then rather than before
going onto the next phase (i.e. the OK or
"Next >>" button in a wizard). But then again, that's just me.

Sun, 20 Jun 2004 14:21:40 GMT
If Then ElseIf the solution to this bug?

Quote:

>> Jason's code below is perfectly fine.  However, I suggest you put that
>code
>> into the VALIDATE event of the text box, so that you have to make the
>> required fixes before leaving the text box.  You want the user to get
>> validation messages while they are still working in that field, not later,
>> after they've already moved on to other things.

>I hate apps that force you to fix changes there and then rather than before
>going onto the next phase (i.e. the OK or
>"Next >>" button in a wizard). But then again, that's just me.

Agreed. I hate the Validate event myself.
The validate also has a drawback of having to provide a 'cancel input'
mechanism, as you can't get out of the textbox until the value is
accepted. (afaik)

Regards, Frank

Sun, 20 Jun 2004 15:26:59 GMT
If Then ElseIf the solution to this bug?

Quote:
> ElseIf Not IsNumeric(txtAmount.Text) Then
>     MsgBox "You must enter a numeric value for the deposit amount (the
> principal)", vbCritical
>     Exit Sub
> End If
> principal = CCur(txtAmount.Text)

I usually try and steer people away from using IsNumeric to "proof" supposedly numeric
text or, as you are suggesting, to prove its negative. Consider this (and read the note at
the end of this message).

ReturnValue = IsNumeric("(\$1,23,,3.4,,,5,,E67\$)")

Most people would NOT expect that to return True. IsNumeric has some "flaws" in what it
considers a proper number and what most programmers are looking for.

magazine that covered some of these flaws. Originally, the tip was free to view but is now
viewable only by subscribers.. Basically, it said that IsNumeric returned True for things
like -- currency symbols being located in front or in back of the number as shown in my
example (also applies to plus, minus and blanks too); numbers surrounded by parentheses as
shown in my example (some people use these to mark negative numbers); numbers containing
any number of commas before a decimal point as shown in my example; numbers in scientific
notation (a number followed by an upper or lower case "D" or "E", followed by a number
equal to or less than 305 -- the maximum power of 10 in VB); and Octal/Hexadecimal numbers
(&H for Hexadecimal, &O or just & in front of the number for Octal).

NOTE:
======
In the above example and in the referenced tip, I refer to \$ signs and commas and dots --
these were meant to refer to your currency, thousands separator and decimal point symbols
as defined in your local settings -- substitute your local regional symbols for these
where appropriate.

Rick

Sun, 20 Jun 2004 17:02:45 GMT
If Then ElseIf the solution to this bug?

Quote:
> I need to remindl the user to enter the principal if he forgets to.
> According to the de{*filter*}, my code should go somewhere in this part of
> the prog:

> years = txtYears.Text
> principal = txtAmount.Text
> interestRate = txtInterest.Text / 100

years = Invalidate(txtYears, "How many years, dillhole?", 1)
principal = Invalidate(txtAmount, "You call that a dollar amount?", 1)
interestRate = Invalidate(txtInterest, "Fine, I'll just call Tony...", 1) / 100

Public Function Invalidate(ByVal C As Control, ByVal Blank As String, _
Optional ByVal AtLeast As Variant, Optional ByVal AtMost As Variant) As Variant

If IsMissing(AtLeast) Then AtLeast = Null
If IsMissing(AtMost) Then AtMost = Null

Dim Text As String: Text = Trim\$(C.Text)
Dim V As Variant: If IsNumeric(Text) Then V = CCur(Text)

If IsEmpty(V) Or V < AtLeast Or V > AtMost Then
C.BackColor = &H8070&
C.ForeColor = vbRed
C.Text = Blank

Else
C.BackColor = vbWindowBackground
C.ForeColor = vbWindowText
C.Text = CStr(V)
Invalidate = V
End If

C.SelStart = 0
C.SelLength = 32767
End Function

Public Sub CallFromGotFocus(ByVal C As Control)
C.BackColor = vbWindowBackground
C.ForeColor = vbWindowText
End Sub

Public Sub CallFromLostFocus(ByVal C As Control)
C.SelStart = 0
C.SelLength = 32767
End Sub

--
Joe Foster <mailto:jlfoster%40znet.com>  Auditine {*filter*} < http://www.*-*-*.com/ ;
WARNING: I cannot be held responsible for the above        They're   coming  to
because  my cats have  apparently  learned to type.        take me away, ha ha!

Sun, 20 Jun 2004 17:46:19 GMT
If Then ElseIf the solution to this bug?

Quote:
> > ElseIf Not IsNumeric(txtAmount.Text) Then
> >     MsgBox "You must enter a numeric value for the deposit amount (the
> > principal)", vbCritical
> >     Exit Sub
> > End If
> > principal = CCur(txtAmount.Text)

> I usually try and steer people away from using IsNumeric to "proof"
supposedly numeric
> text or, as you are suggesting, to prove its negative. Consider this (and
> the end of this message).

>     ReturnValue = IsNumeric("(\$1,23,,3.4,,,5,,E67\$)")

> Most people would NOT expect that to return True. IsNumeric has some
"flaws" in what it
> considers a proper number and what most programmers are looking for.

I did not know this, otherwise I wouldn't have used it (and will never use
it again I don't think).

Function IsCurrency(x as Variant) as Boolean
On Error Resume Next
x = CCur(x)
IsCurrency = (Err.Number = 0)
Err.Clear
On Error Goto 0
End Function

Will return True if the input can be coerced into a variable of type
Currency.

Jason

Sun, 20 Jun 2004 18:10:43 GMT
If Then ElseIf the solution to this bug?

Quote:

> Function IsCurrency(x as Variant) as Boolean
>     On Error Resume Next
>     x = CCur(x)
>     IsCurrency = (Err.Number = 0)
>     Err.Clear
>     On Error Goto 0
>  End Function

> Will return True if the input can be coerced into a variable of type
> Currency.

That will work OK under most circumstances, but that Err.Clear could possibly obscure a
pending error produced earlier in the code. For example, if a user had this

On Error Resume Next
....
....
If Err.Number Then ...

then, because VB will execute both expressions even if the first one is false, any error
generated in ADifferentFunction will be "cleared" by your function and the Err.Number test
won't fire. As I said, the odds against this kind of occurrence is very slim... but
possible.

I would approach the problem this way

Function IsDecimal(X As String) As Boolean
IsDecimal = Not (X Like "*[!0-9.]*" Or X Like "*.*.*")
End Function

Note: I changed the function's name and it takes a String argument (not sure when you
would need to input a Variant that was not a String into this type of function)

Rick

Sun, 20 Jun 2004 21:38:23 GMT
If Then ElseIf the solution to this bug?

Quote:
>      If ADifferentFunction() And IsCurrency(x) Then
>      ....
>      ....
> then, because VB will execute both expressions even if the first one is

false

Is this *really* the case ??? If so, can anyone explain *why* ?

Sun, 20 Jun 2004 22:02:55 GMT
If Then ElseIf the solution to this bug?

Quote:

> > Function IsCurrency(x as Variant) as Boolean
> >     On Error Resume Next
> >     x = CCur(x)
> >     IsCurrency = (Err.Number = 0)
> >     Err.Clear
> >     On Error Goto 0
> >  End Function

> > Will return True if the input can be coerced into a variable of type
> > Currency.

> That will work OK under most circumstances, but that Err.Clear could
possibly obscure a
> pending error produced earlier in the code. For example, if a user had
this

>      On Error Resume Next
>      If ADifferentFunction() And IsCurrency(x) Then
>      ....
>      ....
>      If Err.Number Then ...

> then, because VB will execute both expressions even if the first one is
false, any error
> generated in ADifferentFunction will be "cleared" by your function and the
Err.Number test
> won't fire. As I said, the odds against this kind of occurrence is very
slim... but
> possible.

Hmm..

-----
Function IsCurrency(x As Variant) As Boolean
'On Error Resume Next
x = CCur(x)
IsCurrency = (Err.Number = 0)
'Err.Clear
'On Error GoTo 0
End Function

Function ErrorFunc() As Boolean
Err.Raise vbObjectError
End Function

Sub Main()
On Error Resume Next
Debug.Print Err.Number,
ErrorFunc
Debug.Print Err.Number,
IsCurrency 1
Debug.Print Err.Number
End Sub
-----

Uncommenting any of the 3 commented lines in the first function causes the
3rd number outputted to be 0. Even "On Error Goto xxx" causes this. One
should be checking for errors after each call anyway if using "On Error
Resume Next".

-----
Sub Main()
On Error Resume Next
If ErrorFunc() And IsCurrency(1) Then
' do nothing
End If
Debug.Print Err.Number
End Sub
-----

with the original IsCurrency function outputs what I expected, -2147221504.
If the call to ErrorFunc() returns an errorness HRESULT then IsCurrency is
never called. I see no problem with my function.

Quote:
> I would approach the problem this way

>      Function IsDecimal(X As String) As Boolean
>         IsDecimal = Not (X Like "*[!0-9.]*" Or X Like "*.*.*")
>      End Function

Test case 1: "3452345345353534534523453.234523"

IsDecimal returns True, IsCurrency returns False, CCur raises error number
6, overflow.

Test case 2: "-123456.789"

IsDecimal returns False, IsCurrency returns True, CCur succeeds.

Your function checks for positive decimal numbers, not variables who's
values can be coerced into variables of type Currency.

Quote:
> Note: I changed the function's name and it takes a String argument (not
sure when you
> would need to input a Variant that was not a String into this type of

function)

I had chosen Variant because that is what CCur takes as its parameter, is it
not? In any case, it is foreseeable that one might want to check if the
contents of a Double could be stored in a Currency variable.

Jason

Sun, 20 Jun 2004 22:45:27 GMT
If Then ElseIf the solution to this bug?

Quote:
> Test case 2: "-123456.789"

> IsDecimal returns False, IsCurrency returns True, CCur succeeds.

> Your function checks for positive decimal numbers, not variables who's
> values can be coerced into variables of type Currency.

Hmm! I forgot about negative numbers. Easily corrected though

Function IsDecimal(ByVal X As String) As Boolean
If X Like "[+-]*" Then X = Mid\$(X, 2)
IsDecimal = Not (X Like "*[!0-9.]*" Or X Like "*.*.*")
End Function

This also allows the plus sign as well as the minus sign to be the first character.

Rick

Sun, 20 Jun 2004 23:54:34 GMT
If Then ElseIf the solution to this bug?

Quote:

> >      If ADifferentFunction() And IsCurrency(x) Then
> >      ....
> >      ....
> > then, because VB will execute both expressions even if the first one is
> false

> Is this *really* the case ??? If so, can anyone explain *why* ?

This is easy to show; just put this code in a CommandButton's Click event and click the
button. The first logical expression is clearly False, but the second argument will be
"evaluated" anyway.

If 0 > 1 And MsgBox("2nd expression executed") Then
' We will never get here
Else
MsgBox "We got here AFTER the other MessageBox displayed"
End If

VB does not do what is known as "short circuit" evaluation of logical expressions as do
other languages (to be rectified in VB.NET, although I'm not sure the "other" changes in
the language make it the place to go).

Rick

Mon, 21 Jun 2004 00:01:33 GMT
If Then ElseIf the solution to this bug?

Quote:

> > Function IsCurrency(x as Variant) as Boolean
> >     On Error Resume Next
> >     x = CCur(x)
> >     IsCurrency = (Err.Number = 0)
> >     Err.Clear
> >     On Error Goto 0
> >  End Function

> > Will return True if the input can be coerced into a variable of type
> > Currency.

It'll also accept nearly anything IsNumeric would.  If we can know that
certain characters will not be accepted, why leave them in the control?

Quote:
> That will work OK under most circumstances, but that Err.Clear could possibly obscure a
> pending error produced earlier in the code. For example, if a user had this

Will the Err.Clear really obscure anything that the On Error won't?
From the VB5 help:

The Clear method is called automatically whenever any of the following
statements is executed:

Any type of Resume statement

Exit Sub, Exit Function, Exit Property

Any On Error statement

Quote:
> Note: I changed the function's name and it takes a String argument (not sure when you
> would need to input a Variant that was not a String into this type of function)

Could a reference to the control be passed in via that Variant?

--
Joe Foster <mailto:jlfoster%40znet.com>  Sacrament R2-45 <http://www.xenu.net/>
WARNING: I cannot be held responsible for the above        They're   coming  to
because  my cats have  apparently  learned to type.        take me away, ha ha!

Mon, 21 Jun 2004 01:32:34 GMT
If Then ElseIf the solution to this bug?

Quote:

> > >      If ADifferentFunction() And IsCurrency(x) Then
> > >      ....
> > >      ....
> > > then, because VB will execute both expressions even if the first one
is
> > false

> VB does not do what is known as "short circuit" evaluation of logical
expressions as do
> other languages (to be rectified in VB.NET, although I'm not sure the
"other" changes in
> the language make it the place to go).

> Rick

Thanks for informing me of this, Rick. It's hard to believe that *any*
language would function this way, although I guess I should have realized
the implications much earlier having encountered situations which forced me
into nested Ifs. But, it certainly seems to make a case for *always* using
'nested Ifs' instead of 'Ands' in cases when either method suits the task.

Hugh

Mon, 21 Jun 2004 20:56:58 GMT

 Page 1 of 2 [ 20 post ] Go to page: [1] [2]

Relevant Pages