Type mismatch error using custom class subroutine in Excel VBA - vba

Working in Excel VBA, I have a class module where I define my class 'Marker'. One of the properties of my class is TextLine(), which is an array that holds up to 5 strings. I have defined the two methods below in my class module. In another (regular) module, I fill markerArr() with my custom Marker objects. Loading each object's properties with data at each array index is working fine... However, after loading data into the object at each index, I try to use markerArr(count).ProcessLines but receive a type mismatch error. Since ProcessLines is a public sub in my class module, and markerArr(count) contains a Marker object, I can't seem to understand why this error is occurring... Am I overlooking something obvious?
'Serial number replacement processing function
Public Sub ProcessLines()
Dim strSerial As String
Dim toggle As Boolean
toggle = False
Dim i As Integer
For i = 0 To 4
If Trim(m_TxtLines(i)) <> "" Then
'Add linefeed char to non-empty text lines
m_TxtLines(i) = m_TxtLines(i) & Chr(10)
'Detect if it is a serialized line
If InStr(1, m_TxtLines(i), "XXXXXX-YYY") > 0 Then
m_Serial(i) = True
toggle = True
End If
End If
Next
'When at least one line on the marker is serialized, create and replace serial text
If toggle = True Then
'Only prompt for input once
If startSerNo < 1 And Num_Sers < 1 Then
startSerNo = InputBox("Enter the serial number to start printing at." & Chr(10) & _
"Entering 1 will result in -001, entering 12 will result in -012, etc.", "Starting Serial #", "1")
Num_Sers = InputBox("Enter the amount of serializations to perform." & Chr(10) & _
"This will control how many copies of the entire marker set are printed.", "Total Serializations", "1")
End If
strSerial = CreateSerial(startSerNo)
Dim j As Integer
For j = 0 To 4
If m_Serial(j) Then
m_TxtLines(j) = Replace(m_TxtLines(j), "XXXXXX-YYY", strSerial)
End If
Next
End If
End Sub
'Creates the string to replace XXXXXX-YYY by concatenating the SFC# with the starting serial number
Private Function CreateSerial(ByVal startNum As Integer)
Dim temp
temp = SFC_Num
Select Case Len(CStr(startNum))
Case 1
temp = temp & "-00" & startNum
Case 2
temp = temp & "-0" & startNum
Case 3
temp = temp & "-" & startNum
Case Else
temp = temp & "-001"
End Select
CreateSerial = temp
End Function

Your CreateSerial function takes an integer as a parameter, but you are attempting to pass a string. I've pointed out some problems:
If startSerNo < 1 And Num_Sers < 1 Then 'Here I assume, you have these semi-globals as a variant - you are using numeric comparison here
startSerNo = InputBox("Enter the serial number to start printing at." & Chr(10) & _
"Entering 1 will result in -001, entering 12 will result in -012, etc.", "Starting Serial #", "1") 'Here startSerNo is returned as a string from the inputbox
Num_Sers = InputBox("Enter the amount of serializations to perform." & Chr(10) & _
"This will control how many copies of the entire marker set are printed.", "Total Serializations", "1") 'here Num_Sers becomes a String too
End If
strSerial = CreateSerial(startSerNo) 'here you are passing a String to the CreateSerial function. Either pass an integer, or allow a variant as parameter to CreateSerial
'......more code.....
Private Function CreateSerial(ByVal startNum As Integer)

Related

Trying to get the value in vba from the combo box selection in a form

