I currently have a list of employees which have completed training within the whole company. I am trying to create a macro to find the employees with my department via their employee number and copy them over to Worksheet 2.
Employee Number is in column A. This employee may have multiple entries under their ID. I want to copy all information on that row from Column A to Column N. I than want to paste those entries into Sheet2.
We have 187 Employees within our department. Any help with finishing this would be greatly appreciated.
Sub ()
Worksheets("Sheet1").Activate
Range("A1").Activate
' Find the first ID Number
Cells.Find(What:="10503", After:=ActiveCell, SearchDirection:=xlPrevious).Select
' copy and paste Text2
ActiveCell.Offset(0, 0).Copy
Worksheets("Sheet2").Select
Range("A65000").End(xlUp).Offset(1, 0).Select
ActiveCell.PasteSpecial (xlPasteAll)
Worksheets("Sheet1").Activate
End Sub
Try this:
Sub FindandCopyRow()
Dim targetSh As Worksheet
Set targetSh = ThisWorkbook.Worksheets("Sheet2")
Dim i As Long
For i = 1 To Cells(Rows.Count, "A").End(xlUp).Row
If Cells(i, 1).Value = "10503" Then '--->change ID here as required
Rows(i).EntireRow.Copy Destination:=targetSh.Range("A" & targetSh.Cells(Rows.Count, "A").End(xlUp).Row + 1)
End If
Next i
End Sub
I just added some data to #Mrig's answer.
One being the use of Application.InputBox which prompts the user to insert the employee number instead of the user editing the code every time.
I also just Sheet referencing for the various part of the For loop, always good to reference the sheets you are in to avoid consufion for the next user and then Application itself.
Sub FindandCopyRow()
Dim DataSh As Worksheet
Set DataSh = ThisWorkbook.Worksheets("Sheet1")
Dim targetSh As Worksheet
Set targetSh = ThisWorkbook.Worksheets("Sheet2")
Dim EmployeeNumber As Long
'This allows you to enter an employee number and not have to edit the code every time
EmployeeNumber = Application.InputBox(Prompt:="Please Enter Employee Number:", Type:=1)
'Try use descriptive naming for variables.....always
Dim DataShRowRef As Long
'Remember to always reference the sheet you are in when counting and copying etc
For DataShRowRef = 1 To DataSh.Cells(DataSh.Rows.Count, "A").End(xlUp).Row
If DataSh.Cells(DataShRowRef, 1).Value = EmployeeNumber Then
DataSh.Rows(DataShRowRef).EntireRow.Copy Destination:=targetSh.Range("A" & targetSh.Cells(targetSh.Rows.Count, "A").End(xlUp).Row + 1)
End If
Next DataShRowRef
End Sub
Related
I am currently working on deleting rows. I have already made it work in one sheet, but I just want to ask if there is any way to delete rows in several sheets at the same time? I have a unique key which is the student ID that is in Column C of all the sheets that will be affected. So, by clicking on the delete button, all data with this student ID will be deleted.
Using the code below, I can delete a row from the STUDENTS_INFO sheet.
Sub del_stud()
Set ws = ActiveWorkbook.Worksheets("STUDENTS_INFO")
LastRow = ws.Cells(Rows.Count, "C").End(xlUp).Row
For r = 10 To LastRow
If CStr(ThisWorkbook.Sheets("HOME").Range("K11").Value) = ws.Cells(r, 3) Then
ws.Rows(r).EntireRow.Delete
MsgBox "Student's data is now deleted!"
Unload Me
End If
Next r
End Sub
The sheets that will be affected are STUDENTS_INFO, G1-Q1, G1-Q2, G1-Q3, G1-Q4, G2-Q1, G2-Q2, G3-Q3, G4-Q4, and so on... I also have sheets that, hopefully, will not be touched. Is this possible?
Based on my research, it uses the For Each ws In ThisWorkbook.Sheets. I tried to use it, but it still deletes the row in STUDENTS_INFO sheet and not on multiple sheets.
Here's the code that I tried.
Application.ScreenUpdating = False
For Each ws In ThisWorkbook.Sheets
LastRow = ws.Cells(Rows.Count, "C").End(xlUp).Row
For r = 10 To LastRow
If CStr(ThisWorkbook.Sheets("HOME").Range("K11").Value) = ws.Cells(r, 3) Then
ws.Rows(r).EntireRow.Delete
MsgBox "Student's data is now deleted!"
Unload Me
End If
Next r
Next ws
Application.ScreenUpdating = True
I’d agree with #urdearboy’s suggestion of using a filter to delete the rows – plus looping through an array of sheets that you designate. The following code assumes the Student ID is sourced from the cell K11 on the HOME sheet. You can add/remove sheets from the array as you see fit.
Try the following & let me know how you go.
Option Explicit
Sub del_stud()
Dim StudID As String, ws As Worksheet
'Get the filter criteria from cell K11 in the HOME sheet
StudID = ThisWorkbook.Sheets("HOME").Range("K11").Value
'Do the STUDENTS_INFO sheet by itself
With ThisWorkbook.Sheets("STUDENTS_INFO").Cells(8, 3).CurrentRegion
.AutoFilter 1, StudID
.Offset(1).EntireRow.Delete
.AutoFilter
End With
'Do the other generic sheets next - add/remove sheets as required
For Each ws In Sheets(Array("G1-Q1", "G1-Q2"))
With ws.Cells(9, 3).CurrentRegion
.AutoFilter 1, StudID
.Offset(1).EntireRow.Delete
ws.AutoFilterMode = False
End With
Next ws
End Sub
I would like every day, when I open excel, that my excel would add a today's date to it. I have this code, but it isn't working, sometimes it does what it's supposed to and sometimes it skips a line, any help please?
Sub Stretching()
'This procedure will run each time you open the workbook
'Specify the required worksheet name in double quotes
Dim ws As Worksheet
Set ws = Sheets("Stretching")
'Get the last row number filled with a value in Column A
Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
'Check if the last entered date is the same as the current date, if so, exit
'You need this check to see if you close the workbook then open it on the same day
'so that the code does not enter the same date again in a new row.
If ws.Cells(lastRow, 1).Value = Date Then Exit Sub
'Fill a new row in Column A with the current date
If IsEmpty(Cells(lastRow, 1)) Then
ws.Cells(lastRow, 1).Value = Date
Else
ws.Cells(lastRow, 1).Offset(1, 0).Value = Date
End If
End Sub
Some suggestions on your code:
Fully qualifying the ranges help you avoiding inconsistent results. This means, you can be running the procedure when an active sheet is different than the one you are targeting, and this line: Cells(Rows.Count, 1).End(xlUp).Row would return a different "last row" than the one you'd expect
Also try to use variable names that are easily understandable. For example, ws vs targetSheet
Please try this code and let me know if it works:
Public Sub Stretching()
'This procedure will run each time you open the workbook
'Specify the required worksheet name in double quotes
Dim targetSheet As Worksheet
Set targetSheet = ThisWorkbook.Sheets("Stretching")
'Get the last row number filled with a value in Column A
Dim lastRow As Long
lastRow = targetSheet.Cells(targetSheet.Rows.Count, 1).End(xlUp).Row
'Check if the last entered date is the same as the current date, if so, exit
'You need this check to see if you close the workbook then open it on the same day
'so that the code does not enter the same date again in a new row.
If targetSheet.Cells(lastRow, 1).Value = Date Then Exit Sub
'Fill a new row in Column A with the current date
If IsEmpty(targetSheet.Cells(lastRow, 1)) Then
targetSheet.Cells(lastRow, 1).Value = Date
Else
targetSheet.Cells(lastRow, 1).Offset(1, 0).Value = Date
End If
End Sub
I have a sheet which contains a column full of Item IDs called "Werkzeugtabelle Vormontage" and another sheet which contains part of the item IDs listed in sheet 1.
I want to filter Sheet 1 by the Item IDs that are similar to the ones in sheet 2. So basically have the sheet with more IDs chopped to the size of the sheet with less IDs. (Deleting the not similar ones would also be an option but no clue how that might work.)
If CheckSheet("BMV Vormontage") Then
Sheets("Werkzeugtabelle").Select
Sheets("Werkzeugtabelle").Copy After:=Sheets("BMV Vormontage")
ActiveSheet.Name = "Werkzeugtabelle Vormontage"
lRow = Cells(Rows.Count, 1).End(xlUp).Row
Sheets("Restanschluss Vormontage").Select
xRow = Cells(Rows.Count, 11).End(xlUp).Row
'CountUnique ("K3:K100")
'critCount = CountUnique.Count
For i = 3 To lRow
For a = 10 To xRow
Sheets("Werkzeugtabelle Vormontage").Cells(i, 1).AutoFilter Field:=1, Criteria1:=Sheets("Restanschluss Vormontage").Cells(a, 11).Value
Next a
Next i
End If
The CheckSheet is looking for that sheet to get a starting point in the workbook. "Werkzeugtabelle" is the non filtered vanilla sheet.
Whenever I have more than one similar Item ID between the two sheets, it won't show, because I am only looking for one criteria it seems.
I tried to do a loop.
Alright I guess I have found the solution. At least it does everything it does and doesn't spam me with error. Could you guys double check if this is a good code?
Sub Werkzeugtabelle_splitten()
Dim ws As Worksheet
Dim rng As Variant
Set ws = Sheets("Werkzeugtabelle")
' Splitten Vormontage
If CheckSheet("BMV Vormontage") Then
rng = Sheets("Restanschluss Vormontage").Range("K10:K100").Value
ws.Range("A3").AutoFilter _
Field:=1, _
Criteria1:=Application.Transpose(rng), _
Operator:=xlFilterValues
ws.Copy After:=Sheets("BMV Vormontage")
ActiveSheet.Name = "Werkzeugtabelle Vormontage"
ws.ShowAllData
End If
End Sub
So I have made that the orginial "Werkzeugtabelle" sheet will still exist and it only filters it > copies it to the right spot in the workbook and afterwards resets the filter on the original.
I have a workbook with two sheets. The "Companies" Worksheet has a dynamic rows and with set columns A - J.
In Worksheet "Table - Summary" I have a summary of the unique company names and I have used a code to get the unique names from column b in the "Companies" Worksheet. In the "Table Summary" sheet is where people get assign to the unique companies and sheets are distributed according to which companies an individual has been assign to. Which the name of the individual is entered in column 3 in the "Table - Summary" Sheet.
I have some code where it creates a worksheet according to what was enter in the "Table - Summary" sheet in cells(LastRow, 3). There are more than 10 individuals that are assign to several companies which varies depending what name the assigner inputs in column C. Please see picture. I don't want to create duplicate worksheets for each assignee. I did a google search for suggestions, such as a function were it checks if the worksheet exists but had no clue what it was doing. If I could get assistance with this too. Please and thank you.
How can I tell VBA to check through columns b in the "Table - Summary" sheet to copy and paste the rows that have the customer names in column b of the "companies" sheet. And place it into the corresponding worksheet of the assignee.
I'm very new to VBA. If I was unclear. P Lease let me know
Sub GetAssignedCompanies()
Dim wbMaster As Workbook
Dim shI As Worksheet
Dim shS As Worksheet
Set wbMaster = Workbooks("Workbook1.xlsx")
Set shI = wbMaster.Worksheets("Companies")
Set shS = wbMaster.Worksheets("Table - Summary")
Dim LastRow As Integer
Dim EndRow As Integer
Dim aName As String
LastRow = 4
EndRow = 2
While Len(shS.Cells(LastRow, 2).Value) > 0
aName = shS.Cells(LastRow, 3).Value
If Not aName = vbNullString Then
Sheets.Add(After:=Sheets(Sheets.count)).Name = aName
End If
LastRow = LastRow + 1
Wend
End Sub
This is an example; You need to create the new worksheets for each employee before you Run this macro; It will write the company names from "Table - Summary" column 1, into column 1 of the employee's worksheet. Change the names of your employee worksheets as needed.
'You need to create the individual worksheet before running this macro.
Dim nameShtArr, i As Long, shS As Worksheet, shI As Worksheet
Set shI = ThisWorkbook.Worksheets("Companies")
Set shS = ThisWorkbook.Worksheets("Summary")
nameShtArr = Array("Tom", "Bob", "Joe")
For i = LBound(nameShtArr) To UBound(nameShtArr)
With shS.Range("C2:C" & Cells(Rows.Count, "C").End(xlUp).Row)
.AutoFilter Field:=1, Criteria1:=nameShtArr(i)
End With
'Place the company names assigned to the employee in column A.
shS.Range("B2:B20").SpecialCells(xlCellTypeVisible).Copy Worksheets(nameShtArr(i)).Range("A1")
'This next section will loop through each company name in the current worksheet and find it in ColB,
'if it finds the company name it will copy the data in the row to ColJ and paste it into the current worksheet.
Dim lRow As Long
lRow = Worksheets(nameShtArr(i)).Range("A" & Rows.Count).End(xlUp).Row
For Each Cel In Sheets(nameShtArr(i)).Range("A1:A" & lRow)
Dim fndCel As Range
Set fndCel = shI.Range("B:B").Find(Cel.Value)
If Not fndCel Is Nothing Then
fndCel.Offset(, 1).Resize(, 10).Copy Cel.Offset(, 1)
End If
Next Cel
Next i
shS.Cells.AutoFilter
This code is working to copy the filtered data of "Award" column marked "Yes" to another sheet; however, I'm receiving an error of "Type Mismatch." I'm not 100% now that the code is working properly to filter the data and copy correctly. I currently have 23 rows of test data for proper functionality. If I only put one row of data, then it doesn't copy and paste the data correctly. I am left with the copied 1st row of data plus the 2nd empty row of data. Additionally, it is not clearing the contents of the rows after the paste, so I may add new data as the days progress.
Sub CopySheet()
Dim i As Integer
Dim LastRow As Integer
Dim Search As String
Dim Column As Integer
Sheets("MasterData").Activate
Sheets("MasterData").Range("A1").Select
'Sets an Autofilter to sort out only your Yes rows.
Selection.AutoFilter
'Change Field:=5 to the number of the column with your Y/N.
Sheets("MasterData").Range("$A$1:$G$200000").AutoFilter Field:=7, Criteria1:="Yes"
'Finds the last row
LastRow = Sheets("MasterData").Cells(Sheets("MasterData").Rows.Count, "A").End(xlUp).row
i = 1
'Change the 3 to the number of columns you got in Sheet2
Do While i <= 11
Search = Sheets("ActiveJobStatus").Cells(1, i).Value
Sheets("MasterData").Activate
'Update the Range to cover all your Columns in MasterData.
If IsError(Application.Match(Search, Sheets("MasterData").Range("A1:G1"), 0)) Then
'nothing
Else
Column = Application.Match(Search, Sheets("MasterData").Range("A1:G1"), 0)
Sheets("MasterData").Cells(2, Column).Resize(LastRow, 1).Select
Selection.Copy
Sheets("ActiveJobStatus").Activate
Sheets("ActiveJobStatus").Cells(2, i).Select
ActiveSheet.Paste
End If
i = i + 1
Loop
'Clear all Y/N = Y
'Update the Range to cover all your Columns in MasterData.
Sheets("MasterData").Activate
Column = Application.Match("Award", Sheets("MasterData").Range("A1:F1"), 0)
Sheets("MasterData").Cells(2, Column).Resize(LastRow, 1).Select
Selection.ClearContents
End Sub
Sorry to change your code up so much, but it looks like you might be over-complicating how to do it.
This is some code from a previous question I answered where someone wanted to highlight a specific range whenever the word "Total" was found.
I changed the find to "Yes". Change the SearchRange to your column. (I think G is right).
Also, for future reference, Select should [almost never] be used.
It slows down code execution quite a bit and is not required.
I know the macro recorder likes to use it, but everything can be referenced without using select.
Brief example:
Sheets("ActiveJobStatus").Activate
Sheets("ActiveJobStatus").Cells(2, i).Select
ActiveSheet.Paste
Can Be replaced by:
Sheets("ActiveJobStatus").Cells(2, i).Paste
This code is working to copy the filtered data of "Award" column marked "Yes" to another sheet.
Sub CopyAwardsToActiveJobStatusSheet()
Dim SearchRange, First, Finder As Range
Dim PasteRow as Integer 'Add this to increment the rows we paste your data to
Set SearchRange = Sheets("MasterData").Range("G:G") 'Search This Range for "Yes"
Set Finder = SearchRange.Find("Yes") 'This is what we're looking for
If Finder Is Nothing Then Exit Sub 'We didn't find any "Yes" so we're done
'Drastically increases speed of every macro ever
'(well, when the sheets are modified at least - and it doesn't hurt)
Application.ScreenUpdating = False
First = Finder.Address 'Grab the address of the first "Yes" so we know when to stop
'Get the last row of column "A" on ActiveJobStatusSheet and start pasting below it
PasteRow = Sheets("ActiveJobStatus").Cells(Sheets("ActiveJobStatus").Rows.Count, "A").End(xlUp).Row + 1
Do
'Copy the entire row and paste it into the ActiveJobStatus sheet
'Column A and PasteRow (the next empty row on the sheet)
'You can change these if needed
Finder.EntireRow.Copy Sheets("ActiveJobStatus").Range("A" & PasteRow)
'If you just want A:G, you can use this instead:
'Finder returns the cell that contains "Yes",
'So we offset/resize to get the 6 cells before it and just copy that
'Resize doesn't like negative numbers so we have to combine:
'Finder.Offset(,-6).Resize(,7).Copy Sheets("ActiveJobStatus").Range("A" & PasteRow)
'Look for the next "Yes" after the one we just found
Set Finder = SearchRange.FindNext(after:=Finder)
PasteRow = PasteRow + 1 'Faster than looking for the end again
'Do this until we are back to the first address
Loop While Not Finder Is Nothing And Finder.Address <> First
'Clear MasterData
Sheets("MasterData").Range("A2:G" & Sheets("MasterData").UsedRange.Rows.Count).ClearContents
Application.ScreenUpdating = True 'Drastically increases speed of every macro ever.
End Sub
Just the code:
Sub CopyAwardsToActiveJobStatusSheet()
Dim SearchRange, First, Finder As Range
Dim PasteRow as Integer
Set SearchRange = Sheets("MasterData").Range("G:G")
Set Finder = SearchRange.Find("Yes")
If Finder Is Nothing Then Exit Sub
Application.ScreenUpdating = False
First = Finder.Address
PasteRow = Sheets("ActiveJobStatus").Cells(Sheets("ActiveJobStatus").Rows.Count, "A").End(xlUp).Row + 1
Do
Finder.EntireRow.Copy Sheets("ActiveJobStatus").Range("A" & PasteRow)
Set Finder = SearchRange.FindNext(after:=Finder)
PasteRow = PasteRow + 1
Loop While Not Finder Is Nothing And Finder.Address <> First
Sheets("MasterData").Range("A2:G" & Sheets("MasterData").UsedRange.Rows.Count).ClearContents
Application.ScreenUpdating = True
End Sub
Results:
MasterData Sheet:
ActiveJobStatus Sheet: