Custom error handling vba - vba

I have a cell that is a brutal nested if and if error. I don't want to have to paste my vlookup 5 times in the formula. Instead, I'd like to have a macro check the errors. The special case is 0 or 1.
I wrote this function to get the value of the vlookup.
Public Function ValidateRealization(value As String)
Dim validate As String
If value = "#N/A" Or value = "#VALUE!" Or value or = "#REF!" Or value = "#DIV/0!" Or value = "#NUM!" Or value = "#NAME?" Or value = "#NULL!" Or value = "0" Or value = "1" Then
validate = ""
Else
validate = value
End If
ValidateRealization = validate
End Function
However, I know it can be improved for one when I set the value, the formatting as a percentage is overridden.
Is there a better way to do this? Maybe by getting the active cells range, and setting the value property?

You are bringing in a string and not a value, so the return is a string.
set the parameter as variant and test for error:
Public Function ValidateRealization(value) As Variant
Dim validate As Variant
If Not IsError(value) Then
If value = 0 Or value = 1 Then
validate = ""
Else
validate = value
End If
Else
validate = ""
End If
ValidateRealization = validate
End Function
Which can be simplified to:
Public Function ValidateRealization(value) As Variant
ValidateRealization = ""
If Not IsError(value) Then
If Not (value = 0 Or value = 1) Then
ValidateRealization = value
End If
End If
End Function

2 points: first, you have ervalue which is undefined. Go to the top of your module, and add the line Option Explicit. Then go "Tools" > "Options..." and tick "Require Variable Declaration".
Secondly: Why not accept a Variant instead of a String, and use IsError?
Public Function ValidateRealization(value As Variant) As Variant
If IsError(value) Or CStr(value) = "0" Or CStr(value) = "1" Then
ValidateRealization = ""
Else
ValidateRealization = value
End If
End Function
{EDIT} If you have converted your value to a String before passing it, then use Select Case
Public Function ValidateRealization(value As Variant) As Variant
If IsError(value) Then
ValidateRealization = ""
Else
Select Case CStr(value)
Case "#N/A", "#VALUE!", "#REF!", "#DIV/0!", "#NUM!", "#NAME?", "#NULL!", "0", "1"
ValidateRealization = ""
Case Else
ValidateRealization = value
End Select
End If
End Function

Related

Passing blank array to a function to and populate it from there

I am trying to pass a blank array to a function that will manipulate the array dependent on certain scenarios. I don't know where I am going wrong with this but I am getting the following error Type mismatch. Below shows how I am creating the blank array:
Dim testArray(0 to 10) as string
Dim ABredu() As String
ABredu = Equipment(testArray)
Below shows the function that I have written to populate the array
Function Equipment(Test() As String)
If standYes = True And .ComboBox2.ListIndex = 0 Then
ReDim ABredu(1 To 3)
ABredu(1) = "Pen"
ABredu(2) = "Ruler"
ABredu(3) = "Monitor"
Else
ReDim ABredu(1 To 3)
ABredu(1) = "17-P2"
ABredu(2) = "17-L73"
ABredu(3) = "16-ENR"
End If
End sub
If someone could help me or give a push in the right direction it would be greatly appreciated!
Pass the array by reference as a variant.
Function Equipment(ByRef Test As Variant)
If standYes = True And .ComboBox2.ListIndex = 0 Then
ReDim Test(1 To 3)
Test(1) = "Pen"
Test(2) = "Ruler"
Test(3) = "Monitor"
Else
ReDim Test(1 To 3)
Test(1) = "17-P2"
Test(2) = "17-L73"
Test(3) = "16-ENR"
End If
End sub
Slightly different approach using variant arrays.
Sub Some_Macro()
Dim ABredu As Variant, i As Long
ABredu = Equipment(True, 0)
For i = LBound(ABredu) To UBound(ABredu)
Debug.Print ABredu(i)
Next i
ABredu = Equipment(False, 0)
For i = LBound(ABredu) To UBound(ABredu)
Debug.Print ABredu(i)
Next i
End Sub
Public Function Equipment(standYes As Boolean, cdLI As Long)
Dim vEQUIP As Variant
If standYes And cdLI = 0 Then
vEQUIP = Array("Pen", "Ruler", "Monitor")
Else
vEQUIP = Array("17-P2", "17-L73", "16-ENR")
End If
Equipment = vEQUIP
End Function
There are several ways to accomplish what you are looking for. Pick the one that makes the most sense to you.
Okay, so I'm going to make a couple of assumptions about your expected logic here, since the code in your question is a bit nonsensical.
You're trying (I think) to:
Create an array of strings called ABredu
Use a function or subroutine to populate that array based on some conditions
With that in mind, you can create the following sub
Sub PopulateEquipment(EquipArr() As String)
ReDim EquipArr(1 To 3)
If <condition> Then '<~~ Insert your own conditions here
EquipArr(1) = "Value 1"
EquipArr(2) = "Value 2"
EquipArr(3) = "Value 3"
Else
EquipArr(1) = "AltVal 1"
EquipArr(2) = "AltVal 2"
EquipArr(3) = "AltVal 3"
End If
End Sub
Then to populate your array using this, you need only Dim it and then call the subroutine, passing the variable as an argument.
Dim ABredu() As String
Call PopulateEquipment(ABredu)
Even simpler, use an ArrayList.
Public arList As Object
Sub PartOne()
Set arList = CreateObject("System.Collections.ArrayList")
Call Equipment
End Sub
Private Sub Equipment() '// No Need to pass argument as arList is of Public scope.
With arList
If standYes And Me.ComboBox2.ListIndex = 0 Then
.Add "Pen"
.Add "Ruler"
.Add "Monitor"
Else
.Add "17-P2"
.Add "17-L73"
.Add "16-ENR"
End If
End With
End Sub

