Need to return value from a function in vba - vba

I am trying to return a value from a function but is not happening.
Public sub test()
x = 2
msgbox number(x)
Exit Sub
Public Function number(num)
if len(num) = 1 then
num = "0" + num
End if
End Function
The function is returning a null value.

You need to assign the result to the name of the function, and concatenate the 0, like this:
Public Function number(num) As String
if len(num) = 1 then
number = "0" & num
Else
number = num
End if
End Function
though it would seem easier to just use Format(num, "00")

Public function number(num as string) as string
If len(num) = 1 then
Number ="0" & num
Else
Number = num
End if
End function
You need to have code in the function that sets a value to the name of the function - the return value.

Related

Getting 15th digit

variable contains 15 digits,how to get 15th digit value from another function?
Function isvalid(stringvalue As String) As Boolean
Dim methodToCall As String
methodToCall = "somefunction"
isvalid = stringvalue Like "[0-9][0-9][A-Z][A-Z][A-Z][A-Z][A-Z]####[A-Z][A-Z][A-Z][methodToCall(stringvalue)]"
Here the methodToCall will call another function and that function is return value for my 15th digit
How to get the Value from anothor function from isvalid function
Say we have a string containing with a mixture of digits and other characters and we want the 15th digit. The UDF:
Public Function GetFifteenth(sin As String) As Variant
kount = 0
For i = 1 To Len(sin)
ch = Mid(sin, i, 1)
If IsNumeric(ch) Then
kount = kount + 1
If kount = 15 Then
GetFifteenth = CLng(ch)
Exit Function
End If
End If
Next i
GetFifteenth = ""
End Function
should do that. For example:
Sub MAIN()
Dim s As String, L As Variant
s = "t2}nf[aW(494U,Oay8OWkh{xa*9>9b2SY5yPt14;m98AYd$|>U%orIJ[iF*Q)0w21!0:eX9,kU<_ x=B+cAFU<)%#{JMSze}"
L = GetFifteenth(s)
MsgBox L
End Sub
The code would be a little simpler if the string always contained exactly 15 digits.

Extract right side of string specify by separator

This is my code to get right side of string specifying char separator and either to keep separator within string or not. Possibility also to specify if just last occurence of char separator or manually define it. My question is how to make same version but this time to get right side of string instead of left?
Public Shared Function GetLetSideStringByChar(splitterChar As String, searchingWord As String, keepCharAsWell As Boolean, lastindexof As Boolean, splitterCharPosition As Integer) As String
Dim index As Integer
Select Case lastindexof
Case False
index = GetNthIndex(searchingWord, splitterChar, splitterCharPosition)
Case True
index = searchingWord.LastIndexOf(splitterChar)
End Select
If index > 0 Then
If keepCharAsWell Then
searchingWord = searchingWord.Substring(0, index + splitterChar.Length)
Else
searchingWord = searchingWord.Substring(0, index)
End If
Else
searchingWord = String.Empty
End If
Return searchingWord
End Function
'jesli n separator nie odnalzeiony bedzie return -1, np jesli charseparator = . i damy n = 2 a word bedzie mial tlko jedna . to -1
Public Shared Function GetNthIndex(searchingWord As String, charseparator As Char, n As Integer) As Integer
Dim count As Integer = 0
For i As Integer = 0 To searchingWord.Length - 1
If searchingWord(i) = charseparator Then
count += 1
If count = n Then
Return i
End If
End If
Next
Return -1
End Function
I had written a code for your previous problem that you deleted.
To make the code more understandable I used an Enum to specify right or left:
Public Enum Direction
Left = 0
Right = 1
End Enum
then you can call the function like this:
Console.WriteLine(StringExtract("5345.342.323.323#$%", Direction.Right, 2, False))
Here the Seperator Index represents the dot number (starting at 1)
For Example:
648674.2327.12 first dot is 1 second is 2
And here is the function, I'm sure it could be shortened:
Public Function StringExtract(ByVal MyStr As String, ByVal Side As Direction, ByVal SeperatorIndex As Integer, ByVal SeperatorKeep As Boolean) As String
Dim MySubs() As String = MyStr.Split(".".ToCharArray, StringSplitOptions.RemoveEmptyEntries)
Dim IndexOfSplit As Integer
Dim MyResult As String = ""
If Side = Direction.Left Then
IndexOfSplit = SeperatorIndex - 1
For i As Integer = IndexOfSplit To 0 Step -1
MyResult = MyResult.Insert(0, MySubs(i) & ".")
Next
If SeperatorKeep = False Then
MyResult = MyResult.Remove(MyResult.LastIndexOf("."), 1)
End If
Else
IndexOfSplit = SeperatorIndex
For i As Integer = IndexOfSplit To MySubs.Length - 1
MyResult = MyResult & MySubs(i) & "."
Next
If SeperatorKeep = False Then
MyResult = MyResult.Remove(MyResult.LastIndexOf("."), 1)
Else
MyResult = "." & MyResult.Remove(MyResult.LastIndexOf("."), 1)
End If
End If
Return MyResult
End Function
Output example:
Input 1:
StringExtract("5345.342.323.323#$%", Direction.Right, 2, False)
Output 1:
323.323#$%
Input 2:
StringExtract("5345.342.323.323#$%", Direction.Right, 3, True)
Output 2:
.323#$%
Input 3:
StringExtract("4.34!2.3323.", Direction.Left, 2, True)
Output 3:
4.34!2.
PS: If anyone has any suggestions to shorten the function let me know I'm happy to learn.

