PDA

View Full Version : call a sub from another sub



puppy123
09-03-2011, 09:40 PM
I'm new to VBA and I have this sub that calculates the perimeter and area of rectangle. It should pass the length, breadth and perimeter as parameters. Then I need to call this sub from another sub and use debug.print to display the result in immediate window. This is the code I have:
Sub Rectangle(ByVal Area As Double, ByVal Perimeter As Double, ByVal Length As Double, ByVal Breadth As Double)
Area = Length * Breadth
Perimeter = (Length + Breadth) * 2
End Sub

Sub ShowResult()
Call Rectangle(Area, Perimeter, 3, 5)
Debug.Print "Length=" & Length & "Breadth=" & Breadth & "Area=" & Area & "Perimeter=" & Perimeter
End Sub
It gives error, I can't figure out how to do it after a day of researching on the web.
Can anyone pls help and give some hint, thanks.

Kenneth Hobs
09-03-2011, 10:57 PM
Use ByRef rather than ByVal.

Bob Phillips
09-04-2011, 03:55 AM
Use ByRef rather than ByVal.

Only for Area and Perimeter ...

Paul_Hossler
09-04-2011, 10:10 AM
1. 'Option Explicit' is your friend

2. ByRef puts the address of the variable on the stack when it calls the Sub or Function. That way the sub will be updating the original variable

3. ByVal puts a copy of the variable or value on the stack, where it's used but does not update the original. So by using the ByVal calling convention on Rectangle(), Length and Breadth come in as 'numbers (as did Area and Perimeter), but Area and Perimeter from the calling routine (ShowResults) were never updated.



Option Explicit
Sub Rectangle(ByRef Area As Double, ByRef Perimeter As Double, Length As Double, Breadth As Double)
Area = Length * Breadth
Perimeter = (Length + Breadth) * 2
End Sub

Sub ShowResult()
Dim Area As Double, Perimeter As Double, Length As Double, Breadth As Double

Length = 3
Breadth = 5

Call Rectangle(Area, Perimeter, Length, Breadth)

'or Call Rectangle(Area, Perimeter, 3, 5)

Debug.Print "Length= " & Length & " Breadth= " & Breadth & " Area= " & Area & " Perimeter=" & Perimeter

End Sub


Paul

Paul_Hossler
09-04-2011, 10:30 AM
I had a thought that to avoid confusing the variables with the same names in the different routines, it might be a little clearer use A, P, L and B in one routine, instead of Area in both. That way the scope of the variables might be easier to follow


Option Explicit
Sub Rectangle(ByRef Area As Double, ByRef Perimeter As Double, Length As Double, Breadth As Double)
Area = Length * Breadth
Perimeter = (Length + Breadth) * 2
End Sub

Sub ShowResult()
Dim A As Double, P As Double, L As Double, B As Double

L = 3
B = 5

Call Rectangle(A, P, L, B)
Debug.Print "Length= " & L & " Breadth= " & B & " Area= " & A & " Perimeter=" & P

L = 300
B = 500
'Note 3 and 5 are passed, not L=300 and B=500
'so the Area and Preimeter from Rectangle are based on 3 and 5, not 300 and 500
'even though the Debug is still based on the values of L and B
Call Rectangle(A, P, 3, 5)
Debug.Print "Length= " & L & " Breadth= " & B & " Area= " & A & " Perimeter=" & P


Call Rectangle(A, P, 2 * L, 0.5 * B)
Debug.Print "Length= " & L & " Breadth= " & B & " Area= " & A & " Perimeter=" & P

End Sub


Paul

Bob Phillips
09-04-2011, 03:40 PM
Paul,

In

Sub Rectangle(ByRef Area As Double, ByRef Perimeter As Double, Length As Double, Breadth As Double)

Length and Breadth are also passed ByRef, it is the default. Best to be explicit.

Paul_Hossler
09-04-2011, 04:13 PM
You are correct Sir

I was in the wrong language I think, at least as far as calling convention defaults are concerned

Thanks for pointing that out

Paul