How do you check if an input is a negative number in VB

I am trying to do some validation which checks if the value in a textbox is an integer then checks if the the value is negative. It correctly checks if the value is an integer but I can't get it to check if the value is negative.
Note: The value being entered is the number of competitions attended so comps = competition etc...
Dim comps As Integer
Dim value As Double
If Integer.TryParse(txtCompsEntered.Text, integer) Then
value = txtCompsEntered.Text
If value < 0 Then
lblcompsatten.ForeColor = Color.Red
txtCompsEntered.ForeColor = Color.Red
lblcompsatten.Text = "No negative numbers"
Else
lblcompsatten.ForeColor = Color.Black
txtCompsEntered.ForeColor = Color.Black
lblcompsatten.Text = ""
End If
lblcompsatten.ForeColor = Color.Black
txtCompsEntered.ForeColor = Color.Black
lblcompsatten.Text = ""
Else
lblcompsatten.ForeColor = Color.Red
txtCompsEntered.ForeColor = Color.Red
lblcompsatten.Text = "Not a number"
End If
I have already looked at this thread but it didn't seem to work
how-to-check-for-negative-values-in-text-box-in-vb
Tryparse will convert the input to an integer if it succeeds - you don't need both the comps and value variables. Here's an example of how it works:
Dim comps As Integer
Dim input As String = "im not an integer"
Dim input2 As String = "2"
'tryparse fails, doesn't get into comps < 0 comparison
If Integer.TryParse(input, comps) Then
If comps < 0 Then
'do something
End If
Else
'I'm not an integer!
End If
'tryparse works, goes into comps < 0 comparison
If Integer.TryParse(input2, comps) Then
If comps < 0 Then
'do something
End If
End If
There are a couple of things off with your code but the main issue is using Integer.TryParse incorrectly.
Incorrect:
Dim value As Double
If Integer.TryParse(txtCompsEntered.Text, integer) Then
value = txtCompsEntered.Text
If value < 0 Then
Correct:
Dim value As Integer
If Integer.TryParse(txtCompsEntered.Text, value) Then
If value < 0 Then
The things to note are that Integer.TryParse will return a boolean value (true if the value can be convertan integer, false if not). It will them dump the converted value into the second parameter you pass into it. In your case, you had 'integer', which is incorrect. You should be passing in a variable and then using that variable for your comparison.
Also, be careful with your types. You have 'value' as a double when you seem to be working with integers.
Maybe try this?
If myinteger.toString.Contains("-") Then
'it's negative
Else
'it isn't
End If
Or even simplier
If myinteger < 0 Then
'it's not negative
Else
'it is negative
End if

Excel VBA - Custom Function; #VALUE error; VLOOKUP on different worksheet

I am attempting to do a VLOOKUP on a different worksheet based on given parameters in the function. I've played around with it for several hours and can not figure out why it is not working. I cut down the code as much as I could to test, but am unable to effectively find a solution. I think it might be an issue of how I am calling the range from the other worksheet for the VLOOKUP. Code is below. Please advice. If I'm unclear about what I'm asking just ask and I will provide feedback. Thank you
Function GraphDataA(cR As String, time As String, aClient As String, tps As String, dat As String)
Dim client As Boolean
Dim day As Boolean
Dim tot As Boolean
Dim dayTotData As Range
Dim dayTotDatas As Worksheet
Set dayTotDatas = ActiveWorkbook.Sheets("DayTot")
Set dayTotData = dayTotDatas.Range("A3:AI168")
client = False
day = False
tot = False
If date = "" Then
GraphDataA = ""
End If
If aClient = "" Then
GraphDataA = ""
End If
If cR = "Client" Then
client = True
End If
If time = "Day" Then
day = True
End If
If tps = "Total" Then
tot = True
End If
If client = True Then
If day = True Then
If tot = True Then
GraphDataA = WorksheetFunction.VLookup(aClient, dayTotData, WorksheetFunction.Match(dat, dayDate, 0) + 8, _
False)
End If
End If
End If
End Function
VLOOKUP() will throw an error if nothing matches. So you need to add error catching code to your function.
You need to modify the function as
Function MyFunction() as Something
On Error Goto ErrorHandler
' Your existing code goes here
Exit Function
ErrorHandler:
MyFunction = -1 ' Or something which indicates that the value isn't found
End Function
You don't appear to be returning any value from your function. Try adding As Variant to the end of the first line like so:
Function GraphDataA(cR As String, time As String, aClient As String, tps As String, dat As String) As Variant

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.

Varient data type changes value 0 to empty or blank

I am passing value 0 in the below code
Dim searchtext As Varient
Public Sub xyz_page_load()
searchtext = 0
If searchtext = "" Or searchtext = Empty Then
Debug.Print "Error" 'this line should not execute.
Else
Debug.Print "Good"
End If
End Sub
It should not go in "Error" line of code.
Can anyone make me know why it is happening so?
Why varient data type is considering 0 as empty or blank?
Empty equals to default value of compared type.
Say for Integer type Empty would be 0:
MsgBox 0 = Empty ' returns True
MsgBox CInt(Empty) ' returns 0
for String type Empty would be empty string "":
MsgBox "" = Empty ' returns True
MsgBox CStr(Empty) ' returns ""
for Boolean type Empty would be False:
MsgBox False = Empty ' returns True
MsgBox CBool(Empty) ' returns False
Since you're using Dim searchtext As Variant, variable searchtext can store values of any type, but when you assign 0 to a variable: searchtext = 0, type becames Variant / Integer:
and Empty for this type is 0. That's why searchtext = Empty evaluates to True for searchtext = 0