how to call a function within an if statement (vba)

I am trying to call a function within my if statement. The function is called classyear and is just after the if. I am trying to run through a timetable and see what classes belong to each year. so if it ends in a 1 it will be counted. Does anyone know how I would go about calling the function? Any help is appreciated
Public Sub time()
Dim rgTimeTable As Range, rgClass As Range, counter As Integer
Set rgTimeTable = Range("B3, N11")
For Each rgClass In rgTimeTable
If rgClass.Value = classyear Then counter = counter + 1 ' classyear is the function
Next rgClass
MsgBox test ' also a function
End Sub
EDIT
Code for the function i am trying to call
Public Function classyear(class As String) As Integer
Dim yr As String
yr = Right(class, 1)
If IsNumeric(yr) Then classyear = yr Else classyear = 0
End Function
Your classyear function takes a string input, so you need to give it one. Something like:
If CInt(rgClass.Value) = classyear("Year1") Then counter = counter + 1
Also you can neaten up your classyear function:
Public Function classyear(class As String) As Integer
On Error Resume Next 'if error classyear will return 0
classyear = CInt(Right(class, 1))
End Function
You can call a Sub inside if block like:
(Use function if you want to return some value else use Sub)
if (...)
classyear() '<--Calling the Sub defined below
End if
Private Sub classyear()
.
.
End Sub
Hope this is what you are looking for.

VB perfect function

What is wrong with this perfect number function?
The method is supposed to decide whether the input number is/is not a perfect number. The answer is supposed to be all the perfect numbers from 1 to the input.
For example: 1 - 100 the answer would be 6 and 28
Public Function isPerfect(myInput As Integer) As Boolean
endCounter = myInput \ 2
sum = 1
For perfectCounter As Integer = 2 To endCounter
If myInput Mod perfectCounter = 0 Then
sum += perfectCounter
If sum = myInput Then
Return True
End If
End If
Next
Return False
End Function
Private Sub btnPerfect_Click(sender As Object, e As EventArgs) Handles btnPerfect.Click
input = Convert.ToInt32(txtNumber.Text)
msg = "The perfect numbers between 1 and " & input & " are : "
For inputCounter As Integer = 0 To input
If isPerfect(inputCounter) = True Then
msg += inputCounter & " "
End If
Next
MsgBox(msg, , "Perfect Number")
txtNumber.Focus()
txtNumber.Text = Nothing
End Sub
You have at least a couple of problems:
You are validating the perfect number inside the loop, before you've even finished summing the divisors.
For instance...
If sum = myInput Then
Return True
End If
The above should be checked after the loop.
More importantly, because you are setting endCounter to myInput \ 2, you are not summing all the divisors. Maybe you did this as an optimization. But if so, you forgot something along the way.
A quick fix is to change the endCounter assignment to:
endCounter = myInput - 1
Also, to avoid getting back 1 as a valid perfect number, I would initialize sum to 0, and would start the loop normally at 1 instead of 2.
So your function could look something like:
Public Function isPerfect(myInput As Integer) As Boolean
Dim endCounter As Integer = myInput - 1
Dim sum As Integer = 0
For perfectCounter As Integer = 1 To endCounter
If myInput Mod perfectCounter = 0 Then
sum += perfectCounter
End If
Next
Return sum = myInput
End Function
I'm sure you could optimize this further if you want to.
(*) Consider turning on Option Explicit as well.
Here is the correct implementation of isPerfect:
Public Function isPerfect(myInput As Integer) As Boolean
dim Sum as Integer = 1
For i as Integer = 2 To myInput / 2
If myInput Mod i = 0 Then Sum = Sum + i
Next
Return Sum = myInput
End Function

