Calling a Sub and returning a value - vb.net

This might seem like an insanely easy question, but I can't seem to find an answer anywhere to it. I'd like to think that I am decent at VB but while I was learning javascript the other day I found something that seemed awesome and now I can't figure out how to do it in VB.
In javascript it looks like this:
var someValue = getThatValue()
It's both calling and setting the value from the getThatValue() sub. what is the VB equivalent?
Edit
I've tried doing this:
private sub main()
dim value = getValue()
'do something with value
end sub
private sub getValue()
return 3
end sub
That doesn't seem to work, how can I get that to work?

Private Sub Main()
Dim value = getValue()
'do something with value
End Sub
Private Function getValue() As Integer
Return 3
End Function

You should be using a Property:
Private _myValue As String
Public Property MyValue As String
Get
Return _myValue
End Get
Set(value As String)
_myValue = value
End Set
End Property
Then use it like so:
MyValue = "Hello"
Console.write(MyValue)

Sub don't return values and functions don't have side effects.
Sometimes you want both side effect and return value.
This is easy to be done once you know that VBA passes arguments by default by reference so you can write your code in this way:
Sub getValue(retValue as Long)
...
retValue = 42
End SUb
Sub Main()
Dim retValue As Long
getValue retValue
...
End SUb

Related

How to declare a variable as given Type in vb.net

Please help me to resolve this little task: how to declare a variable as given type. In this case - interface.
I guess, the answer is simple, but I don't know it, and Google don't too.
I tried everything, but I can't resolve it.
Thank you.
Public Interface IMyInterface
Property MyProperty
End Interface
Public Sub MySimpleSub()
Dim tType As System.Type = GetType(IMyInterface)
Call SubAcceptsInterface(tType)
End Sub
Public Sub SubAcceptsInterface(ByVal tType As System.Type)
Dim arrMyArray() As tType= {} ' <-- here's an error: Error 1 Type 'tType' is not defined.
End Sub
If you want to pass a type of a class/structure/interface to a function, you can template the function like this:
Public Sub SubAcceptsInterface(Of tType)()
Dim arrMyArray() As tType = {} 'This should declare fine
End Sub
Pass the tType parameter of the template like this:
Public Sub MySimpleSub()
SubAcceptsInterface(Of IMyInterface)()
End Sub

VBA Encryption Method

I have written a very simple Ceaser Cipher encryption algorithm on VBA. It takes a string value and applies x shift.
Quite happy with it. However, would like to take it to the next step, but I am not sure if it is doable.
I would like to call this encryption function in another module and pass a string value to encrypt.
I.e. What I am trying to do is something like this
Private Sub Encryption()
'Encryption method of string Var
End Sub
---- and in another sub ----
Private Sub function()
Dim Text as String
Text = "Hello"
Encryption(Text)
End Sub
So in this example, I have defined a method to encrypt any string variable. In the other function, I defined a string and initialised it as "Hello". Then called Encryption function on it... Not sure if this is doable in VBA?
I am not sure how I could pass in a variable when I am calling a function within a function. Any advise please?
You would need to change the Sub Routine to a Function. Also, get rid of the Private keyword as this will not allow you to call it across different modules.
So Change this:
Private Sub Encryption()
'Encryption method of string Var
End Sub
to this:
Function Encryption(ByVal inputString as String) As String
'Encryption method of string Var
End Sub
Now, inside your function you need to change whatever variable holds the first string (the one to be encrypted) to the newly created variable, inputString. It's hard to help you in this area as you did not provide the full code for Sub Encryption().
Also, ensure that you set the Function name itself to the newly encrypted text within the function. So your function would essentially look as follows:
Function Encryption(ByVal inputString as String) As String
'Encryption method of string Var
Encryption = 'the value to return from this function
End Sub
Now, your second sub would look like this:
Private Sub test()
Dim Text as String, encryptedText as String
Text = "Hello"
encryptedText = Encryption(Text)
End Sub
You will just make the new variable encryptedText equal to the new function, Encryption.
So, the major difference between a Sub and a Function is that a Function will return values. They both essentially process code the same way.
METHOD 2 (Edit)
After rethinking your question, I believe that you were using your Sub to obtain your encrypted text from passing the variable as ByRef, and you may just be having difficulties with calling the Sub because of the Private keyword.
If this what was going on, then you can simply remove the Private keyword and it should work as intended.
So your Sub should look like:
Sub Encryption() '<-- Notice, no Private scope
'Encryption method of string Var
End Sub
or
Public Sub Encryption()
'Encryption method of string Var
End Sub
You should take a look at this for additional reading regarding scope.

Passing a parameter to a function to get a string back

I think this is relatively a simple question but it seems like I've been having a small issue with this...
I have a form where I try to pass a parameter to a function and get a string back in return with a value
ParmValue = "Juarez"
dim CheckValue = GetValueFromFunction(parmValue)
Private Sub GetValueFromFunction (ByVal Optional ValueFromFunc as string)
'do stuff
getValueFromFunction = "OK"
or
getValueFromFuncton="NOTOK"
return GetValueFromFunction
End sub
Basically I'm looking to get a string value back from my GetValueFromFunction so that CheckValue holds that value. What am I doing wrong?
You can't return something from a Sub; it has to be a Function:
Private Function GetValueFromFunction(Optional ValueFromFunc as String = Nothing) As String
Dim returnValue As String
'do stuff...
If someCondition Then
returnValue = "OK"
Else
returnValue = "NOTOK"
End If
Return returnValue
End Function
A Function is a method that returns something, whereas a Sub is a method that doesn't return something (it's more like an action). In C#, a Sub would return void.
Because you are returning a value, you need to use a Function. Your code is wrong because it declares a Sub (procedure).
The correct use of a Function is:
Private Function GetValueFromFunction (ByVal ValueFromFunc As String) As String
' do stuff
GetValueFromFunction = "OK"
' or
GetValueFromFunction = "NOTOK"
Return GetValueFromFunction
End Function
Note the use of As String. This is to dictate the return type of your Function.

