Vlookup in a User form not working, Cant find string - vba

New to VBA, and using it in Excel.
I have a User form, and I am trying to use a lookup to fill TextBox4 from the value that is entered in ComboBox3. I have the following code which compiles, however it is producing the msgbox to say that the string cant be found...
Private Sub ComboBox3_Change()
Dim strFind As String
Dim rFound As Range
ws = "Year-to-Date Summary"
If ComboBox3.ListIndex > -1 Then
strFind = ComboBox3
On Error Resume Next
With ws.Column(2, 3)
Set rFound = .Find(What:="strFind", After:=.Cells(39, 49), _
LookIn:=.Cells(39, 49), LookAt _
:=.Cells(39, 49), SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:= False)
End With
If rFound Is Nothing Then
MsgBox strFind & " cannot be found"
Exit Sub
Else
TextBox4 = rFound(1, 2)
End If
End If
End Sub
I also tried Vlookup, however this sprung error messages...
Private Sub ComboBox3_Change()
TextBox4.Text = WorksheetFunction.VLookup(Val(ComboBox3.Text), _
Sheets("Year-to-Date Summary").Range("C39:C49" & LastRow), 2, False)
End Sub

ws is a variant. You do not assign worksheets like this. You have to use Set
strFind is within quotes so it will be considered as a string
See this example (UNTESTED)
Private Sub ComboBox3_Change()
If ComboBox3.ListIndex = 0 Then Exit Sub
Dim strFind As String
Dim ws As Worksheet
Dim rFound As Range
Set ws = ThisWorkbook.Sheets("Year-to-Date Summary")
strFind = ComboBox3.Value
Set rFound = ws.Columns(3).Find(What:=strFind, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not rFound Is Nothing Then
TextBox4 = rFound.Offset(,1)
Else
MsgBox strFind & " cannot be found"
End If
End Sub
If your range is fixed then change ws.Columns(3) to ws.Range("C39:C49") in the above code.
If you would like to use the worksheet function then you this (TRIED AND TESTED)
Note: I have not used error trapping in the below code. i am sure you can take care of that.
Private Sub ComboBox3_Change()
If ComboBox3.ListIndex = 0 Then Exit Sub
TextBox4.Text = Application.WorksheetFunction.VLookup( _
Val(ComboBox3.Value), _
Sheets("Year-to-Date Summary").Range("C39:D49"), _
2, _
False _
)
End Sub
Note how we used C39:C49 / Columns(3) + Offset in the first example and how we used C49:D49 in the 2nd Example
EDIT: I forgot to comment on On Error Resume Next Never use it until and unless required. It is like telling the code to "shut up!" if it finds an error :)

Your ws is obviously a string, which does not have a .column property.
Replace line ws = "Year-to-Date Summary" by
set ws = worksheets("Year-to-Date Summary") and see if that helps.
Do you make sure that every module has an "Option Explicit" and that your app compiles successfully ? You would have spotted that error I think.

Private Sub ComboBox3_Change()
TextBox4.Text = WorksheetFunction.VLookup(Me.ComboBox3.Text, Sheets("Year-to-Date Summary").Range("$B$39:$C$49"), 2, False)
TextBox3.Text = WorksheetFunction.VLookup(Me.TextBox4.Text, Sheets("Year-to-Date Summary").Range("$C$39:$D$49"), 2, False)
End Sub
This worked for me, to do two textboxes from the combobox

Private Sub ComboBox3_Change()
Dim strFind As String
Dim rFound As Range
Dim ws As Worksheet
Set ws = ActiveWorkbook.Sheets("Year-to-Date Summary")
If ComboBox3.ListIndex > -1 Then
strFind = ComboBox3.text
On Error Resume Next
'editted removing the whole vlookup part...
'added for loop to search the text within the range
Set rSearch = ws.Range("B:C")
For Each rFound In rSearch
If rFound.Value = strFind Then
TextBox4.Text = rFound.value
else
MsgBox strFind & " cannot be found"
Exit Sub
End If
Next rFound
End Sub

Related

Fix “compile error: next without for” error in VBA?

