-
[RESOLVED] Function Return More Than One Value
I know this is a stupid question but I've never needed to do this until now. How can I make a function return more than one value? For example, if I want a function to return the time, day, month, and year all in different variables, how would I do this? Thanks
-
Re: Function Return More Than One Value
You can make Sub rather than a function.
Private Sub ReturnTime
Private Sub ReturnDay
Private Sub ReturnMonth
Private Sub ReturnYear
-
Re: Function Return More Than One Value
How do I even use subs? I never used subs because they didn't return values so I used functions.
-
Re: Function Return More Than One Value
Code:
Option Explicit
Private Sub Command1_Click()
Dim lngA As Long
Dim lngB As Long
Call Example(20, lngA, lngB)
Debug.Print lngA
Debug.Print lngB
End Sub
Private Sub Example(lngIn As Long, lngOutA As Long, lngOutB As Long)
lngOutA = lngIn * 2
lngOutB = lngIn \ 2
End Sub
-
Re: Function Return More Than One Value
abazabam, just so you don't get the wrong idea from what has been posted so far, it's not the fact that Subs are being used but rather as in Logophobic's example that the values that are being passed to the sub are being passed (by default) ByRef, so it could be rewritten as follows.
Private Sub Example(ByRef lngIn As Long, ByRef lngOutA As Long, ByRef lngOutB As Long)
When you pass something ByVal only a copy of the value is passed so any changes to the value remain in the called sub, but if you pass ByRef you are actually passing a pointer to the variable in memory so changes made in the called sub affect the variable in the calling routine.
-
Re: Function Return More Than One Value
This might need a bit more explanation: by default variables are passed to subs and functions ByRef. This means that a reference to a variable is used in the procedure, so changing the contents of the variable change the variable that was passed to the procedure.
When variables are passed ByVal, then you can change the contents of the variable just as much you like within the procedure and it has no effects to the variable that was given as a parameter to the procedure.
For some random knowledge, speedwise ByRef is faster for Strings and Variants, ByVal is faster for numeric datatypes. This because ByVal makes a copy of the variable contents, and copying a String includes memory management. However, it is faster to use local (ByVal) variables than external (ByRef) variables, so datatypes such as Long that only have four bytes get copied instantly and are also faster to access when passed as ByVal.
Edit!
Slow, that I am, with all this useless extra information :D
-
Re: Function Return More Than One Value
The best way to do it - is returning Array of Variant from function:
vb Code:
Function ABC(n As Integer) As Variant()
Dim x(2) As Variant
x(0) = 12
x(1) = "HHH"
ABC = x
End Function
Private Sub Command1_Click()
Debug.Print ABC(1)(0)
End Sub
Create new project, add a form and put a command button to it. Then insert the code written above. Start project and press a button. Then change line in click event : . Start project and press button. OK?
-
Re: Function Return More Than One Value
Variant is never a good solution. You should always use a specific datatype. Reasoning this goes off the scope of the topic of the thread so no more on that.
Returning an array is also bit of a waste if you only need the certain variables out of the procedure. I just fixed a PHP project that returned tons of array variables from functions and it was almost a nightmare to track down how it all worked (of course there were other things that weren't done all that well increasing the difficulty). The point however: if you use good variable names, you self document the code well. Although writing comments is not a bad idea.
-
Re: Function Return More Than One Value
If Variant "is NEVER a good solution" why this data type in VB exist? My solution will also work if type of array is not Variant (Integer, Long, String and so on)! Abazabam wish return from function different data types (Date, Time, integer...). Variant array is one of the simplest solutions. Another way - returning UDT-variable.
-
Re: Function Return More Than One Value
A UDT is a good idea, tho it doesn't necessarily provide an advantage over separate parameters (except ease of reading, as you can use it as the return value for a Function).
Quote:
Originally Posted by CatsTail
If Variant "is NEVER a good solution" why this data type in VB exist?
To make things easier for people who are new to programming.. it means that they can ignore one subject (Data types) for a while as they are learning.
Variants have many bad points, such as: memory wastage, they are slow, and they are prone to coercion errors.
-
Re: Function Return More Than One Value
Do You like "Variant" as well as "GoTo"?
-
Re: Function Return More Than One Value
Two of the three worst things to ever happen to VB.... Variant (#3) and GoTo (#2). The #1 worst thing to ever happen to VB... On Error Resume Next.
But that's just this gnomes opinion.
The array gives you no advantage to individual return parameters (byRef). It gives no context as to what's in it. Element 1... what is it? I don't know. No one knows, it's a variant. Could be anything. IS it the time? Or is it the date? There's no data typing so when it's returned, before I can do anything with it, it has to be validated, checked and in the end remains suspicious. It can't be trusted. But a parameter typed specific to a Date and called BirthDay, well, heck I know what that is.
-tg
-
Re: Function Return More Than One Value
you could create a custom type that contains your two variables and return that type
-
Re: Function Return More Than One Value
Element 1 of Variant type... What is it? No problem! Do you know such functions as isNumeric(), isDate(), and so on.
-
Re: Function Return More Than One Value
Of course - but that's lots of extra work (that is prone to errors), which is not required if the sub/function is set up properly. ;)
Using a custom type as you and TBeck suggested is a suitable alternative to parameters.. but typically (tho not always) involves slightly more work than the parameter method.
-
Re: Function Return More Than One Value
Quote:
Originally Posted by CatsTail
Element 1 of Variant type... What is it? No problem! Do you know such functions as isNumeric(), isDate(), and so on.
This is exactly what makes Variant array return value a pain to debug: if it doesn't always return the same datatype that is expected, then it really is horrible to know all the return values that it gives by the end user of the function, if it is someone else than who has written the function.
With regular functions that return a certain datatype you immediately know what is the range of values that can be returned. You can also know the error situatation.
What is important with functions is that they can handle errors. First thing for a function is to handle it's input values so that it validates them to be in the format the function can handle. Easiest way for this is to set specific datatypes, which narrows down the possible values. If you need further validation, then that needs some code.
The next thing is to handle return values: if an error occurs, the function should return some value that is out of the normal scope of possible return values. For functions returning a string the easiest way is to return a null string (codewise this either means giving vbNullString or not returning anything at all). But to go for actual topic, how to tell such a thing when returning multiple values?
Code:
Public Function GetDataByID(ByVal ID As Long, ByRef Title As String, ByRef Description As String) As Boolean
' the ID can't be negative or zero: database starts from ID 1
If ID < 1 Then Exit Function
' get data from database... just some pseudocode
' the ID might be unexistant in which case the database call fails!
' we can't trust input values to be always correct
If DatabaseCallSucceeded Then
' set return values
Title = TitleValueFromDB
Description = TitleValueFromDB
' return true in success
GetDataByID = True
End If
End Function
Now the advantages: the function itself returns True in success, so in the main code that calls the function you know if you can continue a certain processing:
Code:
Dim strTitle As String, strDescription As String, lngID As Long
' get written ID from textbox:
' we don't need to validate it here because we know the function does that for us!
lngID = CLng(Val(Text1.Text))
' now call the function
If GetDataByID(lngID, strTitle, strDescription) Then
' show the data in a message box
MsgBox strDescription, vbInformation, strTitle
Else
' show error message in failure
MsgBox "The ID value you gave is invalid. Please make sure the ID is a positive number and exists in the database.", vbExclamation, "Error"
End If
Far far easier than doing complicated checks for Variant return values!
-
Re: Function Return More Than One Value
I see. You are right. And original question is "return more than one value". Return, but no changing with using ByRef modificator...
-
Re: Function Return More Than One Value
Which is kind of irrelevant. If you always help strictly by the question, you end up giving bad help. Sometimes it is even impossible to know what exactly is wanted. I find it more important also to teach good techniques. The person who asks the question doesn't know of the better way to do things, so that is why it is important to let them know. Of course at times there is no one right way to do things -> there is space for different answers and opinions.
But all this is already pretty thick offtopic, so...
-
Re: Function Return More Than One Value
Quote:
Originally Posted by techgnome
Two of the three worst things to ever happen to VB.... Variant (#3) and GoTo (#2). The #1 worst thing to ever happen to VB... On Error Resume Next.
But that's just this gnomes opinion.
The array gives you no advantage to individual return parameters (byRef). It gives no context as to what's in it. Element 1... what is it? I don't know. No one knows, it's a variant. Could be anything. IS it the time? Or is it the date? There's no data typing so when it's returned, before I can do anything with it, it has to be validated, checked and in the end remains suspicious. It can't be trusted. But a parameter typed specific to a Date and called BirthDay, well, heck I know what that is.
-tg
#2 GoTo is not actually worst thing to happen in VB. In fact it's useful on error handlers and the On Error Resume Next, yes it's to be avoided as much as possible but there are some circumstances that it is needed.
However, the Variant usage is a waste of memory.
-
Re: Function Return More Than One Value
On Error GoTo and GoTo are not the same thing.... the GoTo stands alone. On Error GoTo is a complete statement.
I've never, ever, ran in to a case where OERN was needed. I'll admit, I used to use it pretty judiciously, until I learned better. Granted error handling on VB6- isn't all that, but there really is no need for OERN.
-tg
-
Re: Function Return More Than One Value
I know where you are coming from, almost every time I see O.E.R.N. on the forums it is completely inappropriate - it is just being used to mask errors, at which point we are asked "why doesn't this code do what it should?" :rolleyes:
There are times when (if used properly) it is the most appropriate method tho.. typically I will use it 2 or 3 times in a program (out of about 500 subs/functions). Most often is when working with groups of controls (which may or may not be part of a control array).
Apart from "On Error", I have yet to find a valid use for GoTo.
-
Re: Function Return More Than One Value
Quote:
Originally Posted by si_the_geek
I have yet to find a valid use for GoTo.
The only potential semi-legit use I've seen for it was for it in VB6 to act as a stand-in Continue For or Continue Loop statement. I inherited some code where the original programmer had done something like this:
VB6 Code
vb Code:
Private Sub BigHugeProcess()
Dim nLoop As Long
For nLoop = 1 To NumberOfLinesInFile
'
' Check for a condition at the start of the loop
'
If SkipThisLine(LineText) Then
GoTo EndOfLoop
End If
'
' about 3 pages of processing follows
'
EndOfLoop:
Next
End Sub
What it would look like in VB.Net code
vb Code:
Private Sub BigHugeProcess()
For nLoop As Integer = 1 To NumberOfLinesInFile
'
' Check for a condition at the start of the loop
'
If SkipThisLine(LineText) Then
Continue For
End If
'
' about 3 pages of processing follows
'
Next
End Sub
Of course, it's usually a lot better idea to break up BigHugeProcess into several smaller routines since it's also a bad coding practice to have large monolithic routines.
As for variants in VB6, I have used them in a few cases to implement kind of a "poor man's overloading" and as variant arrays in return values where they acted somewhat like Serialization or other object packaging methods in .NET. I agree these are risky to use and great care must be exercised to avoid conversion problems and that the performance impact has to be weighed against the flexibility advantages. Flexibility won out in the apps where I used these methods since quickly implementing new clients and processes was the most important requirement.
-
Re: Function Return More Than One Value
Quote:
Originally Posted by techgnome
I've never, ever, ran in to a case where OERN was needed.
Needed, no. Used properly, yes.
Code:
On Error GoTo XYZ
...
'code
On Error Resume Next
Kill sFileNameToBeKilled
On Error GoTo XYZ
You could trap the file not found error and figure out if it's the file we're trying to delete, but it's simpler to resume around that one line. That particular error in that particular place - once the program has been fully debugged - is to be expected at times.
-
Re: Function Return More Than One Value
Quote:
Originally Posted by bgmacaw
The only potential semi-legit use I've seen for it was for it in VB6 to act as a stand-in Continue For or Continue Loop statement.
You can just invert the logic to avoid most uses of this type
Code:
Private Sub BigHugeProcess()
Dim nLoop As Long
For nLoop = 1 To NumberOfLinesInFile
'
' Check for a condition at the start of the loop
'
If Not SkipThisLine(LineText) Then
' about 3 pages of processing follows
End If
'
Next
End Sub
There's no real difference, but it's more "PC", if that matters.
-
Re: Function Return More Than One Value
Quote:
Originally Posted by Al42
You can just invert the logic to avoid most uses of this type
True, although in a large routine where there is a lot of If...Then...Else or Select...Case filtering the indent levels also create a readibility problem. That's why it's best to break these huge routines up into more manageable and readable chunks.