Sorting a variable number of pivot items in a pivot table

midoop

New Member
Joined
Aug 9, 2013
Messages
37
Hello all,
I am trying to have a pivot table that sorts the columns in a particular order. The issue is that if i use pivotitems.position = X, then I have to have a separate hidden function that tests to see if all the choices are there and if not then sort this way, and....well, I have 7 possible choices so trying to account for even half the combinations is not feasible. So then I tried making a sort variable dummy field, but then if I try to hide that so it doesn't display in the pivot table, the sort order goes back to default.

This is my attempt at some code. In this "IsItem" is calling a private boolean function:

Code:
If IsItem(ActiveSheet.PivotTables("All iCRF Status"), "iCRF Status", "Partial Monitored") _And IsItem(ActiveSheet.PivotTables("All iCRF Status"), "iCRF Status", "Reviewed") Then
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("No Data").Position = 1
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Incomplete").Position = 2
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Complete").Position = 3
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Partial Monitored").Position = 4
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Monitored").Position = 5
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Reviewed").Position = 6
    'ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Locked").Position = 7
ElseIf IsItem(ActiveSheet.PivotTables("All iCRF Status"), "iCRF Status", "Reviewed") Then
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("No Data").Position = 1
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Incomplete").Position = 2
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Complete").Position = 3
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Monitored").Position = 4
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Reviewed").Position = 5
    'ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Locked").Position = 6
Else
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("No Data").Position = 1
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Incomplete").Position = 2
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Complete").Position = 3
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status").PivotItems("Monitored").Position = 4
End If

This is just a few examples of what all combinations are possible. And as the data change, the combination possibilities will change, too.

ALL STATUS POSSIBILITIES AND ORDER
1. No Data
2. Incomplete
3. Complete
4. Partial Monitored
5. Monitored
6. Reviewed
7. Locked

Since STUDYNAME is newer it is really looking like this right now:

1. No Data
2. Incomplete
3. Complete
4. Partial Monitored
5. Monitored

And it looks like this in cases where there’s no partially monitored CRFs:

1. No Data
2. Incomplete
3. Complete
4. Monitored

Any and all help is very much appreciated! Thank you!
 

Excel Facts

Which Excel functions can ignore hidden rows?
The SUBTOTAL and AGGREGATE functions ignore hidden rows. AGGREGATE can also exclude error cells and more.
Hi

Right now I don´t have the time, but I´m planning to look into this tomorrow...
 
Upvote 0
Hi</SPAN></SPAN>
To write a VBA solution we basically need two things:</SPAN></SPAN>

  1. The necessary programming tools – you seem to have them. The position property will place the columns where needed, and the ‘Is Item’ function will tell if a particular item is present at the table. As you didn´t post it, I wrote my own.</SPAN></SPAN>

2. An algorithm that does what we want to accomplish. Could you elaborate more on what would be the input possibilities and the desired outcome? I got the general idea but not sure if this is a combinatory analysis problem.


Code:
Option Explicit
Option Base 1
Sub ReverseOrder()
Dim a, i%, p As PivotTable
Set p = ActiveSheet.PivotTables(1)
a = Array("Dec", "Nov", "Oct", "Sep", "Aug", "Jul", "Jun", "May", "Apr", "Mar", "Feb", "Jan")
For i = LBound(a) To UBound(a)
    p.PivotFields("Month").PivotItems(a(i)).Position = i
Next
End Sub
Function IsItem(p As PivotTable, pf$, pi$) As Boolean
Dim n$
IsItem = False
On Error Resume Next
Err.Clear
n = p.PivotFields(pf).PivotItems(pi).Name
If Err.Number = 0 Then IsItem = True
On Error GoTo 0
End Function
</SPAN></SPAN>
 
Upvote 0
Reply 1 of 2

This my code without trying to order the columns in the pivot table.

Code:
Sub CustomDataMetricsMDS()


'Define variables
Dim ws1 As Worksheet, ws2 As Worksheet, ws3 As Worksheet, ws4 As Worksheet
Dim myrows As Integer
Dim LRow As Long
Dim sLastValue As String
Dim cell As Range
Dim urrow As Long
Dim LH As String
Dim LastRow As Long


Application.ScreenUpdating = False


Set ws1 = ActiveSheet


'Add and name worksheets
With ActiveWorkbook.Worksheets
    Set ws2 = .Add(After:=ws1)
    ws2.Name = "Critical CRFs"
    Set ws3 = .Add(After:=ws2)
    ws3.Name = "All iCRF Status Metrics"
    Set ws4 = .Add(After:=ws3)
    ws4.Name = "Critical iCRF Status Metrics"
