Hi Virat,

I'm not sure what you have in mind in terms of debugging. For scheduling an export of IRIS BI results to a PDF, I would recommend looking at the Pivot Subscriptions app, which is available here on Open Exchange. This tool allows you to export individual pivots, not dashboards, but you could schedule multiple pivots to be exported (and emailed) on the schedule that you need. The other option that comes to mind is %DeepSee.Utils:%ExportPDFToFile(), but that method is for exporting a query's results; I would expect Pivot Subscriptions to be much more useful for your situation.

Hi Ephraim,

It looks to me like you have defined the Region level with a source expression of "sourceRegion". The source expression will be interpreted as an ObjectScript expression to be computed for each record when you build the cube. In this case, it is being interpreted as a literal string, so the value of the level for every fact is "sourceRegion".

Do you have a property in your source class called Region or sourceRegion? Assuming your source class has a property called Region, you can select the Property option in the level details (above the Expression option), and enter Region (without quotes) there. This is equivalent to using the Expression option and entering %source.Region (again, no quotes).

If you are still having trouble with this level after trying this, please feel free to open a WRC issue to get support.

Calculated measures (and other calculated members) are evaluated at runtime whether they are defined in the cube definition or elsewhere. (Measures other than calculated measures are evaluated at build time and their values are stored in the fact table, but I don't think that would be suitable for what Nick wanted to do here.)

- provide 2023.1.x tag which will follow the latest minor version

It's not clear to me whether or not this is already the plan for the new Major.Minor tags. For instance, when IRIS 2024.1.1 is released, will it be at containers.intersystems.com/intersystems/iris:2024.1 (where IRIS 2024.1.0 images would likely have existed previously) or containers.intersystems.com/intersystems/iris:2024.1.1? @Bob Kuszewski can you please clarify?

Hi Jacinto,

If these values can be determined at the time you build or synchronize the cube, you could create a level (in Architect) with a source expression that uses $SELECT to determine the value based on the logic you described.

I think this might be closer to what you have in mind than using calculated members - you could, for example, display the four categories you are mapping values to on rows just by putting the level on rows. (If you use calculated members, I think you'd want to define one member for each of the categories you're mapping values to.)

Hi Colin,

It's been a while since I used them, but I think POST /Info/Filters returns some information on dimensions/hierarchies/levels, and POST /Info/FilterMembers returns information on the members of a level. If you need metadata on properties specifically, I'm not sure if that is included. I don't think we have information on namespaces as part of the REST API for IRIS BI, but maybe someone has a suggestion of other ways to get that kind of information about an IRIS instance over REST. Anyway, I'd recommend taking a look at those two /Info services, and possibly opening a WRC issue if you find that they don't provide what you need.

Hi Jenna,

I think the %DeepSee.Utils:%GetMDXFromPivot() method may be helpful here. (The class reference is here, though I think the first line of the description is confusing.)

If the pivot is saved with the filters you want in effect (e.g. with the &[2023] member already selected), you can get the MDX and execute it directly by passing a result set and pExecute = 1 to %GetMDXFromPivot():

SAMPLES>set rs = ##class(%DeepSee.ResultSet).%New()
SAMPLES>set pivot = "Filter Examples/One Member Filter"
SAMPLES>set mdx = ##class(%DeepSee.Utils).%GetMDXFromPivot(pivot,.sc,1,,.rs)
SAMPLES>write sc, !, mdx
1
SELECT NON EMPTY NONEMPTYCROSSJOIN([GenD].[H1].[Gender].Members,[Measures].[%Count]) ON 0,NON EMPTY {[DiagD].[H1].[Diagnoses].Members,[AgeD].[All Patients]} ON 1 FROM [PATIENTS] %FILTER [AllerD].[H1].[Allergies].&[wheat]
SAMPLES>do rs.%Print()
                       Patient Count        Patient Count
1 None                             23                   16
2 asthma                            3                    4
3 diabetes                          1                    2
4 All Patients                     27                   21
 
If the pivot table is not saved with all the filters that you want, you can use %GetMDXFromPivot() just to get the MDX query text, then append a %FILTER clause to it (make sure to include a space between the original query and the %FILTER) and pass the modified text to a %DeepSee.ResultSet object to be prepared and executed:

SAMPLES>set pivot = "Chart Demos/Bar Chart"
SAMPLES>set mdx = ##class(%DeepSee.Utils).%GetMDXFromPivot(pivot,.sc)
SAMPLES>write sc, !, mdx
1
SELECT NON EMPTY [Measures].[Amount Sold] ON 0,NON EMPTY [DateOfSale].[Actual].[YearSold].Members ON 1 FROM [HOLEFOODS]
SAMPLES>set mdx = mdx_" %FILTER [Product].[P1].[Product Category].&[Cereal]"
SAMPLES>write mdx
SELECT NON EMPTY [Measures].[Amount Sold] ON 0,NON EMPTY [DateOfSale].[Actual].[YearSold].Members ON 1 FROM [HOLEFOODS] %FILTER [Product].[P1].[Product Category].&[Cereal]
SAMPLES>set rs = ##class(%DeepSee.ResultSet).%New()
SAMPLES>write rs.%PrepareMDX(mdx)
1
SAMPLES>write rs.%Execute()
1
SAMPLES>do rs.%Print()
                                   Revenue
1 2017                               $40.69
2 2018                               $59.65
3 2019                              $103.13
4 2020                               $40.70
5 2021                               $99.96
6 2022                               $68.35

Hi Jenna,

Is something like this what you have in mind?

SAMPLES>set relatedFilters("[DateOfSale].[Actual].[YearSold]") = "&[2021]"
 
SAMPLES>set sc = ##class(%DeepSee.Utils).%GetDimensionMembers("HOLEFOODS","[DateOfSale].[Actual].[MonthSold]","filter",.members,,.memberClass,.relatedFilters)
 
SAMPLES>zwrite members                                                         
members(1)=$lb("[NOW]","NOW","NOW","NOW")
members(2)=$lb("[Jan-2021]","Jan-2021","202101","202101","")
members(3)=$lb("[Feb-2021]","Feb-2021","202102","202102","")
members(4)=$lb("[Mar-2021]","Mar-2021","202103","202103","")
members(5)=$lb("[Apr-2021]","Apr-2021","202104","202104","")
members(6)=$lb("[May-2021]","May-2021","202105","202105","")
members(7)=$lb("[Jun-2021]","Jun-2021","202106","202106","")
members(8)=$lb("[Jul-2021]","Jul-2021","202107","202107","")
members(9)=$lb("[Aug-2021]","Aug-2021","202108","202108","")
members(10)=$lb("[Sep-2021]","Sep-2021","202109","202109","")
members(11)=$lb("[Oct-2021]","Oct-2021","202110","202110","")
members(12)=$lb("[Nov-2021]","Nov-2021","202111","202111","")
members(13)=$lb("[Dec-2021]","Dec-2021","202112","202112","")

I'll admit I'm not completely sure why the NOW member is coming back in this case, since there shouldn't be any data with a year of 2021 and a month of NOW, but other than that I think this may be what you were describing.

There are a couple of ways you might be able to do this, but the simplest one is probably to use the %NOT MDX function. You can write a filter that excludes one member by appending .%NOT to the member spec:

%FILTER [Demographics].[H10].[Citizenship].&[USA].%NOT

If you want to write a filter that excludes multiple individual members of one or more levels, you can filter by a tuple of the members that you want to exclude. Append .%NOT to each of the member specs, and do not use %OR:

%FILTER ([Demographics].[H10].[Citizenship].&[USA].%NOT,[Demographics].[H10].[Citizenship].&[U.S.A].%NOT,[Demographics].[H10].[Citizenship].&[US].%NOT)

I'd like some clarification on the prompt "Using %MDX and %KPI instead of Subject Area in IRIS Analytics". I don't typically think of %MDX and %KPI as alternatives to creating/using a subject area in the way that the prompt implies - is the intention just to have an article that explains how to use %MDX and %KPI, or is there a specific use case that you are hoping it will explain?
edit: Doesn't look like I'm eligible to participate, but maybe someone else wants to write this...

Hi Evgeny,

I agree that that would be useful, and I have tried something along those lines using the result set's %Statistics property in the past. However, the AuditQueryCode routine runs too early for the performance statistics to be complete for most asynchronous queries. If this changes in the future, I'll post an update and add it to the sample classes.

Hi Evgenii,

If the list of branches will not change over time (or will change very infrequently, so that you can manually update your cube model when it does), you might consider manually specifying the members for the Branch level, as documented here.

If you do this, keep in mind that the Analyzer adds the NON EMPTY keyword to many MDX queries by default, which will prevent members with no data from being shown in the resulting pivot table. You may need to remove this keyword from MDX queries where you want the members with no data to show up.

The KPI doesn't need to be the data source for the widget. You can specify the KPI class as the actionClass for a cube (this is an attribute of a <cube> element) and then the actions in it will be available to pivots based on that cube. That will in turn make those actions available as controls on widgets whose data source is a pivot based on that cube.

If the data source for a widget isn't a pivot or a KPI, I'm not sure whether it's possible to use custom actions on that widget.

Hi Evgeny,

Please take a look at the documentation on custom actions. You will need to create a KPI class and define the actions you want to make available in it. You can then add widget controls that correspond to these actions. For a real-world example that includes an action to rebuild a cube, take a look at this class from the CubeEventMonitor.

I think you know this, but to clarify for other readers - this allows developers to write any methods they would like and end-users to execute the defined methods at any time. It doesn't allow end-users to define and execute arbitrary methods of their own.

Hi Lee,

The "range" language may be a bit confusing, so to be clear - %TIMERANGE() returns a single member expression.

I'm on a different version, but COUNT(%TIMERANGE(...)) appears to work for me, and it returns 1 (which is expected because %TIMERANGE() returns a single member). In general, member expressions like the result of %TIMERANGE() can also be interpreted as set expressions containing a single item, so I would expect COUNT(%TIMERANGE(...)) and the like to be valid MDX.

I'd suggest opening a WRC issue for this as well - it's great to post questions like this on the Developer Community when you're uncertain about the expected behavior, but once we've determined that the behavior you're seeing is unexpected, there is more that we can do to investigate and help you in the context of a support issue.