I have a form in which there is a combobox that holds all the badge numbers (example of a badge # : 12345) but when I try to assign it to a variable in vba it gives me the following error:
run-time error '6'
overflow
But when I go to debug it shows that Combo529.Value = 12345 but it wont assign it to my variable and gives the error
Private Sub reportRecord_Click()
Dim badgeNum As Integer
badgeNum = Combo529.Value
reportRecord.Value = getReport(badgeNum)
End Sub
and here is the code for the getReport() function:
Function getReport(badge As Integer)
Dim yearNow As Integer
yearNow = year(Date)
Dim report As String
report = badge & "-" & yearNow & "-"
Dim i As Integer
For i = 1 To 3
If Not IsNull(DLookup("Badge_ID", "Employee_Self_Assessment", "Report_ID = ' " & report & "0" & i & "'")) Then
getReport = 0
Else
Next i
getReport = 1
End If
End Function
Presume Badge_ID is an autonumber or long integer field and apparently the value is too large for Integer variable. Declare the variable as Long. Or a Variant type should work - variables not explicitly declared will default to Variant.

VBA Public Variable Not Working - MS Word - Counting Characters in a Table

The main VBA procedure counts characters in table cells in a Word document. Since it can count characters different ways:
Count the "Objective" text for the selected table
Count the "Accomplishment" text for the selected table
Count both the Obj and Acc texts in each table (loop), for all tables (another loop)
I created calling procedures for each option above that calls the main procedure. This way I pass variables from the calling Sub to the main Sub. These variables (1) tell the main Sub whether I want to count what is in row 3 (objective) or in row 5 (accomplishment) or both, and (2) feed the If/then lines in the main Sub to make sure the right row is counted. At the time, it seemed elegant, in hindsight - not so much.
Word template below:
There will be text in O1 and the VBA will count it (characters, spaces + paragraphs) and output it in C1, and the C1 fill changes red or green if over/under the character limit. The same for A1 and C2 and so on for any number of following tables.
PROBLEM DESCRIPTION
The VBA was working for the actions above when I had the row/columns hard coded into various places in the code. If rows/columns were ever added/deleted from the tables, they would have to updated in multiple spots. It would be simpler if the row/column numbers were in one place and referred back to as variables, so I changed the row/col #s to public variables. Then the problem began.
In the code, I track (debug.print) what becomes of oRow (output row) & chcct (character count col) and both are 0 as the main Sub runs, despite both being initialized as 3 in the public Sub Row_Col_Num() below.
My public variables are at the top of the module before the first Sub() and denoted as Public. Sub Row_Col_Num() which contains the variable assignments is also Public. All Subs are in the same standard module.
Option Explicit
Public oRow As Integer 'row with "Objectives" text
Public aRow As Integer 'row with "Accomplishments" text
Public cOnA As Integer 'column that both obj and accmp text are in
Public cChCt As Integer 'column that the char count is output to
Public Sub Row_Col_Num()
oRow = 3
aRow = 5
cOnA = 1
cChCt = 3
Debug.Print "cchct pub sub: " & cChCt
End Sub
ATTEMPTS TO FIX PROBLEM & RESULTS
I used the variable normally and left it Public as well as the Sub that assigns the variables (oRow =3) values.
Sub TableCharCount_Obj()
'Run character count for the "Objectives" in the SELECTED table
Debug.Print "orow = " & oRow
Call TableCharCount(oRow, oRow) 'provide it 2x to make IF and FOR loop
End Sub
I tried putting the Sub() name in front of the variable when it is used, e.g. Row_Col_Num.orow, in the Sub above.
Call TableCharCount(Row_Col_Num.oRow, Row_Col_Num.oRow)
I tried the module name in front of the variable as well, e.g. Module1.orow.
Call TableCharCount(Module1.oRow, Module1.oRow)
RESULTS
#1 & #3 resulted in the macro counting the wrong row and outputting to the wrong cell.
#2 resulted in error "Expected Function or variable" at line: Call TableCharCount(Row_Col_Num.oRow, Row_Col_Num.oRow)
All 3 cases orow and cchct both continued to be 0 throughout the run.
QUESTIONS / SOLUTIONS
a) Can a Public variable (oRow) be used as an argument passed from calling Sub to called Sub as ByVal a As Integer?
b) Does Public Sub Row_Col_Num(), which assigns values to the public variables, have to be explicitly run or called to populate the variables in the other Subs w/ the correct values?
c) Should I call Public Sub Row_Col_Num() in every calling Sub before calling the main Sub?
Sub TableCharCount_Obj()
Call Public Sub Row_Col_Num() '<<< add this call
Call TableCharCount(oRow, oRow) 'provide it 2x to make IF and FOR loop
End Sub
This option seems like a bad design.
If it's not obvious, there was some mission creep as I added more capability For now, if I could get the public variables to work, it would be done. Appreciate any suggestion to get these variables to work. For the purposes of this question, I only left the code for the variable Sub, the first calling Sub and the main Sub. VBA below:
'#0 -- This creates variables for column and row number used in all the macros. Only need to change row/col number here if row/col are added/deleted
Option Explicit
Public oRow As Integer 'row with "Objectives" text
Public aRow As Integer 'row with "Accomplishments" text
Public cOnA As Integer 'column that both obj and accmp text are in
Public cChCt As Integer 'column that the char count is output to
'This assigns row/column numbers to the variables
Public Sub Row_Col_Num()
oRow = 3
aRow = 5
cOnA = 1
cChCt = 3
Debug.Print "cchct pub sub: " & cChCt End Sub
'#2
Sub TableCharCount_Obj() 'Run character count for the "Objectives" in the SELECTED table
Debug.Print "orow = " & oRow
Call TableCharCount(oRow, oRow) 'provide it 2x to make IF and FOR loop
End Sub
'other calling procedures removed
'#5
Option Explicit
Sub TableCharCount(ByVal a As Integer, ByVal b As Integer)
'Counts total characters in a cell w/in a table and outputs the number to a different cell, and colors the cell red or green if over/under the maximum number of characters.
Dim charCount, charWSCount, paraCount, charTot As Double
Dim iRng, oRng, txtRng As Word.Range
Dim i, max, s, t, x As Integer
Dim tcount, tbl As Integer
Dim DocT As Table 'for active doc tables
Debug.Print "cchct1= " & cChCt 'Debug.Print vbCr & "-----START-------" & vbCr Application.ScreenUpdating = False
If a <> b Then
tcount = ActiveDocument.Tables.Count
tbl = 1 'used in FOR loop, start w/ table #1
s = b - a '"STEP" used in FOR loop = # of rows between objectives text and accomplishments text Else
On Error GoTo ErrMsg 'handles expected user error of not selecting a table to execute on
tbl = ActiveDocument.Range(0, Selection.Tables(1).Range.End).Tables.Count 'ID the table that is selected
tcount = tbl 'prevents FOR loop from trying to run again
s = 1 '"STEP" used in FOR loop = # of rows between objectives text and accomplishments text / do not set to zero = infinite loop End If
'Debug.Print "# of Tables: " & tcount
For t = tbl To tcount 'loops thru the tables
Set DocT = ActiveDocument.Tables(t)
For x = a To b Step s 'loops thru the applicable row(s) in the table
'Debug.Print "x # start = " & x
'Debug.Print "table " & t
iRng = DocT.Cell(x, cOnA)
iRng.Select
'Count used in output
Selection.MoveLeft wdCharacter, 1, wdExtend 'computerstats requires the text itself selected, characters.count can use the whole cell selected
charWSCount = Selection.Range.ComputeStatistics(Statistic:=wdStatisticCharactersWithSpaces) 'counts bullets & space after bullet / not line breaks (paragraphs)
'Debug.Print "Comp statchar# " & charWSCount
'---------
paraCount = Selection.Range.ComputeStatistics(Statistic:=wdStatisticParagraphs)
'Debug.Print "#paras = " & paraCount
'----------
charTot = charWSCount + paraCount
'Output to table cell
i = x - 1 'output cell is 1 row above cell that is counted
Set oRng = DocT.Cell(i, cChCt).Range 'Char count ouput row,column
Debug.Print "cchct2= " & cChCt
oRng.Text = charTot
Set txtRng = DocT.Cell(i, cChCt - 1).Range '"# Char:" location row,column
txtRng.Text = "# Char:"
'Maximum # of char allowed in a cell. Used to change cell fill red or green.
max = 2000 '"Accomplishment" row (row 5) has a max of 2000
If i = 2 Then max = 1500 '"Objective" row (row 3) has a max of 1500
'Change color of cell to indicate over/under max # of characters
If charCount < max Then
oRng.Shading.BackgroundPatternColor = wdColorBrightGreen
Else: oRng.Shading.BackgroundPatternColor = wdColorRed
End If
'Debug.Print "x # end = " & x
'Debug.Print "--------Next x--------------"
Next x
'Debug.Print "------Next Table------"
Next t
ActiveDocument.Tables(tbl).Select 'attempt to move to top of 1st table if using CharCount_AllTab() or just to the top of the selected table for the other macros
Selection.GoTo What:=wdGoToBookmark, Name:="\Page" Selection.StartOf
Application.ScreenUpdating = True
Exit Sub
ErrMsg: Msgbox "Select a table by placing the cursor anywhere in the table. Press OK and try the macro again numnuts!", _
vbOKOnly, "Table not selected"
End Sub