VBA excel Passing back parameter

Okay I want to add something to this macro
Sub Search()
Inputbox myInput
found = false
loop
Call getInput (myInput) '~> check multiple files
end loop
If found = false
'DO something
End if
End sub
Sub getInput(ByVal inputVar As String, ByVal Input as Boolean)
If a = inputVar Then
found = true '~> I want to pass this parameter back to search
End If
End sub
The case is like, I want my sub to pass the found parameter from
Search() to getInput() and then getInput() return the found parameter to
Search()
Should I add something like search(ByVal found as boolean) ?
if you want to return a value, then you should change the getInput Sub to a function as they can return values.
Sub Search()
Dim found As Boolean
InputBox myInput
found = checkInput(myInput)
If found = False Then
'DO something
End If
End Sub
Function checkInput(inputVar As String) As Boolean
Dim result As Boolean
'do your checking here and set result
'return the result
checkInput = result
End Function

Pass property to access using .NET

I'm fairly sure this is possible, but what I want to do is have a generic method where I can pass in an object along with a Expression that will tell the method which Property to use in it's logic.
Can anyone get me started on the syntax for something like this?
Essentially what I would like to code is something like:
Dim firstNameMapper as IColumnMapper = new ColumnMapper(of Author)(Function(x) x.FirstName)
Dim someAuthorObject as new Author()
fistNameMapper.Map("Richard", someAuthorObject)
Now the mapper object would know to set the FirstName property to "Richard".
Now using a Function here won't work, I know this... I'm just trying to give an idea what I'm trying to work towards.
Thanks for any help!
You could use expression trees to implement this behavior, but it would be a lot simpler to pass the ColumnMapper a slightly different function. Instead of using expression that reads the property, you could give it a function that sets the value of the property:
Dim firstNameMapper as IColumnMapper = _
new ColumnMapper(of Author)(Sub(x, newValue) _
x.FirstName = newValue _
End Sub)
I think this syntax is new in Visual Studio 2010 (but I'm not a VB expert). Anyway, the type of the parameter would be Action<Author, string> and you could simply invoke it anytime you needed from the ColumnMapper to set the property.
Using expression trees, you'd have to construct expression that sets the property and compile it at runtime, so I think the additional few bits of code above are easier way to solve the problem.
Okay, so I have implemented an analogous solution (i'm not using 2010 so I can't use Tomas' solution directly) but although it compiles, the property does not seem to be set. So here are all the pieces:
Module Module1
Sub Main()
Dim inputSource() As String = {"Richard", "Dawkins"}
Dim firstNameMapper As New ColumnMapper(Of Author)(Function(obj, value) obj.FirstName = value, 0)
Dim lastNameMapper As New ColumnMapper(Of Author)(Function(obj, value) obj.LastName = value, 1)
Dim theAuthor As New Author
firstNameMapper.map(inputSource, theAuthor)
lastNameMapper.map(inputSource, theAuthor)
System.Console.WriteLine(theAuthor.FirstName + " " + theAuthor.LastName)
System.Console.ReadLine()
End Sub
End Module
Public Class ColumnMapper(Of T As {Class})
Dim _propertyMapper As Action(Of T, String)
Dim _columnIndex As Int32
Public Sub New(ByVal mapAction As Action(Of T, String), ByVal columnNumber As Int32)
_propertyMapper = mapAction
_columnIndex = columnNumber
End Sub
Public Sub map(ByVal sourceFields As String(), ByRef destinationObject As T)
_propertyMapper(destinationObject, sourceFields(_columnIndex))
End Sub
End Class
Public Class Author
Private _firstName As String
Private _lastName As String
Public Property FirstName() As String
Get
Return _firstName
End Get
Set (ByVal value As String)
_firstName = value
End Set
End Property
Public Property LastName() As String
Get
Return _lastName
End Get
Set (ByVal value As String)
_lastName = value
End Set
End Property
End Class
Any idea why the property is not being set?
Not sure why the solution using inline 'Function' doesn't work. Perhaps someone more versed in the inner workings of vb.net can explain it, but if you implement the main module as below, it works. Thanks Tomas for pointing me in the right direction!
Module Module1
Sub Main()
Dim mapAction As Action(Of Author, String)
Dim inputSource() As String = {"Richard", "Dawkins"}
Dim firstNameMapper As New ColumnMapper(Of Author)(AddressOf setFirstName, 0)
Dim lastNameMapper As New ColumnMapper(Of Author)(AddressOf setLastName, 1)
Dim theAuthor As New Author
firstNameMapper.map(inputSource, theAuthor)
lastNameMapper.map(inputSource, theAuthor)
System.Console.WriteLine(theAuthor.FirstName + " " + theAuthor.LastName)
System.Console.ReadLine()
End Sub
Public Sub setFirstName(ByVal obj As Author, ByVal value As String)
obj.FirstName = value
End Sub
Public Sub setLastName(ByVal obj As Author, ByVal value As String)
obj.LastName = value
End Sub
End Module