How to simplify macros - excel

I'm new here and to the world of VBA.
I've been asked to create a spreadsheet which a user can enter a task number of a job they have been given, from this auto populate other columns with data from a master list, and then when they change the status of the job the row changes colour.
I know that this is easy to do using the vlookup function as a formula in each cell and conditional formatting.
I have searched the web and have found differnt macros that can do the job, but some of them take far to long to find a match, the master task list can contain upto 3000 items.
So I've very crudely cobbled together something that works and quickly.
I was wondering how I can clean these macros up as I'm sure the way I've done it will cause problems in the future or if there is a better way to do the job.
Also as a secoundry question is there any way to get a message box to pop up if the number the user enters doesn't match anything on the master list.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Dim Status As Range
Set KeyCells = Range("B1:B700") 'Range Looking for Change
Set Status = Range("K1:K700")
Application.ScreenUpdating = False
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
Dim SourceLastRow As Long
Dim OutputLastRow As Long
Dim sourceSheet As Worksheet
Dim outputSheet As Worksheet
Set sourceSheet = Worksheets("Task List")
Set outputSheet = Worksheets("2016")
'Determine last row of Task List
With sourceSheet
SourceLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
With outputSheet
'Determine last row in col B
OutputLastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
'Put formula in relevant cell
.Range("F2:F" & OutputLastRow).Formula = _
"=VLOOKUP(B2,'Task List'!$A$2:$D$" & SourceLastRow & ",2,0)"
End With
With outputSheet
OutputLastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
.Range("H2:H" & OutputLastRow).Formula = _
"=VLOOKUP(B2,'Task List'!$A$2:$D$" & SourceLastRow & ",3,0)"
End With
With outputSheet
OutputLastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
.Range("G2:G" & OutputLastRow).Formula = _
"=VLOOKUP(B2,'Task List'!$A$2:$D$" & SourceLastRow & ",4,0)"
End With
End If
If Not Application.Intersect(Status, Range(Target.Address)) _
Is Nothing Then
Dim n As Long
iLastRow = Cells(Rows.Count, "B").End(xlUp).Row
For n = iLastRow To 1 Step -1
If Cells(n, "K").Value = "Closed" Then
Rows(n).Interior.Color = RGB(57, 255, 20)
End If
If Cells(n, "K").Value = "Bond" Then
Rows(n).Interior.Color = RGB(249, 255, 1)
End If
If Cells(n, "K").Value = "Eng Bond" Then
Rows(n).Interior.Color = RGB(255, 102, 0)
End If
If Cells(n, "K").Value = "Fail" Then
Rows(n).Interior.Color = RGB(255, 1, 1)
End If
If Cells(n, "K").Value = "" Then
Rows(n).Interior.ColorIndex = 2
End If
Next n
End If
Application.ScreenUpdating = True
End Sub

Related

How to loop through a list and print the outputs

