MS Office Forum / Excel / Programming / October 2008
Function to return two values
|
|
Thread rating:  |
Jac Tremblay - 09 Oct 2008 21:13 GMT Hi, Is it possible to create a function that will return two values, a boolean and a string? I need to exit the main procedure if the data checked by the function is not valid and also display a message according to the particular validation. For example: If Not DataIsValid Then Msgbox strErrorMsg ' Returned from the function Exit Sub end IF Thanks
 Signature Jac Tremblay
Jim Cone - 09 Oct 2008 21:50 GMT Maybe... '-- Function IcelandBanking(ByRef strMsg As String) As Boolean Dim WontPay As Long Dim NoReserves As Boolean
'Code here to calculate WontPay and NoReserves WontPay = 0 NoReserves = True
If WontPay > 0 Then strMsg = "Small Withdrawals Only" Else strMsg = "You are out of luck" End If IcelandBanking = NoReserves End Function '-- Sub FinancialStatus() Dim strText As String MsgBox IcelandBanking(strText) & vbCr & strText End Sub
 Signature Jim Cone Portland, Oregon USA
"Jac Tremblay" <jac.tremblay@donotspam.com> wrote in message Hi, Is it possible to create a function that will return two values, a boolean and a string? I need to exit the main procedure if the data checked by the function is not valid and also display a message according to the particular validation. For example: If Not DataIsValid Then Msgbox strErrorMsg ' Returned from the function Exit Sub end IF Thanks -- Jac Tremblay
Peter T - 09 Oct 2008 22:07 GMT ouch, LOL!
Peter T
> Maybe... > '-- [quoted text clipped - 18 lines] > MsgBox IcelandBanking(strText) & vbCr & strText > End Sub Jac Tremblay - 10 Oct 2008 07:10 GMT Hi Jim, When I first read your answer, I thought that wouldn't work. But I tried it out and found it is interesting. I changed it a bit so I could get the two values in two separated variables. Here is what I came up with: Function IcelandBanking(ByRef strMsg As String) As Boolean Dim WontPay As Long Dim NoReserves As Boolean 'Code here to calculate WontPay and NoReserves WontPay = 1 NoReserves = False If WontPay > 0 Then strMsg = "Small Withdrawals Only" Else strMsg = "You are out of luck" End If IcelandBanking = NoReserves End Function '-- Sub FinancialStatus() Dim strText As String Dim strTrueOrFalse As String Dim strMsg As String Dim strResult As String Dim intPosVbCr As Integer ' MsgBox IcelandBanking(strText) & vbCr & strText strResult = IcelandBanking(strText) & vbCr & strText intPosVbCr = InStr(1, strResult, vbCr) strTrueOrFalse = Mid(strResult, 1, intPosVbCr - 1) strMsg = Mid(strResult, intPosVbCr + 1, Len(strResult) - intPosVbCr) MsgBox "strTrueOrFalse = " & strTrueOrFalse & vbCrLf & _ "strMsg = " & strMsg End Sub It works OK, but I am not sure I will use it. My problem is that I have to check 4 different information from a transaction. I want to group the 4 validations in a separate procedure or function. If an error occurs, I want to display a pertinent message and exit the main proc. Here is another way I figured out to solve my problem: Option Explicit Public strMessage As String ' --- Function fbooDataIsValid(ByVal pstrParam1 As String, _ ByVal pintParam2 As Integer) As Boolean If pstrParam1 = "Hi Jim" Then strMessage = "Error, my friend. You should have said Hello!." fbooDataIsValid = False Exit Function End If If pintParam2 < 100 Then strMessage = "Error, your number is < 100." fbooDataIsValid = False Exit Function End If fbooDataIsValid = True End Function ' --- Sub TestDeJac() Dim strText As String strText = "Hi Jim" If Not fbooDataIsValid(strText, 36) Then MsgBox strMessage, vbCritical, "Sofica" Exit Sub End If MsgBox "It's OK...", vbInformation, "Sofica" End Sub Thank you for your original comment and good night.
 Signature Jac Tremblay