I cant seem to figure out this. I would like to search my worksheets to see if there is a "=REF!" and if there is a error to not run my code. The problem with it is that when I run it the error in the code is revolved around the next part
Sub logs()
Dim numberofsheets As Integer
For numberofsheets = 1 To 5
Set checkRange = Sheets("Final Four").Range("A1:Z100")
If IsError(CheckCell) And _
CVErr(CheckCell) = CVErr(2023) Then
Exit Sub
End If
Next
Set checkRange = Sheets("Top Left").Range("A1:Z100")
If IsError(CheckCell) And _
CVErr(CheckCell) = CVErr(2023) Then
Exit Sub
End If
Next
Set checkRange = Sheets("Bottom Left").Range("A1:Z100")
If IsError(CheckCell) And _
CVErr(CheckCell) = CVErr(2023) Then
Exit Sub
End If
Next
Set checkRange = Sheets("Top Right").Range("A1:Z100")
If IsError(CheckCell) And _
CVErr(CheckCell) = CVErr(2023) Then
Exit Sub
End If
Next
Set checkRange = Sheets("Bottom Right").Range("A1:Z100")
If IsError(CheckCell) And _
CVErr(CheckCell) = CVErr(2023) Then
Exit Sub
End If
ActiveSheet.EnableCalculation = True
lst = Sheets("data").UsedRange.Rows.Count
x = lst + 1
' Display a message when one of the designated cells has been
' changed.
' Place your code here.
Sheets("data").Range("A" & x) = ActiveSheet.Range("I3")
Sheets("data").Range("B" & x) = ActiveSheet.Range("I4")
End Sub
Not sure how to do this. I'm very new at it.
I think you are looking for something like the For loop below to implement in your code:
Sub logs()
Dim Sht As Worksheet
Dim checkRange As Range, CheckCell As Range
For Each Sht In ThisWorkbook.Sheets ' loop through your worksheets
With Sht
Select Case .Name ' check for the sheet.Name
Case "Final Four", "Top Left", "Bottom Left", "Top Right", "Bottom Right"
Set checkRange = .Range("A1:Z100") ' set the range for the current sheet
For Each CheckCell In checkRange
If IsError(CheckCell) Then
If CheckCell.Value = CVErr(2023) Then Exit Sub
' you can use the following syntax as well
If CheckCell.Value = CVErr(xlErrRef) Then Exit Sub
End If
Next CheckCell
Set checkRange = Nothing
Case Else
' do nothing
End Select
End With
Next Sht
' rest of your code
End Sub

How do you pass in the set variable name of a field from one sub-routine to another in VBA?

