Sub Main()
Dim calc As Integer, a, e, ms As Worksheet, ws As Worksheet
Dim r As Range, c As Range, cn As Integer, rc As Range, rt As Range
Dim d As Double
d = Timer
'******************* INPUT ***********************************
Set ms = Worksheets("Master")
cn = 11 'Title columns to copy from row 1, 11=K.
'******************* END INPUT *******************************
With Application
.ScreenUpdating = False
.EnableEvents = False
calc = .Calculation
.Calculation = xlCalculationManual
End With
On Error GoTo EndSub
With ms
Set rc = .Range("A1", .Cells(1, cn)) 'Title row
Set r = .Range("B2", .Cells(Rows.Count, "B").End(xlUp))
a = UniqueArrayByDict(r.Value)
a = ArrayListSort(a)
For Each e In a
'Create worksheet if needed.
If Not WorkSheetExists(CStr(e)) Then
Worksheets.Add after:=Worksheets(Worksheets.Count)
ActiveSheet.Name = e
rc.Copy Worksheets(e).[a1]
End If
'Setup autofilter
Set ws = Worksheets(e)
.UsedRange.AutoFilter 2, e
'Copy and paste found data.
Set r = .Range("A2:A" & .Cells(.Rows.Count, "B").End(xlUp).Row).Resize(, cn).SpecialCells(xlCellTypeVisible)
Set rt = ws.Cells(Rows.Count, "A").End(xlUp).Offset(1)
r.Copy
rt.PasteSpecial xlPasteColumnWidths
r.Copy rt
r.Delete xlUp
Next e
End With
EndSub:
On Error Resume Next
ms.AutoFilterMode = False
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = calc
.CutCopyMode = False
End With
Debug.Print Timer - d
End Sub
'WorkSheetExists in a workbook:
Function WorkSheetExists(sWorkSheet As String, Optional sWorkbook As String = "") As Boolean
Dim ws As Worksheet, wb As Workbook
On Error GoTo notExists
If sWorkbook = "" Then
Set wb = ActiveWorkbook
Else
Set wb = Workbooks(sWorkbook) 'sWorkbook must be open already. e.g. ken.xlsm, not x:\ken.xlsm.
End If
Set ws = wb.Worksheets(sWorkSheet)
WorkSheetExists = True
Exit Function
notExists:
WorkSheetExists = False
End Function
'Early Binding method requires Reference: MicroSoft Scripting Runtime, scrrun.dll
Function UniqueArrayByDict(Array1d As Variant, Optional compareMethod As Integer = 0) As Variant
Dim dic As Object 'Late Binding method - Requires no Reference
Set dic = CreateObject("Scripting.Dictionary") 'Late or Early Binding method
'Dim dic As Dictionary 'Early Binding method
'Set dic = New Dictionary 'Early Binding Method
Dim e As Variant
dic.CompareMode = compareMethod
'BinaryCompare=0
'TextCompare=1
'DatabaseCompare=2
For Each e In Array1d
If Not dic.Exists(e) Then dic.Add e, Nothing
Next e
UniqueArrayByDict = dic.Keys
End Function
Function ArrayListSort(a As Variant, Optional bAscending As Boolean = True)
With CreateObject("System.Collections.ArrayList")
Dim cl
For Each cl In a
.Add cl
Next
.Sort 'Sort ascendending
If bAscending = False Then .Reverse 'Sort and then Reverse to sort descending
ArrayListSort = .Toarray()
End With
End Function