What does := mean in VB? - vb.net

I've been using Visual Studio and I work with VB. Now I've noticed something called text:= in the IntelliSense suggestion list it gives me when coding. I'm not sure what it is. Could anyone explain it to me?

It allows you to specify the value of a particular parameter when passing arguments to a method. Normally, the parameters are determined by the order of the arguments. For instance, if you had a method like this:
Public Sub WriteStrings(s1 As String, s2 As String)
Console.AppendLine(s1 & s2)
End Sub
You would normally just call it like this:
WriteStrings("A", "B") ' Outputs "AB"
However, you could call it with named parameters like this:
WriteStrings(s1:="A", s2:="B") ' Outputs "AB"
In that example, the only real advantage is that it is obvious, when looking at the code, which argument is being passed for each parameter. However, it also allows the interesting possibility of passing the arguments in a different order. For instance:
WriteStrings(s2:="A", s1:="B") ' Outputs "BA"
However, the most common place you'll see it is when the parameters are optional. For instance, when calling this method:
Public Sub DisplayPerson(Optional includeName As Boolean = True,
Optional includeAge As Boolean = False,
Optional includeAddress As Boolean = True)
And you want to leave the default settings for the first two parameters and just want to force includeAddress to be False, you could just call it like this:
DisplayPerson(, , False)
But that's a little confusing. Many people find it less confusing to specify the name of the parameter to make the code easier to read:
DisplayPerson(includeAddress:=False)
Since arguments to set the properties of an attribute have no particular order, it's very common to see named arguments used there as well:
<DataContract(Name:="Test")>

Related

Format - Expected Array

I keep getting an error when I try to format this number. I've done it in VBA before and I tried to change the SOPID to a variant, a string, and an integer.
Dim SOPID As Integer
SOPID = DMax("file_id", "tblSOP") + 1
'Output test data
MsgBox (format(SOPID, "000"))
I have no idea what I am doing wrong.
Assuming the code was pasted directly from your IDE, the casing of format is suspicious; that would be Format, unless there's a format variable or function that's in-scope, ...and that's being invoked here.
Look for a public (could be implicitly Public, or if it's in the same module then it could also be Private) format function procedure that expects an array argument: that's very likely what's being invoked here.
Rubberduck (free, open-source; I manage this project) can help you easily identify exactly what's being invoked and an inspection would tell you about any shadowed declarations, but to be sure you can fully-qualify the function call to avoid inadvertently invoking another function that's in scope:
MsgBox VBA.Strings.Format$(SOPID, "000")
Note that there are no parentheses around the argument list of a parameterized procedure call in VBA; the parentheses you have there are surrounding the first argument and making the expression be evaluated as a value that is then passed to the invoked function: this isn't necessary.
Also note the $: the VBA.Strings.Format function takes and returns a Variant; VBA.Strings.Format$ takes and returns a String. If you aren't dealing with any Null values (an Integer couldn't be Null), consider using the String-returning alias.

Check if Optional Parameter has changed

i have a Function with1 Parameter and 10 optional Parameters.
The optional Parameters are all nothing.
Now i want to check if a optional Parameter had changed his Value or the Function was started with an optional Parameter.
Think of it that the Parameters can have the Value Nothing then the Function returns too.
ty for your help. :D
10 parameters.. that's a bit excessive... and hard to manage.
You would be better passing a class or structure.
Checking the optional parameter is the default value is the usual method for this for determining if it is pre-set or not as in the previous answer.
You would need to pass an object by reference if you need to test if it changed while the routine was running, but if it was originally passed as "Nothing" that will not work.
Without more information on what your usage intent is, it is a little hard to answer this conclusively.
If Parameter1 Is Nothing then
'Parameter1 changed
EndIf
If your other optional parameters is nothing I trust that their reference type is a string.
The following from MSDN to check if an optional argument is present -
A procedure cannot detect at run time whether a given argument has been omitted or the calling code has explicitly supplied the default value. If you need to make this distinction, you can set an unlikely value as the default. The following procedure defines the optional parameter office, and tests for its default value, QJZ, to see if it has been omitted in the call:
Sub notify(ByVal company As String, Optional ByVal office As String = "QJZ")
If office = "QJZ" Then
Debug.WriteLine("office not supplied -- using Headquarters")
office = "Headquarters"
End If
' Insert code to notify headquarters or specified office.
End Sub
Link can be found HERE

Meaning of `:=` Syntax in VBA methods

