# Moduals



## eddionne (Feb 27, 2005)

I am new to and confused by VB.Net!

I am trying to learn to use VB.Net and the book that I am using requires writing a program to calculate a discount amount on an order, to display the discount and deducted it from the order amount to show the total charge. 

I have written the program and it works fine, I am now trying to create modules for the program. I have written the following code:

This appears in the class area: 
"Call mInvoiceTotal(txtOrderTotal.Text, lblDiscountAmount.Text, lblInvoiceTotal.Text)"

I placed this code in a modual:
"Public Function mInvoiceTotal(ByVal OrderTotal As Decimal, ByVal DiscountAmount As Decimal, ByVal InvoiceTotal As Decimal) As Decimal

Select Case OrderTotal
Case Is >= 500
DiscountAmount = 0.2

Case Is >= 250
DiscountAmount = 0.15

Case Is >= 100
DiscountAmount = 0.1

Case Is < 100
DiscountAmount = 0

End Select

End Function"

When I run debug stepping through this function I see all the correct answers, but when I get to the end of the function and return to the calling program all the values go away and I get no results. What is wrong with my code?

Any help would be welcome.

Thank you

eddionne


----------



## eddionne (Feb 27, 2005)

I do not have a reply to your question but I am curious; is there another eddionne out there?

This eddionne did not post this question nor the one about duel boot.

If another ed dionne exists email me at [email protected]


----------



## OBP (Mar 8, 2005)

To the poster, I do not know VB.net but I do know VBA and I think your VB's "logic" is not correct. If a value is greater than 500 then it is also greater than 100 and 250 therefore when it meets the requirement of >= 500 or 250 you need to exit the select.
Have you dimensioned the variables as "public"?


----------



## cristobal03 (Aug 5, 2005)

To OP:

Your function *mInvoiceTotal* has no return value set. The argument *DiscountAmount* is being passed *ByVal* not *ByRef*, so any change to DiscountAmount remains local to the function and is not reflected in the calling procedure.

I think you've confused a couple of things. If you want the function itself to have a return value of type *Decimal*, instead of your


```
DiscountAmount = 0.2
DiscountAmount = 0.15
DiscountAmount = 0.1
DiscountAmount = 0
```
you'd want to use something like this:


```
mInvoiceTotal = 0.2
mInvoiceTotal = 0.15
mInvoiceTotal = 0.1
mInvoiceTotal = 0
```
A function's return value is the value assigned to the function's name within the procedure. With the above changes, you'd call *mInvoiceTotal* using the following model:


```
Dim decSomeOrder       As Decimal
Dim decSomeDiscount    As Decimal
Dim decSomeTotal       As Decimal
Dim decTheReturnValue  As Decimal

decSomeOrder = 312
decSomeDiscount = 0
decSomeTotal = 0.03

decTheReturnValue = mInvoiceTotal(decSomeOrder, _
                                  decSomeDiscount, _
                                  decSomeTotal)

' decSomeOrder contains 312 still
' decSomeDiscount contains 0 still
' decSomeTotal contains 0.03 still
' decTheReturnValue contains 0.15 now
```
On the other hand, if you want to affect the variables in the calling procedure directly, you should change your Function declaration like so:


```
Public Function mInvoiceTotal(ByRef OrderTotal As Decimal, _
                              ByRef DiscountAmount As Decimal, _
                              ByVal InvoiceTotal As Decimal)

  ' Select Case statements generally list cases in ascending
  ' order; also, Select Case is generally used for exclusive
  ' conditions.  As OBP pointed out, your cases are
  ' non-exclusive.  You need to disambiguate this contitional
  ' control block somehow.  The easiest way, as OBP noted,
  ' is to include an Exit Select statement in each Case.  If
  ' you don't want to use Exit Select, put your cases in
  ' ascending order.

  Select Case OrderTotal
    Case Is >= 500
      DiscountAmount = 0.2
      Exit Select

    Case Is >= 250
      DiscountAmount = 0.15
      Exit Select

    Case Is >= 100
      DiscountAmount = 0.1
      Exit Select

    Case Is < 100
      DiscountAmount = 0

  End Select
End Function
```
And you'd use the function like so:


```
Dim decSomeOrder      As Decimal
Dim decSomeDiscount   As Decimal
Dim decSomeTotal      As Decimal

decSomeOrder = 312
decSomeDiscount = 0.64859
decSomeTotal = 0.03

mInvoiceTotal decSomeOrder, decSomeDiscount, decSomeTotal

' decSomeOrder contains 312 still
' decSomeDiscount contains 0.15 now
' decSomeTotal contains 0.03 still
```
Is the difference clear? Passing an argument *ByRef* means the called procedure doesn't necessarily _have_ to return a value because it affects the values in the calling procedure directly. On the other hand, if you want the called procedure to interact with the calling procedure and want to pass arguments *ByVal*, the called procedure needs a return value.

Here's a simple example. If you wrote a book report, and you wanted me to edit it, you could do two things. You could give me a photocopied version of the report (think: ByVal), or you could send me a link to the file itself (think: ByRef). If I had a photocopy, I'd mark my changes on it and hand the photocopy back to you for you to do something with. If I had a link, I could open the file directly--while it was still on your computer, even--and change it directly. If I had a photocopy and didn't give it back to you, I haven't given you a return value. Reciprocally, if you haven't given me a link to the report, I have no reference to the report. So you need either a value and a return, or a defined reference.

I personally don't use *ByRef* unless I have to; passing references is arguably more efficient but it's a bad idea for beginning coders; references are considerably harder to debug than values.

You probably also want to consider how you're using *data types*. The *Decimal* data type is the largest *floating-point precision* data type; for your application, it looks like you could get by using *Single*s instead of *Decimal*s.

If none of this makes sense, post back and I'll try to explain a bit more.

chris.

[edit]
Added a couple of things I left out.
[/edit]

[edit 2]
Added OBP's logic about *Select Case* to my code example.
[/edit 2]

[edit 3]
Just realized OP posted 8 months ago. If anyone else is curious, though, post back and I'll explain a bit more.
[/edit 3]


----------

