Here is my query:
PARAMETERS ...
TRANSFORM ...
SELECT ...
...
PIVOT Mytable.type In (\"Other\",\"Info\");
This is a cross query and I need
If the IN list is excluded from the PIVOT clause, the TRANSFORM query automatically creates columns for every PIVOT value generated from the SELECT statement. The final columns can be filtered by specifying the IN expression with "hard-coded" (i.e. literal) values. That is of course known from the other answers.
The exact same effect can be achieved by limiting the data from the SELECT query to start with... before the TRANSFORM needs to filter it. In this way, one is not limited to only pre-defined literal values--rather combinations of JOINS, sub-queries and/or VBA functions can also pre-filter the data, effectively choosing which columns appear in the transform table. Note that the HAVING clause is not allowed in a TRANSFORM query, but it could be used in another query which the TRANSFORM then selects on, so there are effectively no limits to how the data is prepared before the TRANSFORM.
All of the following produce equivalent results. First using PIVOT...IN:
TRANSFORM Count(Services.ID) AS [Schedules]
SELECT Agreement.City FROM Agreement INNER JOIN Services ON Agreement.Account = Services.Account
WHERE ( Services.Code = "IS" )
GROUP BY Agreement.City ORDER BY Agreement.City
PIVOT Month([ServiceDate]) In (1,4,12)
Using IN operator in WHERE clause:
TRANSFORM Count(Services.ID) AS [Schedules]
SELECT Agreement.City FROM Agreement INNER JOIN Services ON Agreement.Account = Services.Account
WHERE ( (Month([ServiceDate]) In (1,4,12)) AND Services.Code = "IS" )
GROUP BY Agreement.City ORDER BY Agreement.City
PIVOT Month([ServiceDate])
but unlike the PIVOT...IN clause, the list can also be another query:
WHERE ((Month([ServiceDate]) In (SELECT Values FROM PivotValues)) AND Services.Code = "IS" )
Finally, using a VBA function (which answers the original question):
TRANSFORM Count(Services.ID) AS [Schedules]
SELECT Agreement.City FROM Agreement INNER JOIN Services ON Agreement.Account = Services.Account
WHERE ( ReportMonth([ServiceDate]) AND Services.Code = "IS" )
GROUP BY Agreement.City ORDER BY Agreement.City
PIVOT Month([ServiceDate])
With the VBA function defined in a standard module:
Public Function ReportMonth(dt As Date) As Boolean
Select Case Month(dt)
Case 1, 4, 12: ReportMonth= True
Case Else: ReportMonth= False
End Select
End Function
(iDevlop already suggested this solution in a comment, but I don't think it was understood and good examples are required.)