End With
  
'Format Source Sheet
ws1.Select
Range("1:4").Delete xlShiftUp
Range("A:A").Delete xlShiftToLeft
Range("B:B").Delete xlShiftToLeft
Range("C:C").Delete xlShiftToLeft




'Delete CRFs with no associated Patient ID
With ws1.Columns("A:N").Resize(ws1.UsedRange.Rows.Count)
    .AutoFilter 2, "="
    With .Offset(1).SpecialCells(xlCellTypeVisible)
        .EntireRow.Delete
    End With
    .AutoFilter
End With


'Deleting CRFs not needed for screen failures
With ws1.Columns("A:N").Resize(ws1.UsedRange.Rows.Count)
    .AutoFilter 13, "="
    .AutoFilter 7, "No Data"
    .AutoFilter 5, ">=300001"
     With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
         .EntireRow.Delete
     End With
     .AutoFilter
End With
       
myrows = WorksheetFunction.CountA(ws1.Range("A:A"))


For i = 2 To myrows
    If Cells(i, 8) = "Locked" Then
    Cells(i, 7) = "Locked"
    ElseIf Cells(i, 9) = "Reviewed" Then
    Cells(i, 7) = "Reviewed"
    Else
    End If
Next i


Range("H:N").Delete xlShiftToLeft


'Name worksheet and sort by visit and patient
With ws1
    .Name = "All iCRF Status"
    .Range("B1") = [{"Patient"}]
    .Range("C1") = [{"Visit"}]
    .Columns("A:G").Sort key1:=.Range("C2"), order1:=xlAscending, key2:=.Range("B2"), order2:=xlAscending, Header:=xlYes
End With
                  
'Label columns on worksheets 2
  With ws2.Cells(1).Resize(, 9)
     .Value = Array("Site", "Patient", "Visit", "Visit Date", "iCRF Sequence", "iCRF", "iCRF Status")
  End With


'Selecting and moving the AE data to the Critical CRFs sheet
    With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
        .AutoFilter 3, "Adverse Event"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .Copy ws2.Cells(2, 1)
        End With
        .AutoFilter
    End With
    
'Selecting and moving ConMed data to the Critical CRFs sheet


urrow = WorksheetFunction.CountA(ws2.Range("A:A"))


    With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
        .AutoFilter 3, "CONCOMITANT MEDICATIONS"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .Copy ws2.Cells(urrow, 1)
        End With
        .AutoFilter
    End With
  
'Selecting and moving Transfusion data to the Critical CRFs sheet
    With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
        .AutoFilter 3, "Transfusions"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .Copy ws2.Cells(urrow, 1)
        End With
        .AutoFilter
    End With
    
'Sort ws1 by Patient
ws1.Select
ws1.Range("B1") = [{"Patient"}]
ws1.Columns("A:I").Sort key1:=ws1.Range("B1"), order1:=xlAscending, Header:=xlYes


'Populating the Visit Date Column
LRow = Cells(Rows.Count, "A").End(xlUp).Row


Do While LRow > 0
If Cells(LRow, 6) = "Visit" Then
    sLastValue = Cells(LRow, 4)
Else
    Cells(LRow, 4) = sLastValue
End If


LRow = LRow - 1


Loop


Range("D:D").EntireColumn.ColumnWidth = 9
Range("D1").Value = "Visit Date"


'Deleting CRFs that do not need to be counted. These are CRFs with No Data and no associated visit date.
With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
    .AutoFilter 4, "="
    .AutoFilter 7, "No Data"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .EntireRow.Delete
        End With
        .AutoFilter
End With


'Selecting and moving Eligibility data to the Critical CRFs sheet
    With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
        .AutoFilter 5, "100001"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .Copy ws2.Cells(urrow, 1)
        End With
        .AutoFilter
    End With
    
'Selecting and moving Disease History data to the Critical CRFs sheet
    With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
        .AutoFilter 5, "300001"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .Copy ws2.Cells(urrow, 1)
        End With
        .AutoFilter
    End With
    
'Selecting and moving Prior Treatment data to the Critical CRFs sheet
    With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
        .AutoFilter 5, "400001"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .Copy ws2.Cells(urrow, 1)
        End With
        .AutoFilter
    End With


'Selecting and moving Hematology data to the Critical CRFs sheet
    With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
        .AutoFilter 6, "Hematology" & "*"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .Copy ws2.Cells(urrow, 1)
        End With
        .AutoFilter
    End With
    
