Create sheets based on unique values in rows based on Primary Key - excel

I am trying to populate multiple sheets based on the given data (attached Samplesheet SampleSheet.xlsx) as per the below rules:
Customer Code is the primary key, there should be each sheet for each unique customer code.
The new sheets should be named as "CustomerCode_Leads"
Every worksheet should have same headers.
I have started up with a logic and build a code behind but am lacking the knowledge on how to read the customer code data line by line, copy the rows with the same customer code and paste it in the sheet based on unique customer code.
Code written so far:
Sub Test()
Dim ws1 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Data")
ws1.Copy ThisWorkbook.Sheets(Sheets.Count)
Selection.AutoFilter
Selection.End(xlDown).Select
ActiveCell.Offset(1, 0).Select
ActiveCell.EntireRow.Select
Selection.Delete Shift:=xlUp
Application.Goto Reference:="R2C2"
ActiveCell.EntireColumn.Select
Selection.Copy
Sheets.Add After:=ActiveSheet
ActiveSheet.Paste
Application.CutCopyMode = False
ActiveSheet.Range("$A$1:$A$5000").RemoveDuplicates Columns:=1, Header:=xlYes
Dim CurSheet As Worksheet
Dim Source As Range
Dim c As Range
Set CurSheet = ActiveSheet
Set Source = Selection.Cells
Application.ScreenUpdating = False
For Each c In Source
sName = Trim(c.Text)
If Len(sName) > 0 Then
Worksheets.Add After:=Worksheets(Worksheets.Count)
ActiveSheet.Name = sName + "_Leads"
End If
Next c
End Sub
Output Desired:
Can someone advise how to read the data row by row and paste it in a new worksheet named "CustomerCode_Lead" where "CustomerCode" is a variable with some values in the Data sheet.
The algorithm that I am following is:
Copy the datasheet and paste it into a new worksheet
Sort the data in ascending order based on Customer Code (it'll bring all the similar customer code together and ease the row by row reading)
Read the data row by row and copy the entire row and paste into a new sheet until the customer code stays the same, once different code arrives in the next row, it creates a new sheet named "CustomerCode_Leads"
Do the reading of data until the end of the data in the "Data" sheet.
I would absolutely thank you in advance for the help I'll get here from the community. :)

This is all you need:
Get all unique values of customer ID column
Filter data and copy to another sheet
It could look like below:
Option Explicit
Public Sub SplitDataByCustomerIntoSheets()
Dim wsData As Worksheet
Set wsData = ThisWorkbook.Worksheets("Data")
Dim LastRow As Long
LastRow = wsData.Cells(wsData.Rows.Count, "A").End(xlUp).Row
'creat unique list of customer codes (https://stackoverflow.com/questions/36044556/quicker-way-to-get-all-unique-values-of-a-column-in-vba)
Dim UniqueValues() As Variant
UniqueValues = wsData.Range("A2:A" & LastRow).Value
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Dim iRow As Long
For iRow = 1 To UBound(UniqueValues)
dict(UniqueValues(iRow, 1)) = Empty
Next
UniqueValues = WorksheetFunction.Transpose(dict.Keys())
'check if filter was already set
If wsData.FilterMode = False Then
wsData.Range("A1").AutoFilter
Else
wsData.ShowAllData
End If
Dim CustomerID As Variant
For Each CustomerID In UniqueValues 'loop through all customer IDs
With wsData.Range("A1:B" & LastRow) 'make sure to adjust B to the last column of your data
.AutoFilter Field:=1, Criteria1:=CustomerID 'filter by customer ID
'create a new sheet as last sheet and name it by customer ID
Dim NewSheet As Worksheet
Set NewSheet = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count))
NewSheet.Name = CustomerID & "_Leads"
'copy visible cells of filtered data to new sheet
.SpecialCells(xlCellTypeVisible).Copy NewSheet.Range("A1")
End With
Next CustomerID
End Sub
Data sheet:
It will create a sheet for each customer ID like this:

Related

Looking to find the last row on my sheet where there is another record of it, then copy and paste data below

