Issues with Index Match Match and Userform in VBA - excel

I am trying to run code to use sap_a and sap_b (both text boxes in a userform) to look up the variable 'Run'. I wrote the code so that the person entering the sap_a and sap_b values could enter the values in either box and the 'Run' variable would be found, which is why ErrorCheck1 exists. ErrorCheck2 exists simply to provide a message if the values in sap_a/b are unable to be matched with a 'Run' variable. The issue I'm having is that this code generates a 'Run' value even when one of the sap_a or sap_b values is not correct (i.e. sap_a is a value that does exist in the spreadsheet, sap_b is a fake value not existing in the spreadsheet, and a 'Run' variable is still produced). Do you have any input specifically regarding issues with my code or any issues you see? Code is attached.
Thank you!
Private Sub SearchButtonTEST_Click()
Dim sap_a As Variant
Dim sap_b As Variant
Dim Run_ As Variant
Sheets("R_Database Sheet").Activate
sap_a = textbox5.Value
sap_b = textbox8.Value
If sap_a = "" And sap_b = "" Then
Run_ = ""
Let textbox1.Text = Run_
Msgbox "Must enter SAP Codes in SAP # A and SAP # B to search."
Exit Sub
Else
Check1:
On Error GoTo ErrorCheck1
Run_ = Application.WorksheetFunction.Index(Sheets("R_Database Sheet").Range("A:A"), Application.WorksheetFunction.Match(CLng((sap_a)), Sheets("R_Database Sheet").Range("E:E"), Application.WorksheetFunction.Match(CLng((sap_b)), Sheets("R_database sheet").Range("H:H"), 0)))
Let textbox1.Text = Run_
Check2:
On Error GoTo ErrorCheck2
Run_ = Application.WorksheetFunction.Index(Sheets("R_Database Sheet").Range("A:A"), Application.WorksheetFunction.Match(CLng((sap_b)), Sheets("R_Database Sheet").Range("E:E"), Application.WorksheetFunction.Match(CLng((sap_a)), Sheets("R_database sheet").Range("H:H"), 0)))
Let textbox1.Text = Run_
Exit Sub
Check3:
Msgbox "No data found for specified SAP #'s."
End If
Exit Sub
ErrorCheck1:
Resume Check2
ErrorCheck2:
Resume Check3
End Sub

Your code will be easier to manage if you drop the Worksheetfunction and just use Application.Match
If you include the worksheetfunction then a run-time error is raised if there's no match (requiring tricky error handling). If you drop it, then a no-match just returns an error value which you can test using IsError(). Personally I find this much easier to manage.
Private Sub SearchButtonTEST_Click()
Dim sap_a As Variant, sap_b As Variant
Dim ws As Worksheet, mA, mB
Set ws = Sheets("R_Database Sheet")
sap_a = Trim(textbox5.Value)
sap_b = Trim(textbox8.Value)
If sap_a = "" And sap_b = "" Then
textbox1.Text = ""
MsgBox "Must enter SAP Codes in SAP # A and SAP # B to search."
Exit Sub
Else
mA = Application.Match(CLng(sap_a), ws.Range("E:E"), 0)
mB = Application.Match(CLng(sap_b), ws.Range("H:H"), 0)
If Not IsError(mA) Then
textbox1.Text = ws.Cells(mA, "A")
ElseIf Not IsError(mB) Then
textbox1.Text = ws.Cells(mB, "A")
Else
textbox1.Text = "Not found!"
End If
End If
End Sub

Related

add .SendKeys to an existing macro

I have a code that would help me with printing a document from Excel.
It has a couple dialogue questions for adding serial number sequence and number of copies.
Unfortunately, it doesn't open the Print dialogue, where I can select a printer and it's preferences.
The code would just immediately print to my default printer.
I need to add some custom features like 2-side printing and stapling in the top left corner.
For that purpose I want to use .Sendkeys
I tried adding the string Application.SendKeys "%fpr" (my printer preferences dialogue) here and there inside the code to no avail.
Please help inserting the sting.
Alternatively - maybe there is a command for .PrintOut that I could add for 2-side printing and a staple finish?
Private Sub CommandButton1_Click()
Dim xCount As Variant
Dim xJAC As Variant
Dim xID As Variant
Dim xScreen As Boolean
Dim I As Long
On Error Resume Next
Application.SendKeys "%fpr"
LInput:
xJAC = Application.InputBox("Please enter the job number (Leave Out JAC):", "")
xCount = Application.InputBox("Please enter the number of copies you want to print:", "")
xID = Application.InputBox("Please enter the Starting ID of the product:", "")
If TypeName(xJAC) = "Boolean" Then Exit Sub
If TypeName(xCount) = "Boolean" Then Exit Sub
If TypeName(xID) = "Boolean" Then Exit Sub
If (xCount = "") Or (Not IsNumeric(xCount)) Or (xCount < 1) Or (xID < 1) Or (xCount = "") Or (Not IsNumeric(xID)) Then
MsgBox "error entered, please enter again", vbInformation, "Kutools for Excel"
GoTo LInput
Else
xScreen = Application.ScreenUpdating
Application.ScreenUpdating = False
For c = 0 To xCount - 1
ActiveSheet.Range("E2").Value = "JAC" & xJAC
ActiveSheet.Range("G2").Value = xID + c
ActiveSheet.PrintOut
Next
ActiveSheet.Range("E2").ClearContents
ActiveSheet.Range("G2").ClearContents
Application.ScreenUpdating = xScreen
End If
End Sub

For each code not making check box value true