> Maybe... > '-- [quoted text clipped - 18 lines] > MsgBox IcelandBanking(strText) & vbCr & strText > End Sub keiji kounoike - 11 Oct 2008 08:09 GMT You seem to have already solved your problem. so, you maybe don't need this one. but just for a reference. I would use a user defined variable instead of using global variable. Using this way, your sample code looks like this.
Type fboo msg As String state As Boolean End Type
Function fbooDataIsValid(ByVal pstrParam1 As String, _ ByVal pintParam2 As Integer) As fboo
Dim tmp As fboo
If pstrParam1 = "Hi Jim" Then tmp.msg = "Error, my friend. You should have said Hello!." tmp.state = False fbooDataIsValid = tmp Exit Function End If
If pintParam2 < 100 Then tmp.msg = "Error, your number is < 100." tmp.state = False fbooDataIsValid = tmp Exit Function End If
tmp.msg = "Suceed" tmp.state = True
fbooDataIsValid = tmp
End Function
' --- Sub TestDeJac() Dim strText As String Dim result As fboo
strText = "Hi Jim" result = fbooDataIsValid(strText, 136) If Not result.state Then MsgBox result.msg, vbCritical, "Sofica" Else MsgBox "It's OK...", vbInformation, "Sofica" End If End Sub
keiji
> Hi Jim, > When I first read your answer, I thought that wouldn't work. But I tried it [quoted text clipped - 63 lines] > End Sub > Thank you for your original comment and good night. Peter T - 09 Oct 2008 22:04 GMT A function can return an array of values so the direct answer to your question is yes. However, unless your function is a UDF (for use in cell formulas), it would probably be better to pass an additional argument 'ByRef', eg
Sub Test dim v as variant Dim bResult as boolean sMsg as string
v = 123 bResult = foo(v, sMsg) if not bResult then msgbox sMsg Else msgbox bResult End if
End Sub
Function foo(ByVal data as Variant, ByRef strErrorMsg as String) as Boolean ' code to check data If Not DataIsValid then strErrorMsg = "this data not right right for this reason" Else foo = True End If End function
Regards, Peter T
> Hi, > Is it possible to create a function that will return two values, a boolean [quoted text clipped - 8 lines] > end IF > Thanks Jac Tremblay - 10 Oct 2008 07:26 GMT Hi Peter, I tried your code but it does not return two values at the same time. It returns one or the other. See my answer to Jim's comment. Thank you for your time.
 Signature Jac Tremblay
> A function can return an array of values so the direct answer to your > question is yes. However, unless your function is a UDF (for use in cell [quoted text clipped - 40 lines] > > end IF > > Thanks Peter T - 10 Oct 2008 15:29 GMT Jac,
I can only repeat what I tried to explain previously, perhaps in different words. A function can only return one 'thing'. This 'thing' can be a value, an object or an array of values or objects. IOW, a function can return multiple values in an array, indeed virtually unlimited subject resources.
When multiple values are required back from a function the alternative to an array is to pass arguments ByRef. Such arguments can be assigned or changed in the function and are returned to the calling procedure. Obviously, as I mentioned previously, this approach is of no use if your function is intended as a UDF (although a UDF can return a 1 or 2D array of values for use in an array entered function).
Both Jim's and my examples demonstrated the ByRef approach to give you your second value, the first being returned by the function itself. Jim's example was rather more prescient, mine included a typo -
>> sMsg as string should of course have read Dim sMsg as string
I do not agree with Bernd's recommendation not to change ByRef variables, it's exactly what ByRef is intended for in this context (and assuming not a UDF).
Regards, Peter T
Jim - Q. What's the capital of Iceland A. About 25 dollars, a bit less by the time you read this
> Hi Peter, > I tried your code but it does not return two values at the same time. It [quoted text clipped - 49 lines] >> > end IF >> > Thanks Jim Cone - 10 Oct 2008 16:10 GMT Hi Peter, re: "Q. What's the capital of Iceland A. About 25 dollars, a bit less by the time you read this"
That's a good one, I can't top that. Regards, Jim Cone
Bernd P - 10 Oct 2008 19:11 GMT Hello Peter,
[Not OT - w.r.t ByRef] Then let's agree to disagree.
My basis is: http://ei.cs.vt.edu/~cs2604/Standards/Standards.html
[Search for the first two occurances of "reference".]
Regards, Bernd
Peter T - 10 Oct 2008 20:47 GMT Hi Bernd,
I take it you are referring to this comment -
" Limit the number of parameters passed by reference (var parameters in Pascal, pointers passed in C). There are only two ways that a subroutine can screw up a variable in another subroutine: global variables and variables passed such that they can be changed. The problem in both cases is that you increase the chance that something will be changed in a way that you didn't expect. "
The paper is all about style, by definition that's subjective albeit based on hard learnt experience. As a general comment I do not entirely disagree, however ByRef has a valid and useful purpose. Indeed in our example the only reason for the existence of the argument is to be able to pass it ByRef, for the sole purpose of returning it with a new value.
For other purposes, where there is no deliberate intention to change the ByRef argument, it can still be worth sending ByRef where performance is an issue. It depends slightly on the data type but in general it's faster to send a pointer to the variable (ByRef) rather than make and send a copy of the variable (ByVal).
> Then let's agree to disagree. No problem :-)
Regards, Peter T
PS in VB/A ByRef is the default
> Hello Peter, > [quoted text clipped - 8 lines] > Regards, > Bernd Jac Tremblay - 11 Oct 2008 00:49 GMT Hi Peter, Thanks again for your time and your quick answer. I did understand what you explained and am now more aware of the utility of ByRef. Thanks to Bernd and Jim who posted comments as well. But, as I wrote in the previous answer (to Jim), I found a simple way to solve my problem and posted the code that goes with it. It works fine and I decided to use that solution because it is simple and sweet. Your post was very helpful and informative. Thanks again and have a good night.
 Signature Jac Tremblay
> Jac, > [quoted text clipped - 82 lines] > >> > end IF > >> > Thanks Bernd P - 10 Oct 2008 12:40 GMT Hello,
I would suggest an explicite variant which contains two values.
Take my UDF NRN as an example: http://www.sulprobil.com/html/nearest_rational_number.html
Changing Byref variables I would NOT recommend.
Regards, Bernd
|
|
|