I'm really new to Excel VBA but recently need to come up with a solution to have excel iterate through a list and print the output.
Here on tab "Sheet2" is the item master. Each of the items is designated an Item Code.
On "Sheet1" I have a formula that finds the Unit Price and Starting Level and calculates the Total On Hand Liabilities.
I'd like to have Excel populate in cell Sheet1!A2 with each of the values in range Sheet2!A1:A, do the calculations, and paste all each of the outputs in a new sheet, as shown below.
Thank you.
I made a basic macro to do this, maybe you could tweak it to suit your needs.
Option Explicit
Sub Test()
Dim rng As Range
Dim switch As Boolean
switch = False
For Each rng In Worksheets("Sheet2").Range("A2", Worksheets("Sheet2").Range("A" & Rows.Count).End(xlUp))
Worksheets("Sheet1").Select
Range("A" & Rows.Count).End(xlUp).Select
'so that for the first iteration it will not offset, assuming you start off with blank wksht
If switch = True Then
ActiveCell.Offset(2, 0).Select
End If
ActiveCell.Value = "Item Number"
ActiveCell.Offset(0, 1).Value = "Description"
ActiveCell.Offset(0, 2).Value = "On Hand Liability"
ActiveCell.Offset(1, 0).Value = rng.Value
ActiveCell.Offset(1, 1).Value = rng.Offset(0, 1).Value
ActiveCell.Offset(1, 2).Value = rng.Offset(0, 2) * rng.Offset(0, 3)
switch = True
Next rng
End Sub
Suggest you use the Microsoft VBA language reference to look up loops. E.g. https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/for-eachnext-statement
Here is an example which will produce your output:
Option Explicit
Public Sub PopulateSheet1()
Dim SourceSheet As Worksheet
Dim SourceRow As Range
Dim SourceRows As Long
Dim TargetSheet As Worksheet
Dim TargetRow As Long
Set SourceSheet = ActiveWorkbook.Sheets("Sheet2")
Set TargetSheet = ActiveWorkbook.Sheets("Sheet1")
SourceRows = SourceSheet.Cells(Rows.Count, 1).End(xlUp).Row
TargetRow = 1
For Each SourceRow In SourceSheet.Range("A2:A" & SourceRows)
TargetSheet.Cells(TargetRow, 1) = Array("Item Number", "Description", "On Hand Liability")
TargetRow = TargetRow + 1
SourceRow.Cells(1, 1).Copy TargetSheet.Cells(TargetRow, 1)
TargetSheet.Cells(TargetRow, 2) = "=VLOOKUP(Sheet1!A" & TargetRow & ",Sheet2!A:B,2,FALSE)"
TargetSheet.Cells(TargetRow, 3) = "=VLOOKUP(Sheet1!A" & TargetRow & ",Sheet2!A:D,3,FALSE) * VLOOKUP(Sheet1!A" & TargetRow & ",Sheet2!A:D,4,FALSE)"
TargetSheet.Cells(TargetRow, 3).NumberFormat = "$#,##0.00"
TargetRow = TargetRow + 2
Next
End Sub

Is there an alternative to a for-if loop in VBA?