I am in the process of trying to create a Macro so that we can press a button and it updates the whole sheet.
Essentially all my data is being collected from another workbook, but it has to be non macro hence all my data is pulling through to my sheet Do Not Delete.
I have got my Macro to cycle through and copy/paste as values onto another sheet and remove all the rows that contain the text '#VALUE!'.
I have tried searching around on how to do this, but to no avail. I am trying to find out how to search each row on the 'Do Not Delete' sheet for the value that is in Column G on each row for anywhere that this exists elsewhere in the workbook, but I am unable to do this. From the point that I find the last record where it exists, I want to then copy down from there onwards.
Sub CopyToSheet()
'
' CopyToSheet Macro
Dim wb As Workbook
Dim ws, wscopy, wsdnd As Worksheet
Dim i, LastRowa, LastRowd As Long
Dim WSheet As String
Dim SheetName As String
Set wsdnd = Sheets("Do Not Delete")
Set wscopy = Sheets("CopyAndClear")
Set wb = ActiveWorkbook
Set ws = ActiveWorkbook.Sheets("Macro - Do not delete")
'Finding Sheet to use
SheetName = Range("L2")
Debug.Print Range("L2")
'Clear Contents
wscopy.Activate
wscopy.Cells.Clear
'Activating Do Not Delete Sheet to copy the data
wsdnd.Activate
LastRowa = wsdnd.Cells(Rows.Count, "A").End(xlUp).Row
wsdnd.Range("A1:IP" & LastRowa).Select
wsdnd.Range("A1:IP" & LastRowa).Copy
'Copy and paste cells onto new sheet
wscopy.Activate
wscopy.Range("A1").PasteSpecial xlPasteValues
Application.CutCopyMode = False
'Apply Filter
Application.DisplayAlerts = False
LastRowc = wscopy.Cells(Rows.Count, "A").End(xlUp).Row
wscopy.Range("A1:IP" & LastRowc).AutoFilter Field:=1, Criteria1:="#VALUE!"
'Delete Rows
wscopy.Range("A1:IP" & LastRowc).SpecialCells(xlCellTypeVisible).Delete
'Clear Filter
On Error Resume Next
wscopy.ShowAllData
On Error GoTo 0
End Sub

Is there a way to create a loop that loops through a set of code then offsets a certain number on the next loops

I am new to VBA. I am trying to input values from multiple sheets into a "header" block that I have created on my master spreadsheet. I have multiple sheets with the same information but specific to that set of data. I have figured out how to do the first header block from the first sheet of data. Now I am wondering if I can create a loop that offsets the information a certain amount and input the information for the next remaining sheets. If possible I want it to not depend on how many sheets are imported. Whether 1 sheet or 50 sheets. Thanks!
Here is my code:
Private Sub Generate_Click()
'Set Header info for Raw Data
'Program Name Entry Sheet 2
ActiveSheet.Next.Activate
Dim Part As Range
Set Part = ActiveSheet.Range("B1:B10").Find("Part Name")
Part.Offset(0, 1).Select
Selection.Copy
Sheets("Variable Data").Select
Dim PName As Range
Set PName = ActiveSheet.Range("A1:AA10").Find("Program Name")
PName.Offset(0, 1).Select
ActiveSheet.Paste
'Program Rev Entry Sheet 2
ActiveSheet.Next.Activate
Dim Rev As Range
Set Rev = ActiveSheet.Range("B1:B10").Find("Revision Number")
Rev.Offset(0, 1).Select
Selection.Copy
Sheets("Variable Data").Select
Dim PRev As Range
Set PRev = ActiveSheet.Range("A1:AA10").Find("Program Rev")
PRev.Offset(0, 1).Select
ActiveSheet.Paste
'Program Date Entry Sheet 2
ActiveSheet.Next.Activate
Dim PDate As Range
Set PDate = ActiveSheet.Range("B1:B10").Find("Date")
PDate.Offset(0, 1).Select
Selection.Copy
Sheets("Variable Data").Select
Dim RDate As Range
Set RDate = ActiveSheet.Range("A1:AA10").Find("Run Date")
RDate.Offset(0, 1).Select
ActiveSheet.Paste
'Program Lot Entry Sheet 2
ActiveSheet.Next.Activate
Dim Serial As Range
Set Serial = ActiveSheet.Range("B1:B10").Find("Serial Number")
Serial.Offset(0, 1).Select
Selection.Copy
Sheets("Variable Data").Select
Dim Lot As Range
Set Lot = ActiveSheet.Range("A1:AA10").Find("Lot Number")
Lot.Offset(0, 1).Select
ActiveSheet.Paste
End Sub
EDIT: you can take an approach like this
Private Sub Generate_Click()
'Set Header info for Raw Data
Dim wb As Workbook, ws As Worksheet, wsVD As Worksheet
Dim rngVDHeaders As Range, rowOffset As Long
Set wb = ThisWorkbook
'summary sheet and headers
Set wsVD = wb.Worksheets("Variable Data")
Set rngVDHeaders = wsVD.Range("A1:AA10")
rowOffset = 1 'starting offset from header row
'loop over all worksheets
For Each ws In wb.Worksheets
'excluding the summary sheet
If ws.Name <> wsVD.Name Then
'find and copy values to summary sheet
With ws.Range("B1:B10")
.Find("Part Name").Copy rngVDHeaders.Find("Program Name").Offset(rowOffset, 0)
.Find("Revision Number").Copy rngVDHeaders.Find("Program Rev").Offset(rowOffset, 0)
.Find("Date").Copy rngVDHeaders.Find("Run Date").Offset(rowOffset, 0)
.Find("Serial Number").Copy rngVDHeaders.Find("Lot Number").Offset(rowOffset, 0)
End With
End If
rowOffset = rowOffset + 1 'next line down
Next ws
End Sub