So, I have two sub-routines.
The 1st is for importing worksheets and the 2nd is for deleting blank rows if a certain condition holds true.
I would like to pass in the name of the sheet that has been imported, to the DeleteBlankCells() sub-routine. I think this is the Set wsSht = .Sheets(sWSName) variable here that we are setting.
In the 2nd sub-routine, you can see the hardcoded sheet value that I would like to replace with the value being passed in from the import.
This is the 1st sub-routine:
Sub ImportSheet()
Dim sImportFile As String, sFile As String
Dim sThisBk As Workbook
Dim vfilename As Variant
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set sThisBk = ActiveWorkbook
sImportFile = Application.GetOpenFilename( _
FileFilter:="Microsoft Excel Workbooks, *.xls; *.xlsx", Title:="Open Workbook")
If sImportFile = "False" Then
MsgBox "No File Selected!"
Exit Sub
Else
vfilename = Split(sImportFile, "\")
sFile = vfilename(UBound(vfilename))
Application.Workbooks.Open Filename:=sImportFile
Set wbBk = Workbooks(sFile)
With wbBk
If SheetExists(sWSName) Then
Set wsSht = .Sheets(sWSName)
wsSht.Copy after:=sThisBk.Sheets("Sheet3")
Else
MsgBox "There is no sheet with name :Raw_Data in:" & vbCr & .Name
End If
wbBk.Close SaveChanges:=False
End With
End If
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Sheets("Sheet1").Activate
End Sub
Private Function SheetExists(sWSName) As Boolean
Dim ws As Worksheet
On Error Resume Next
sWSName = InputBox("Enter sheet name")
Set ws = Worksheets(sWSName)
If Not ws Is Nothing Then SheetExists = True
End Function
and this is the 2nd sub-routine:
Sub DeleteBlankCells()
Dim Rng As Range
Sheets("HARDCODED SHEET NAME").Activate
Set Rng = Rows("1:1").Find(What:="HIVE_FIELD_TYPE", after:=Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext)
Sheets("HARDCODED SHEET NAME").Columns(Rng.EntireColumn.Address).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub
You can sen over the Worksheet itself, no need to use the Sheet's name.
In your 2nd Sub, change to:
Sub DeleteBlankCells(ws As Worksheet)
Dim Rng As Range
With ws
Set Rng = .Rows("1:1").Find(What:="HIVE_FIELD_TYPE", after:=.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext)
.Columns(Rng.EntireColumn.Address).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End With
End Sub
And in your 1st Sub call it after:
Set wsSht = .Sheets(sWSName)
With:
DeleteBlankCells wsSht
Alternatively, perhaps a global variable? (it is hacky way to accomplish it)
How to declare Global Variables in Excel VBA to be visible across the Workbook

IF Null exit sub code

I'm trying to check that if cells are empty or null, that it would display a message and exit sub. Here's my code:
With Worksheets(1).[D3:D4, D6:D14]
If WorksheetFunction.CountA(.Cells) = 0 Then
MsgBox "Nothing to generate" & vbNewLine & _
"Set parameters and click generate."
Exit Sub
End If
End With
But the code only works if the entire [D3:D4, D6:D14] are empty. I want it to exit sub even just one of the cells are empty. All cells needs have content for it to continue sub. Please help.
You need to seach inside the Range, try the code below:
Sub CheckEmptyCellsinRange()
Dim Rng As Range
Dim cell As Range
Set Rng = Worksheets(1).[D3:D4, D6:D14]
For Each cell In Rng
If IsEmpty(cell) Or IsNull(cell) Then
MsgBox "Nothing to generate" & vbNewLine & _
"Set parameters and click generate."
Exit Sub
End If
Next cell
End Sub
You can also use SpecialCells:
Sub Check()
Dim rng1 As Range
On Error Resume Next
With Worksheets(1).[D3:D4, D6:D14]
Set rng1 = .SpecialCells(xlBlanks)
If Not rng1 Is Nothing Then
MsgBox "Nothing to generate" & vbNewLine & _
"Set parameters and click generate."
Exit Sub
End If
End With
End Sub
Follow-up question
Sub Check2()
Dim rng1 As Range
Dim rng2 As Range
With Worksheets(1)
Set rng1 = .Range(.[D3:D4], .[D6:D14])
End With
On Error Resume Next
Set rng2 = rng1.SpecialCells(xlBlanks)
On Error GoTo 0
If Not rng1 Is Nothing Then
MsgBox rng1.Cells.Count - rng2.Cells.Count & " were used"
Else
MsgBox "all cells used"
End If
End Sub

FindNext from InputBox throughout Workbook

Noob here. I've found plenty of code on this site and want to say thanks to all those who contribute.
My question is I have a UserForm. I click a button to bring up an InputBox, where they enter a value to search for bank name, banker name, business name, etc.
I have the code to do the search no problem, but I want to be able to be able to continue to search all of the instances of the InputBox value. For example, searching for the name "Smith" and if the first one isn't the one I need, to continue the search until I've landed on the one I'm looking for.
Dim ws As Worksheet
Dim rFound As Range
Dim strName As String
On Error Resume Next
strName = InputBox("Please Enter Search Value." & vbNewLine & "Entry Must Be Exact Cell Value!", "Search Value")
If strName = "" Then Exit Sub
For Each ws In Worksheets
With ws.UsedRange
Set rFound = .Find(What:=strName, After:=.Cells(1, 1), LookIn:=xlValues, LookAt:=xlPart)
If Not rFound Is Nothing Then
firstaddress = rFound.Address
Application.Goto rFound, True
Exit Sub
End If
End With
Next ws
On Error GoTo 0
MsgBox "Merchant not found. Please make sure you typed it correctly.", vbOKOnly + vbCritical, "Invalid Entry"
You need to modify your search so your code 'remembers' where it left off, like this:
Option Explicit
Dim ws As Worksheet
Dim rFound As Range
Dim strName As String
Static First as Range
'On Error Resume Next
if First is Nothing Then 'we haven't found anything yet
Set First = Worksheets(1).Cells(1,1) 'start searching at the beginning
End If
strName = InputBox("Please Enter Search Value." & vbNewLine & "Entry Must Be Exact Cell Value!", "Search Value")
If strName = "" Then Exit Sub
For Each ws In Worksheets
With ws.UsedRange
Set rFound = .Find(What:=strName, After:=First, LookIn:=xlValues, LookAt:=xlPart)
while Not rFound Is Nothing
if first is nothing then
First = rFound 'store off this address for use in our next search
end if
if first <> rFound Then 'we've found a NEW instance of the search item
firstaddress = rFound.Address
Application.Goto rFound, True
MsgBox "Found one!"
Set rFound = .Find(What:=strName, After:=rFound, LookIn:=xlValues, LookAt:=xlPart)
else 'we're back at the start, so jump out of the loop
set rFound = Nothing
End If
wEnd
End With
Next ws
On Error GoTo 0
MsgBox "Merchant not found. Please make sure you typed it correctly.", vbOKOnly + vbCritical, "Invalid Entry"
A couple of points:
I added Option Explicit which means your code won't run now because you never declared firstaddress. It's vital for your sanity to enable that option from the ribbon: Tools | Options | Editor then check Require Variable Declaration
By declaring First as a Static, it will remain set between calls to your search routine. That way, since we're feeding First into the .Find() function, it will pick up the search where it left off.
If you need to start the search from the beginning again, you could store off the 'last' search term - if the current term is different from the last term, reset set First = Worksheets(1).Cells(1,1)
Additional note - On Error Resume Next is useful in very limited situations. This isn't one of them. It allows you to ignore an error in your code so that you can immediately handle it, which isn't what you want in this situation. The follow up On Error Goto 0, which reenables the default error handling should really never be more than 1 line of code later - not an entire subroutine.
VBA already has a .FindNext() method for this very purpose:
Sub SO()
Dim inputString As String
Dim foundCell As Excel.Range
Dim wSheet As Excel.Worksheet
Dim foundAddress As String
inputString = InputBox("Please enter search term:", "Search")
For Each wSheet In ActiveWorkbook.Worksheets
Set foundCell = wSheet.Cells.Find(inputString, , -4163, 2)
If Not foundCell Is Nothing Then
Application.Goto foundCell, True
foundAddress = foundCell.Address
If MsgBox("Match in " & wSheet.Name & " (" & foundCell.Address & ")" & vbCrLf & "Continue?", 68, "Match Found") = vbYes Then
Do
Set foundCell = wSheet.Cells.FindNext(foundCell)
If Not foundCell Is Nothing And Not foundCell.Address = foundAddress Then
Application.Goto foundCell, True
Else
Exit Do
End If
Loop While MsgBox("Match in " & wSheet.Name & " (" & foundCell.Address & ")" & vbCrLf & "Continue?", 68, "Match Found") = vbYes And _
Not foundCell Is Nothing And Not foundCell.Address = foundAddress
Set foundCell = wSheet.Cells.FindNext(foundCell)
End If
End If
If MsgBox("All matches in this sheet found - move to next sheet?", 68, "Next Sheet?") = vbNo Then Exit Sub
Next wSheet
End Sub

Excel vba username/ password lookup

Private Sub cmdLogin_Click()
On Error GoTo ErrorHandler
Dim RowNo As Long
Dim Id As String
Dim pw As String
Dim ws As Worksheets
Application.ScreenUpdating = False
Set ws = Worksheets("User&Pass")
Id = LCase(Me.txtLogin)
RowNo = Application.WorksheetFunction.Match(Id, ws.range("A2:A999"), 0)
CleanExit:
Set ws = Nothing ' free memory
Application.ScreenUpdating = True ' turn on the screen updating
Exit Sub
ErrorHandler:
MsgBox "Unable to match ID, enter valid ID.", vbOKOnly
GoTo CleanExit
End Sub
I've got an excel userform i've been working on and now I need it to look more professional by having a log-in screen. I've started with the code above but I have come to a dead end.
how its set up my aim is to say if id & password matches then load up workbook or unhide the workbook and continue. the username and password are on a sheet called "User&Pass"
Aim is it reads from there in columns a- user / b- pw respectively and if it's a success I will hide that sheet so they cant see other user's information
with what I started above I just need it to say if it matches usercolumn then corresponding pw next door to it continue else go to my errorhandler
i can do the formatting about hiding and unhiding sheets etc just need help with reading username and pw
thanks very much in advance
Z
Editted attempt one;
Private Sub cmdLogin_Click()
On Error GoTo ErrorHandler
Dim RowNo As Long
Dim Id As String
Dim pw As String
Dim ws As Worksheets
Application.ScreenUpdating = False
Set ws = Worksheets("User&Pass")
Id = LCase(Me.txtLogin)
RowNo = Application.WorksheetFunction.Match(Id, ws.range("A2:A999"), 0)
RowNo = RowNo + 1
pw = ws.range("B" & RowNo)
If pw = Me.txtLogin Then
'continue
txt1.Value = "yes"
Else
GoTo ErrorHandler
End If
CleanExit:
Set ws = Nothing ' free memory
Application.ScreenUpdating = True ' turn on the screen updating
Exit Sub
ErrorHandler:
MsgBox "Unable to match ID, enter valid ID.", vbOKOnly
GoTo CleanExit
End Sub
#siddarthRout
Private Sub cmdLogin_Click()
Dim RowNo As Long
Dim Id As String, pw As String
Dim ws As Worksheet
Dim aCell As range
On Error GoTo ErrorHandler
Application.ScreenUpdating = True
Set ws = Worksheets("Details")
Id = LCase(Me.txtLogin)
Set aCell = ws.Columns(1).Find(What:=Id, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
'~~> If match found
If Not aCell Is Nothing Then
RowNo = aCell.Row
'~~> Rest of your code. For example if the password is
'~~> Stored in Col B then
Debug.Print aCell.Offset(, 1)
Unload Me
FrmMenu.Show
'~~> You can then use the above aCell.Offset(, 1) to
'~~> match the password which the user entered
Else '<~~ If not found
MsgBox "Unable to match ID, enter valid ID.", vbOKOnly
End If
CleanExit:
Set ws = Nothing
Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
MsgBox Err.Description
Resume CleanExit
End Sub
TESTED AND TRIED
Is this what you are trying?
CODE
Option Explicit
Private Sub cmdLogin_Click()
Dim RowNo As Long
Dim Id As String, pw As String
Dim ws As Worksheet
Dim aCell As Range
On Error GoTo ErrorHandler
If Len(Trim(txtLogin)) = 0 Then
txtLogin.SetFocus
MsgBox "Username cannot be empty"
Exit Sub
End If
If Len(Trim(txtPassword)) = 0 Then
txtPassword.SetFocus
MsgBox "Password cannot be empty"
Exit Sub
End If
Application.ScreenUpdating = False
Set ws = Worksheets("User&Pass")
Id = LCase(Me.txtLogin)
Set aCell = ws.Columns(1).Find(What:=Id, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
'~~> If match found
If Not aCell Is Nothing Then
RowNo = aCell.Row
If Me.txtPassword = aCell.Offset(, 1) Then
FrmMenu.Show
Unload Me
Else
MsgBox "Unable to match UserID or PasswordID, Please try again", vbOKOnly
End If
Else '<~~ If not found
MsgBox "Unable to match UserID or PasswordID, Please try again", vbOKOnly
End If
CleanExit:
Set ws = Nothing
Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
MsgBox Err.Description
Resume CleanExit
End Sub
TIP:
Never let your user know (from security perspective) what was incorrect - The username or the password. Always show a generic message like "Unable to match UserID or PasswordID, Please try again" :)
HTH
Sid
Another way
On Error Resume Next
If Me.password <> Application.VLookup(Me.username, Sheet1.Cells(1, 1).CurrentRegion, 2, False) Then
MsgBox ("incorrect")
Exit Sub
Else
MsgBox ("Correct Password Entered")
End If
Also you will need to make sure that all your sheets are xlSheetVeryHidden from the outset to combat having macros disabled and un-hide them as part of your successful log in routine. You'll also want to set a password on your VBA project to prevent people unhiding the sheets. Bear in mind however, Excel is about as secure as a wet paper bag ;)