Vb.net Data is not being incremented and added to list

I'm having an issue trying to create a program that takes user input for a text file's location containing medical records. The diseases and number of patients are being added to a list. I'm having an issue where my console is printing 0 for both the total of XX unique diseases and YYY patient encounters. I am not getting any errors, just not the correct output.
I believe my issue is in my processData() sub, however I am unsure why it's printing back 0. Also, how do I go about keeping track of duplicate diseases that are added to the list as I'm trying to add a counter next to each time the disease is seen.
Sample from Disease.txt
3710079 JUDITH CLOUTIER 2012-08-04 Spastic Colonitis
3680080 VIRGINIA ALMOND 2012-07-25 Chronic Phlegm
3660068 ELLEN ENGLEHARDT 2012-04-06 Whooping Cough
3810076 LILLIAN KEMMER 2014-07-04 Scurvy
3630055 TERESA BANASZAK 2012-06-15 Scurvy
Output:
There were a total of 0 unique diseases observed.
A total of 0 patient encounters were held
Main():
' Global variables
Dim inputFile As String
Dim patientCounter = 0
Dim diseaseList As New List(Of String)
Dim dateList As New List(Of Date)
Sub Main()
Dim reportFile As String
Dim yn As String
Console.ForegroundColor = ConsoleColor.Yellow
Console.BackgroundColor = ConsoleColor.Blue
Console.Title = "Medical Practice Data Analysis Application"
Console.Clear()
Console.WriteLine("Please enter the path and name of the file to process:")
inputFile = Console.ReadLine
If (File.Exists(inputFile)) Then
' Call to processData sub if input file exists
processData()
Console.WriteLine(vbCrLf & "Processing Completed...")
Console.WriteLine(vbCrLf & "Please enter the path and name of the report file to generate")
reportFile = Console.ReadLine
File.Create(reportFile).Dispose()
If (File.Exists(reportFile)) Then
Console.WriteLine(vbCrLf & "Report File Generation Completed...")
Else
' Call to sub to end program if directory does not exist
closeProgram()
End If
' Get user input to see report
Console.WriteLine(vbCrLf & "Would you like to see the report file [Y/n]")
yn = Console.ReadLine
' If user inputs "y" or "Y" then print report
' Otherwise close the program
If (yn = "y" OrElse "Y") Then
printFile()
Else
closeProgram()
End If
Else
' Call to sub to end program if file does not exist
closeProgram()
End If
Console.ReadLine()
End Sub
processData Sub():
Public Sub processData()
Dim lines As String() = File.ReadAllLines(inputFile)
Dim tab
Dim dates
Dim diseaseCounter = 0
For Each line As String In lines
tab = line.Split(vbTab)
patientCounter += 1
dates = Date.Parse(line(3))
dateList.Add(dates)
'diseaseList.Add(line(4))
Dim disease As New disease(line(4))
diseaseList.Add(disease.ToString)
'diseaseList(line(4)).
For Each value In diseaseList
'If value.Equals(line(4)) Then disease.counter += 1
Next
Next
Dim uniqueDiseases As String() = diseaseList.Distinct().ToArray
End Sub
Disease.class
Class disease
Dim counter As Integer = 0
Dim name As String = ""
Sub New(newDisease As String)
name = newDisease
counter = 0
End Sub
End Class
printFile()
Sub printFile()
Dim muchoMedical As String = "MuchoMedical Health Center"
Dim diseaseReport As String = "Disease Report For the Period " & "earliest_date" & " through " & "latest_date"
Console.WriteLine(vbCrLf & muchoMedical.PadLeft(Console.WindowWidth / 2))
Console.WriteLine(diseaseReport.PadLeft(Console.WindowWidth / 2))
Console.WriteLine(vbCrLf & "There were a total of " & diseaseList.Count & " unique diseases observed")
Console.WriteLine("A total of " & patientCounter & " patient encounters were held")
Console.WriteLine(vbCrLf & "Relative Histogram of each disease")
For Each disease As String In diseaseList
Console.WriteLine(vbCrLf & disease & vbTab & " ")
Next
End Sub
closeProgram()
Sub closeProgram()
Console.WriteLine(vbCrLf & "File does not exist")
Console.WriteLine("Press Enter to exit the program...")
Console.ReadLine()
End Sub
You don't need a disease class, really, if the most complicated thing you are doing is counting disease occurrences (your disease class had no public members so I don't know what you were doing there anyway). You can simply do everything with a little LINQ.
' processing section
Dim lines = File.ReadAllLines(inputFile)
Dim splitLines = lines.Select(Function(l) l.Split({vbTab}, StringSplitOptions.RemoveEmptyEntries))
Dim diseaseGrouping = splitLines.GroupBy(Function(s) s(3))
Dim patients = splitLines.Select(Function(s) s(1))
Dim dates = splitLines.Select(Function(s) DateTime.Parse(s(2)))
' report section
Dim padAmount = CInt(Console.WindowWidth / 2)
Dim muchoMedical As String = "MuchoMedical Health Center"
Dim diseaseReport As String = $"Disease Report For the Period {dates.Min():d} through {dates.Max():d}"
Console.WriteLine()
Console.WriteLine(muchoMedical.PadLeft(padAmount))
Console.WriteLine(diseaseReport.PadLeft(padAmount))
Console.WriteLine()
Console.WriteLine($"There were a total of {diseaseGrouping.Count()} unique diseases observed.")
Console.WriteLine($"A total of {patients.Count()} patient encounters were held")
For Each diseaseAndCount In diseaseGrouping
Console.WriteLine()
Console.WriteLine($"{diseaseAndCount.Key}{vbTab}{diseaseAndCount.Count()}")
Next
I think your disease name is in index 3. You were looking at 4 originally. Maybe you have a tab between first and last name? Change it if I was wrong. This may apply to any or all of the indices.
Output:
MuchoMedical Health Center
Disease Report For the Period 4/6/2012 through 7/4/2014
There were a total of 4 unique diseases observed.
A total of 5 patient encounters were held
Spastic Colonitis 1
Chronic Phlegm 1
Whooping Cough 1
Scurvy 2
I think the main issue with your code as listed above is that in the processData sub you have:
For Each line As String In lines
tab = line.Split(vbTab)
patientCounter += 1
dates = Date.Parse(line(3))
dateList.Add(dates)
'diseaseList.Add(line(4))
Dim disease As New disease(line(4))
diseaseList.Add(disease.ToString)
'diseaseList(line(4)).
For Each value In diseaseList
'If value.Equals(line(4)) Then disease.counter += 1
Next
Next
I think you more likely mean to use tab(3) and tab(4) instead of line(3) and line(4) etc. You split the line into the "tab" variable but then don't use it. While you could rewrite everything and handle it differently, if you want to go with what you've got, I think that's your core error.
I liked your idea of a class. You can wrap up all your data in one list. I enhanced your class so it could contain all the data in the file. Public Properties are automatic properties that have Get, Set, and the Private fields that hold the data written by the compiler. I have added an Overrides of the .ToString because you were not getting the results you expected. We have the parameterized constructor like you have except expanded to include all the properties.
The magic comes in the Linq query. The d stands for an item in the diseaseList which is an instance of the Disease class. Then I added an order by clause which will produce the results in alphabetical order by DiseaseName which is a string. Grouping by the unique DiseaseName into a Group with Count.
Notice in the second For Each loop we have all the properties of the class available.
I happened to be in a Windows Forms app so I used Debug.Print. Just replace with Console.WriteLine. I leave to you the fancy formatting if you desire.
Public Class Disease
Public Property Name As String
Public Property DiagnosisDate As Date
Public Property DiseaseName As String
Public Property ID As Integer
Public Sub New(PatientID As Integer, PatientName As String, dDate As Date, sDisease As String)
ID = PatientID
Name = PatientName
DiagnosisDate = dDate
DiseaseName = sDisease
End Sub
'If you don't override ToString you will get the fully qualified name of the class
'You can return any combination of the Properties as long as the end
'result is a string
Public Overrides Function ToString() As String
Return Name
End Function
End Class
Public Sub processData()
Dim lines As String() = File.ReadAllLines(inputFile)
Dim diseaseList As New List(Of Disease)
For Each line As String In lines
'I was having trouble with the tabs so I changed it to a comma in the file
'3710079,JUDITH CLOUTIER,2012-08-04,Spastic Colonitis
'the small c following the "," tells the compiler that this is a Char
Dim tab = line.Split(","c)
Dim inputDate = Date.ParseExact(tab(2), "yyyy-MM-dd", CultureInfo.InvariantCulture)
Dim Studentdisease As New Disease(CInt(tab(0)), tab(1), inputDate, tab(3))
diseaseList.Add(Studentdisease)
Next
Dim diseaseGrouping = From d In diseaseList
Order By d.DiseaseName
Group By d.DiseaseName
Into Group, Count
For Each diseaseAndCount In diseaseGrouping
Debug.Print($"{diseaseAndCount.DiseaseName} {diseaseAndCount.Count()} ")
For Each d In diseaseAndCount.Group
Debug.Print($" {d.Name}, {d.DiagnosisDate.ToShortDateString}")
Next
Next
End Sub

