PDA

View Full Version : [SOLVED:] PivotTable.DrillDown and filtering the output based on target column data type



jaffey
01-30-2020, 12:40 PM
Hello all,

I am looking for assistance in modifying a piece of code I found in another thread on this site. The code runs via the Worksheet_BeforeDoubleClick event and is designed to be used in conjunction with a pivot table's drill down function, overriding it essentially. However, it only works properly if the underlying data in the target column consists of 1's and/or 0's. It then delete any rows that don't have a "1" in the target column. This is fine if know you are double clicking on a column that contains 1's and 0's, however, if there is anything else in the column, you end up staring at a blank page drill down page. So I would like to modify it such that it checks to see if the data in the target column does consist of 1's and/or 0's before executing. If not, just exit the sub.

The original thread does provide a partial workaround for this problem by allowing you to specify the column headers in the macro, however, this is not ideal as I have over fifty columns of 1's and 0's and new ones get added all the time

This is the code I would like to make check the target column for 1's and 0's before it runs:




Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim PTCll As PivotCell


On Error Resume Next
Set PTCll = Target.PivotCell
On Error GoTo 0


If Not PTCll Is Nothing Then
If PTCll.PivotCellType = xlPivotCellValue Then
Cancel = True
Target.ShowDetail = True
With ActiveSheet
FieldNo = Application.Match(PTCll.DataField.SourceName, .Rows(1), 0)
If Not IsError(FieldNo) Then
With .ListObjects(1)
.Range.AutoFilter Field:=FieldNo, Criteria1:="<>1" ', Operator:=xlAnd
.DataBodyRange.EntireRow.Delete
.Range.AutoFilter Field:=FieldNo
End With
.Range("A1").Select
End If
End With
End If
End If
End Sub





and this is the version that specifies the column headers:


Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim PTCll As PivotCell


On Error Resume Next
Set PTCll = Target.PivotCell
On Error GoTo 0


If Not PTCll Is Nothing Then
If PTCll.PivotCellType = xlPivotCellValue Then
Cancel = True
Target.ShowDetail = True
If Not IsError(Application.Match(PTCll.DataField.SourceName, Array("Metric1", "Metric2", "Metric4", "Metric5", "Metric6", "Metric7"), 0)) Then
With ActiveSheet
FieldNo = Application.Match(PTCll.DataField.SourceName, .Rows(1), 0)
If Not IsError(FieldNo) Then
With .ListObjects(1)
.Range.AutoFilter Field:=FieldNo, Criteria1:="<>1"
.DataBodyRange.EntireRow.Delete
.Range.AutoFilter Field:=FieldNo
End With
.Range("A1").Select
End If
End With
End If
End If
End If
End Sub


EDIT: I tried to add link to original post but I can't get the editor to accept it. If you search on "PivotTable.DrillDown and filtering the output" it should come up.

snb
01-31-2020, 02:20 AM
Just upload the file.

p45cal
01-31-2020, 08:41 AM
I echo snb's request. It will answer a lot of questions.

This is the link to the other thread:
http://www.vbaexpress.com/forum/showthread.php?60250-PivotTable-DrillDown-and-filtering-the-output&highlight=PTCll.DataField

In the meantime, the area you could be checking might be referred to with the likes of:
With .ListObjects(1) 'existing line
Application.Goto .ListColumns(PTCll.DataField.SourceName).DataBodyRange 'new code
If you're wanting to check the pivot table's entire source data for that field it will depend on what type of source data that is.

jaffey
01-31-2020, 12:10 PM
Hi, I've attached the file. I'm definitely open to any solution that doesn't require me to maintain/edit dozens of column header names within the macro itself. An external table would suffice as I could make another macro to populate it whenever a new column containing 1's/0's gets added. 25902

p45cal
01-31-2020, 06:58 PM
I'm not sure of what outcome you want yet, but this, I think, does what you ask (with adjustments from you), but we can be very precise about what's left in the drill down sheet, so in an ideal world, what would you like to see there?
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim PTCll As PivotCell

On Error Resume Next
Set PTCll = Target.PivotCell
On Error GoTo 0