Extract unique values to separate sheet based on values in another column

I'm sure this has already been answered elsewhere but I just can't find it (or get what I've found to work for me).
Col "A" is a list of items with many duplicates.
In Col "B" I've placed an "X" for the items in Col "A" that I'm interested in.
What I'd like to get out of this on a separate sheet is a list of unique values for only the items on the list where there's an "X" in Col "B".
Values only would be a plus.
If your sheet has headers, the below might work for you.
If your sheet doesn't have headers, you could modify the code so that it inserts a row first.
Option Explicit
Private Sub FilterAndPasteUniques()
Dim sourceSheet As Worksheet
Set sourceSheet = ThisWorkbook.Worksheets("Sheet1") ' Change to whatever yours is called
Dim lastSourceRow As Long
lastSourceRow = sourceSheet.Cells(sourceSheet.Rows.Count, "A").End(xlUp).Row
Dim toFilterIncludingHeaders As Range
Set toFilterIncludingHeaders = sourceSheet.Range("A1", "B" & lastSourceRow)
toFilterIncludingHeaders.AutoFilter Field:=2, Criteria1:="X"
Dim cellsToCopy As Range
On Error Resume Next
Set cellsToCopy = toFilterIncludingHeaders.Offset(1).Resize(toFilterIncludingHeaders.Rows.CountLarge - 1, 1).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If Not (cellsToCopy Is Nothing) Then
cellsToCopy.Copy
Dim destinationSheet As Worksheet
Set destinationSheet = ThisWorkbook.Worksheets("Sheet2") ' Change to whatever yours is called
With destinationSheet.Range("A1")
.PasteSpecial xlPasteValuesAndNumberFormats
.Resize(cellsToCopy.Rows.CountLarge, cellsToCopy.Columns.CountLarge).RemoveDuplicates Columns:=1, Header:=xlNo
End With
End If
sourceSheet.AutoFilterMode = False
Application.CutCopyMode = False
End Sub

Creating a Loop Through 4 worksheets Paste not working

Hi guys I'm doing a course for Udemy and the lecturer unfortunately has not been the most responsive.
I have a workbook called QuarterlyReport and 5 sheets.
East Records
West Records
North Records
South Records
Yearly Report
My code formats the Worksheets 1-4 and then copy pastes the information to Yearly Report on the last unused row. For some reason, the code is only pasting South Records. My goal is to copy every single sheet 1 - 4 and paste it onto the fifth sheet "YEARLY REPORT".
Public Sub Finalreportloop()
Dim i As Integer
i = 1
Do While i <= Worksheets.Count - 1
Worksheets(i).Select
AddHeaders
FormatData
AutoSum
' copy the current data
Range("A1").Select
Selection.CurrentRegion.Select
Selection.Copy
' select the final report WS'
Worksheets("yearly report").Select
'find the empty cells
LastRow = Sheets(i).Range("A" & Sheets(i).Rows.Count).End(xlUp).Row
'paste the new data in
ActiveSheet.Paste
i = i + 1
Loop
End Sub
The Addheaders, FormatData and AutoSum are in reference to other Modules I've created. Thank you everyone!
The code determines the last row of the sheet that you are copying from, but you don't do anything with that information. Instead, it just pastes into the active sheet and overwrites the data posted in the last loop instance. Hence it looks as if it is only copying/pasting the last data set.
You need to find the last row in the Yearly sheet, then paste the data below that.
You coudld try one of the methods below:
Option Explicit
Sub test()
Dim ws As Worksheet
Dim wsLastRow As Long, wsLastColumn As Long, yrLastRow As Long
Dim rngCopy As Range
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> "YEARLY REPORT" Then
With ws
'Method 1 - You can siply used range
' .UsedRange.Copy
'Method 2 - You can calculate LastColumn & LastRow and create the range
wsLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row '<- Find last row of column A.
wsLastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column '<- Find the last column of row 1.
Set rngCopy = .Range(Cells(1, 1), Cells(wsLastRow, wsLastColumn)) '<- Create the range to be copy.
rngCopy.Copy
End With
With ThisWorkbook.Worksheets("YEARLY REPORT")
yrLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row '<- Find last row of column A.
.Range("A" & yrLastRow + 1).PasteSpecial xlPasteValues
End With
End If
Application.CutCopyMode = False
Next ws
End Sub

Copy rows in Excel if cell contains name from an array

I have an Excel sheet that contains entries for ~150 employees. Each row contains the name as well as hours worked, pay, team, etc etc etc etc. The B column in each row contains the employees name in Last,First format. About half the employees on the sheet are part time employees. What i'm trying to do is write a macro in VB that copies the entire row if the name in the B column matches one of the names of the part time employees so that one of my coworkers can simply run the macro and paste all of the rows of copied users into a new sheet each week. Here's what I currently have. (I have all of the employees names in the array however I have censored them out) I really don't understand much of the last 50% of the code. This stuff was stuff I found online and have been messing around with.
`Sub PartTime()
Dim strArray As Variant
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim NoRows As Long
Dim DestNoRows As Long
Dim I As Long
Dim J As Integer
Dim rngCells As Range
Dim rngFind As Range
Dim Found As Boolean
nameArray = Array(NAMES CENSORED)
Set wsSource = ActiveSheet
NoRows = wsSource.Range("A65536").End(xlUp).Row
DestNoRows = 1
Set wsDest = ActiveWorkbook.Worksheets.Add
For I = 1 To NoRows
Set rngCells = wsSource.Range("C" & I & ":F" & I)
Found = False
For J = 0 To UBound(strArray)
Found = Found Or Not (rngCells.Find(strArray(J)) Is Nothing)
Next J
If Found Then
rngCells.EntireRow.Copy wsDest.Range("A" & DestNoRows)
DestNoRows = DestNoRows + 1
End If
Next I
End Sub`
This code should work for what you are looking for. It is important to note that the string names in your array must be identical to that in Column B (with the exception of leading and trailing spaces), so if the names are written "LastName, FirstName" then your input data must be identical. This code could be tweaked to not have this requirement, but for now I've left it as such. Let me know if you'd prefer the code be adjusted.
Option Explicit
Sub PartTimeEmployees()
Dim NewSheet As Worksheet, CurrentSheet As Worksheet, NameArray As Variant
Set CurrentSheet = ActiveWorkbook.ActiveSheet
Set NewSheet = Sheets.Add(After:=Sheets(Worksheets.Count))
NewSheet.Name = "Part Time Employees"
NameArray = Array("NAMES CENSORED")
'Pulling headers from the first row
CurrentSheet.Rows(1).EntireRow.Copy
NewSheet.Select 'Redundant but helps avoid the occasional error
NewSheet.Cells(1, 1).Select
ActiveSheet.Paste
CurrentSheet.Select
Dim NextRow As Long
NextRow = 2
'Writing this code to not assume that the data is continuous
Dim Count As Long
'Iterating to the end of the data in the sheet
For Count = 2 To CurrentSheet.UsedRange.Rows.Count
If Not IsEmpty(CurrentSheet.Cells(Count, 2)) Then
For Counter = 1 To UBound(NameArray)
'Performing string operations on the text will be faster than the find method
'It is also essential that the names are entered identically in your array
If UCase(Trim(CurrentSheet.Cells(Count, 2).Value)) = UCase(NameArray(Counter)) Then
CurrentSheet.Rows(Count).Copy
NewSheet.Select
NewSheet.Cells(NextRow, 1).Select
ActiveSheet.Paste
CurrentSheet.Select
NextRow = NextRow + 1
Exit For
End If
Next Counter
End If
Next Count
End Sub
No need to loop through the array if you use a Range.AutoFilter Method with the array as criteria.
See comment for each line of operational code.
Option Explicit
Sub partTimers()
Dim nameArray As Variant
'construct an array of the part-time employees' names
nameArray = Array("Trgh, Evtfk", "Mtre, Sdnrm", _
"Sfgd, Pxduj", "Lsds, Qwrml", _
"Eqrd, Oqtts")
With Worksheets("Sheet1") 'you should know what worksheet the names are on
'turn off AutoFilter is there is one already in operation
If .AutoFilterMode Then .AutoFilterMode = False
'use the 'island' of cells radiating out from A1
With .Cells(1, 1).CurrentRegion
'apply AutoFilter using array of names as criteria
.AutoFilter field:=2, Criteria1:=nameArray, Operator:=xlFilterValues
'check if there is anything to copy
If Application.Subtotal(103, .Columns(2)) > 1 Then
'copy the filtered range
.Cells.Copy
'create a new worksheet
With .Parent.Parent.Worksheets.Add(After:=Sheets(Sheets.Count))
'paste the filtered range, column widths and cell formats
.Cells(1, 1).PasteSpecial Paste:=xlPasteColumnWidths
.Cells(1, 1).PasteSpecial Paste:=xlPasteFormats
.Cells(1, 1).PasteSpecial Paste:=xlPasteValues
End With
End If
End With
'turn off the AutoFilter
If .AutoFilterMode Then .AutoFilterMode = False
'turn off active copy range
Application.CutCopyMode = False
End With
End Sub

Resources