I've got two Worksheets in Excel. I've written the following code to copy some data from Worksheet 1 to Worksheet 2, based on some values that the user inserts in Worksheet 2.
The macro works fine, and does what I need it to do, but after writing it down I've come to realize two things:
It takes quite some time for a small set of records(260 or so), as it goes one row at a time.
I read that using .select is not good practice, and I modified the code so that I would not use it, but I'm left wondering if I could improve the code to work faster if I did use it.
So, my main questions are:
How can I improve the speed of the code, so that it will be able to read copy rows faster.
Would it be better in this case to use .select in my case, so that it would work faster.
My code is the following:
Private Sub FillUp()
Dim DateVal, EquivalentDate As Date
Dim CrncyVal
Dim CountrVal
Dim DataRng As Range
Dim endrow As Long, startrow As Long
Dim ws1 As Worksheet
Dim ws2 As Worksheet
'Selecting the worksheets
Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")
''''declaring date, country and currency variables''''
DateVal = ws2.Range("E3").Value
CountryVal = UCase(ws2.Range("H3").Value)
CurrencyVal = UCase(ws2.Range("H4").Value)
EquivalentDateVal = DateAdd("yyyy", -1, DateVal)
'declaring other useful variables
startrow = 3
pasterow = 6
endrow = ws1.Cells(Rows.Count, 1).End(xlUp).Row
'delete the range we will be working with
ws2.Range("A6:F265").Clear
'start the ifs, to see what info the user wants to get
If ws2.Range("E3").Value = "" Then
'If the country cell is empty, we do nothing. We need at least this info
MsgBox prompt:="You didn't choose a month!!", Title:="Error: Please Choose a Month"
Exit Sub
ElseIf ws2.Range("H3").Value = "" Then
For i = 3 To endrow
If ws1.Cells(i, 3).Value <> "TOT" Then
With ws1
Set Rng = .Range(.Cells(i, 1), .Cells(i, 5))
End With
Rng.Copy
ws2.Cells(pasterow, 1).PasteSpecial
ws2.Cells(pasterow, 6) = DateVal
pasterow = pasterow + 1
End If
Next i
Exit Sub
ElseIf ws2.Range("H4").Value = "" Then
For i = 3 To endrow
If ws1.Cells(i, 3).Value <> "TOT" Then
If ws1.Cells(i, 1).Value = CountryVal Then
With ws1
Set Rng = .Range(.Cells(i, 1), .Cells(i, 5))
End With
Rng.Copy
ws2.Cells(pasterow, 1).PasteSpecial
ws2.Cells(pasterow, 6) = DateVal
pasterow = pasterow + 1
End If
End If
Next i
Exit Sub
Else
For i = 3 To endrow
If ws1.Cells(i, 3).Value <> "TOT" Then
If ws1.Cells(i, 1).Value = CountryVal Then
If ws1.Cells(i, 2).Value = CurrencyVal Then
With ws1
Set Rng = .Range(.Cells(i, 1), .Cells(i, 5))
End With
Rng.Copy
ws2.Cells(pasterow, 1).PasteSpecial
ws2.Cells(pasterow, 6) = DateVal
pasterow = pasterow + 1
End If
End If
End If
Next i
Exit Sub
End If
End Sub
Any help or opinion on how I can get the code to be faster or better in any way is welcome, as I am quite new to the whole Excel/VBA world.
Thanks!!
Well, after some time and using DhirendraKumar 's idea to use Autofilter I've managed to get the code to work much faster. Thanks again!!
I'm answering the question so that anyone that might come searching for an answer can see this example and maybe apply it to their problem.
Answers
I've answered my first question with the code below. The speed has been improved by using Autofilter, it works faster because it doesn't go row by row.
I didn't use Select in my code, and I don't use Activate anymore, so I guess I did not need to use neither.
Sub FillUp()
Dim DateVal
Dim CountryVal
Dim CurrencyVal
Dim endrow As Long, lastrow As Long, pasterow As Long
Dim ws1 As Worksheet
Dim ws2 As Worksheet
'Selecting the worksheets
Set ws1 = Worksheets("Cost Evolution 2")
Set ws2 = Worksheets("Sheet1")
''''declaring date, country and currency variables''''
DateVal = ws2.Range("E3").Value
CountryVal = UCase(ws2.Range("H3").Value)
CurrencyVal = UCase(ws2.Range("H4").Value)
'declaring other useful variables
pasterow = 6
lastrow = ws1.Cells(Rows.Count, 1).End(xlUp).Row
'delete the range we will be working with
ws2.Range("A6:F265").Clear
'start the ifs, to see what info the user wants to get
If DateVal = "" Then
'If the country cell is empty, we do nothing. We need at least this info
MsgBox prompt:="You didn't choose a month!!", Title:="Error: Please Choose a Month"
Exit Sub
ElseIf CountryVal = "" Then
With ws1.Range("A2:E2")
.AutoFilter Field:=3, Criteria1:="<>TOT"
End With
' make sure results were returned from the filter
If (ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Address <> "$A$1") Then
ws1.Range("A3:E" & lastrow).Copy ws2.Range("A" & CStr(pasterow))
endrow = ws2.Cells(Rows.Count, 2).End(xlUp).Row
ws2.Range("F" & pasterow & ":F" & endrow).Formula = DateVal
pasterow = endrow + 1
End If
ws1.AutoFilterMode = False
MsgBox prompt:="Inserted complete month"
Exit Sub
ElseIf CurrencyVal = "" Then
With ws1.Range("A2:E2")
.AutoFilter Field:=3, Criteria1:="<>TOT"
.AutoFilter Field:=1, Criteria1:=CountryVal
End With
' make sure results were returned from the filter
If (ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Address <> "$A$1") Then
ws1.Range("A3:E" & lastrow).Copy ws2.Range("A" & CStr(pasterow))
endrow = ws2.Cells(Rows.Count, 2).End(xlUp).Row
ws2.Range("F" & pasterow & ":F" & endrow).Formula = DateVal
pasterow = endrow + 1
End If
ws1.AutoFilterMode = False
MsgBox prompt:="Inserted complete month for the chosen country"
Exit Sub
Else
With ws1.Range("A2:E2")
.AutoFilter Field:=1, Criteria1:=CountryVal
.AutoFilter Field:=2, Criteria1:=CurrencyVal
.AutoFilter Field:=3, Criteria1:="<>TOT"
End With
' make sure results were returned from the filter
If (ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Address <> "$A$1") Then
ws1.Range("A3:E" & lastrow).Copy ws2.Range("A" & CStr(pasterow))
endrow = ws2.Cells(Rows.Count, 2).End(xlUp).Row
ws2.Range("F" & pasterow & ":F" & endrow).Formula = DateVal
pasterow = endrow + 1
End If
ws1.AutoFilterMode = False
MsgBox prompt:="Inserted complete month for the chosen country and currency"
Exit Sub
End If
End Sub

