Hello, and thanks in advance for any help.
I have a giant list of social security numbers, about 30,000 rows. I use a function to get the first five digits of the social security number in Column D. I can't have more then 4 rows with the first five digits on the same sheet. Currently I run the code below that sorts the list then separates the five digit code to new worksheets with four rows per worksheet and names them sequentially ie 10660_1, 10660_2, 10660_3 etc.
Sub Stack()
Const ROWS_PER_SHEET As Long = 4
Const COL_ID As Long = 4
Dim Lastrow As Long, LastCol As Long, i As Long
Dim ws As Worksheet, wsData As Worksheet, wb As Workbook
Dim currId, n As Long, id, idSeq As Long
Application.ScreenUpdating = False
Set wb = ActiveWorkbook
Set wsData = ActiveSheet
With wsData
Lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 1), .Cells(Lastrow, LastCol)).Sort Key1:=.Cells(2, COL_ID), Order1:=xlAscending, _
Header:=xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
currId = Chr(10) 'any non-existing id...
For i = 2 To Lastrow
id = .Cells(i, COL_ID).Value
If id <> currId Or n = ROWS_PER_SHEET Then 'new id or reached ROWS_PER_SHEET limit?
Set ws = wb.Sheets.Add(after:=wb.Sheets(wb.Sheets.Count))
'copy headers
ws.Cells(1, 1).Resize(1, LastCol).Value = .Cells(1, 1).Resize(1, LastCol).Value
If id <> currId Then
idSeq = 1 'new id: reset sequence for sheet name suffix
currId = id
Else
idSeq = idSeq + 1 'same id: increment sequence for sheet name suffix
End If
ws.Name = currId & "_" & idSeq
n = 0 'reset row count for this sheet
End If
n = n + 1
'copy this row
ws.Range("A1").Offset.Resize(1, LastCol).Value = .Cells(i, 1).Resize(1, LastCol).Value
Next i
End With
Application.ScreenUpdating = True
End Sub
I then run a second code, below, to compile these tabs onto five separate sheets based on the suffix ie 10660_1 is copied to a worksheet named First Upload, 10660_2 is copied to a worksheet named Second upload. I have five of these worksheets (First Upload - Fifth Upload) and that is enough, I usually have less then 16 of the same first five digits.
Sub Stack2()
Dim Sheet As Worksheet
Dim TargetRow As Long
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
TargetRow = 1
For Each Sheet In ActiveWorkbook.Sheets
If Sheet.Name Like "*" & strSearch & "_1" Then
Sheets(Sheet.Name).Range("A2:E5").Copy
With ThisWorkbook.Sheets("First Upload").Cells(TargetRow, 1)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
End With
TargetRow = TargetRow + 4
End If
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
TargetRow = 1
For Each Sheet In ActiveWorkbook.Sheets
If Sheet.Name Like "*" & strSearch & "_2" Then
Sheets(Sheet.Name).Range("A2:E5").Copy
With ThisWorkbook.Sheets("Second Upload").Cells(TargetRow, 1)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
End With
TargetRow = TargetRow + 4
End If
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
TargetRow = 1
For Each Sheet In ActiveWorkbook.Sheets
If Sheet.Name Like "*" & strSearch & "_3" Then
Sheets(Sheet.Name).Range("A2:E5").Copy
With ThisWorkbook.Sheets("Third Upload").Cells(TargetRow, 1)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
End With
TargetRow = TargetRow + 4
End If
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
TargetRow = 1
For Each Sheet In ActiveWorkbook.Sheets
If Sheet.Name Like "*" & strSearch & "_4" Then
Sheets(Sheet.Name).Range("A2:E5").Copy
With ThisWorkbook.Sheets("Fourth Upload").Cells(TargetRow, 1)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
End With
TargetRow = TargetRow + 4
End If
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
TargetRow = 1
For Each Sheet In ActiveWorkbook.Sheets
If Sheet.Name Like "*" & strSearch & "_5" Then
Sheets(Sheet.Name).Range("A2:E5").Copy
With ThisWorkbook.Sheets("Fifth Upload").Cells(TargetRow, 1)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
End With
TargetRow = TargetRow + 4
End If
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
This takes a very long time, usually 1.5 hours and excel freezes.
Is there a better way to do this? I have been thinking that simply sorting based on the five digit number in Column D, then copying the first four rows to the First Upload tab, the second four rows to the Second Upload tab etc then after Fifth upload looping back to the First Upload tab and pasting below the data in that tab would result with unique first five digit numbers per tab. I have been trying to use offset to accomplish this but I am getting lost on how to utilize it.
Sorry for the long post. Any help with this would be greatly appreciated. Thank you.
I have a giant list of social security numbers, about 30,000 rows. I use a function to get the first five digits of the social security number in Column D. I can't have more then 4 rows with the first five digits on the same sheet. Currently I run the code below that sorts the list then separates the five digit code to new worksheets with four rows per worksheet and names them sequentially ie 10660_1, 10660_2, 10660_3 etc.
Sub Stack()
Const ROWS_PER_SHEET As Long = 4
Const COL_ID As Long = 4
Dim Lastrow As Long, LastCol As Long, i As Long
Dim ws As Worksheet, wsData As Worksheet, wb As Workbook
Dim currId, n As Long, id, idSeq As Long
Application.ScreenUpdating = False
Set wb = ActiveWorkbook
Set wsData = ActiveSheet
With wsData
Lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 1), .Cells(Lastrow, LastCol)).Sort Key1:=.Cells(2, COL_ID), Order1:=xlAscending, _
Header:=xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
currId = Chr(10) 'any non-existing id...
For i = 2 To Lastrow
id = .Cells(i, COL_ID).Value
If id <> currId Or n = ROWS_PER_SHEET Then 'new id or reached ROWS_PER_SHEET limit?
Set ws = wb.Sheets.Add(after:=wb.Sheets(wb.Sheets.Count))
'copy headers
ws.Cells(1, 1).Resize(1, LastCol).Value = .Cells(1, 1).Resize(1, LastCol).Value
If id <> currId Then
idSeq = 1 'new id: reset sequence for sheet name suffix
currId = id
Else
idSeq = idSeq + 1 'same id: increment sequence for sheet name suffix
End If
ws.Name = currId & "_" & idSeq
n = 0 'reset row count for this sheet
End If
n = n + 1
'copy this row
ws.Range("A1").Offset.Resize(1, LastCol).Value = .Cells(i, 1).Resize(1, LastCol).Value
Next i
End With
Application.ScreenUpdating = True
End Sub
I then run a second code, below, to compile these tabs onto five separate sheets based on the suffix ie 10660_1 is copied to a worksheet named First Upload, 10660_2 is copied to a worksheet named Second upload. I have five of these worksheets (First Upload - Fifth Upload) and that is enough, I usually have less then 16 of the same first five digits.
Sub Stack2()
Dim Sheet As Worksheet
Dim TargetRow As Long
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
TargetRow = 1
For Each Sheet In ActiveWorkbook.Sheets
If Sheet.Name Like "*" & strSearch & "_1" Then
Sheets(Sheet.Name).Range("A2:E5").Copy
With ThisWorkbook.Sheets("First Upload").Cells(TargetRow, 1)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
End With
TargetRow = TargetRow + 4
End If
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
TargetRow = 1
For Each Sheet In ActiveWorkbook.Sheets
If Sheet.Name Like "*" & strSearch & "_2" Then
Sheets(Sheet.Name).Range("A2:E5").Copy
With ThisWorkbook.Sheets("Second Upload").Cells(TargetRow, 1)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
End With
TargetRow = TargetRow + 4
End If
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
TargetRow = 1
For Each Sheet In ActiveWorkbook.Sheets
If Sheet.Name Like "*" & strSearch & "_3" Then
Sheets(Sheet.Name).Range("A2:E5").Copy
With ThisWorkbook.Sheets("Third Upload").Cells(TargetRow, 1)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
End With
TargetRow = TargetRow + 4
End If
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
TargetRow = 1
For Each Sheet In ActiveWorkbook.Sheets
If Sheet.Name Like "*" & strSearch & "_4" Then
Sheets(Sheet.Name).Range("A2:E5").Copy
With ThisWorkbook.Sheets("Fourth Upload").Cells(TargetRow, 1)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
End With
TargetRow = TargetRow + 4
End If
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
TargetRow = 1
For Each Sheet In ActiveWorkbook.Sheets
If Sheet.Name Like "*" & strSearch & "_5" Then
Sheets(Sheet.Name).Range("A2:E5").Copy
With ThisWorkbook.Sheets("Fifth Upload").Cells(TargetRow, 1)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
End With
TargetRow = TargetRow + 4
End If
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
This takes a very long time, usually 1.5 hours and excel freezes.
Is there a better way to do this? I have been thinking that simply sorting based on the five digit number in Column D, then copying the first four rows to the First Upload tab, the second four rows to the Second Upload tab etc then after Fifth upload looping back to the First Upload tab and pasting below the data in that tab would result with unique first five digit numbers per tab. I have been trying to use offset to accomplish this but I am getting lost on how to utilize it.
Sorry for the long post. Any help with this would be greatly appreciated. Thank you.