Function 'DisplayArray' doesn't return a value on all code paths. A null reference exception could occur at run time when the result is used

I keep getting a error and because of this my code wont work. The error is "Function 'DisplayArray' doesn't return a value on all code paths. A null reference exception could occur at run time when the result is used". I can't get rid of this error. I'm new to programming, can anyone help?
Private Function DisplayArray() As String
Dim j As Integer = 0
ReDim Preserve Array(UpperSub)
Dim AddNum As Double = 0.0
txtAddNum.Focus()
If Double.TryParse(txtAddNum.Text, AddNum) Then
If AddNum > 100 Then
MessageBox.Show("Number must be below 100")
ElseIf AddNum < 0 Then
MessageBox.Show("Number must be above 0")
Else
Array(UpperSub) = CDec(AddNum)
UpperSub = UpperSub + 1
End If
Else
MessageBox.Show("Value has to be a number")
End If
txtAddNum.Clear()
txtDisplay.Clear()
For j = 0 To UpperSub - 1
txtDisplay.Text = txtDisplay.Text _
& CStr(Array(j)) & ControlChars.NewLine
Next
txtNumberOfScores.Text = CStr(UpperSub)
End Function
A Function is designed to return a result, using the Return keyword. Your Function does not have a Return statement. Since none of the possible code paths (determined by branching on the If statements as well as the flow from beginning to end) return a value, you're getting this part of the error message: "Function 'DisplayArray' doesn't return a value on all code paths."
The second part of the error message means that if you tried to assign the return value of the Function to a variable, like this:
Dim result As String = DisplayArray()
You'd get a null value, as nothing is returned from the function.
The simplest solution is to change from a Function to a Sub. Subs in VB.NET do not return a value. So change
Private Function DisplayArray() As String
To
Private Sub DisplayArray()
And
End Function
To
End Sub
Note that the As String() in the Function declaration says this method will return a value that is a String, and the Sub has no return value (again, because it doesn't return a value).
To make this a Function that returns a value, you'll have to return at least one value from the method. Here's an example:
Private Function DisplayArray() As String
Dim j As Integer = 0
ReDim Preserve Array(UpperSub)
Dim AddNum As Double = 0.0
txtAddNum.Focus()
If Double.TryParse(txtAddNum.Text, AddNum) Then
If AddNum > 100 Then
MessageBox.Show("Number must be below 100")
Return String.Empty
ElseIf AddNum < 0 Then
MessageBox.Show("Number must be above 0")
Return String.Empty
Else
Array(UpperSub) = CDec(AddNum)
UpperSub = UpperSub + 1
txtAddNum.Clear()
txtDisplay.Clear()
For j = 0 To UpperSub - 1
txtDisplay.Text = txtDisplay.Text _
& CStr(Array(j)) & ControlChars.NewLine
Next
Return CStr(UpperSub)
End If
Else
MessageBox.Show("Value has to be a number")
Return String.Empty
End If
End Function
Essentially, if the validation fails, an empty string is returned. If the validation passes, the rest of the code is executed and the string value of UpperSub is returned.
You could then assign it to the TextBox like this:
txtNumberOfScores.Text = DisplayArray()
The above is a simple example based on your posted code, intended to show you how to return values from a Function. Adjust it to fit your needs (or use a Sub instead). Given that you want to update the display of the txtDisplay with the array and txtNumberOfScores as well you should do fine with a Sub.