'Selecting and moving BL Disease Assessment data to the Critical CRFs sheet
    With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
        .AutoFilter 5, "1800001"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .Copy ws2.Cells(urrow, 1)
        End With
        .AutoFilter
    End With
    
'Selecting and moving FU Disease Assessment data to the Critical CRFs sheet
    With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
        .AutoFilter 3, "<>" & "Screening"
        .AutoFilter 6, "Disease Assessment"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .Copy ws2.Cells(urrow, 1)
        End With
        .AutoFilter
    End With
    
'Selecting and moving Response Assessment data to the Critical CRFs sheet
    With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
        .AutoFilter 6, "Response Assessment"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .Copy ws2.Cells(urrow, 1)
        End With
        .AutoFilter
    End With
    
'Selecting and moving EOS data to the Critical CRFs sheet
    With ws1.Columns("A:G").Resize(ws1.UsedRange.Rows.Count)
        .AutoFilter 3, "End of Study"
        With .Offset(1, 0).SpecialCells(xlCellTypeVisible)
            .Copy ws2.Cells(urrow, 1)
        End With
        .AutoFilter
    End With
    
'***PIVOT TABLE FOR ALL CRFS*****
'----------------------------------------------------------------------------------------------------------
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
     Worksheets("All iCRF Status").Range("A1").CurrentRegion, Version:=xlPivotTableVersion12). _
     CreatePivotTable TableDestination:="'All iCRF Status Metrics'!R3C1", TableName:="All iCRF Status" _
     , DefaultVersion:=xlPivotTableVersion12
     
ws3.Select
Cells(3, 1).Select
    With ActiveSheet.PivotTables("All iCRF Status").PivotFields("Site")
        .Orientation = xlRowField
        .Position = 1
    End With
    With ActiveSheet.PivotTables("All iCRF Status").PivotFields("Patient")
        .Orientation = xlRowField
        .Position = 2
    End With
    With ActiveSheet.PivotTables("All iCRF Status").PivotFields("iCRF Status")
        .Orientation = xlColumnField
        .Position = 1
    End With
    ActiveSheet.PivotTables("All iCRF Status").AddDataField ActiveSheet.PivotTables( _
        "All iCRF Status").PivotFields("iCRF"), "Count of iCRF", xlCount
    With ActiveSheet.PivotTables("All iCRF Status").PivotFields("Count of iCRF")
        .Calculation = xlPercentOfRow
        .NumberFormat = "0.0%"
    End With
    ActiveSheet.PivotTables("All iCRF Status").RowGrand = False
    ActiveSheet.PivotTables("All iCRF Status").CompactLayoutRowHeader = "Site"
    ActiveSheet.PivotTables("All iCRF Status").CompactLayoutColumnHeader = "iCRF Status"


    
If ActiveSheet.PivotTables("All iCRF Status").PivotFields("Patient").Orientation = xlHidden Then
    ActiveSheet.PivotTables("All iCRF Status").PivotFields("Patient").Orientation = xlRowField
    Else: ActiveSheet.PivotTables("All iCRF Status").PivotFields("Patient").Orientation = xlHidden
End If
    
Cells(3, 1).Value = "All iCRF Status Metrics"
Cells(3, 1).Interior.ColorIndex = 49
Cells(3, 1).Font.Color = vbWhite


'***PIVOT TABLE FOR CRITICAL CRFS*****
'----------------------------------------------------------------------------------------------------------
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
     Worksheets("Critical CRFs").Range("A1").CurrentRegion, Version:=xlPivotTableVersion12). _
     CreatePivotTable TableDestination:="'Critical iCRF Status Metrics'!R3C1", TableName:="Critical iCRF Status" _
     , DefaultVersion:=xlPivotTableVersion12
     
ws4.Select
Cells(3, 1).Select
    With ActiveSheet.PivotTables("Critical iCRF Status").PivotFields("Site")
        .Orientation = xlRowField
        .Position = 1
    End With
    With ActiveSheet.PivotTables("Critical iCRF Status").PivotFields("Patient")
        .Orientation = xlRowField
        .Position = 2
    End With
    With ActiveSheet.PivotTables("Critical iCRF Status").PivotFields("iCRF Status")
        .Orientation = xlColumnField
        .Position = 1
    End With
    ActiveSheet.PivotTables("Critical iCRF Status").AddDataField ActiveSheet.PivotTables( _
        "Critical iCRF Status").PivotFields("iCRF"), "Count of iCRF", xlCount
    With ActiveSheet.PivotTables("Critical iCRF Status").PivotFields("Count of iCRF")
        .Calculation = xlPercentOfRow
        .NumberFormat = "0.0%"
    End With
    ActiveSheet.PivotTables("Critical iCRF Status").RowGrand = False
    ActiveSheet.PivotTables("Critical iCRF Status").CompactLayoutRowHeader = "Site"
    ActiveSheet.PivotTables("Critical iCRF Status").CompactLayoutColumnHeader = "iCRF Status"
    