I am trying to create code that runs through a list of user ID's (B Numbers) and then when it finds the corresponding ID it checks to see if there's an X in the column directly next to it for a certain subject named SBB005 See image. If there is an X, I want the check box value to be true. The for each loop ends when it reaches a blank cell.
I have declared the 'RowYear2' and 'Year2CourseRange' ranges as public variables, and when running the code, nothing happens and the check box remains unticked! Any idea why the checkbox isn't being ticked as expected?
I am planning on setting up multiple checkboxes once this is working for all the subjects in each column:
See image
Hoping that someone can help me to get this working or may even introduce an easier way to do so for another 20 checkboxes!
Many thanks :)
Private Sub UserForm_Initialize()
Set Year2CourseRange = Sheets("Year2").Range("A:A")
For Each RowYear2 In Year2CourseRange.Cells
If RowYear2.Value = BNumberTxt Then
If RowYear2.Offset(0, 1) = "x" Then
Me.CHKSBB005.value = True
Else
Me.CHKSBB005.value = False
End If
ElseIf IsEmpty(RowYear2) Then
Exit For
End If
Next RowYear2
LoggedInTxt = Row.Offset(0, -3)
BNumberTxt = Row.Offset(0, -7)
CourseTxt = Row.Offset(0, -1)
CourseNumTxt = Row.Offset(0, -2)
End Sub
Private Sub EnterBtn_Click()
Dim LIMatch As Boolean
Dim Win As Boolean
Email = Me.EmailTxt
Password = Me.PasswordTxt
Set UserRange = Sheets("StudentInformation").Range("H:H")
For Each Row In UserRange.Cells
If Me.EmailTxt = "" And Me.PasswordTxt = "" Then
MsgBox ("Please enter an email and password")
LIMatch = False
Win = True
Exit For
ElseIf Me.EmailTxt = "" Then
MsgBox ("Please enter an email address")
LIMatch = False
Win = True
Exit For
ElseIf Me.PasswordTxt = "" Then
MsgBox ("Please enter a password")
LIMatch = False
Win = True
Exit For
Else
If UCase(Row.Value) = UCase(Email) Then
If UCase(Row.Offset(0, -6)) = UCase(Password) Then
MsgBox "Welcome"
LIMatch = True
Win = True
Attempts = 0
Exit For
ElseIf IsEmpty(Row) Then
Exit For
Win = False
Else
LIMatch = False
Win = False
Exit For
End If
Else
LIMatch = False
Win = False
End If
End If
Next Row
If LIMatch = True And Win = True Then
Unload Me
NewForm.Show
ElseIf LIMatch = False And Win = False Then
MsgBox ("Incorrect login")
Attempts = Attempts + 1
Else
End If
If Attempts >= 3 Then
MsgBox ("You have entered the incorrect login 3 times")
Unload Me
End If
End Sub
Once you fix your problem with the Row global, you can do something like this:
Private Sub UserForm_Initialize()
Dim shtData As Worksheet
Dim Year2CourseRange As Range, HeaderRange As Range, m, c As Range
Set shtData = ThisWorkbook.Sheets("Year2")
With shtData
Set Year2CourseRange = .Range("A:A")
Set HeaderRange = .Range(.Range("B2"), .Cells(2, 500).End(xlToLeft))
End With
'you'll need to fix this part....
BNumberTxt = Row.Offset(0, -7)
'etc
'find a matching row: Match() is a good approach here
m = Application.Match(BNumberTxt, Year2CourseRange, 0)
'loop over all the column headers
For Each c In HeaderRange.Cells
'Assumes all checkboxes are named "CHK[ColumnHeaderHere]"
With Me.Controls("CHK" & c.Value)
If IsError(m) Then
.Value = False 'clear all if no match
Else
.Value = (UCase(shtData.Cells(m, c.Column)) = "X") 'set if "x"
End If
End With
End If
End Sub
Ranges and Ranges
This is your code squashed a little bit and below is your data:
Private Sub UserForm_Initialize()
Set Year2CourseRange = Sheets("Year2").Range("A:A")
For Each RowYear2 In Year2CourseRange.Cells
If RowYear2.Value = BNumberTxt Then
If RowYear2.Offset(0, 1) = "x" Then
Me.CHKSBB005.value = True
Else: Me.CHKSBB005.value = False: End If
ElseIf IsEmpty(RowYear2) Then
Exit For: End If: Next RowYear2
LoggedInTxt = Row.Offset(0, -3): BNumberTxt = Row.Offset(0, -7)
CourseTxt = Row.Offset(0, -1): CourseNumTxt = Row.Offset(0, -2): End Sub
Take a look for a while, you might see the error yourself.
The CheckBox Tick Mystery
When you write Range("A:A") that refers to the whole column including Range("A1") which appears to be EMPTY. The code never even enters the If RowYear2.Offset... line but exits via the ElseIf line.
The Row Variable
I hate the idea of declaring a variable Row. But it is valid. Since there is an Offset involved, Row should be a range, probably a cell. As in the comments indicated, it has to 'survive' from another UserForm let's say UserFormX. If it has 'survived' you have to refer to it like this:
UserFormX.Row
or you have to declare it in a 'not-object' module to use only Row.
Another EnterBtn_Click
Probably useless now but here is the code I worked on the other day:
Option Explicit
Public intAttempts As Integer
Private Sub CancelBtn_Click()
Unload Me
End Sub
Private Sub EnterBtn_Click()
Const strEmail = "Please enter email address." ' Email Input Message
Const strPassword = "Please enter a password." ' Password Input Message
Const strLoginCorrect = "Welcome" ' Correct Login Message
Const strLoginIncorrect = "Incorrect Login." ' Incorrect Login Message
Const strAttempts = "Too many login attempts." ' Login Attempts Message
' Use worksheet name or index e.g. "SInfo" or 1.
Const vntWsName As String = "StudentInformation" ' Worksheet
' Use column letter or column number e.g. "F" or 6.
Const vntEmailColumn As Variant = "F" ' Email Column
Const intFirstRow As Integer = 2 ' Email Column First Row
Const intPasswordColumnOffset As Integer = -4 ' Password Column Offset
Const intMaxAttempts As Integer = 3 ' Maximum Login Attempts
Dim lngCounter As Long ' Email Column Row Counter
Dim lngLastrow As Long ' Email Column Last Row
' Check number of login attempts.
If intAttempts >= intMaxAttempts Then
MsgBox strAttempts
Exit Sub
End If
' Show annoying text messages if nothing was entered.
If Me.EmailTxt.Text = "" Then
Me.EmailTxt.Text = strEmail: Exit Sub
ElseIf Me.EmailTxt.Text = strEmail Then Exit Sub
End If
If Me.PasswordTxt.Text = "" Then
Me.PasswordTxt.Text = strPassword: Exit Sub
ElseIf Me.PasswordTxt.Text = strPassword Then Exit Sub
End If
' Check for data in specified worksheet.
With ThisWorkbook.Worksheets(vntWsName)
' Determine last row of data in Email Column.
lngLastrow = .Cells(Rows.Count, vntEmailColumn).End(xlUp).Row
For lngCounter = intFirstRow To lngLastrow
' Ceck for email in Email Column.
If UCase(.Cells(lngCounter, vntEmailColumn).Value) _
= UCase(EmailTxt.Text) Then ' Correct email.
' Check if correct password in Password Column
If UCase(.Cells(lngCounter, vntEmailColumn) _
.Offset(0, intPasswordColumnOffset).Value) _
= UCase(PasswordTxt.Text) Then ' Correct password.
Exit For
Else ' Wrong password. Set "counter" to "end".
' Faking that the loop was not interrupted.
lngCounter = lngLastrow
End If
' Else ' Wrong Email. Do nothing. Not necessary.
End If
Next
' When the loop wasn't interrupted, "lngcounter = lnglastrow + 1".
End With
' Check if loop was NOT interrupted.
If lngCounter = lngLastrow + 1 Then ' Loop was NOT interrupted.
intAttempts = intAttempts + 1
MsgBox strLoginIncorrect
Else ' Loop was interrupted. Correct email and password.
MsgBox strLoginCorrect
Unload Me
NewForm.Show
End If
End Sub