Insert lines between based on values in one column but ignores hidden rows

I have to generate a spreadsheet of upcoming events, and I use a macro that creates a thick line that separates each date from the one above it. It's based on the value change in the "Date" column". However, sometimes I have to filter the data by another criteria (say, the county). In those cases, the offset macro I've been using doesn't always work, as the data that changes and produces the line is in a hidden row, and therefore the line is as well. Can anyone help?
I've tried various ways of defining the range as active cells only, but I don't think I'm doing it correctly.
The macro I'm using is as follows, without applying to hidden rows:
Sub UpcomingLines()
Application.ScreenUpdating = False
Dim LastRow As Long
LastRow = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Dim rng As Range
For Each rng In Range("A1:A100" & LastRow)
If rng <> rng.Offset(1, 0) Then
Range("A" & rng.Row & ":H" & rng.Row).Borders(xlEdgeBottom).Weight = xlThick
End If
Next rng
Application.ScreenUpdating = True
End Sub
I've tried integrating SpecialCells like this:
Sub UpcomingLines()
Application.ScreenUpdating = False
Dim LastRow As Long
LastRow = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Dim rng As Range
Set myrange = Range("A1:H" & Cells(Rows.Count, "A").End(xlUp).Row).SpecialCells(xlCellTypeVisible)
For Each rng In Range("A1:A100" & LastRow)
If rng <> rng.Offset(1, 0) Then
Range("A" & myrange.Row & ":H" & rng.Row).Borders(xlEdgeBottom).Weight = xlThick
End If
Next rng
Application.ScreenUpdating = True
End Sub
However, this generates lines in places I don't want them -- basically, the show up between date changes, but also everyplace there is a hidden row, even if there is no date change before or after the hidden row.
Try something like this:
Sub UpcomingLines()
Dim ws As Worksheet, LastRow As Long, c As Range, theDate
Application.ScreenUpdating = False
Set ws = ActiveSheet
ws.Range("A1").CurrentRegion.Borders.LineStyle = xlNone 'remove existing borders
LastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
theDate = 0
For Each c In ws.Range("A2:A" & LastRow).SpecialCells(xlCellTypeVisible)
'different date from previous visible row?
If c.Value <> theDate Then
'add border to top of row if not the first change
If theDate <> 0 Then c.Resize(1, 8).Borders(xlEdgeTop).Weight = xlThick
theDate = c.Value 'remember this date
End If
Next c
Application.ScreenUpdating = True
End Sub

Cut and Paste Blocks of Data underneath first block using VBA

I have been trying to come up with/find a VBA code that copies blocks of data under my first block. Each block is 19 columns followed by a blank. The number of rows per block can vary.
See my screenshot below:
Therefore, I would like all my data continuous in the first columns A:S. Any help is highly appreciated.
I found the following code online, but this only pastes everything into the first column
Sub Column()
Dim iLastcol As Long
Dim iLastRow As Long
Dim jLastrow As Long
Dim ColNdx As Long
Dim ws As Worksheet
Dim myRng As Range
Dim ExcludeBlanks As Boolean
Dim mycell As Range
ExcludeBlanks = (MsgBox("Exclude Blanks", vbYesNo) = vbYes)
Set ws = ActiveSheet
iLastcol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
On Error Resume Next
Application.DisplayAlerts = False
Worksheets("Alldata").Delete
Application.DisplayAlerts = True
Sheets.Add.Name = "Alldata"
For ColNdx = 1 To iLastcol
iLastRow = ws.Cells(ws.Rows.Count, ColNdx).End(xlUp).Row
Set myRng = ws.Range(ws.Cells(1, ColNdx), _
ws.Cells(iLastRow, ColNdx))
If ExcludeBlanks Then
For Each mycell In myRng
If mycell.Value <> "" Then
jLastrow = Sheets("Alldata").Cells(Rows.Count, 1) _
.End(xlUp).Row
mycell.Copy
Sheets("Alldata").Cells(jLastrow + 1, 1) _
.PasteSpecial xlPasteValues
End If
Next mycell
Else
myRng.Copy
jLastrow = Sheets("Alldata").Cells(Rows.Count, 1) _
.End(xlUp).Row
mycell.Copy
Sheets("Alldata").Cells(jLastrow + 1, 1) _
.PasteSpecial xlPasteValues
End If
Next
Sheets("Alldata").Rows("1:1").EntireRow.Delete
ws.Activate
End Sub
Basic approach:
Sub Tester()
Dim c As Range, addr
Set c = ActiveSheet.Range("T1")
Do
Set c = c.End(xlToRight)
If c.Column = Columns.Count Then Exit Do
addr = c.Address 'strire the address since Cut will move c
c.CurrentRegion.Cut c.Parent.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Set c = ActiveSheet.Range(addr) '<< reset c
Loop
End Sub
This is a little more basic than #TimWilliams
With ThisWorkbook.Sheets("Alldata")
Dim lRow As Long, lCol As Long, cpyrng As Range
lCol = Cells(1, Columns.Count).End(xlToLeft).Column
For i = 21 To lCol Step 20
If .Cells(1, i).Value <> "" And .Cells(1, i).Offset(, -1).Value = "" Then
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row
Set cpyrng = .Cells(1, i).CurrentRegion
cpyrng.Cut
Sheets("Sheet2").Cells(lRow, 1).Offset(2).Insert Shift:=xlDown
End If
Next i
End With

An Excel code to search data from command button

I have tried to make a button which searches through a selection of data on one sheet for a ID number then returns the corresponding data in the row after onto a different sheet. I thought i had it sorted but this just wont work and have run out ideas.
Any help would be appreciated.
see code below:
Private Sub CommandButton2_Click()
Dim Userentry As String
Dim DataRange As Range
Dim i As Long
Dim location As Integer
Dim ws, ws1 As Worksheet
Set ws = Sheets("Sheet1")
Set ws1 = Sheets("Sheet4")
With TextBox2
Userentry = .Value
End With
Range("A36").Value = Userentry
For i = 2 To ws.Range("A" & Rows.Count).End(xlUp).Row
If LCase(Cells(i, 1).Value) = Userentry Then ws1.Range("F" & Rows.Count).End(xlUp).Offset(1, 0).Value = Cells(i, 2).Value
Next i
For i = 2 To ws.Range("A" & Rows.Count).End(xlUp).Row
If LCase(Cells(i, 1).Value) = Userentry Then ws1.Range("G" & Rows.Count).End(xlUp).Offset(1, 0).Value = Cells(i, 3).Value
Next i
For i = 2 To ws.Range("A" & Rows.Count).End(xlUp).Row
If LCase(Cells(i, 1).Value) = Userentry Then ws1.Range("H" & Rows.Count).End(xlUp).Offset(1, 0).Value = Cells(i, 4).Value
Next i
For i = 2 To ws.Range("A" & Rows.Count).End(xlUp).Row
If LCase(Cells(i, 1).Value) = Userentry Then ws1.Range("I" & Rows.Count).End(xlUp).Offset(1, 0).Value = Cells(i, 5).Value
Next i
End Sub
I'd throw in two possible solutions, with the goal to minimize execution time (should it be an issue)
solution 1
here you're still actually looping through column A cells but:
only if there's at least one matching value
considering non empty cells with text values only
`
Option Explicit
Private Sub CommandButton2_Click()
Dim Userentry As String, firstAddr As String
Dim ws1 As Worksheet
Dim f As Range
Set ws1 = Sheets("Sheet4")
Userentry = TextBox2.Value
ws1.Range("A36").Value = Userentry
With Sheets("Sheet1")
With .Range("A1:A" & .Cells(.Rows.Count, 1).End(xlUp).Row).SpecialCells(xlCellTypeConstants, xlTextValues)'<~~ consider column "A" cells with text values down to the LAST non empty one
Set f = .Find(What:=Userentry, LookAt:=xlWhole, LookIn:=xlValues)
If Not f Is Nothing Then '<~~ loop only if there's at least one matching value
firstAddr = f.Address
Do
ws1.Range("F" & Rows.Count).End(xlUp).Offset(1, 0).Resize(1, 4).Value = _
f.Offset(, 1).Resize(1, 4).Value
Set f = .FindNext(f)
Loop While f.Address <> firstAddr
End If
End With
End With
End Sub
`
solution 2
this avoids looping at all, but at the "expense" of sorting rows
Option Explicit
Private Sub CommandButton2_Click()
Dim Userentry As String
Dim countVal As Long
Dim ws1 As Worksheet
Set ws1 = Sheets("Sheet4")
Userentry = TextBox2.Value
ws1.Range("A36").Value = Userentry
With Sheets("Sheet1")
With .Range("A1:A" & .Cells(.Rows.Count, 1).End(xlUp).Row) '<~~ consider column "A" cells down to the LAST non empty one
countVal = Application.WorksheetFunction.CountIf(.Cells, Userentry) '<~~ count matching values
If countVal > 0 Then '<~~ if any then ...
.Resize(, 5).Sort key1:=.Range("A1"), order1:=xlDescending, Header:=xlNo '<~~ ... sort columns "A" to "E" by column "A" values...
ws1.Range("F" & Rows.Count).End(xlUp).Offset(1, 0).Resize(countVal, 4).Value = .Find(What:=Userentry, LookAt:=xlWhole, LookIn:=xlValues).Offset(, 1).Resize(countVal, 4).Value '<~~ ... and copy/paste values
End If
End With
End With
End Sub
if you should ever mind having Sheet1 rows sorted, then here's the "patch"
Private Sub CommandButton2_Click()
Dim Userentry As String
Dim countVal As Long
Dim ws1 As Worksheet
Dim helperCol As Range
Set ws1 = Sheets("Sheet4")
Userentry = TextBox2.Value
ws1.Range("A36").Value = Userentry
With Sheets("Sheet1")
Set helperCol = .UsedRange.Columns(.UsedRange.Columns.Count + 1) '<~~ set a helper column "out of the town" not to interfere with data already there
With .Range("A1:A" & .Cells(.Rows.Count, 1).End(xlUp).Row) '<~~ consider column "A" cells down to the LAST non empty one
countVal = Application.WorksheetFunction.CountIf(.Cells, Userentry) '<~~ count matching values
If countVal > 0 Then '<~~ if any then ...
With Intersect(.Rows.EntireRow, helperCol) '<~~ consider helper column rows corresponding to your data ones
.Formula = "=ROW()" '<~~ place an ascending index to every row
.Value = .Value '<~~ get rid of formulas, otherwise subsequent sorting would have no effect on their result
End With
.Resize(, helperCol.Column).Sort key1:=.Range("A1"), order1:=xlDescending, Header:=xlNo '<~~ ... sort columns "A" to "helpercol" rows by column "A" values...
ws1.Range("F" & Rows.Count).End(xlUp).Offset(1, 0).Resize(countVal, 4).Value = .Find(What:=Userentry, LookAt:=xlWhole, LookIn:=xlValues).Offset(, 1).Resize(countVal, 4).Value '<~~ ... copy/paste values ...
.Resize(, helperCol.Column).Sort key1:=helperCol, order1:=xlAscending, Header:=xlNo '<~~ ... and sort columns "A" to "helpercol" rows back by "helpercol" values
helperCol.Clear '<~~ finally clear "helpercol" column
End If
End With
End With
End Sub
Private Sub CommandButton2_Click()
Dim Userentry As String
Dim i As Long
Dim ws, ws1 As Worksheet
Set ws = Sheets("Sheet1")
Set ws1 = Sheets("Sheet4")
Userentry = TextBox2.Value
ws1.Range("A36").Value = Userentry
For i = 2 To ws.Range("A" & Rows.Count).End(xlUp).Row
If LCase(ws.Cells(i, 1).Value) = Userentry Then
ws1.Range("F" & Rows.Count).End(xlUp).Offset(1, 0).Resize(1, 4).Value = _
ws.Cells(i, 2).resize(1, 4).Value
End If
Next i
End Sub

Resources