If ActiveSheet.PivotTables("Critical iCRF Status").PivotFields("Patient").Orientation = xlHidden Then
    ActiveSheet.PivotTables("Critical iCRF Status").PivotFields("Patient").Orientation = xlRowField
    Else: ActiveSheet.PivotTables("Critical iCRF Status").PivotFields("Patient").Orientation = xlHidden
End If
    
Cells(3, 1).Value = "Critical iCRF Status Metrics"
Cells(3, 1).Interior.ColorIndex = 49
Cells(3, 1).Font.Color = vbWhite


'setting up pages to be exported to pdf
LH = "MDS Custom CRF Metrics Report"
LastRow = Cells(Rows.Count, "A").End(xlUp).Row




ws3.Select
With ws3.PageSetup
 .PrintArea = "$A$3:$I$" & LastRow
 .Orientation = xlLandscape
 .LeftMargin = Application.InchesToPoints(0.5)
 .RightMargin = Application.InchesToPoints(0.5)
 .TopMargin = Application.InchesToPoints(1)
 .BottomMargin = Application.InchesToPoints(0.5)
 .HeaderMargin = Application.InchesToPoints(0.5)
 .FooterMargin = Application.InchesToPoints(0.5)
 .FitToPagesWide = 1
 .FitToPagesTall = False
 .Zoom = False
 .LeftHeader = LH
 .CenterHeader = ActiveSheet.Name
 .RightHeader = "Printed on &D"
End With


ws4.Select
With ws4.PageSetup
 .PrintArea = "$A$3:$I$" & LastRow
 .Orientation = xlLandscape
 .LeftMargin = Application.InchesToPoints(0.5)
 .RightMargin = Application.InchesToPoints(0.5)
 .TopMargin = Application.InchesToPoints(1)
 .BottomMargin = Application.InchesToPoints(0.5)
 .HeaderMargin = Application.InchesToPoints(0.5)
 .FooterMargin = Application.InchesToPoints(0.5)
 .FitToPagesWide = 1
 .FitToPagesTall = False
 .Zoom = False
 .LeftHeader = LH
 .CenterHeader = ActiveSheet.Name
 .RightHeader = "Printed on &D"
End With




End Sub
 
Upvote 0
Reply 2 of 2

These are all the possibilities

1. No Data

2. Incomplete
3. Complete
4. Partial Monitored
5. Monitored
6. Reviewed
7. Locked

Sample of Desired Outcome

[TABLE="class: grid, width: 500"]
<tbody>[TR]
[TD]Site[/TD]
[TD]No Data[/TD]
[TD]Incomplete[/TD]
[TD]Complete[/TD]
[TD]Partial Monitored[/TD]
[TD]Monitored[/TD]
[TD]Reviewed[/TD]
[TD]Locked[/TD]
[/TR]
[TR]
[TD]1234abc[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[/TR]
[TR]
[TD]5678def[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[/TR]
[TR]
[TD]910ghi[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[/TR]
[TR]
[TD]......[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[TD]xx.x%[/TD]
[/TR]
</tbody>[/TABLE]

 
Upvote 0
Please test this:

Code:
Option Explicit: Option Base 1
Function IsItem(p As PivotTable, pf$, ByVal pi$) As Boolean
Dim n$
IsItem = False
Err.Clear
On Error Resume Next
n = p.PivotFields(pf).PivotItems(pi).Name
If Err.Number = 0 Then IsItem = True
On Error GoTo 0
End Function
Sub OrderColumns()
Dim a, i%, pos, p As PivotTable
Set p = ActiveSheet.PivotTables(1)
' type the list in the desired order here
a = Array("Existing", "Old", "New")
pos = 1
For i = LBound(a) To UBound(a)
    ' replace "Customer" with your actual pivot field
    If IsItem(p, "Customer", a(i)) Then
        p.PivotFields("Customer").PivotItems(a(i)).Position = pos
        pos = pos + 1
    End If
Next
End Sub
 
Upvote 0

Forum statistics

Threads
1,223,236
Messages
6,170,906
Members
452,366
Latest member
TePunaBloke

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top