If Not PTCll Is Nothing Then
If PTCll.PivotCellType = xlPivotCellValue Then
Cancel = True
Target.ShowDetail = True
With ActiveSheet
FieldNo = Application.Match(PTCll.DataField.SourceName, .Rows(1), 0)
If Not IsError(FieldNo) Then
With .ListObjects(1)
'new check code starts here.
Set rngToCheck = .ListColumns(PTCll.DataField.SourceName).DataBodyRange
myArray = Array(0, 1, "#VALUE!", "plonk") 'a list of items that can be in the column; if there's anything else the sub will be exited.
CellCount = 0
For Each itm In myArray
CellCount = CellCount + Application.CountIf(rngToCheck, itm)
Next itm
If CellCount <> rngToCheck.Rows.Count Then Exit Sub
'new check code ends here.
.Range.AutoFilter Field:=FieldNo, Criteria1:="<>1" 'not sure if you'll want to alter/keep this.
.DataBodyRange.EntireRow.Delete
.Range.AutoFilter Field:=FieldNo
End With
.Range("A1").Select
End If
End With
End If
End If
End Sub

jaffey
02-03-2020, 09:41 AM
Thank you so much p45cal! This is a huge improvement!! One thing I must not have stated clearly is that I want to keep the rows with error values. Perhaps that was what you were alluding to in your comment at the end of this line.


.Range.AutoFilter Field:=FieldNo, Criteria1:="<>1" 'not sure if you'll want to alter/keep


So yes, I would like to alter it, something to the effect of
.Range.AutoFilter Field:=FieldNo, Criteria1:="<>1", Criteria2:="#VALUE!"
but that doesn't work as written unfortunately. I think this was stumping them in the original thread as well.

p45cal
02-03-2020, 10:34 AM
So can we say:
In the drilldown new sheet you want to see everything but the zeroes?

jaffey
02-03-2020, 08:53 PM
Zeroes or blanks basically

p45cal
02-04-2020, 02:23 AM
Try the attached which contains the following code:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'http://www.vbaexpress.com/forum/showthread.php?66714-PivotTable-DrillDown-and-filtering-the-output-based-on-target-column-data-type
Dim PTCll As PivotCell

On Error Resume Next
Set PTCll = Target.PivotCell
On Error GoTo 0

If Not PTCll Is Nothing Then
If PTCll.PivotCellType = xlPivotCellValue Then
Cancel = True
Target.ShowDetail = True
With ActiveSheet
FieldNo = Application.Match(PTCll.DataField.SourceName, .Rows(1), 0)
If Not IsError(FieldNo) Then
Set uuu = .ListObjects(1)
With .ListObjects(1)
.Range.AutoFilter Field:=FieldNo, Criteria1:=0, Criteria2:="=", Operator:=xlOr
On Error Resume Next
Application.DisplayAlerts = False
.DataBodyRange.SpecialCells(xlCellTypeVisible).Delete
Application.DisplayAlerts = True
On Error GoTo 0
.Range.AutoFilter Field:=FieldNo
End With
.Range("A1").Select
End If
End With
End If
End If
End Sub

The word 'basically' worries me though…

jaffey
02-05-2020, 08:05 AM
Me too, lol. I said it because I couldn't think of another use case at that moment. Sure enough, one occurred to me shortly afterward, and that is when the source data consists of Y and N's, or even Yes and No, instead of 1 and 0. In those situations, we want to keep the Y's or Yes's and get rid of the N's or No's. So, ideally, it will delete 0's, blanks, N's and No's.

p45cal
02-05-2020, 11:44 AM
will delete 0's, blanks, N's and No's.
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'http://www.vbaexpress.com/forum/showthread.php?66714-PivotTable-DrillDown-and-filtering-the-output-based-on-target-column-data-type
Dim PTCll As PivotCell

On Error Resume Next
Set PTCll = Target.PivotCell
On Error GoTo 0

If Not PTCll Is Nothing Then
If PTCll.PivotCellType = xlPivotCellValue Then
Cancel = True
Target.ShowDetail = True
With ActiveSheet
FieldNo = Application.Match(PTCll.DataField.SourceName, .Rows(1), 0)
If Not IsError(FieldNo) Then
Set uuu = .ListObjects(1)
With .ListObjects(1)
myCrits = Array("0", "", "N", "No") 'a list of stuff you want deleted: delete 0's, blanks, N's and No's.
.Range.AutoFilter Field:=FieldNo, Criteria1:=myCrits, Operator:=xlFilterValues
On Error Resume Next
Application.DisplayAlerts = False
.DataBodyRange.SpecialCells(xlCellTypeVisible).Delete
Application.DisplayAlerts = True
On Error GoTo 0
.Range.AutoFilter Field:=FieldNo
End With
.Range("A1").Select
End If
End With
End If
End If
End Sub

jaffey
02-06-2020, 10:34 PM
This is fantastic p45cal! Please consider this solved! Thank you so much!