When writing the following VBA, what is the root cause of the error "Expected =" given that we are using the Format:=2.
Workbook.Open (filename, Format:=2)
I understand that this format works when setting the variable as in the following code, but why does it work here and not in the above format?
Set wrkb = Workbook.Open (filename, Format:=2)
Also what is this operator called, := and how is it used?
It's not an operator, it's a named argument.
You can chose the order of the arguments/parameters by directly specifying what they are.
The concept of named arguments also exists in multiple modern languages, such as c# (its optional, just like in VBA) and swift (by default it's required, but you can disable it).
Named arguments also allow you to omit arguments that are optional altogether, but pass an argument that is further back in the list of arguments. A good way to try named arguments out is the messagebox, since it has many optional arguments with default values.
Example: MsgBox only specifying title:
MsgBox Title:="wew lad"
Or, in the more modern way of writing vb(a) code:
Call MsgBox(Title:="wew lad")
The MsgBox is a good example, since you can call it normally, and then specify a parameter further back directly (works with other methods too):
Call MsgBox("Yes!", Title:="wew lad")
Once there are named parameters, you can't add ordered parameters after:
'Call MsgBox (Prompt:="Yes!", vbOkCancel Title:="wew lad")
'this doesnt work!
Now, why does this raise an error:
MsgBox ("Hello", Title:="test")
This is some of the weirder parts of vba. Calling functions with return values but ignoring the value while using parentheses is a bit broken.
You can circumvent this by adding a Call in front of it (vba then knows it can ignore the result).
This would look like this:
Call MsgBox ("Hello", Title:="test")
Honestly, I don't know why this is, but I've had it cause really weird bugs. When you use the parentheses syntax, I can really recommend using the Call keyword before the method call.
As Macro Man mentioned, you can also omit the parentheses, instead of using Call:
MsgBox "Hello", Title:="test"
And it will work, too. This was the original vba coding style and isn't really used anymore.

Optional ByVal boolean parameter is not taking its default value

I am debugging a project right now and it has a function with the following signature:
Public Function changeRemoteDirectory(ByVal newDirectory As String, Optional ByVal Direction As Boolean = True) As Boolean
MsgBox(direction)
'rest of code
End Function
I was trying to figure out what was causing this function to return a value of False when I knew that it should return True given the input that I was supplying, so I put MsgBox(direction) into the Function to see what the value of direction was when I called the Function. I called the function like this, yet I received a MsgBox that showed the value of direction to be False:
changeRemoteDirectory("/internal")
The first parameter works just fine and the code that requires it to execute works correctly, but I cannot figure out why Direction has a value of False in a situation where, I believe, it should have its default value of True. I'm not totally opposed to rewriting the Function if need be, but can anybody here discern why Direction does not have a value of True when the function changeRemoteDirectory() is called without the second parameter supplied?
It sounds like you're experiencing one of many pains that optional parameters cause.
When the code that calls changeRemoteDirectory is compiled, the optional parameter is injected into the calls just like a const would be replaced at compile time. Changes to the value of an optional parameter will not take effect without recompiling the caller.
See this article for more info.
In general, you should use method overloads instead of optional parameters. You get all of the same functionality without the pain and performance drawbacks.

How Do I Create Something 'OF' a Variable's Type?

I have some code like:
Lookup(Of String)("Testing")
Lookup(Of Integer)("Testing")
And both of those Lookups work great. What I'm trying to is call the appropriate LookUp based on the type of another variable. Something that would look like...
Lookup(Of GetType(MyStringVariable))("Testing")
I've tried to Google this but I'm having a hard time coming up with an appropriate search. Can anyone tell me how to do what I want?
You do not specify the full signature for the method that you're calling, but my psychic powers tell me that it is this:
Function Lookup(Of T)(key As String) As T
And you want to avoid having to repeat Integer twice as in the example below:
Dim x As Integer
x = Lookup(Of Integer)("foo");
The problem is that type parameters are only deduced when they're used in argument context, but never in return value context. So, you need a helper function with a ByRef argument to do the trick:
Sub Lookup(Of T)(key As String, ByRef result As T)
T = Lookup(Of T)(key)
End Sub
With that, you can write:
Dim x As Integer
Lookup("foo", x);
One solution to this is to use reflection. See this question for details.
You can't use a dynamic type unless you do runtime compiling, which of course is really inefficient.
Although generics allows you to use different types, the type still has to be known at compile time so that the compiler can generate the specific code for that type.
This is not the way to go. You should ask about what problem you are trying to solve, instead of asking about the way that you think that it should be solved. Even if it might be possible to do something close to what you are asking, it's most likely that the best solution is something completely different.
The VB.NET compiler in VS2008 actually uses type-inference. That means if you are using a generic method, and one of the parameters is of the generic type, then you don't need to specify the generic type in your call.
Take the following definition...
Function DoSomething(Of T)(Target As T) As Boolean
If you call it with a strongly-typed String for Target, and don't specify the generic parameter, it will infer T as String.
If you call it with a strongly-typed Integer for Target, and don't specify the generic parameter, it will infer T as Integer.
So you could call this function as follows:
Dim myResult As Boolean = DoSomething("my new string")
And it will automatically infer the type of T as String.
EDIT:
NOTE: This works for single or multiple generic parameters.
NOTE: This works also for variables in the argument list, not just literals.