I have a list that contains Employee ID in Col A, First Name in Col B, Last Name in Col C. I am needing to write a macro that gives a userform to input First and Last Name and from there it will put the proper Employee ID into the first unused cell in Col E and then loop back to the userform.
I already know how to build the Userform and will have two buttons on it one that reads "Next" and one that reads "End". The "Next" button will loop the Userform and the "End" will just close the Userform.
Plan on leaving the Userform named Userform1 and naming the input boxes as "FirstName" and "LastName". So I know that to reference these from the macro I would call for Userform1.FirstName.Value or Userform1.LastName.Value depending on which part I need at the moment.
The part I am not sure on is how to the matching of two variables and then looking to the left for the ID. I can move the ID Col to be after the name Cols if that helps but I am still not sure how to write so that both names must match.
As for error trapping I planned on having a MsgBox state "There are no matching entries." If the person does not exist in the list. However I am unsure of how to handle the super unlikely but possible situation of if two people on the list have the same name. So any suggestions for this would be greatly appreciated.
I am using Excel 2013.
Try this for the next button
Private Sub NextButton_Click()
Dim emptyRow As Long
Dim matchFound As Boolean
Dim matchCount As Long
Dim matchRow As Long
Dim i As Long
'Determine the first empty cell in column E
If Cells(1, 5).Value = "" Then
emptyRow = 1
Else
emptyRow = Cells(Columns(5).Rows.Count, 5).End(xlUp).Row + 1
End If
matchFound = False
matchCount = 0
matchRow = 0
'Loop through all of rows that have an employee id
For i = 1 To Cells(Columns(1).Rows.Count, 1).End(xlUp).Row
If (UCase(FirstName.Value) = UCase(Cells(i, 2).Value)) And (UCase(LastName.Value) = UCase(Cells(i, 3).Value)) Then
matchCount = matchCount + 1
matchRow = i
matchFound = True
End If
Next
'Alert user of any errors
If matchFound = False Then
MsgBox ("There are no matching entries")
ElseIf matchCount > 1 Then
MsgBox ("There were multiple matches")
Else
'If there are no errors add employee id to the list
Cells(emptyRow, 5).Value = Cells(matchRow, 1).Value
emptyRow = emptyRow + 1
End If
'Clear the userform
FirstName.Text = ""
LastName.Text = ""
End Sub
I'm not sure what the best course of action to take if there are multiple matches, so for now I just included a message to alert the sure. It wouldn't be hard to change the code to track each of the matched rows instead of just the last one.
I would suggest using vlookup, as it's basically designed around your problem. It takes an input, finds it in one column, then outputs the same row in a different column. It shouldn't be difficult to make the output dependent on two vlookups matching to the same output.
http://www.howtogeek.com/howto/13780/using-vlookup-in-excel/
Related
I have been searching for almost 2 days to find an answer to this and it is driving me insane. I am very new to VBA so I don't have any code to share, just been trying out things I find on other sites and youtube. I have a technician sign in sheet that I have been working on and these are the steps I need done:
select your name from the "Metrology Tech." combobox on the 'Metrology Tech log-in' sheet
VBA searches thru column H in 'metrology tracker' to find all matching names
The lot numbers from column E in 'metrology tracker' sheet are put into the "Lot Number" combobox if the value in column M in 'metrology tracker' sheet is equal to "Pend."
I've tried this Create Dependent Combo Boxes on a Userform - Excel VBA and it did not work it just returned all the values of the column I need and all the other articles and videos were pretty much the same thing.
one thing I should note is that most of the values in the metrology tracker are referenced from another file so the lot numbers are equal to a cell value in another file.
Edit:
Ive tried this even though I knew it wasn't going to work
Private Sub cboTech_change()
Select Case cboTech.Value
Case Is = "employee 1"
cboLotNum.RowSource = "LotNumber"
Case Is = "employee 2"
cboLotNum.RowSource = "LotNumber"
Case Is = "employee 3"
cboLotNum.RowSource = "LotNumber"
End Select
End Sub
and also tried this, but kept on gettting a "run-time error '424' object required"
Sub FndLot()
Dim idx As Long
Dim lngRow As Long
idx = TechBox.ListIndex
If idx <> -1 Then
lngRow = TechBox.ListIndex
Worksheets("Metrology Tracker").Range("E" & lngRow).Value = LotNum.Value
End If
End Sub
Not too sure what you want but this should get you started.
Private Sub cboTech_Change()
Dim sName As String
sName = cboTech.Text
cboLotNum.Clear
Dim ws As Worksheet, lastrow As Long, i As Long
Set ws = Sheets("metrology tracker")
With ws
lastrow = .Cells(.Rows.Count, "H").End(xlUp).Row
For i = 1 To lastrow
If .Cells(i, "H") = sName And .Cells(i, "M") = "pend" Then
cboLotNum.AddItem .Cells(i, "E")
End If
Next
End With
End Sub
i have main user-form 1 which has all the information including list box and when user select the name of the person it will find for duplicate and if user press Yes to duplicate msgbox another user-form 2 will popup requiring password and if user enters the correct password it will popup another user-form 3 which has comment box to be updated against initial duplicate find..
problem is that it only updates comment on 1st line row on sheet 1 (where the data updates) and NOT the actual duplicate it finds using staff ID number in column G in sheet1. it only finds first line which is within User-form1 listbox not the line you have selected in User-form1.
below it is the code which works fine within User-form1 and however it dose not work of what i wants to work when placed in user-form 3
Private Sub CommandButton1_Click()
Dim p As Variant
Dim lCol As Variant
Dim response As Variant
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Jobs_Allocation")
Dim y As Long
Application.EnableCancelKey = xlDisabled
If TextBox1 > False Then
Unload Me
lCol = frmSelector.lstSelector.List(x, 3)
Set findvalue = Sheet1.Range("G:G").Find(What:=lCol, LookIn:=xlValues)
If Not findvalue Is Nothing Then
adr = findvalue.Address
Do
Sheet1.Unprotect Password:="123"
If findvalue.Offset(0, -1).Value = frmSelector.lstSelector.List(x, 2) Then
findvalue.Offset(0, 6).Value = Format(Now, "HH:MM:SS")
findvalue.Offset(0, 7).Value = TextBox1.Value
y = sh.Range("C" & Application.Rows.Count).End(xlUp).Row
Exit Do
End If
Set findvalue = Sheet1.Range("G:G").FindNext(findvalue)
Loop While findvalue.Address <> adr
Set findvalue = Nothing
End If
End If
If TextBox1.Value > 0 Then
MsgBox "You must enter the comment", vbCritical, "Error message"
Exit Sub
End If
End Sub
I'm sorry as I'm not helping you thouroghly, but I think you need to do the loop in your CommandButton1_Click which reside in the third Userform.
I give you a very simple simulation which I hope you can implement it to your code.
From the image above, it's the first userform, in your case it's frmselector.
The listbox is named to lstselector, and (in the image) the selected item is the fourth row. So, the index number is 3, the x value in your case.
I see that to get the lCol value, you do the code :
For x = 0 To Me.lstSelector.ListCount - 1
If Me.lstSelector.Selected(x) Then
**If Me.txtJob.Value = Value = False Then**
lCol = Me.lstSelector.List(x, 3)
So, disregarding the code-line I put in between two asterisk,
based on the image above, we know that the value of the lCol variable is 80.
To get the lCol value (in other words, to get the selected value on the fourth column of the lstselector in frmselector/first_userform) when running the CommandButton1_Click sub of the third userform, we need to do the loop again. Below is the example of the code, which we hope that the code will give lCol value as 80 :
Private Sub CommandButton1_Click()
With frmselector
For x = 0 To .lstselector.ListCount - 1
If .lstselector.Selected(x) Then Exit For
Next
lCol = .lstselector.List(x, 3)
End With
MsgBox "The value of selected selector in frmselector is: " & lCol
End Sub
I apologize, this is my first crack at Excel VBA so excuse my lack of knowledge!
So I have a list of (currently) 3 names to assign to the days in column A in a repeating order in Excel.
Currently my VBA code allows it to populate the selected cells with the names in a repeating pattern (this part is good), however there are two pieces I need help with.
1- with current code, once it reaches the bottom of the names it checks for the blank box that would end that list and starts over at the tops as directed but it puts a blank cell first (see screenshot). How can I have it put next name without adding blank cell first?
2- I want to be able to (once this gets going)select the entire D column through what dates need to be filled and:
-check the lowest non blank box
-match to list and set the
counter to name below that so
it continues the name order
from the last person who was
assigned
This is code I have now:
Sub EXAMPLE()
Dim count As Integer
count = 0
For Each c In Selection
c.Value = Range("X1").Offset(count, 0).Value
If c.Value = "" Then count = -1 And c.Value = Range("x1").Offset(count, 0).Value
count = count + 1
Next c
End Sub
Sorry I know that was long, I hope this makes sense.
I think it's worth reading about arrays, as this task is ideally suited to their use. Your best bet would be to read the names into an array and then build a recurring array whose dimension is equal to the number of rows in your dates column (or selection, or however you want to define the size of the output range).
Code would look a little like this:
Dim v As Variant
Dim people() As Variant, output() As Variant
Dim rowCount As Long, i As Long, j As Long
Dim endRange As Range
'Read the list of names into an array.
'This just takes all data in column "X" -> amend as desired
With Sheet1
Set endRange = .Cells(.Rows.Count, "X").End(xlUp)
v = .Range(.Cells(1, "X"), endRange).Value
End With
'Sense check on the names data.
If IsEmpty(v) Then
MsgBox "No names in Column ""X"""
Exit Sub
End If
If Not IsArray(v) Then
ReDim people(1 To 1, 1 To 1)
people(1, 1) = v
Else
people = v
End If
'Acquire the number of rows for repeating list of names.
'This just takes all data in column "A" -> amend as desired
With Sheet1
Set endRange = .Cells(.Rows.Count, "A").End(xlUp)
rowCount = .Range(.Cells(3, "A"), endRange).Rows.Count
End With
'Sense check date data.
If endRange.Row < 3 Then
MsgBox "No dates in Column ""A"""
Exit Sub
End If
'Make a recurring array.
ReDim output(1 To rowCount, 1 To 1)
i = 1
Do While i <= rowCount
For j = 1 To UBound(people, 1)
output(i, 1) = people(j, 1)
i = i + 1
If i > rowCount Then Exit Do
Next
Loop
'Write the output to column "D"
Sheet1.Range("D3").Resize(UBound(output, 1)).Value = output
Goes directly to MsgBox without seemingly changing anything.
I've been playing around with this code for awhile now since I'm new to VBA. I'm aware this script isn't pointed at a specific spreadsheet.
Private Sub MergeData()
'The cell it will use to search
Dim idCheck As Range
'The cell it will use to compare text
Dim currentCell As Range
'The cell is will use to compare duplicates
Dim oneRowBelow As Range
'Will briefly say if something changed in furthest column
Dim changes As String
'This will be used to format the "Changes" column
Dim rowNumberValue As Integer, columnNumberValue As Integer, rowBelow As Integer
colNum = 3
rowNumberValue = ActiveCell.Row
columnNumberValue = ActiveCell.Column
rowBelow = ActiveCell.Row + 1
'Searches by ID column
For Each idCheck In Worksheets("Test").Range("B2:B1000")
'This checks to find duplicate ID rows
If idCheck.Value = idCheck.Offset(-1, 0).Value Then
'Goes from each column starting from the ID column (H = 7th letter in alphabet and H is the last column)
'Technically S is the last column since S just lists what has changed
For colNum = 3 To 7
'Checks to see if the current cell has no value but the duplicate cell does
If Cells(rowNumberValue, colNum) = "" And Cells(rowBelow, colNum) <> "" Then
'Changes current cell value to the duplicate cell value
Cells(rowNumberValue, colNum) = Cells(rowBelow, colNum)
'Writes in the 19th column whether or not data has been changed
changes = "Added"
Cells(rowNumberValue, 19) = changes
Cells(rowNumberValue, 19).Interior.ColorIndex = 4
End If
'Checks to see if current cell has value but the duplicate cell doesn't
If Cells(rowNumberValue, colNum) <> "" And Cells(rowBelow, colNum) = "" Then
'Merges the two cells ( Unfortunately .Merge takes the top cell value only)
Range(Cells(rowNumberValue, colNum), Cells(rowBelow, colNum)).Merge
'Writes in the 19th column whether or not data has been changed
changes = "Added"
Cells(rowNumberValue, 19) = changes
Cells(rowNumberValue, 19).Interior.ColorIndex = 4
End If
'Checks to see if the cell value is different from the duplicate value
If Cells(rowNumberValue, colNum) <> Cells(rowBelow, colNum) Then
'This just sets the first value to the duplicate value (since it doesn't matter which one is overwritten)
Cells(rowBelow, colNum) = Cells(rowNumberValue, colNum)
'Writes in the 19th column whether or not data has been changed
changes = "Changed"
Cells(rowNumberValue, 19) = changes
Cells(rowNumberValue, 19).Interior.ColorIndex = 6
End If
Next colNum
End If
colNum = 3
Next
MsgBox "All done"
End Sub
So for example, if two rows have the number 123 in their ID column, and the Name column in the first row lists Timothy and the second row lists Tim, the script should change the row to say Bob and say in the furthest column what was changed. Or, if the first or second row has an empty cell while the other row doesn't, the data from the non-empty cell would be merged/copied over to the empty one.
It doesn't matter which data is overwritten, as long as all empty cells that can be filled, are filled.
From my comment, I believe you're causing false conditions due to where your variables are defined:
'Searches by ID column
For Each idCheck In Worksheets("Test").Range("B2:B1000")
'find current cell's row to be used in if-statements
rowNumberValue = ActiveCell.Row 'MOVED INTO ROW LOOP ==============
rowBelow = ActiveCell.Row + 1 'MOVED INTO ROW LOOP ==============
'This checks to find duplicate ID rows
If idCheck.Value = idCheck.Offset(-1, 0).Value Then
'Goes from each column starting from the ID column (H = 7th letter in alphabet and H is the last column)
'Technically S is the last column since S just lists what has changed
For colNum = 3 To 7 'COLNUM IS DEFINED, NOT NEEDED BEFOREHAND ==========
columnNumberValue = ActiveCell.Column 'if you need this, put it inside of this section, but you shouldn't need it due to colNum existing =========
'Your other code here
Next colNum
End If
Next
You also don't need to reset, manually, your colNum to 3 at the end, due to the For loop doing that when it iterates.
Flagged my comments/changes in your code with ======== after the comments.
So first my disclaimer. While I have some programming background, im not proficient in VB scripting so I may need some hand holding on this but I am mighty grateful for any help you wonderful people can render.
Im creating a print button that will print a worksheet based on criteria that the user will type in. Well basically I need the script to check certain cells in a row and if there is data in those cells, move to the next line. Rinse and repeat until you get to a row with no data in those certain cells and then automatically print the correct number of pages based on the data. I hope that makes sense. I hope that makes sense.
I tried writing a piece of code to check certain columns and return the value when all of those columns are blank. Hope that helps you
Sub Printing()
Dim CheckCol1 As Integer, CheckCol2 As Integer
Dim rowCount As Integer, rowCount1 As Integer, rowCount2 As Integer, currentRow As Integer
Dim currentRowValue1 As String, currentRowValue2 As String
Dim found As String
found = "No"
CheckCol1 = 1 'column A has a value of 1
CheckCol2 = 2 'column B has a value of 2
rowCount1 = Cells(Rows.Count, CheckCol1).End(xlUp).Row
rowCount2 = Cells(Rows.Count, CheckCol2).End(xlUp).Row
rowCount = Application.Max(rowCount1, rowCount2)
' find the first blank cell on both the columns
For currentRow = 1 To rowCount
currentRowValue1 = Cells(currentRow, CheckCol1).Value
currentRowValue2 = Cells(currentRow, CheckCol2).Value
If (IsEmpty(currentRowValue1) Or currentRowValue1 = "") And (IsEmpty(currentRowValue2) Or currentRowValue2 = "") Then
MsgBox ("No data on Column A and B in row" & currentRow)
found = "Yes"
End If
Next
If found = "No" Then ' This will return rowcount+1 when the columns have values throughout the range
MsgBox ("No data on Column A and B in row" & rowCount + 1)
End If
End Sub
Note:- You can increase the number of columns to be checked by adding few variables. You can try Adding third column by adding Checkcol3, rowcount3, currentrowvalue3 and adding one more condition to the if clause