This is part 2 or a follow up blog of the previous VB6 blog regarding ByVal and ByRef which explores a use case that I often use when defining functions where I return a boolean and pass the value through parameter(s).
If you haven’t read that blog, here’s the link (cause this expects you to know what I discussed on that one):
I first used this technique several years ago when I was trying to find a way to get the return value and at the same time also allow me to know if there was an error and thereby allow the calling routine to change behavior depending on success or failure. If there was no error, the caller would consume the value but show the error when the call didn’t succeed.
I thought of using dictionary as the return value since it would allow me to pack many values in it, values and error.
I thought of using a class as a return value which would have properties like error and value.
And both of those worked, until I was trying to evaluate the return value to figure out if the call succeeded or not.
Long story short, I didn’t like it — so I tried something else and this is what I came up with and ended up using, as the better version among the versions I tried. Here’s the template (or function signature):
function function_name(byval input_values, ByRef outvalue, ByRef outerror As String) As Boolean
First set of parameters are those needed by the function and they’re passed by value.
The last two (2) are for containing the result of function execution and the error it produced/encountered respectively, and that both of these are passed by reference.
Lastly, the function returns True when there’s no error and False when it does. Additionally, the function sets the value of outerror to a blank string if successful and the error (via Err.Description) otherwise.
Here’s a trivial example when implementing this function signature for computing the vehicles fuel efficiency:
Function compute_km_per_liter_hybrid(ByVal km As Single, ByVal liters As Single, _
ByRef outvalue As Single, ByRef outerror As String) As Boolean
'
' computes fuel efficiency and returns the computed value.
' returns True if no error, False otherwise.
' additionally, "outerror" contains the error if returning False
'
Dim value_was_computed As Boolean
Try:
On Error GoTo Catch
outvalue = km / liters
outerror = ""
value_was_computed = True
GoTo Finally
Catch:
outvalue = -1
outerror = Err.Description
value_was_computed = False
Finally:
compute_km_per_liter_hybrid = value_was_computed
End Function
And here’s how this would be used:
Private Sub TestHybrid(ByVal liters_consumed As Integer)
Dim error_text As String
If compute_km_per_liter_hybrid(km_travelled, liters_consumed, fuel_economy, error_text) Then
StandardSummary "Using Hybrid"
Else
StandardSummary "Using Hybrid", "Unable to compute fuel efficiency: " & error_text
End If
End Sub
The function is called and evaluated (for success or failure) on the same line which makes it look like a simple IF..THEN..ELSE code and that it is more “obvious” where the values will be and what we’re trying to do, versus Dictionary or Class. Plus, this signature doesn’t require you to reference external libraries (like Scripting Runtime) or force you to create a Class just to make it work.
When you need to return multiple values, you can combine function and byref…or do the other options I mentioned.
And there’s one more…
That’s not the only reason why you need to understand this concept (of passing values via a arguments). Most Windows API are passing the return value via the argument, and you’d have a hard time using Windows APIs if you have not tried passing value back through an argument.
Here’s one of the many Windows API that uses a parameter to store the value (instead of returning it):
Private Declare Function GetComputerName Lib "kernel32" Alias _
"GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long
To use this, you have to define a buffer string that will contain the value of computer-name. Here’s what you’ll see from Microsofts web site:

In VB6, here’s how the code would look like:
Private Sub Form_Load()
Dim return_value As Long
Dim hostname As String
hostname = Space(100)
return_value = GetComputerName(hostname, Len(hostname))
Debug.Print return_value, hostname
End Sub
Here’s the GitHub link for the source codes used in this blog (in case you want to test and explore it):
https://github.com/vegitz/codes/tree/master/0021%20ByVal%20vs%20ByRef%20in%20VB6