Search code examples
vbaexcelpivot-tablecube

Getting "Type Mismatch" with VBA PivotTables and Filter Dates


I'm writing a script in Excel VBA (MS0 365 - version 1708).

The objective of the script is to apply different date ranges to "pre-structured" pivot tables, the pivot tables are connected to a Tabular Cube.

I have Googled and have seen similar issues but I haven't found any solutions to my issue unfortunately

In the script, I loop through the years and then the Quarters, Months and finally the Dates as needed (the dates are calculated via a worksheet), the idea here is to simulate what a user does with his mouse, but I understand that there might be a more efficient method? (I have tried .PivotFilters.Add2 instead but it doesn't seem to work seen as it is a xlPageField field).

So at the moment with the below Sub, for a given PivotTable, in order to select for example all dates starting from the 1st of January 2017 up until Sunday the 8th of April included I will select :

  1. 2017
  2. then the first Quarter of 2018 (called "T1-JFM" below)
  3. then nothing for Months
  4. then all the dates of April up until the 8th included

However, once I hit the Sub that concerns the Dates, I get an error on the line:

ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = Array(DIM_ARRAY)

There I get a:

"Run-time error '13' : Type mismatch

that line is the line that actually applies the Date filters, (prior to applying the filters DIM_ARRAY is an Array that "accumulates" the strings used in the filter).

I have tried adding another quotation mark to DIM_ARRAY at the beginning and the end of the array to ensure that it wasn't badly evaluated as a string, this didn't work out.

The Dates Sub portion is this :

Private Sub Cycle_Date(YEAR_i_max As String, TRIMESTRE_i As String,MONTH_i As String, MONTH_i_max As Integer)

i = 0
DATE_i_min = StdFilter(SheetName, "DATE_i_min")
DATE_i_max = StdFilter(SheetName, "DATE_i_max")

For i = DATE_i_min To DATE_i_max
DATE_i=WorksheetFunction.Proper(WorksheetFunction.Text(DateSerial(YEAR_i_max
,MONTH_i_max, i), "YYYY-MM-DDTHH:MM:SS"))


DIM_ARRAY_elmt = DIM_DATE_SUB & DIM_DATE_MOD_YEAR & ".&[" & YEAR_i_max & "]" 
& ".&[" & TRIMESTRE_i & "]" & ".&[" & MONTH_i & "]" & ".&[" & DATE_i & "]"
'Debug.Print DIM_ARRAY_elmt

If i = DATE_i_min Then
DIM_ARRAY = DIM_ARRAY_elmt

ElseIf i = DATE_i_max Then
    DIM_ARRAY = DIM_ARRAY & """" & "," & """" & DIM_ARRAY_elmt

ElseIf DIM_ARRAY <> "" Then
    DIM_ARRAY = DIM_ARRAY & """" & "," & """" & DIM_ARRAY_elmt

End If

Next

'Debug.Print DIM_ARRAY
ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = Array(DIM_ARRAY)

Below is the entire macro. The Dim(s) are at the top and Functions at the bottom. How can I resolve this?

Option Explicit

Dim DIM_DATE_CREATION_BASE As String
Dim DIM_DATE_SUB As String
Dim DIM_DATE_PTF As String

Dim DIM_DATE_MOD_YEAR As String
Dim DIM_DATE_MOD_TRIMESTRE As String
Dim DIM_DATE_MOD_MONTH As String
Dim DIM_DATE_MOD_DATE As String

Dim DIM_ARRAY As Variant
Dim DIM_ARRAY_elmt As String

Dim YEAR_i As Integer
Dim YEAR_i_min As String
Dim YEAR_i_max As String

Dim TRIMESTRE_i As String
Dim TRIMESTRE_i_max As String
Dim TRIMESTRE_i_min As String

Dim MONTH_i As String
Dim MONTH_i_max As Integer
Dim MONTH_i_min As Integer

Dim DATE_i As String
Dim DATE_i_min As Integer
Dim DATE_i_max As Integer

Dim i As Integer

Dim ws As Variant
Dim SheetNames As Variant
Dim SheetName As String

Dim Continue_Flag As Boolean


Sub Launch_Update()

Application.ScreenUpdating = False

Call Date_Filters

Application.ScreenUpdating = True

End Sub


Private Sub Date_Filters()

Continue_Flag = True

SheetNames = Array("NOW", "A-0 || J-7", "A-1 || à Date Equiv.", "A-1 || J-7 Atterissage")

DIM_DATE_CREATION_BASE = "[DIM_DATE_CREATION].[CALENDRIER_CREATION]"
DIM_DATE_SUB = DIM_DATE_CREATION_BASE & DIM_DATE_MOD_YEAR

For Each ws In SheetNames

Sheets(ws).Select
SheetName = ActiveSheet.Name


DIM_DATE_MOD_YEAR = ".[ANNEE]"
DIM_DATE_PTF = DIM_DATE_CREATION_BASE & DIM_DATE_MOD_YEAR

Call Cycle_Year

DIM_DATE_MOD_TRIMESTRE = ".[TRIMESTRE]"
DIM_DATE_PTF = DIM_DATE_CREATION_BASE & DIM_DATE_MOD_TRIMESTRE

Call Cycle_Trimestre(YEAR_i_max)

DIM_DATE_MOD_MONTH = ".[MOIS]"
DIM_DATE_PTF = DIM_DATE_CREATION_BASE & DIM_DATE_MOD_MONTH

Call Cycle_Month(YEAR_i_max, TRIMESTRE_i)

DIM_DATE_MOD_DATE = ".[DATE]"
DIM_DATE_PTF = DIM_DATE_CREATION_BASE & DIM_DATE_MOD_DATE

Call Cycle_Date(YEAR_i_max, TRIMESTRE_i, MONTH_i, MONTH_i_max)


Next ws

Continue_Flag = False

MsgBox "Date Filter Sub has ended"

End Sub

Private Sub Cycle_Year()

YEAR_i_min = StdFilter(SheetName, "YEAR_i_min")
YEAR_i_max = StdFilter(SheetName, "YEAR_i_max")

If YEAR_i_min = YEAR_i_max Then
YEAR_i_max = YEAR_i_min + 1
End If


For YEAR_i = YEAR_i_min To YEAR_i_max - 1

DIM_ARRAY_elmt = DIM_DATE_PTF & ".&[" & YEAR_i & "]"

If YEAR_i = YEAR_i_min Then
DIM_ARRAY = DIM_ARRAY_elmt

ElseIf YEAR_i = YEAR_i_max - 1 Then
DIM_ARRAY = DIM_ARRAY & "," & DIM_ARRAY_elmt

ElseIf DIM_ARRAY <> "" Then
DIM_ARRAY = DIM_ARRAY & "," & DIM_ARRAY_elmt

End If

Next



ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = Array(DIM_ARRAY)


End Sub

Private Sub Cycle_Trimestre(YEAR_i_max As String)


TRIMESTRE_i_min = StdFilter(SheetName, "TRIMESTRE_i_min")
TRIMESTRE_i_max = StdFilter(SheetName, "TRIMESTRE_i_max")

For i = TRIMESTRE_i_min To TRIMESTRE_i_max

If i = 1 Then
TRIMESTRE_i = "T1 - JFM"

ElseIf i = 2 Then
TRIMESTRE_i = "T2 - AMJ"

ElseIf i = 3 Then
TRIMESTRE_i = "T3 - JAS"

ElseIf i = 4 Then
TRIMESTRE_i = "T4 - OND"

End If


DIM_ARRAY_elmt = DIM_DATE_SUB & DIM_DATE_MOD_YEAR & ".&[" & YEAR_i_max & "]" & ".&[" & TRIMESTRE_i & "]"


If i = TRIMESTRE_i_min Then
DIM_ARRAY = DIM_ARRAY_elmt

ElseIf i = TRIMESTRE_i_max Then
DIM_ARRAY = DIM_ARRAY_elmt
GoTo ApplyFilter1

ElseIf DIM_ARRAY <> "" Then
DIM_ARRAY = DIM_ARRAY & "," & DIM_ARRAY_elmt

End If

Next

ApplyFilter1:

ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = Array(DIM_ARRAY)


End Sub
Private Sub Cycle_Month(YEAR_i_max As String, TRIMESTRE_i As String)

i = 0
MONTH_i_min = StdFilter(SheetName, "MONTH_i_min")
MONTH_i_max = StdFilter(SheetName, "MONTH_i_max")


For i = MONTH_i_min To MONTH_i_max

MONTH_i = WorksheetFunction.Proper(WorksheetFunction.Text(DateSerial(2018, i, 1), "[$-40C]MMMM"))




DIM_ARRAY_elmt = DIM_DATE_SUB & DIM_DATE_MOD_YEAR & ".&[" & YEAR_i_max & "]" & ".&[" & TRIMESTRE_i & "]" & ".&[" & MONTH_i & "]"


If i = MONTH_i_min Then
DIM_ARRAY = DIM_ARRAY_elmt

ElseIf i = MONTH_i_max Then
DIM_ARRAY = DIM_ARRAY_elmt
GoTo ApplyFilter2

ElseIf DIM_ARRAY <> "" Then
DIM_ARRAY = DIM_ARRAY & "," & DIM_ARRAY_elmt

End If

Next

ApplyFilter2:

ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = Array(DIM_ARRAY)

MONTH_i = WorksheetFunction.Proper(WorksheetFunction.Text(DateSerial(2018, i - 1, 1), "[$-40C]MMMM"))

End Sub
Private Sub Cycle_Date(YEAR_i_max As String, TRIMESTRE_i As String, MONTH_i As String, MONTH_i_max As Integer)

i = 0
DATE_i_min = StdFilter(SheetName, "DATE_i_min")
DATE_i_max = StdFilter(SheetName, "DATE_i_max")


For i = DATE_i_min To DATE_i_max

DATE_i = WorksheetFunction.Proper(WorksheetFunction.Text(DateSerial(YEAR_i_max, MONTH_i_max, i), "YYYY-MM-DDTHH:MM:SS"))


DIM_ARRAY_elmt = DIM_DATE_SUB & DIM_DATE_MOD_YEAR & ".&[" & YEAR_i_max & "]" & ".&[" & TRIMESTRE_i & "]" & ".&[" & MONTH_i & "]" & ".&[" & DATE_i & "]"

Debug.Print DIM_ARRAY_elmt


If i = DATE_i_min Then
DIM_ARRAY = DIM_ARRAY_elmt

ElseIf i = DATE_i_max Then
DIM_ARRAY = DIM_ARRAY & """" & "," & """" & DIM_ARRAY_elmt

ElseIf DIM_ARRAY <> "" Then
DIM_ARRAY = DIM_ARRAY & """" & "," & """" & DIM_ARRAY_elmt

End If

Next

Debug.Print DIM_ARRAY

ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = Array(DIM_ARRAY)

End Sub

Public Function StdFilter(SheetPointer As String, DateField As String)

StdFilter = WorksheetFunction.Index(Sheets("Standard_FILTERS").Range("A1:J5"), _
 WorksheetFunction.Match(SheetPointer, Sheets("Standard_FILTERS").Range("A:A"), 0), _
 WorksheetFunction.Match(DateField, Sheets("Standard_FILTERS").Range("1:1"), 0))

End Function

Solution

  • RESOLUTION:

    DIM_ARRAY had to be an Array data type and was a String data type (that resembled an array in a misleading manner but wasn't one).

    I believe that the other portions of the code worked only because only 1 element was applied every time in the "fake array", what is certain is that the data/parameters used in the "test conditions" led me to a misleading diagnosis.

    (Lesson learnt: change your test conditions to see if they allow you to gather new information)

    Below the full code, that really works this time :

    Private Sub Date_Filters()
    
            SheetNames = Array("NOW", "A-0 || J-7", "A-1 || à Date Equiv.", "A-1 || J-7 Atterissage") 'list of relevant sheets
    
            'setting variables:
            DIM_DATE_CREATION_BASE = "[DIM_DATE_CREATION].[CALENDRIER_CREATION]"
            DIM_DATE_SUB = DIM_DATE_CREATION_BASE & DIM_DATE_MOD_YEAR
            mymsg = "Dates à jour pour TDC :"
            i = 0
    
        For Each ws In SheetNames
    
            Sheets(ws).Select
            SheetName = ActiveSheet.Name
    
                DIM_DATE_MOD_YEAR = ".[ANNEE]"
                DIM_DATE_PTF = DIM_DATE_CREATION_BASE & DIM_DATE_MOD_YEAR
    
            Call Cycle_Year
    
                i = 0
                DIM_DATE_MOD_TRIMESTRE = ".[TRIMESTRE]"
                DIM_DATE_PTF = DIM_DATE_CREATION_BASE & DIM_DATE_MOD_TRIMESTRE
    
            Call Cycle_Trimestre(YEAR_i_max)
    
                i = 0
                DIM_DATE_MOD_MONTH = ".[MOIS]"
                DIM_DATE_PTF = DIM_DATE_CREATION_BASE & DIM_DATE_MOD_MONTH
    
            Call Cycle_Month(YEAR_i_max, TRIMESTRE_i)
    
                i = 0
                DIM_DATE_MOD_DATE = ".[DATE]"
                DIM_DATE_PTF = DIM_DATE_CREATION_BASE & DIM_DATE_MOD_DATE
    
            Call Cycle_Date(YEAR_i_max, TRIMESTRE_i, MONTH_i, MONTH_i_max)
    
    
            mymsg = mymsg & SheetName & " -ET- "
            Application.StatusBar = mymsg
    
        Next ws
    
    End Sub
    
    Private Sub Cycle_Year()
    
            YEAR_i_min = StdFilter(SheetName, "YEAR_i_min")
            YEAR_i_max = StdFilter(SheetName, "YEAR_i_max")
            ReDim TRUE_ARRAY(1 To 2)
            Erase TRUE_ARRAY
            ReDim TRUE_ARRAY(YEAR_i_min To YEAR_i_max)
    
        If YEAR_i_min = YEAR_i_max Then ' Fork-out scenario
    
            ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = Array("")
    
            Exit Sub
    
        End If
    
    
        For YEAR_i = YEAR_i_min To YEAR_i_max - 1 ' Loop through
    
            DIM_ARRAY_elmt = DIM_DATE_PTF & ".&[" & YEAR_i & "]"
            TRUE_ARRAY(YEAR_i) = DIM_ARRAY_elmt
    
            Debug.Print "Year   "; YEAR_i; TRUE_ARRAY(YEAR_i)
    
        Next
    
        ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = TRUE_ARRAY
    
    End Sub
    
    Private Sub Cycle_Trimestre(YEAR_i_max As String)
    
            TRIMESTRE_i_min = StdFilter(SheetName, "TRIMESTRE_i_min")
            TRIMESTRE_i_max = StdFilter(SheetName, "TRIMESTRE_i_max")
            ReDim TRUE_ARRAY(1 To 2)
            Erase TRUE_ARRAY
            ReDim TRUE_ARRAY(TRIMESTRE_i_min To TRIMESTRE_i_max)
    
        If TRIMESTRE_i_min = TRIMESTRE_i_max Then ' Fork-out scenario
    
            ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = Array("")
    
            Exit Sub
    
        End If
    
    
        For i = TRIMESTRE_i_min To TRIMESTRE_i_max ' Loop through
    
            If i = TRIMESTRE_i_max Then
    
                    If i = 1 Then
                        TRIMESTRE_i = "T1 - JFM"
    
                        ElseIf i = 2 Then
                            TRIMESTRE_i = "T2 - AMJ"
    
                        ElseIf i = 3 Then
                            TRIMESTRE_i = "T3 - JAS"
    
                        ElseIf i = 4 Then
                            TRIMESTRE_i = "T4 - OND"
    
                    End If
    
                GoTo ApplyFilter
                Else
    
                    If i = 1 Then
                        TRIMESTRE_i = "T1 - JFM"
    
                        ElseIf i = 2 Then
                            TRIMESTRE_i = "T2 - AMJ"
    
                        ElseIf i = 3 Then
                            TRIMESTRE_i = "T3 - JAS"
    
                        ElseIf i = 4 Then
                            TRIMESTRE_i = "T4 - OND"
    
                    End If
            End If
    
        DIM_ARRAY_elmt = DIM_DATE_SUB & DIM_DATE_MOD_YEAR & ".&[" & YEAR_i_max & "]" & ".&[" & TRIMESTRE_i & "]"
        TRUE_ARRAY(i) = DIM_ARRAY_elmt
    
        Debug.Print "Trimestre "; i; TRUE_ARRAY(i)
    
        Next
    
    ApplyFilter:
    
        ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = TRUE_ARRAY
    
    End Sub
    Private Sub Cycle_Month(YEAR_i_max As String, TRIMESTRE_i As String)
    
    
            MONTH_i_min = StdFilter(SheetName, "MONTH_i_min")
            MONTH_i_max = StdFilter(SheetName, "MONTH_i_max")
            ReDim TRUE_ARRAY(1 To 2)
            Erase TRUE_ARRAY
            ReDim TRUE_ARRAY(MONTH_i_min To MONTH_i_max)
    
        If MONTH_i_min = MONTH_i_max Then ' Fork-out scenario
    
            ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = Array("")
    
            MONTH_i = WorksheetFunction.Proper(WorksheetFunction.Text(DateSerial(2018, MONTH_i_min, 1), "[$-40C]MMMM"))
    
            Exit Sub
    
        End If
    
        For i = MONTH_i_min To MONTH_i_max - 1 ' Loop through
    
        MONTH_i = WorksheetFunction.Proper(WorksheetFunction.Text(DateSerial(2018, i, 1), "[$-40C]MMMM"))
    
        DIM_ARRAY_elmt = DIM_DATE_SUB & DIM_DATE_MOD_YEAR & ".&[" & YEAR_i_max & "]" & ".&[" & TRIMESTRE_i & "]" & ".&[" & MONTH_i & "]"
        TRUE_ARRAY(i) = DIM_ARRAY_elmt
    
        Debug.Print "Month    "; i; TRUE_ARRAY(i)
    
        Next
    
        ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = TRUE_ARRAY
    
        MONTH_i = WorksheetFunction.Proper(WorksheetFunction.Text(DateSerial(2018, i, 1), "[$-40C]MMMM"))
    
    End Sub
    Private Sub Cycle_Date(YEAR_i_max As String, TRIMESTRE_i As String, MONTH_i As String, MONTH_i_max As Integer)
    
    
            DATE_i_min = StdFilter(SheetName, "DATE_i_min")
            DATE_i_max = StdFilter(SheetName, "DATE_i_max")
            ReDim TRUE_ARRAY(1 To 2)
            Erase TRUE_ARRAY
            ReDim TRUE_ARRAY(1 To DATE_i_max)
    
        If DATE_i_min = DATE_i_max Then ' Fork-out scenario begin
    
            i = 1
    
            DATE_i = WorksheetFunction.Proper(WorksheetFunction.Text(DateSerial(YEAR_i_max, MONTH_i_max, i), "YYYY-MM-DDTHH:MM:SS"))
    
            DIM_ARRAY = DIM_DATE_SUB & DIM_DATE_MOD_YEAR & ".&[" & YEAR_i_max & "]" & ".&[" & TRIMESTRE_i & "]" & ".&[" & MONTH_i & "]" & ".&[" & DATE_i & "]"
    
            ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = Array(DIM_ARRAY)
    
            Exit Sub
    
        End If ' Fork-out scenario end
    
    
    
        For i = DATE_i_min To DATE_i_max ' Loop through
    
            DATE_i = Format(DateSerial(YEAR_i_max, MONTH_i_max, i), "YYYY-MM-DDTHH:MM:SS")
    
            DIM_ARRAY_elmt = DIM_DATE_SUB & DIM_DATE_MOD_YEAR & ".&[" & YEAR_i_max & "]" & ".&[" & TRIMESTRE_i & "]" & ".&[" & MONTH_i & "]" & ".&[" & DATE_i & "]"
            TRUE_ARRAY(i) = DIM_ARRAY_elmt
    
        Debug.Print "Date      "; Format(i, "00 "); TRUE_ARRAY(i)
    
        Next
    
        ActiveSheet.PivotTables("PivotTable3").PivotFields(DIM_DATE_PTF).VisibleItemsList = TRUE_ARRAY
    
    End Sub