VBA Handling multiple custom datatype possibilities

I have done some research and haven't found any similar question.
I have a VBA macro that imports a .CSV file containing telegrams sent by a device.
In the end of this macro, I want to create a graph with the time elapsed on the x-axis and the value corresponding to the telegram.
The issue is that this value can be of different types: hexadecimal, boolean, integer... And that they don't respect the standard Excel number format, which means that they can't be used to create a graph.
Here are some examples (with " around the value to show its start and end) :
hexadecimal : "A7 C8"
Boolean : "$00" or ""$01"
Percentage : "$30"
And here is an example of data, with custom time format and boolean value
Here is my related code so far, where I try to convert into a custom type then convert back to numeric to get a common number datatype :
If wsRes.Range("R1").Value Like "$##" Then
wsRes.Range("R1:R" & plotLine).NumberFormat = "$##"
wsRes.Range("R1:R" & plotLine).NumberFormat = General
End If
If wsRes.Range("R1").Value Like "??[ ]??" Then
Dim valArray(1) As String
For i = 1 To plotLine Step 1
valArray = Split(wsRes.Range("R" & i), " ")
wsRes.Range("R" & i).Value = ToInt32(valArray(0) + valArray(1), 16)
wsRes.Range("" & i).NumberFormat = General
Next i
End If
I haven't been able to test it with hexa yet, but the conversion trick doesn't work with percentage/boolean
EDIT :
First, thank you for your answers.
Here is my final code for anyone's interested, adapted from Vityata's.
This method will allow to easily add other datatypes if needed.
Sub TestMe()
Dim RangeData as String
Set wsRes = ActiveWorkbook.Sheets("Results")
For i = 1 To plotLine Step 1 'plotLine is the last line on which I have data
DetectType wsRes.Range("R" & i).Value, i
Next i
RangeData = "Q1:R" & plotLine
CreateGraph RangeData 'Call My sub creating the graph
End Sub
Public Sub DetectType(str As String, i As Integer)
Select Case True
Case wsRes.Range("R" & i).Value Like "??[ ]??"
wsRes.Range("R" & i).Value = HexValue(str)
Case wsRes.Range("R" & i).Value Like "?##"
wsRes.Range("R" & i).Value = DecValue(str)
Case Else
MsgBox "Unsupported datatype detected : " & str
End
End Select
End Sub
Public Function HexValue(str As String) As Long
Dim valArray(1) As String 'Needed as I have a space in the middle that prevents direct conversion
valArray(0) = Split(str, " ")(0)
valArray(1) = Split(str, " ")(1)
HexValue = CLng("&H" & valArray(0) + valArray(1))
End Function
Public Function DecValue(str As String) As Long
DecValue = Right(str, 2)
End Function
You need three boolean functions, following your business logic and some of the Clean Code principles (although the author of the book does not recognize VBA people as programmers):
IsHex()
IsBoolean()
IsPercentage()
Public Sub TestMe()
Dim myInput As Variant
myInput = Array("A7C8", "$01", "$30")
Dim i As Long
For i = LBound(myInput) To UBound(myInput)
Debug.Print IsHex(myInput(i))
Debug.Print IsBoolean(myInput(i))
Debug.Print IsPercentage(myInput(i))
Debug.Print "-------------"
Next i
'or use this with the DetectType() function below:
'For i = LBound(myInput) To UBound(myInput)
' Debug.Print DetectType(myInput(i))
'Next i
End Sub
Public Function IsHex(ByVal str As String) As Boolean
On Error GoTo IsHex_Error
IsHex = (WorksheetFunction.Hex2Dec(str) <> vbNullString)
On Error GoTo 0
Exit Function
IsHex_Error:
End Function
Public Function IsBoolean(ByVal str As String) As Boolean
IsBoolean = CBool((str = "$00") Or (str = "$01"))
End Function
Public Function IsPercentage(ByVal str As String) As Boolean
IsPercentage = (Len(str) = 3 And Left(str, 1) = "$" And IsNumeric(Right(str, 2)))
End Function
Then some additional logic is needed, because $01 is both Boolean and Percentage. In this case, you can consider it Percentage. This is some kind of a mapper, following this business logic:
Public Function DetectType(str) As String
Select Case True
Case IsHex(str)
DetectType = "HEX!"
Case IsPercentage(str) And IsBoolean(str)
DetectType = "Boolean!"
Case IsPercentage(str)
DetectType = "Percentage!"
Case Else
DetectType = "ELSE!"
End Select
End Function

Using VLOOKUP to search different sheets

I am trying to search if a number exists in one of the 32 sheets I have in my workbook.
I have tried to use the below mentioned code but it's not working because VLOOKUP is not deciphering the variable(n). Kindly help:
Private Sub SearchAll_Click()
Dim SearchCriteria As Double, s As Integer
SearchCriteria = Me.SearchBox.Value
s = 0
For s = 0 To ThisWorkbook.Sheets.Count
s = s + 1
If Application.WorksheetFunction.VLookup(SearchCriteria, Sheets(s).Range("A:A").Value, 1, False) = SearchCriteria Then
MsgBox ("The Number " & SearchCriteria & " is available in list " & Sheets(s).Name)
Exit For
Else
MsgBox ("The Number is Unavailable")
End If
Next s
End Sub
Legend:
SearchAll is a button used to initiate the search.
SearchCriteria is a textbox used to input the value you want to search for.
There are a few problems in the way you use Application.WorksheetFunction.VLookup to determine if a specific value exists in your workbook. I have modified your code to the following:
Private Sub SearchAll_Click()
Dim SearchCriteria As Double, s As Integer
Dim Lookup As Variant
Dim Match As Boolean
SearchCriteria = Me.SearchBox.Value
For s = 1 To ThisWorkbook.Sheets.Count
Lookup = Application.VLookup(SearchCriteria, Sheets(s).Range("A:A"), 1, False)
If Not IsError(Lookup) Then
MsgBox ("The Number " & SearchCriteria & " is available in list " & Sheets(s).Name)
Match = True
Exit For
End If
Next s
If Match = False Then MsgBox ("The Number is Unavailable")
End Sub
Here I have, instead, made use of Application.VLookup which will return an error to the variant variable Lookup if the search value were not found in the specific sheet. Then, by looking at the error state of Lookup it can be determined if the search value were found. Also, I have moved the message The Number is Unavailable outside the loop in order to avoid it being triggered each time the value were not found in a specific sheet.