Hi Andy,
I've rewritten your code a bit, because it's easier to refer and use the objects.
BTW, a "On Error Resume Next" in the main routine is a bad idea, because you did not get noticed of any error, e.g. your code creates the Pivot table twice.
I did not move the detail sheets when they are created, for me it's easier if we sort all the sheets if we're done.
All your states have a number in front, therefore IMHO it is better if we rename the detail sheets as "[EmployeeName] [Statenumber]".
In that way you can change/add states very easy.
I renamed also the table inside the detail sheet to reflect the sheet name, so if you want to use that table later for analysis you can sue the sheet name without blanks to get the table.
Andreas.
Option Explicit
Sub InsertPivotTable()
'Declare Variables
Dim PSheet As Worksheet, DSheet As Worksheet, NSheet As Worksheet
Dim PCache As PivotCache
Dim PTable As PivotTable
Dim PEmployee As PivotField, PStatus As PivotField
Dim PItem As PivotItem
Dim PRange As Range, Employee As Range, Item As Range
Dim State As Variant
Dim SName As String
Dim Table As ListObject
'Prepare
With Application
.DisplayAlerts = False
.EnableEvents = False
.ScreenUpdating = False
End With
'Define Data Ranges
Set DSheet = Worksheets("JobList")
Set PRange = DSheet.Range("A1").CurrentRegion
'Insert a New Blank Worksheet called "PivotTable"
If SheetExists("PivotTable") Then Sheets("PivotTable").Delete
Set PSheet = Sheets.Add(Before:=DSheet)
PSheet.Name = "PivotTable"
'Define Pivot Cache
Set PCache = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=PRange)
'Insert Blank Pivot Table
Set PTable = PCache.CreatePivotTable(TableDestination:=PSheet.Range("A3"), TableName:="PivotTable")
With PTable
'Insert Row Field "Employee Type" filtering out blanks
Set PEmployee = .PivotFields("Employee Type: Mitigation Review Specialist")
With PEmployee
.Orientation = xlRowField
.PivotItems("(blank)").Visible = False
End With
'Insert Column Field "Alternative Status" filtering out blanks, billed & received
Set PStatus = .PivotFields("Alternative Status")
With PStatus
.Orientation = xlColumnField
.PivotItems("01. Received").Visible = False
.PivotItems("08. Billed").Visible = False
.PivotItems("(blank)").Visible = False
End With
'Insert Data Field "Claim Number" as Count, captioned "Claims"
With .PivotFields("Claim Number")
.Orientation = xlDataField
.Function = xlCount
.Name = "Claims"
End With
'Format Pivot Table
.ShowTableStyleRowStripes = True
.TableStyle2 = "PivotStyleMedium9"
'Create the detail sheets
For Each State In Array("03. Placed in Review", "04. Negotiations Open")
Set PItem = PStatus.PivotItems(State)
For Each Item In PItem.DataRange
Set Employee = Intersect(PEmployee.DataRange, Item.EntireRow)
SName = ValidSheetName(Employee & " " & Left(PItem.Name, 2))
If SheetExists(SName) Then Sheets(SName).Delete
Item.ShowDetail = True
DoEvents
ActiveSheet.Name = SName
Set Table = ActiveSheet.ListObjects(1)
Table.Name = ValidTableName(SName)
Next
Next
End With
'Sort the sheets
SortSheets xlAscending, Array(DSheet.Name, PSheet.Name)
'Finish
PSheet.Select
PSheet.Range("A1").Select
With Application
.DisplayAlerts = True
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
Private Function ValidSheetName(ByVal SheetName As String) As String
'Removes invalid chars from Sheetname
Const InvalidChars = ":/?*[]"
Dim i As Integer
For i = 1 To Len(InvalidChars)
SheetName = Replace(SheetName, Mid(InvalidChars, i, 1), "")
Next
ValidSheetName = Mid(SheetName, 1, 31)
End Function
Private Function ValidTableName(ByVal TableName As String) As String
'Removes invalid chars from TableName
Const InvalidChars = ":/?*[] "
Dim i As Integer
For i = 1 To Len(InvalidChars)
TableName = Replace(TableName, Mid(InvalidChars, i, 1), "")
Next
ValidTableName = Mid(TableName, 1, 255)
End Function
Private Function SheetExists(ByVal SheetNameOrIndex As Variant, Optional ByVal Wb As Workbook = Nothing) As Boolean
'True if sheet SheetNameOrIndex exists
On Error Resume Next
If Wb Is Nothing Then Set Wb = ActiveWorkbook
SheetExists = Not Wb.Sheets(SheetNameOrIndex) Is Nothing
End Function
Private Sub SortSheets(Optional SortOrder As XlSortOrder = xlAscending, _
Optional SortToLeft, Optional SortToRight)
'Sorts the worksheets by SortToLeft/SortToRight and _
others in the middle alphabetically by name
Dim i As Integer, j As Integer
Dim SaveSelectedSheets, SaveScreenUpdating, SaveEnableEvents
With Application
SaveScreenUpdating = Application.ScreenUpdating
Application.ScreenUpdating = False
SaveEnableEvents = Application.EnableEvents
Application.EnableEvents = False
End With
Set SaveSelectedSheets = ActiveWindow.SelectedSheets
For i = 1 To Sheets.Count
For j = i + 1 To Sheets.Count
If (StrComp(Sheets(j).Name, Sheets(i).Name, vbTextCompare) < 0) = _
(SortOrder = xlAscending) Then
If Sheets(j).Visible = xlSheetVisible Then
If SortOrder = xlAscending Then Sheets(j).Move Before:=Sheets(i)
End If
End If
Next
Next
On Error Resume Next
Select Case TypeName(SortToLeft)
Case "Variant()"
For i = UBound(SortToLeft) To LBound(SortToLeft) Step -1
If Sheets(CStr(SortToLeft(i))).Visible = xlSheetVisible Then
Sheets(CStr(SortToLeft(i))).Move Before:=Sheets(1)
End If
Next
Case "String"
If Sheets(CStr(SortToLeft)).Visible = xlSheetVisible Then _
Sheets(CStr(SortToLeft)).Move Before:=Sheets(1)
End Select
Select Case TypeName(SortToRight)
Case "Variant()"
For i = LBound(SortToRight) To UBound(SortToRight)
If Sheets(CStr(SortToRight(i))).Visible = xlSheetVisible Then
Sheets(CStr(SortToRight(i))).Move After:=Sheets(Sheets.Count)
End If
Next
Case "String"
If Sheets(CStr(SortToRight)).Visible = xlSheetVisible Then _
Sheets(CStr(SortToRight)).Move After:=Sheets(Sheets.Count)
End Select
SaveSelectedSheets.Select
ActiveWindow.ScrollWorkbookTabs Position:=xlFirst
ActiveWindow.ScrollWorkbookTabs SaveSelectedSheets.Item(1).Index - 1
With Application
Application.ScreenUpdating = SaveScreenUpdating
Application.EnableEvents = SaveEnableEvents
End With
End Sub