check in- check out sytem using a barcode scanner

I'm trying to create a check in/out system at a lab I work at. I'm not to experienced at using VBA. I was able to tinker with some formulas to get it to do what I wanted, but I wasn't fully successful in getting all the steps I wanted done.
So what I'm trying to do is check in samples using a barcode followed by a date in the cell right next to it.
I want this formula to apply to A2000 so I can check in multiple samples. I'm using an input box and I want this input box to be able to detect matched samples and place them in the checked out column C followed by a date in the cell right next to it.
I would appreciate any help you guys can give me.
Here's the code I am currently using.
Private Sub Worksheet_Activate()
Dim myValue As Variant
Dim code As Variant
Dim matchedCell As Variant
myValue = InputBox("Please scan a barcode")
Range("A2").Value = myValue
Set NextCell = Cells(Rows.Count, "A").End(xlUp)
If NextCell.Row > 1 Then NextCell = NextCell.Offset(1, 0)
Set matchedCell = Range("a2:a2000").Find(what:=code, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=True)
If myValue = True Then Paste ("C2;C2000")
If Not matchedCell Is Nothing Then matchedCell.Offset(-1, 1).Value = Now
End Sub
To add data safety, I would differentiate the Check-In and the Check-Out process.
I'm not sure how you get the Code from the scanner ? Copied to prompt automatically ?
Anyway, below is my solution:
1.Transform your table into an excel table (CTRL+T) and name it "STORE_RECORDS" as below:
2.Create a module and paste following code:
Option Explicit
Sub Check_In()
Dim Code As String: Code = InputBox("Please scan a barcode", "Scan procedure")
If Code = "" Then MsgBox ("No code scanned"): Exit Sub
Dim NbChIn As Integer: NbChIn = Application.CountIf(Range("STORE_RECORDS[CHECK-IN]"), Code)
Dim NbChOut As Integer: NbChOut = Application.CountIf(Range("STORE_RECORDS[CHECK-OUT]"), Code)
If NbChIn > NbChOut And NbChIn > 0 Then
MsgBox ("This item is already Checked-In" & Chr(10) & "Please check it out and retry"): Exit Sub
Else
Cells(Rows.Count, 1).End(xlUp).Offset(1, 0) = Code
Cells(Rows.Count, 1).End(xlUp).Offset(0, 1) = Now
End If
End Sub
Sub Check_Out()
Dim Code As String: Code = InputBox("Please scan a barcode", "Scan procedure")
If Code = "" Then MsgBox ("No code scanned"): Exit Sub
Dim NbChIn As Integer: NbChIn = Application.CountIf(Range("STORE_RECORDS[CHECK-IN]"), Code)
Dim NbChOut As Integer: NbChOut = Application.CountIf(Range("STORE_RECORDS[CHECK-OUT]"), Code)
If NbChIn = NbChOut And NbChIn > 0 Then
MsgBox ("This item is already Checked-Out" & Chr(10) & "Please check it in and retry"): Exit Sub
Else
If Range("STORE_RECORDS[CHECK-IN]").Find(Code, , , xlWhole, , xlPrevious) Is Nothing Then MsgBox ("No match, ask Carlos !"): Exit Sub
Range("STORE_RECORDS[CHECK-IN]").Find(Code, , ,xlWhole , , xlPrevious).Offset(0, 2) = Code
Range("STORE_RECORDS[CHECK-IN]").Find(Code, , ,xlWhole , , xlPrevious).Offset(0, 3) = Now
End If
End Sub
3.Link Check-In and Check-Out buttons to respective procedures and you should be good to go.

Runtime Error 13 - Mismatch

