Maybe something like this
Code:
Option Explicit
Public myvar As Long
Sub Main()
MsgBox Func1(10)
End Sub
Function Func1(a As Long)
myvar = a
Func1 = Func2
End Function
Function Func2()
myvar = myvar + 1
If myvar > 10 Then
Func2 = "OK"
Else
Func2 = "Low"
End If
End Function
M.
I tested that and it works. Thanks.
Unfortunately, as I was testing it, I realized that I didn't explain the situation correctly. Let me try again.
I am working on a UDF that processes rows of data in several passed ranges. The rows are products and the columns are features or properties of those products. Each row contains ratings on some scale for that product for the feature in that column. The UDF is called once on each row (B3:B5). It loops through the columns on that row (C:F) and returns a weighted rating based on relative weights in another fixed row. It looks something like this:
[TABLE="class: grid, width: 500"]
<tbody>[TR]
[TD="align: center"]R/C[/TD]
[TD="align: center"]A[/TD]
[TD="align: center"]B[/TD]
[TD="align: center"]C[/TD]
[TD="align: center"]D[/TD]
[TD="align: center"]E[/TD]
[TD="align: center"]F[/TD]
[/TR]
[TR]
[TD="align: center"]1[/TD]
[TD][/TD]
[TD="align: right"]Features[/TD]
[TD="align: center"]Feat #1[/TD]
[TD="align: center"]Feat #2[/TD]
[TD="align: center"]Feat
#3 [/TD]
[TD="align: center"]Feat
#4 [/TD]
[/TR]
[TR]
[TD="align: center"]2[/TD]
[TD="align: center"]Products[/TD]
[TD="align: right"]Weights[/TD]
[TD="align: center"]3[/TD]
[TD="align: center"]8[/TD]
[TD="align: center"]1[/TD]
[TD="align: center"]6[/TD]
[/TR]
[TR]
[TD="align: center"]3[/TD]
[TD]Product #1[/TD]
[TD="align: center"]78.75[/TD]
[TD="align: center"]$225[/TD]
[TD="align: center"]3.8[/TD]
[TD="align: center"]144[/TD]
[TD="align: center"]90[/TD]
[/TR]
[TR]
[TD="align: center"]4[/TD]
[TD]Product #2[/TD]
[TD="align: center"]90.25[/TD]
[TD="align: center"]$236[/TD]
[TD="align: center"]4.7[/TD]
[TD="align: center"]8[/TD]
[TD="align: center"]100[/TD]
[/TR]
[TR]
[TD="align: center"]5[/TD]
[TD]Product
#3 [/TD]
[TD="align: center"]39.01[/TD]
[TD="align: center"]$400[/TD]
[TD="align: center"]3.2[/TD]
[TD="align: center"]19[/TD]
[TD="align: center"]58[/TD]
[/TR]
</tbody>[/TABLE]
The UDF is called in cells B3:B5, once for each product. For each call, it returns the weighted rating based on the values in that row given the weights in $C$2:$F$2. In this example, the UDF is called 3 times and on each call, it loops through 4 sets of data.
In real life, there could be 50 columns (features) and 30 rows (products). That would be 1500 data points, any one of which could be incorrect. And once entered incorrectly, they could be difficult to find by looking at the table. For example, all values must be numbers, the values for Features
#3 &
#4 must all be integers, etc.
So, the UDF does a lot of data validation. To make the data correction easier, I wrote an error handling subroutine that the UDF calls when it detects any errors. The error handler generates an error message that includes the cell address where the UDF was called (eg, $B$4) and the cell address where the error occurred (eg, $E$8). It puts this message up in a MsgBox with buttons that allow me to continue or issue a Stop statement so I can do some testing.
Here's the problem. If the error is in a single data cell, a single error message will be generated. But if the error is in one of the weights, it will generate an error message for every product. If there are 30 products, I have to clear 30 MsgBox messages before I can stop the code from running so I can correct the error. Worse, if the error is caused by a bug in the code, such as testing for a condition to be True when it should have been False, it could generate an error message on every data cell for every product. Then I would have to clear 1500 MsgBoxes.
Your global variable solution allowed me to solve the second problem. I defined a global variable,
ErrMsgSw, that the error handler checks. If it's False, it does not generate the message.
Here's a snippet of that code:
Code:
Option Explicit
Public ErrMsgSw As Boolean
. . .
Public Function WtdRtg( . . . )
ErrMsgSw = True
. . .
For iCol = RngColBeg To RngColEnd
. . .
If (some condition) then Call WtdRtdErr()
. . .
Next i
. . .
End Function
Public Sub WtdRtgErr(FnName, Caller)
If Not ErrMsgSw Exit Sub
. . .
Dim Button As Integer 'The button that was clicked
Button = MsgBox(msg, vbYesNoCancel + vbDefaultButton2, FnName & " (" & Caller & ")")
If Button = vbYes Then Stop
If Button = vbCancel Then ErrMsgSw = False
End Sub
This all works great. Thanks for the help.
But when the UDF is called for the next product, that switch setting is lost and an error message is again displayed for that product. So if there are
N products in the table, I will have to clear
N messages.
The only solution I have been able to come up with so far is to select the Stop option and then comment out the statement at the top of the UDF that sets ErrMsgSw = True. This works, but then I have to remember to change it back.
I would much rather have an option to set some super-global variable that will persist between UDF calls for as long as the workbook is open.
Is there any such beast?
Thanks