I'm new at VBA coding and working on a match code. The code is working just fine when I run the code in "Data sheet" (the sheet were all my data is and were the match has to be found), but when i'm run the code on the frontpage (Sheet 1 with userforms) the code is debuggen and says "Runtime Error 13". Can anybody tell what the problem is?
And can anybody tell me why my "If isError" doesn't work?
Thanks in advance!
Br
'Find SKU and Test number
Dim icol As Integer
Sheet13.Range("XFD2") = UserForm2.ComboBox1.Value 'Sættes = ComboBox1.value
Sheet13.Range("XFD3") = UserForm2.ComboBox2.Value 'Sættes = ComboBox2.value
icol = [Sheet13.MATCH(XFD2&XFD3,A:A&Q:Q,0)] 'Match af værdien for vores SKU og test nr
With ThisWorkbook.Worksheets("Data sheet")
'If SKU or Test number not found, then messagebox
If IsError("A:A") Then MsgBox "SKU not found": Exit Sub
If IsError("Q:Q") Then MsgBox "Test number not found": Exit Sub
'Add test result/next step and comment
.Cells(icol, 30).Value = Me.ComboBox3.Value
.Cells(icol, 30 + 1).Value = Me.Comments_To_Result.Value
End With
End If
Set objFSO = Nothing
Set openDialog = Nothing
Range("XFD2").Clear
Range("XFD3").Clear
icol should be like this:
icol = Application.match(arg1, arg2, arg3)
See the samples in MSDN:
var = Application.Match(Cells(iRow, 1).Value, Worksheets(iSheet).Columns(1), 0)
Concerning If IsError("A:A") Then MsgBox "SKU not found": Exit Sub, you are doing it wrongly. I assume, that you want to loop through all the cells in the first column and to get whether one of them is an error. You need a loop for this. This is a really simple one, but you should implement it somehow in your code:
Option Explicit
Public Sub TestMe()
Dim rng As Range
For Each rng In Range("A:A")
If IsError(rng) Then Debug.Print rng.Address
Next rng
End Sub

Input Box Error Handling

I am having trouble handling the error associated with a input box "Cancel" click. Or in otherwords, it returns an error within the sub if the value of the input is null. I have tried looking around and still can't seem to get it quite right. Here is my attempt:
Private Sub bttnSavingsExpected_Click()
Dim expected() As String
Dim nPeriods As Integer
Dim counter As Integer
Dim savings As Single
With ActiveSheet.Range("A13")
nPeriods = Range(.Offset(1, 0), .End(xlDown)).Rows.Count
End With
ReDim expected(1 To nPeriods)
counter = 1
For counter = 1 To nPeriods
expected(counter) = Range("A13").Offset(counter, 0).Value
Next
TryAgain:
On Error GoTo ErrH
counter = 1
For counter = 1 To nPeriods
savings = InputBox("How much savings do you expect from " & expected(counter) & "?", "Savings?", Range("A13").Offset(counter, 1).Value)
If savings = "" Then
Exit Sub
Else
Range("A13").Offset(counter, 1).Value = savings
End If
Next
Exit Sub
ErrH:
MsgBox "Please enter value. If the default value is desired then please click 'OK'.", vbOKOnly, "Do Not Click Cancel"
GoTo TryAgain
End Sub
With this attempt, the MsgBox is displayed the first click whether there is a input or not and even if I click "Ok". The second try of clicking "OK" or "Cancel" leads to being kicked back to the editor.
You've got Dim savings As Single and If savings = "" Then. Thats always going to error
Try using Dim savings As Variant
Make sure the variable for the Inbox is set at "", then test the value for False. Much easier than anything else I have seen:
Sub WolfPackURL_input()
Dim TheURL As String
Dim SaveURL As Hyperlink
Set savedURL = Sheets("Data").Range("I1")
TheURL = ""
TheURL = Application.InputBox("Input the Sign-Up URL", "Wolfpack Weekly Players URL", "http://something", 1)
If TheURL = "False" Then
Exit Sub
End If
ThisWorkbook.Worksheets("Data").Activate
Sheets("Data").Range("I1").Hyperlinks.Delete
Sheets("Data").Range("I1").ClearContents
Sheets("Data").Range("I1").Clear
ActiveSheet.Hyperlinks.Add anchor:=Sheets("Data").Range("I1"), Address:=TheURL, ScreenTip:="Open file", TextToDisplay:=TheURL
End Sub

Resources