-
Notifications
You must be signed in to change notification settings - Fork 0
/
MacroActions.json
144 lines (144 loc) · 78.3 KB
/
MacroActions.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
{
"Actions": [
{
"Name": "Macros\\Calculation Group\\Create Calculation Items for all measure (like Field Parameters)",
"Enabled": "true",
"Execute": "// Define the name of the Calculation Group\r\nstring calculationGroupName = \"Parameter - Measure Selection (Calculation Group)\";\r\n\r\n// Check if the Calculation Group already exists\r\nCalculationGroupTable calculationGroup = null;\r\nforeach (var table in Model.Tables)\r\n{\r\n if (table.Name == calculationGroupName && table is CalculationGroupTable)\r\n {\r\n calculationGroup = table as CalculationGroupTable;\r\n break;\r\n }\r\n}\r\n\r\n// Create the Calculation Group if it doesn't exist\r\nif (calculationGroup == null)\r\n{\r\n calculationGroup = Model.AddCalculationGroup(calculationGroupName);\r\n}\r\n\r\n// Iterate through all measures in the model\r\nforeach (var measure in Model.AllMeasures)\r\n{\r\n // Create a new Calculation Item for each measure\r\n var calcItem = calculationGroup.AddCalculationItem(measure.Name);\r\n calcItem.Expression = measure.DaxObjectFullName;\r\n}\r\n\r\n//Create dummy measure to be used in visual for Calculation Group\r\nvar newMeasure = calculationGroup.AddMeasure(\r\n \"Dummy\" , // Name\r\n @\"BLANK()\" // DAX expression\r\n // Display Folder\r\n );\r\n \r\n // Set the format string on the new measure:\r\n newMeasure.FormatString = \"#,0.00\";\r\n\r\n // Provide some documentation:\r\n newMeasure.Description = \"Dummy measure for Calculation Group\" ;\r\n\r\n\r\n",
"Tooltip": "",
"ValidContexts": "Model, Tables, Measure, Column, CalculationGroupTable"
},
{
"Name": "Macros\\Calculation Group\\Create Sort for Calculation Groups",
"Enabled": "true",
"Execute": "//'2023-07-27 / B.Agullo / \r\n// Generate Calc Group to Sort a Matrix by a Calc Item Column\r\n// Automation of the Calculation group introduced in this blog post: https://www.esbrina-ba.com/sorting-a-matrix-by-a-calculation-item-column/\r\n// this script was written live in the Seattle Modern Excel & Power BI User Group on July 26th 2023.\r\n// To execute select a calculation group table and click execute\r\n// It es recommented to store as macro for Calculation Group Table\r\n\r\nstring noSortCalcItemName = \"No Sort\";\r\nif(Selected.Tables.Count != 1)\r\n{\r\n Error(\"Please select a single calculation group and try again.\");\r\n return;\r\n}\r\nif(Selected.Table.GetTypeName() != \"Calculation Group Table\")\r\n{\r\n Error(\"This is not a calculation group\");\r\n return;\r\n}\r\nCalculationGroupTable calculationGroupTable =\r\n Selected.Table as CalculationGroupTable;\r\ncalculationGroupTable.AddCalculationItem(noSortCalcItemName, \"1\");\r\nstring calcTableName = \"Sort \" + calculationGroupTable.Name ;\r\nstring calcTableExpression = calculationGroupTable.DaxObjectFullName;\r\nCalculatedTable calculatedTable =\r\n Model.AddCalculatedTable(calcTableName, calcTableExpression);\r\nbool te2 = (calculatedTable.Columns.Count == 0);\r\nColumn firstCalcTableColumn =\r\n te2 ? calculatedTable.AddCalculatedColumn(\r\n calculationGroupTable.Columns[0].Name, \"1\")\r\n : calculatedTable.Columns[0];\r\nstring sortCalcGroupName = \"Sort\";\r\nstring sortCalcItemExpression =\r\n String.Format(\r\n @\" VAR inTotal =\r\n NOT HASONEVALUE ( {0} )\r\n VAR sortBy =\r\n SELECTEDVALUE ( {1}, \"\"{2}\"\" )\r\n VAR result =\r\n IF (\r\n inTotal,\r\n CALCULATE (\r\n SELECTEDMEASURE (),\r\n {0} = sortBy\r\n ),\r\n SELECTEDMEASURE ()\r\n )\r\n RETURN\r\n result\",\r\n calculationGroupTable.Columns[0].DaxObjectFullName,\r\n calculatedTable.Columns[0].DaxObjectFullName,\r\n noSortCalcItemName);\r\nCalculationGroupTable sortCalcGroup =\r\n Model.AddCalculationGroup(sortCalcGroupName);\r\nCalculationItem sortCalcItem =\r\n sortCalcGroup.AddCalculationItem(\r\n sortCalcGroupName,\r\n sortCalcItemExpression);\r\nsortCalcItem.FormatDax();\r\nif (te2)\r\n{\r\n calculatedTable.Columns[0].Delete();\r\n}",
"Tooltip": "",
"ValidContexts": "Model, Tables, Measure, Column, CalculationGroupTable"
},
{
"Name": "Macros\\Calculation Group\\Create Value Presentation Caclulation Group",
"Enabled": "true",
"Execute": "\r\n// estblish the context table & column as well as table with measure to be totalled\r\n\r\nvar factTable = SelectTable(label: \"Select your table that you wish to use for context of Total\");\r\nif(factTable == null) return;\r\n\r\nvar factTableName = factTable.Name ;\r\n\r\nvar factTableColumn = SelectColumn(factTable.Columns, label: \"Select the column you wish to use for context for Total\");\r\nif(factTableColumn == null) return;\r\n\r\nvar factTableColumnName = factTableColumn.Name ;\r\n\r\nvar factTableMeasure = SelectTable(label: \"Select your table that contains your measure\");\r\nif(factTableMeasure == null) return;\r\n\r\nvar factTableNameMeasure = factTableMeasure.Name ;\r\n\r\nvar factMeasure = SelectMeasure(factTableMeasure.Measures, label: \"Select the measure\");\r\nif(factMeasure == null) return;\r\n\r\nvar factMeasureName = factMeasure.Name ;\r\n\r\n\r\nTable TableCandidate = null;\r\n\r\n// creates Calculation Items\r\n\r\nvar cg = Model.AddCalculationGroup(\"Value Presentation\");\r\n\r\n// Percent of Total by All Selected \r\nvar cg_pct_total = cg.AddCalculationItem(\"% of Total (As Selected)\" , \"IFERROR( DIVIDE( SELECTEDMEASURE() , CALCULATE( SELECTEDMEASURE() , ALLSELECTED( '\" + factTableName + \"'[\" + factTableColumnName + \"]) ) , 0 ) , SELECTEDMEASURE())\");\r\ncg_pct_total.FormatStringExpression = \"\\\"0.00%\\\"\"; \r\ncg_pct_total.Ordinal = 0 ; \r\n\r\n\r\n// Base\r\nvar cg_base = cg.AddCalculationItem(\"Base\", \"SELECTEDMEASURE()\");\r\ncg_base.FormatStringExpression = \"\\\"#,0\\\"\"; \r\ncg_base.Ordinal = 1 ; \r\n\r\n// Thousands\r\nvar cg_thous = cg.AddCalculationItem(\"Thousands\", \"IFERROR( DIVIDE ( SELECTEDMEASURE (), 1000, 0 ) , SELECTEDMEASURE())\");\r\ncg_thous.FormatStringExpression = \"\\\"#,0\\\"\"; \r\ncg_thous.Ordinal = 2 ; \r\n\r\n// Millions\r\nvar cg_mill = cg.AddCalculationItem(\"Millions\", \"IFERROR( DIVIDE ( SELECTEDMEASURE (), 1000000, 0 ) , SELECTEDMEASURE())\");\r\ncg_mill.FormatStringExpression = \"\\\"#,0.0\\\"\" ;\r\ncg_mill.Ordinal = 3 ; \r\n\r\n// Percent of Other Selected Measures (Excample: Selected Measure as a percent of Revenue Measure\r\nvar cg_pct_of_other = cg.AddCalculationItem(\"% of \" + factMeasureName + \" Measure\" , \" IFERROR( DIVIDE( SELECTEDMEASURE() , CALCULATE([\" + factMeasureName + \"] ) , 0 ) , SELECTEDMEASURE())\");\r\ncg_pct_of_other.FormatStringExpression = \"\\\"0.00%\\\"\"; \r\ncg_pct_of_other.Ordinal = 4 ; \r\n\r\n\r\n//;\r\n \r\n// creates the total measure for ALLSELECTED\r\n\r\n//{\r\n // var newMeasure = factTable.AddMeasure(\r\n // \"Total (Based on All Selected from Context Column \" + factTableColumnName + \")\" , // Name\r\n // \"CALCULATE([\" + factMeasureName + \"] , ALLSELECTED( '\" + factTableName + \"'[\" + factTableColumnName + \"]))\" // DAX expression\r\n // Display Folder\r\n // );\r\n // Set the format string on the new measure:\r\n // newMeasure.FormatString = \"#,0\";\r\n \r\n // newMeasure.IsHidden = true ; \r\n // Provide some documentation:\r\n // newMeasure.Description = \"This measure is the sum of column \" ;\r\n//}\r\n",
"Tooltip": "",
"ValidContexts": "Model, Tables, Measure, Column, CalculationGroupTable"
},
{
"Name": "Macros\\Calendar Table\\01 - Create Table",
"Enabled": "true",
"Execute": "// To use this C# Script:\r\n//\r\n// 1. Run the script\r\n// 2. Select the column that has the earliest date\r\n// 3. Select the column that has the latest date\r\n\r\n// List of all DateTime columns in the model\r\nvar _dateColumns = Model.AllColumns.Where(c => c.DataType == DataType.DateTime ).ToList();\r\n\r\nTable dateTableCandidate = null;\r\n\r\n// Select the column with the earliest date in the model\r\ntry\r\n{\r\n \r\n var EarliestDateTable = SelectTable(label: \"Select fact table with earliest date\");\r\n if(EarliestDateTable == null) return;\r\n\r\n string _EarliestDate = \r\n SelectColumn(EarliestDateTable.Columns, label: \"Select the column with earliest main date column\").DaxObjectFullName;\r\n// Select the column with the latest date in the model\r\n try\r\n {\r\n \r\n var LatestDateTable = SelectTable(label: \"Select fact table with latest date\");\r\n if(LatestDateTable == null) return;\r\n \r\n \r\n string _LatestDate = \r\n SelectColumn(LatestDateTable.Columns, label: \"Select the column with latest main date column\").DaxObjectFullName;\r\n \r\n// R.Mason - check if Measure exists already.\r\n \r\n//Define the measure name to check\r\n\r\n string measureName = \"RefDate\";\r\n\r\n// Use LINQ to check if the measure exists in the model\r\nbool measureExists = Model.AllMeasures.Any(m => m.Name == measureName);\r\n\r\n// Output the result of whether each measure already exists. If it does exist, then do nothing, if it doesnt exist\r\n// then create the measure\r\n\r\n if (measureExists) \r\n {\r\n \r\n ////if it exists. do nothing!\r\n \r\n } \r\n else \r\n {\r\n // Create measure for reference date\r\n var _RefDateMeasure = _dateColumns[0].Table.AddMeasure(\r\n \"RefDate\",\r\n \"CALCULATE ( MAX ( \" + _LatestDate + \" ), REMOVEFILTERS ( ) )\"\r\n );\r\n _RefDateMeasure.IsHidden = true;\r\n }\r\n \r\n\r\n // Formatted date table DAX\r\n // Based on a modified date table, original found from https://www.sqlbi.com/topics/date-table/\r\n // To adjust, copy everything after the @\" into a DAX query window & replace\r\n \r\n var _DateDaxExpression = @\"-- Reference date for the latest date in the report\r\n -- Until when the business wants to see data in reports\r\n VAR _Refdate_Measure = [RefDate]\r\n VAR _Today = TODAY ( )\r\n \r\n -- Replace with \"\"Today\"\" if [RefDate] evaluates blank\r\n VAR _Refdate = IF ( ISBLANK ( _Refdate_Measure ), _Today, _Refdate_Measure )\r\n VAR _RefYear = YEAR ( _Refdate )\r\n VAR _RefQuarter = _RefYear * 100 + QUARTER(_Refdate)\r\n VAR _RefMonth = _RefYear * 100 + MONTH(_Refdate)\r\n VAR _RefWeek_EU = _RefYear * 100 + WEEKNUM(_Refdate, 2)\r\n \r\n -- Earliest date in the model scope\r\n VAR _EarliestDate = DATE ( YEAR ( MIN ( \" + _EarliestDate + @\" ) ) - 2, 1, 1 )\r\n VAR _EarliestDate_Safe = MIN ( _EarliestDate, DATE ( YEAR ( _Today ) + 1, 1, 1 ) )\r\n \r\n -- Latest date in the model scope\r\n VAR _LatestDate_Safe = DATE ( YEAR ( _Refdate ) + 2, 12, 1 )\r\n \r\n ------------------------------------------\r\n -- Base calendar table\r\n VAR _Base_Calendar = CALENDAR ( _EarliestDate_Safe, _LatestDate_Safe )\r\n ------------------------------------------\r\n \r\n \r\n \r\n ------------------------------------------\r\n VAR _IntermediateResult = \r\n ADDCOLUMNS ( _Base_Calendar,\r\n \r\n ---YEAR--------------------------------------- \r\n \"\"Year Number\"\", \r\n YEAR ([Date]), \r\n \"\"Year\"\" , \r\n FORMAT ( [Date], \"\"YYYY\"\" ), \r\n \r\n \r\n ---HALF---------------------------------------\r\n \"\"Half Number\"\" , IF( QUARTER( [Date] ) = 1 || QUARTER( [Date] ) = 2 , 1 , 2 ) ,\r\n \"\"Half\"\" , \"\"H\"\" & IF( QUARTER( [Date] ) = 1 || QUARTER( [Date] ) = 2 , 1 , 2 ) & \"\" \"\" & YEAR([Date]) ,\r\n \"\"Half Year\"\" , YEAR([Date]) * 100 + IF( QUARTER( [Date] ) = 1 || QUARTER( [Date] ) = 2 , 1 , 2 ) ,\r\n \r\n ---QUARTER---------------------------------------\r\n \"\"Quarter\"\", \r\n \"\"Q\"\" & \r\n CONVERT(QUARTER([Date]), STRING) & \r\n \"\" \"\" & \r\n CONVERT(YEAR([Date]), STRING), \r\n \r\n \"\"Year Quarter\"\", \r\n YEAR([Date]) * 100 + QUARTER([Date]), \r\n \r\n ---MONTH---------------------------------------\r\n \"\"Month Year\"\", \r\n FORMAT ( [Date], \"\"MMM YY\"\" ), \r\n \r\n \"\"Year Month\"\", \r\n YEAR([Date]) * 100 + MONTH([Date]), \r\n \r\n \"\"Month Name\"\", \r\n FORMAT ( [Date], \"\"MMM\"\" ), \r\n \r\n \"\"Month Number\"\", \r\n MONTH ( [Date] ), \r\n \r\n \"\"Month\"\", \r\n FORMAT([Date] , \"\"YYYY-MM\"\") , \r\n \r\n \r\n ---DAY---------------------------------------\r\n \r\n \"\"YYYYMMDD\"\", \r\n YEAR ( [Date] ) * 10000 \r\n + \r\n MONTH ( [Date] ) * 100 \r\n + \r\n DAY ( [Date] ), \r\n \r\n ---CONTINUOUS GRAPH---------------------------------------\r\n \r\n \"\"Month (Graph)\"\" , EOMONTH( [Date] , 0 ) ,\r\n \"\"Year (Graph)\"\" , EOMONTH( DATE( YEAR( [Date] ) , 12 , 31 ), 0 ) ,\r\n \r\n \r\n \r\n ---BOOLEAN---------------------------------------\r\n \"\"IsDateInScope\"\", \r\n [Date] <= _Refdate \r\n && \r\n YEAR([Date]) > YEAR(_EarliestDate), \r\n \r\n \"\"IsBeforeThisMonth\"\", \r\n [Date] <= EOMONTH ( _Refdate, -1 ), \r\n \r\n \"\"IsLastMonth\"\", \r\n [Date] <= EOMONTH ( _Refdate, 0 ) \r\n && \r\n [Date] > EOMONTH ( _Refdate, -1 ), \r\n \r\n \"\"IsYTD\"\", \r\n MONTH([Date]) \r\n <= \r\n MONTH(EOMONTH ( _Refdate, 0 )), \r\n \r\n \"\"IsActualToday\"\", \r\n [Date] = _Today, \r\n \r\n \"\"IsRefDate\"\", \r\n [Date] = _Refdate, \r\n \r\n \"\"IsHoliday\"\", \r\n MONTH([Date]) * 100 \r\n + \r\n DAY([Date]) \r\n IN {0101, 0501, 1111, 1225}, \r\n \r\n \"\"IsWeekday\"\", \r\n WEEKDAY([Date], 2) \r\n IN {1, 2, 3, 4, 5}) \r\n \r\n \r\n VAR _Result = \r\n \r\n ---BOOLEAN2-----------------------------------------\r\n ADDCOLUMNS ( \r\n _IntermediateResult, \r\n \"\"IsThisYear\"\", \r\n [Year Number] \r\n = _RefYear, \r\n \r\n \"\"IsThisMonth\"\", \r\n [Year Month] \r\n = _RefMonth, \r\n \r\n \"\"IsThisQuarter\"\", \r\n [Year Quarter] \r\n = _RefQuarter \r\n \r\n ) \r\n \r\n \r\n RETURN \r\n _Result\";\r\n \r\n // Create date table\r\n var _date = Model.AddCalculatedTable(\r\n \"Calendar\",\r\n _DateDaxExpression\r\n );\r\n \r\n \r\n \r\n // Mark as date table\r\n _date.DataCategory = \"Time\";\r\n \r\n \r\n //-------------------------------------------------------------------------------------------//\r\n \r\n \r\n Info ( \"Created a new, organized 'Date' table based on the template in the C# Script.\\nThe Earliest Date is taken from \" + _EarliestDate + \"\\nThe Latest Date is taken from \" + _LatestDate );\r\n \r\n }\r\n catch (Exception ex )\r\n{\r\n Output( ex ); \r\n}\r\n}\r\ncatch\r\n{\r\n Error( \"Earliest column not selected! Ending script without making changes.\" );\r\n}\r\n\r\n",
"Tooltip": "",
"ValidContexts": "Model, Table"
},
{
"Name": "Macros\\Calendar Table\\02 - Additional Formatting",
"Enabled": "true",
"Execute": "// Prompt for calendar table selection\r\n\r\nvar dateTable = SelectTable(label: \"Select your date table\");\r\nif(dateTable == null) return;\r\n\r\n// Set the sort by column\r\n\r\n\r\n(dateTable.Columns[\"Quarter\"] as CalculatedTableColumn).SortByColumn = (Selected.Table.Columns[\"Year Quarter\"] as CalculatedTableColumn);\r\n(dateTable.Columns[\"Month Name\"] as CalculatedTableColumn).SortByColumn = (Selected.Table.Columns[\"Month Number\"] as CalculatedTableColumn);\r\n(dateTable.Columns[\"Half\"] as CalculatedTableColumn).SortByColumn = (Selected.Table.Columns[\"Half Year\"] as CalculatedTableColumn);\r\n\r\n// Create Hierarchy\r\nvar h = dateTable.AddHierarchy(\"Calendar Hierarchy\");\r\nh.AddLevel(\"Year\");\r\nh.AddLevel(\"Half\");\r\nh.AddLevel(\"Quarter\");\r\nh.AddLevel(\"Month\");\r\nh.AddLevel(\"Date\");\r\n\r\n// Assign Columns to Folders\r\n\r\n \r\n foreach (var c in dateTable.Columns )\r\n {\r\n c.DisplayFolder = \"7. Boolean Fields\";\r\n c.IsHidden = true;\r\n \r\n // Organize the date table into folders\r\n \r\n \r\n \r\n if ( ( c.DataType == DataType.DateTime & c.Name.Contains(\"Date\") ) )\r\n {\r\n c.DisplayFolder = \"5. Date\";\r\n c.IsHidden = false;\r\n c.IsKey = true;\r\n }\r\n \r\n if ( c.Name == \"YYMMDDDD\" )\r\n {\r\n c.DisplayFolder = \"5. Date\";\r\n c.IsHidden = true;\r\n }\r\n \r\n if ( c.Name.Contains(\"Year\") & c.DataType != DataType.Boolean )\r\n {\r\n c.DisplayFolder = \"1. Year\";\r\n c.IsHidden = false;\r\n }\r\n \r\n if ( c.Name.Contains(\"Half\") & c.DataType != DataType.Boolean )\r\n {\r\n c.DisplayFolder = \"2. Half\";\r\n c.IsHidden = false;\r\n }\r\n\r\n \r\n if ( c.Name.Contains(\"Month\") & c.DataType != DataType.Boolean )\r\n {\r\n c.DisplayFolder = \"4. Month\";\r\n c.IsHidden = false;\r\n }\r\n \r\n if ( c.Name.Contains(\"Quarter\") & c.DataType != DataType.Boolean )\r\n {\r\n c.DisplayFolder = \"3. Quarter\";\r\n c.IsHidden = false;\r\n }\r\n \r\n if ( c.Name == (\"Month (Graph)\") )\r\n {\r\n c.DisplayFolder = \"6. Continuous Graph\";\r\n c.IsHidden = false;\r\n c.DataType = DataType.DateTime;\r\n c.FormatString = \"YYYY-MM\";\r\n }\r\n\r\n \r\n if ( c.Name == (\"Year (Graph)\" ) )\r\n { \r\n c.DisplayFolder = \"6. Continuous Graph\" ;\r\n c.DataType = DataType.DateTime;\r\n c.FormatString = \"YYYY\";\r\n \r\n } \r\n \r\n }\r\n \r\n \r\n \r\n//Format Dax of Calendar Table\r\n \r\n\r\n dateTable.FormatDax();\r\n \r\n ",
"Tooltip": "",
"ValidContexts": "Model, Table"
},
{
"Name": "Macros\\Calendar Table\\03 - Create Relationships",
"Enabled": "true",
"Execute": " // Prompt for Table Selection\r\n \r\nvar factTable = SelectTable(label: \"Select your fact table\");\r\nif(factTable == null) return;\r\n\r\nvar factTableDateColumn = SelectColumn(factTable.Columns, label: \"Select the main date column\");\r\nif(factTableDateColumn == null) return;\r\n\r\nTable dateTableCandidate = null;\r\n\r\nif(Model.Tables.Any\r\n (x => x.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Date Table\" \r\n || x.Name == \"Date\" \r\n || x.Name == \"Calendar\")){\r\n dateTableCandidate = Model.Tables.Where\r\n (x => x.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Date Table\" \r\n || x.Name == \"Date\" \r\n || x.Name == \"Calendar\").First();\r\n\r\n};\r\n\r\nvar dateTable = \r\n SelectTable(\r\n label: \"Select your date table\",\r\n preselect:dateTableCandidate);\r\n\r\nif(dateTable == null) {\r\n Error(\"You just aborted the script\"); \r\n return;\r\n} else {\r\n dateTable.SetAnnotation(\"@AgulloBernat\",\"Time Intel Date Table\");\r\n}; \r\n\r\n\r\nColumn dateTableDateColumnCandidate = null; \r\n\r\nif(dateTable.Columns.Any\r\n (x => x.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Date Table Date Column\" || x.Name == \"Date\")){\r\n dateTableDateColumnCandidate = dateTable.Columns.Where\r\n (x => x.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Date Table Date Column\" || x.Name == \"Date\").First();\r\n};\r\n\r\nvar dateTableDateColumn = \r\n SelectColumn(\r\n dateTable.Columns, \r\n label: \"Select the date column\",\r\n preselect: dateTableDateColumnCandidate);\r\n \r\nstring factTableName = factTable.Name;\r\nstring dateTableName = dateTable.Name;\r\nstring dateTableDateColumnName = dateTableDateColumn.Name;\r\nstring factTableDateColumnName = factTableDateColumn.Name;\r\n\r\n\r\n\r\n\r\nvar fromColumn = Model.Tables[factTableName].Columns[factTableDateColumnName] ; // Enter the 'from' part of the relationship\r\nvar toColumn = Model.Tables[dateTableName].Columns[dateTableDateColumnName ]; // Enter the 'to' part of the relationship\r\nfromColumn.IsHidden = true;\r\n{\r\n var r = Model.AddRelationship();\r\n r.FromColumn = fromColumn;\r\n r.ToColumn = toColumn;\r\n r.FromCardinality = RelationshipEndCardinality.Many;\r\n r.ToCardinality = RelationshipEndCardinality.One;\r\n r.CrossFilteringBehavior = CrossFilteringBehavior.OneDirection; //CrossFilteringBehavior.BothDirections\r\n \r\n}",
"Tooltip": "",
"ValidContexts": "Model, Measure, CalculationGroupTable, CalculationItem"
},
{
"Name": "Macros\\Calendar Table\\04 - Time Intelligence Calculation Group",
"Enabled": "true",
"Execute": "#r \"Microsoft.VisualBasic\"\r\nusing Microsoft.VisualBasic;\r\n//\r\n// CHANGELOG:\r\n// '2021-05-01 / B.Agullo / \r\n// '2021-05-17 / B.Agullo / added affected measure table\r\n// '2021-06-19 / B.Agullo / data label measures\r\n// '2021-07-10 / B.Agullo / added flag expression to avoid breaking already special format strings\r\n// '2021-09-23 / B.Agullo / added code to prompt for parameters (code credit to Daniel Otykier) \r\n// '2021-09-27 / B.Agullo / added code for general name \r\n// '2022-10-11 / B.Agullo / added MMT and MWT calc item groups\r\n// '2024-06-12 / R.Mason / removed calc item groups that I do not use and added ones that I do use\r\n// '2024-06-13 / R.Mason / added check for Label measures. Also added code to impact all measures, but you can edit the table after the fact\r\n\r\n\r\n\r\n// by Bernat Agulló\r\n// twitter: @AgulloBernat\r\n// www.esbrina-ba.com/blog\r\n//\r\n// REFERENCE: \r\n// Check out https://www.esbrina-ba.com/time-intelligence-the-smart-way/ where this script is introduced\r\n// \r\n// FEATURED: \r\n// this script featured in GuyInACube https://youtu.be/_j0iTUo2HT0\r\n//\r\n// THANKS:\r\n// shout out to Johnny Winter for the base script and SQLBI for daxpatterns.com\r\n\r\n//select the measures that you want to be affected by the calculation group\r\n//before running the script. \r\n//measure names can also be included in the following array (no need to select them) \r\nstring[] preSelectedMeasures = {}; //include measure names in double quotes, like: {\"Profit\",\"Total Cost\"};\r\n\r\n//AT LEAST ONE MEASURE HAS TO BE AFFECTED!, \r\n//either by selecting it or typing its name in the preSelectedMeasures Variable\r\n\r\n// **** NOTE THAT THE MEASURES FOR LABEL FORMATTING ARE NOT WORKING CORRECTLY FOR ANYTHING OUTSIDE OF YEAR CALCS. WILL HAVE TO RETURN \r\n// TO THESE AT SOME POINT, BUT LOW PRIORITY FOR NOW - R.MASON ****\r\n\r\n//\r\n// ----- do not modify script below this line -----\r\n//\r\n\r\n\r\nstring affectedMeasures = \"{\";\r\n\r\nint i = 0; \r\n\r\nfor (i=0;i<preSelectedMeasures.GetLength(0);i++){\r\n \r\n if(affectedMeasures == \"{\") {\r\n affectedMeasures = affectedMeasures + \"\\\"\" + preSelectedMeasures[i] + \"\\\"\";\r\n }else{\r\n affectedMeasures = affectedMeasures + \",\\\"\" + preSelectedMeasures[i] + \"\\\"\" ;\r\n }; \r\n \r\n};\r\n\r\n//*** this part of the code lets you select the measures to load to the Time Intellegence Affected Measures table (the impacted measures)\r\n\r\n//if (Selected.Measures.Count != 0) {\r\n// foreach(var m in Selected.Measures) {\r\n\r\n// dont forget to close the bracket below the foreach code\r\n\r\n//*** \r\n\r\nforeach(var m in Model.AllMeasures) { // if you just want load all the measures, use this code. Otherwise replace with the Selected.Measures code above.\r\n if(affectedMeasures == \"{\") {\r\n affectedMeasures = affectedMeasures + \"\\\"\" + m.Name + \"\\\"\";\r\n }else{\r\n affectedMeasures = affectedMeasures + \",\\\"\" + m.Name + \"\\\"\" ;\r\n };\r\n }; \r\n// if you use the Selected.Measures code, then make sure you close the curly bracket:\r\n//};\r\n\r\n\r\n//check that by either method at least one measure is affected\r\nif(affectedMeasures == \"{\") { \r\n Error(\"No measures affected by calc group\"); \r\n return; \r\n};\r\n\r\nstring calcGroupName; \r\nstring columnName; \r\n\r\nif(Model.CalculationGroups.Any(cg => cg.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Calc Group\")) {\r\n calcGroupName = Model.CalculationGroups.Where(cg => cg.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Calc Group\").First().Name;\r\n \r\n}else {\r\n calcGroupName = Interaction.InputBox(\"Provide a name for your Calc Group\", \"Calc Group Name\", \"Time Intelligence\", 740, 400);\r\n}; \r\n\r\nif(calcGroupName == \"\") return;\r\n\r\n\r\nif(Model.CalculationGroups.Any(cg => cg.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Calc Group\")) {\r\n columnName = Model.Tables.Where(cg => cg.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Calc Group\").First().Columns.First().Name;\r\n \r\n}else {\r\n columnName = Interaction.InputBox(\"Provide a name for your Calc Group Column\", \"Calc Group Column Name\", calcGroupName, 740, 400);\r\n}; \r\n\r\nif(columnName == \"\") return;\r\n\r\nstring affectedMeasuresTableName; \r\n\r\nif(Model.Tables.Any(t => t.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Affected Measures Table\")) {\r\n affectedMeasuresTableName = Model.Tables.Where(t => t.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Affected Measures Table\").First().Name;\r\n\r\n} else {\r\n affectedMeasuresTableName = Interaction.InputBox(\"Provide a name for affected measures table\", \"Affected Measures Table Name\", calcGroupName + \" Affected Measures\", 740, 400);\r\n\r\n};\r\n\r\nif(affectedMeasuresTableName == \"\") return;\r\n\r\nstring affectedMeasuresColumnName = Interaction.InputBox(\"Provide a name for affected measures table column name\", \"Affected Measures Table Column Name\", \"Measure\", 740, 400);\r\n\r\nif(Model.Tables.Any(t => t.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Affected Measures Table\")) {\r\n affectedMeasuresColumnName = Model.Tables.Where(t => t.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Affected Measures Table\").First().Columns.First().Name;\r\n\r\n} else {\r\n affectedMeasuresColumnName = Interaction.InputBox(\"Provide a name for affected measures column\", \"Affected Measures Table Column Name\", \"Measure\", 740, 400);\r\n\r\n};\r\n\r\n\r\nif(affectedMeasuresColumnName == \"\") return;\r\n//string affectedMeasuresColumnName = \"Affected Measure\"; \r\n\r\nstring labelAsValueMeasureName = \"Label as Value Measure\"; \r\nstring labelAsFormatStringMeasureName = \"Label as format string\"; \r\n\r\n\r\n // '2021-09-24 / B.Agullo / model object selection prompts! \r\nvar factTable = SelectTable(label: \"Select your fact table\");\r\nif(factTable == null) return;\r\n\r\nvar factTableDateColumn = SelectColumn(factTable.Columns, label: \"Select the main date column\");\r\nif(factTableDateColumn == null) return;\r\n\r\nTable dateTableCandidate = null;\r\n\r\nif(Model.Tables.Any\r\n (x => x.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Date Table\" \r\n || x.Name == \"Date\" \r\n || x.Name == \"Calendar\")){\r\n dateTableCandidate = Model.Tables.Where\r\n (x => x.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Date Table\" \r\n || x.Name == \"Date\" \r\n || x.Name == \"Calendar\").First();\r\n\r\n};\r\n\r\nvar dateTable = \r\n SelectTable(\r\n label: \"Select your date table\",\r\n preselect:dateTableCandidate);\r\n\r\nif(dateTable == null) {\r\n Error(\"You just aborted the script\"); \r\n return;\r\n} else {\r\n dateTable.SetAnnotation(\"@AgulloBernat\",\"Time Intel Date Table\");\r\n}; \r\n\r\n\r\nColumn dateTableDateColumnCandidate = null; \r\n\r\nif(dateTable.Columns.Any\r\n (x => x.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Date Table Date Column\" || x.Name == \"Date\")){\r\n dateTableDateColumnCandidate = dateTable.Columns.Where\r\n (x => x.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Date Table Date Column\" || x.Name == \"Date\").First();\r\n};\r\n\r\nvar dateTableDateColumn = \r\n SelectColumn(\r\n dateTable.Columns, \r\n label: \"Select the date column\",\r\n preselect: dateTableDateColumnCandidate);\r\n\r\nif(dateTableDateColumn == null) {\r\n Error(\"You just aborted the script\"); \r\n return;\r\n} else { \r\n dateTableDateColumn.SetAnnotation(\"@AgulloBernat\",\"Time Intel Date Table Date Column\"); \r\n}; \r\n\r\nColumn dateTableYearColumnCandidate = null;\r\nif(dateTable.Columns.Any(x => x.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Date Table Year Column\" || x.Name == \"Year\")){\r\n dateTable.Columns.Where\r\n (x => x.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Date Table Year Column\" || x.Name == \"Year\").First();\r\n};\r\n\r\nvar dateTableYearColumn = \r\n SelectColumn(\r\n dateTable.Columns, \r\n label: \"Select the year column\", \r\n preselect:dateTableYearColumnCandidate);\r\n\r\nif(dateTableYearColumn == null) {\r\n Error(\"You just abourted the script\"); \r\n return;\r\n} else {\r\n dateTableYearColumn.SetAnnotation(\"@AgulloBernat\",\"Time Intel Date Table Year Column\"); \r\n};\r\n\r\n\r\n//these names are for internal use only, so no need to be super-fancy, better stick to datpatterns.com model\r\nstring ShowValueForDatesMeasureName = \"ShowValueForDates\"; \r\nstring dateWithSalesColumnName = \"DateWith\" + factTable.Name;\r\n\r\n\r\n\r\n\r\n\r\n// '2021-09-24 / B.Agullo / I put the names back to variables so I don't have to tough the script\r\nstring factTableName = factTable.Name;\r\nstring factTableDateColumnName = factTableDateColumn.Name;\r\nstring dateTableName = dateTable.Name;\r\nstring dateTableDateColumnName = dateTableDateColumn.Name;\r\nstring dateTableYearColumnName = dateTableYearColumn.Name; \r\n\r\n// '2021-09-24 / B.Agullo / this is for internal use only so better leave it as is \r\nstring flagExpression = \"UNICHAR( 8204 )\"; \r\n\r\nstring calcItemProtection = \"<CODE>\"; //default value if user has selected no measures\r\nstring calcItemFormatProtection = \"<CODE>\"; //default value if user has selected no measures\r\n\r\n// check if there's already an affected measure table\r\nif(Model.Tables.Any(t => t.GetAnnotation(\"@AgulloBernat\") == \"Time Intel Affected Measures Table\")) {\r\n //modifying an existing calculated table is not risk-free\r\n Info(\"Make sure to include measure names to the table \" + affectedMeasuresTableName);\r\n} else { \r\n // create calculated table containing all names of affected measures\r\n // this is why you need to enable \r\n if(affectedMeasures != \"{\") { \r\n \r\n affectedMeasures = affectedMeasures + \"}\";\r\n \r\n string affectedMeasureTableExpression = \r\n \"SELECTCOLUMNS(\" + affectedMeasures + \",\\\"\" + affectedMeasuresColumnName + \"\\\",[Value])\";\r\n\r\n var affectedMeasureTable = \r\n Model.AddCalculatedTable(affectedMeasuresTableName,affectedMeasureTableExpression);\r\n \r\n affectedMeasureTable.FormatDax(); \r\n affectedMeasureTable.Description = \r\n \"Measures affected by \" + calcGroupName + \" calculation group.\" ;\r\n \r\n affectedMeasureTable.SetAnnotation(\"@AgulloBernat\",\"Time Intel Affected Measures Table\"); \r\n \r\n // this causes error\r\n // affectedMeasureTable.Columns[affectedMeasuresColumnName].SetAnnotation(\"@AgulloBernat\",\"Time Intel Affected Measures Table Column\");\r\n\r\n affectedMeasureTable.IsHidden = true; \r\n \r\n };\r\n};\r\n\r\n//if there where selected or preselected measures, prepare protection code for expresion and formatstring\r\nstring affectedMeasuresValues = \"VALUES('\" + affectedMeasuresTableName + \"'[\" + affectedMeasuresColumnName + \"])\";\r\n\r\ncalcItemProtection = \r\n \"SWITCH(\" + \r\n \" TRUE(),\" + \r\n \" SELECTEDMEASURENAME() IN \" + affectedMeasuresValues + \",\" + \r\n \" <CODE> ,\" + \r\n \" ISSELECTEDMEASURE([\" + labelAsValueMeasureName + \"]),\" + \r\n \" <LABELCODE> ,\" + \r\n \" SELECTEDMEASURE() \" + \r\n \")\";\r\n \r\n \r\ncalcItemFormatProtection = \r\n \"SWITCH(\" + \r\n \" TRUE() ,\" + \r\n \" SELECTEDMEASURENAME() IN \" + affectedMeasuresValues + \",\" + \r\n \" <CODE> ,\" + \r\n \" ISSELECTEDMEASURE([\" + labelAsFormatStringMeasureName + \"]),\" + \r\n \" <LABELCODEFORMATSTRING> ,\" +\r\n \" SELECTEDMEASUREFORMATSTRING() \" + \r\n \")\";\r\n\r\n \r\nstring dateColumnWithTable = \"'\" + dateTableName + \"'[\" + dateTableDateColumnName + \"]\"; \r\nstring yearColumnWithTable = \"'\" + dateTableName + \"'[\" + dateTableYearColumnName + \"]\"; \r\nstring factDateColumnWithTable = \"'\" + factTableName + \"'[\" + factTableDateColumnName + \"]\";\r\nstring dateWithSalesWithTable = \"'\" + dateTableName + \"'[\" + dateWithSalesColumnName + \"]\";\r\nstring calcGroupColumnWithTable = \"'\" + calcGroupName + \"'[\" + columnName + \"]\";\r\n\r\n//check to see if a table with this name already exists\r\n//if it doesnt exist, create a calculation group with this name\r\nif (!Model.Tables.Contains(calcGroupName)) {\r\n var cg = Model.AddCalculationGroup(calcGroupName);\r\n cg.Description = \"Calculation group for time intelligence. Availability of data is taken from \" + factTableName + \".\";\r\n cg.SetAnnotation(\"@AgulloBernat\",\"Time Intel Calc Group\"); \r\n};\r\n\r\n//set variable for the calc group\r\nTable calcGroup = Model.Tables[calcGroupName];\r\n\r\n//if table already exists, make sure it is a Calculation Group type\r\nif (calcGroup.SourceType.ToString() != \"CalculationGroup\") {\r\n Error(\"Table exists in Model but is not a Calculation Group. Rename the existing table or choose an alternative name for your Calculation Group.\");\r\n return;\r\n};\r\n\r\n//adds the two measures that will be used for label as value, label as format string \r\n//built in check to see if the Label measures exists or not. If they exist, then do nothing, otherwise create them.\r\n\r\n// Define the measure name to check\r\nstring measureName = \"Label as format string\";\r\nstring measureName2 = \"Label as Value Measure\";\r\n// Use LINQ to check if the measure exists in the model\r\nbool measureExists = Model.AllMeasures.Any(m => m.Name == measureName);\r\nbool measureExists2 = Model.AllMeasures.Any(m => m.Name == measureName2);\r\n\r\n\r\n// Output the result of whether each measure already exists. If it does exist, then do nothing, if it doesnt exist\r\n// then create the measure\r\n\r\n if (measureExists) \r\n {\r\n \r\n ////if it exists. do nothing!\r\n \r\n } \r\n else \r\n {\r\n var labelAsValueMeasure = calcGroup.AddMeasure(labelAsValueMeasureName,\"\");\r\n labelAsValueMeasure.IsHidden = true;\r\n }\r\n \r\n if (measureExists2) \r\n {\r\n ////if it exists. do nothing! \r\n } \r\n else \r\n {\r\n var labelAsFormatStringMeasure = calcGroup.AddMeasure(labelAsFormatStringMeasureName,\"0\");\r\n labelAsFormatStringMeasure.IsHidden = true;\r\n }\r\n\r\n//var labelAsFormatStringMeasure = calcGroup.AddMeasure(labelAsFormatStringMeasureName,\"0\");\r\n//labelAsFormatStringMeasure.Description = \"Use this measure to show the year evaluated in charts\"; \r\n\r\n//by default the calc group has a column called Name. If this column is still called Name change this in line with specfied variable\r\nif (calcGroup.Columns.Contains(\"Name\")) {\r\n calcGroup.Columns[\"Name\"].Name = columnName;\r\n\r\n};\r\n\r\ncalcGroup.Columns[columnName].Description = \"Select value(s) from this column to apply time intelligence calculations.\";\r\ncalcGroup.Columns[columnName].SetAnnotation(\"@AgulloBernat\",\"Time Intel Calc Group Column\"); \r\n\r\n\r\n//Only create them if not in place yet (reruns)\r\nif(!Model.Tables[dateTableName].Columns.Any(C => C.GetAnnotation(\"@AgulloBernat\") == \"Date with Data Column\")){\r\n string DateWithSalesCalculatedColumnExpression = \r\n dateColumnWithTable + \" <= MAX ( \" + factDateColumnWithTable + \")\";\r\n\r\n Column dateWithDataColumn = dateTable.AddCalculatedColumn(dateWithSalesColumnName,DateWithSalesCalculatedColumnExpression);\r\n dateWithDataColumn.SetAnnotation(\"@AgulloBernat\",\"Date with Data Column\");\r\n dateWithDataColumn.IsHidden = true ;\r\n};\r\n\r\nif(!Model.Tables[dateTableName].Measures.Any(M => M.Name == ShowValueForDatesMeasureName)) {\r\n string ShowValueForDatesMeasureExpression = \r\n \"VAR LastDateWithData = \" + \r\n \" CALCULATE ( \" + \r\n \" MAX ( \" + factDateColumnWithTable + \" ), \" + \r\n \" REMOVEFILTERS () \" +\r\n \" )\" +\r\n \"VAR FirstDateVisible = \" +\r\n \" MIN ( \" + dateColumnWithTable + \" ) \" + \r\n \"VAR Result = \" + \r\n \" FirstDateVisible <= LastDateWithData \" +\r\n \"RETURN \" + \r\n \" Result \";\r\n\r\n var ShowValueForDatesMeasure = dateTable.AddMeasure(ShowValueForDatesMeasureName,ShowValueForDatesMeasureExpression); \r\n\r\n ShowValueForDatesMeasure.FormatDax();\r\n ShowValueForDatesMeasure.IsHidden = true;\r\n\r\n\r\n \r\n};\r\n\r\n\r\n\r\n//defining expressions and formatstring for each calc item\r\nstring Base = \r\n \"/*Base*/ \" + \r\n \"SELECTEDMEASURE()\";\r\n\r\nstring Baselabel = \r\n \"SELECTEDVALUE(\" + yearColumnWithTable + \")\";\r\n\r\nstring MTD = \r\n \"/*MTD*/\" + \r\n \"IF (\" +\r\n \" [\" + ShowValueForDatesMeasureName + \"],\" + \r\n \" CALCULATE (\" +\r\n \" \" + Base+ \",\" + \r\n \" DATESMTD (\" + dateColumnWithTable + \" )\" + \r\n \" )\" + \r\n \") \";\r\n \r\n\r\nstring MTDlabel = Baselabel + \"& \\\" MTD\\\"\"; \r\n \r\nstring QTD = \r\n \"/*QTD*/\" + \r\n \"IF (\" +\r\n \" [\" + ShowValueForDatesMeasureName + \"],\" + \r\n \" CALCULATE (\" +\r\n \" \" + Base+ \",\" + \r\n \" DATESQTD (\" + dateColumnWithTable + \" )\" + \r\n \" )\" + \r\n \") \";\r\n \r\n\r\nstring QTDlabel = Baselabel + \"& \\\" QTD\\\"\"; \r\n \r\nstring YTD = \r\n \"/*YTD*/\" + \r\n \"IF (\" +\r\n \" [\" + ShowValueForDatesMeasureName + \"],\" + \r\n \" CALCULATE (\" +\r\n \" \" + Base+ \",\" + \r\n \" DATESYTD (\" + dateColumnWithTable + \" )\" + \r\n \" )\" + \r\n \") \";\r\n \r\n\r\nstring YTDlabel = Baselabel + \"& \\\" YTD\\\"\"; \r\n\r\n\r\nstring T3M = \r\n \"/*T3M*/\" + \r\n \"IF (\" +\r\n \" [\" + ShowValueForDatesMeasureName + \"],\" + \r\n \" CALCULATE (\" +\r\n \" \" + Base + \",\" + \r\n \" DATESINPERIOD (\" + dateColumnWithTable + \", LASTDATE( \" + dateColumnWithTable + \" ) , -3 , MONTH )\" + \r\n \" )\" + \r\n \") \";\r\n \r\n\r\nstring T3Mlabel = Baselabel + \"& \\\" T3M\\\"\"; \r\n\r\n\r\nstring TTM = \r\n \"/*TTM*/\" + \r\n \"IF (\" +\r\n \" [\" + ShowValueForDatesMeasureName + \"],\" + \r\n \" CALCULATE (\" +\r\n \" \" + Base + \",\" + \r\n \" DATESINPERIOD (\" + dateColumnWithTable + \", LASTDATE( \" + dateColumnWithTable + \" ) , -12 , MONTH )\" + \r\n \" )\" + \r\n \") \";\r\n \r\n\r\n string TTMlabel = Baselabel + \"& \\\" TTM\\\"\"; \r\n\r\n \r\nstring ITD = \r\n \"/*ITD*/\" + \r\n \"VAR MAX_DATE = MAX( \" + dateColumnWithTable + \")\" + \r\n \"RETURN \" + \"/*blankspace*/\" +\r\n \" IF (\" +\r\n \" [\" + ShowValueForDatesMeasureName + \"],\" + \r\n \" CALCULATE (\" +\r\n \" \" + Base+ \",\" + \r\n \" \" + dateColumnWithTable + \"<= MAX_DATE , \" + \r\n \" ALL ('\" + dateTableName + \"' )\" + \r\n \" )\" + \r\n \") \";\r\n \r\n\r\nstring ITDlabel = Baselabel + \"& \\\" ITD\\\"\"; \r\n\r\nstring PMTD = \r\n \"/*PMTD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ MTD + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, MONTH ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \";\r\n \r\n\r\nstring PMTDlabel = \r\n \"/*PMTD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ MTDlabel + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, MONTH ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \"; \r\n \r\nstring PQTD = \r\n \"/*PQTD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ QTD + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, QUARTER ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \";\r\n \r\n\r\nstring PQTDlabel = \r\n \"/*PQTD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ QTDlabel + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, QUARTER ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \"; \r\n \r\nstring PYTD = \r\n \"/*PYTD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ YTD + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, YEAR ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \";\r\n \r\n\r\nstring PYTDlabel = \r\n \"/*PYTD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ YTDlabel + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, YEAR ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \"; \r\n \r\n \r\n \r\nstring PYMTD = \r\n \"/*PYMTD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ MTD + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, YEAR ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \";\r\n \r\n \r\n\r\nstring PYMTDlabel = \r\n \"/*PYMTD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ MTDlabel + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, YEAR ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \"; \r\n \r\n \r\nstring PYQTD = \r\n \"/*PYQTD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ QTD + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, YEAR ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \";\r\n \r\n\r\nstring PYQTDlabel = \r\n \"/*PYQTD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ QTDlabel + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, YEAR ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \"; \r\n \r\n \r\nstring PYITD = \r\n \"/*PYITD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ ITD + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, YEAR ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \";\r\n \r\n\r\nstring PYITDlabel = \r\n \"/*PYITD*/ \" +\r\n \"IF (\" + \r\n \" [\" + ShowValueForDatesMeasureName + \"], \" + \r\n \" CALCULATE ( \" + \r\n \" \"+ ITDlabel + \", \" + \r\n \" CALCULATETABLE ( \" + \r\n \" DATEADD ( \" + dateColumnWithTable + \" , -1, YEAR ), \" + \r\n \" \" + dateWithSalesWithTable + \" = TRUE \" + \r\n \" ) \" + \r\n \" ) \" + \r\n \") \"; \r\n \r\n\r\nstring ΔMoM = \r\n \"/*ΔMoM*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + MTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PMTD + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n\r\nstring ΔMoMlabel = \r\n \"/*ΔMoM*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + MTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PMTDlabel + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n\r\nstring ΔQoQ = \r\n \"/*ΔQoQ*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + QTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PQTD + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n\r\nstring ΔQoQlabel = \r\n \"/*ΔQoQ*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + QTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PQTDlabel + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n \r\nstring ΔYoY = \r\n \"/*ΔYoY*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + YTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYTD + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n\r\nstring ΔYoYlabel = \r\n \"/*ΔYoY*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + YTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYTDlabel + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n \r\n \r\nstring MOMTDpct = \r\n \"/*ΔMOM%*/\" + \r\n \"VAR ValueCurrentPeriod = \" + MTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PMTD + \" \" + \r\n \"VAR CurrentMinusPreviousPeriod = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"VAR Result = \" + \r\n \"DIVIDE ( \" + \r\n \" CurrentMinusPreviousPeriod,\" + \r\n \" ValuePreviousPeriod\" + \r\n \") \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n\r\n\r\nstring MOMTDpctLabel = \r\n \"/*ΔMOM%*/ \" +\r\n \"VAR ValueCurrentPeriod = \" + MTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PMTDlabel + \" \" + \r\n \"VAR Result = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod & \\\" (%)\\\"\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n\r\n \r\nstring QOQTDpct = \r\n \"/*ΔQOQ%*/\" + \r\n \"VAR ValueCurrentPeriod = \" + QTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PQTD + \" \" + \r\n \"VAR CurrentMinusPreviousPeriod = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"VAR Result = \" + \r\n \"DIVIDE ( \" + \r\n \" CurrentMinusPreviousPeriod,\" + \r\n \" ValuePreviousPeriod\" + \r\n \") \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n\r\n\r\nstring QOQTDpctLabel = \r\n \"/*ΔQOQ%*/ \" +\r\n \"VAR ValueCurrentPeriod = \" + QTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PQTDlabel + \" \" + \r\n \"VAR Result = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod & \\\" (%)\\\"\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n\r\n \r\n \r\nstring YOYTDpct = \r\n \"/*ΔYOY%*/\" + \r\n \"VAR ValueCurrentPeriod = \" + YTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYTD + \" \" + \r\n \"VAR CurrentMinusPreviousPeriod = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"VAR Result = \" + \r\n \"DIVIDE ( \" + \r\n \" CurrentMinusPreviousPeriod,\" + \r\n \" ValuePreviousPeriod\" + \r\n \") \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n\r\n\r\nstring YOYTDpctLabel = \r\n \"/*ΔYOY%*/ \" +\r\n \"VAR ValueCurrentPeriod = \" + YTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYTDlabel + \" \" + \r\n \"VAR Result = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod & \\\" (%)\\\"\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n\r\nstring ΔMoM_PY = \r\n \"/*ΔMoM_PY*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + MTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYMTD + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n\r\nstring ΔMoM_PYlabel = \r\n \"/*ΔMoM_PY*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + MTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYMTDlabel + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n\r\nstring ΔQoQ_PY = \r\n \"/*ΔQoQ_PY*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + QTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYQTD + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n\r\nstring ΔQoQ_PYlabel = \r\n \"/*ΔQoQ_PY*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + QTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYQTDlabel + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n \r\nstring ΔYoY_PY = \r\n \"/*ΔYoY_PY*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + YTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYTD + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n\r\nstring ΔYoY_PYlabel = \r\n \"/*ΔYoY_PY*/ \" + \r\n \"VAR ValueCurrentPeriod = \" + YTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYTDlabel + \" \" +\r\n \"VAR Result = \" + \r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result \";\r\n \r\n \r\nstring MOMTD_PYpct = \r\n \"/*ΔMOM%_PY*/\" + \r\n \"VAR ValueCurrentPeriod = \" + MTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYMTD + \" \" + \r\n \"VAR CurrentMinusPreviousPeriod = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"VAR Result = \" + \r\n \"DIVIDE ( \" + \r\n \" CurrentMinusPreviousPeriod,\" + \r\n \" ValuePreviousPeriod\" + \r\n \") \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n\r\n\r\nstring MOMTD_PYpctLabel = \r\n \"/*ΔMOM%_PY*/ \" +\r\n \"VAR ValueCurrentPeriod = \" + MTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYMTDlabel + \" \" + \r\n \"VAR Result = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod & \\\" (%)\\\"\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n\r\n \r\nstring QOQTD_PYpct = \r\n \"/*ΔQOQ%_PY*/\" + \r\n \"VAR ValueCurrentPeriod = \" + QTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYQTD + \" \" + \r\n \"VAR CurrentMinusPreviousPeriod = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"VAR Result = \" + \r\n \"DIVIDE ( \" + \r\n \" CurrentMinusPreviousPeriod,\" + \r\n \" ValuePreviousPeriod\" + \r\n \") \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n\r\n\r\nstring QOQTD_PYpctLabel = \r\n \"/*ΔQOQ%_PY*/ \" +\r\n \"VAR ValueCurrentPeriod = \" + QTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYQTDlabel + \" \" + \r\n \"VAR Result = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod & \\\" (%)\\\"\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n\r\n \r\n \r\n string YOYTD_PYpct = \r\n \"/*ΔYOY%_PY*/\" + \r\n \"VAR ValueCurrentPeriod = \" + YTD + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYTD + \" \" + \r\n \"VAR CurrentMinusPreviousPeriod = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod - ValuePreviousPeriod\" + \r\n \" ) \" + \r\n \"VAR Result = \" + \r\n \"DIVIDE ( \" + \r\n \" CurrentMinusPreviousPeriod,\" + \r\n \" ValuePreviousPeriod\" + \r\n \") \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n\r\n\r\nstring YOYTD_PYpctLabel = \r\n \"/*ΔYOY%_PY */ \" +\r\n \"VAR ValueCurrentPeriod = \" + YTDlabel + \" \" + \r\n \"VAR ValuePreviousPeriod = \" + PYTDlabel + \" \" + \r\n \"VAR Result = \" +\r\n \"IF ( \" + \r\n \" NOT ISBLANK ( ValueCurrentPeriod ) && NOT ISBLANK ( ValuePreviousPeriod ), \" + \r\n \" ValueCurrentPeriod & \\\" vs \\\" & ValuePreviousPeriod & \\\" (%)\\\"\" + \r\n \" ) \" + \r\n \"RETURN \" + \r\n \" Result\";\r\n \r\n \r\nstring defFormatString = \"SELECTEDMEASUREFORMATSTRING()\";\r\n\r\n//if the flag expression is already present in the format string, do not change it, otherwise apply % format. \r\nstring pctFormatString = \r\n\"IF(\" + \r\n\"\\n FIND( \"+ flagExpression + \", SELECTEDMEASUREFORMATSTRING(), 1, - 1 ) <> -1,\" + \r\n\"\\n SELECTEDMEASUREFORMATSTRING(),\" + \r\n\"\\n \\\"#,##0.# %\\\"\" + \r\n\"\\n)\";\r\n\r\n\r\n//the order in the array also determines the ordinal position of the item \r\nstring[ , ] calcItems = \r\n {\r\n {\"Base\", Base, defFormatString, \"Current year\", Baselabel},\r\n {\"MTD\", MTD, defFormatString, \"Month-to-date\", MTDlabel},\r\n {\"QTD\", QTD, defFormatString, \"Quarter-to-date\", QTDlabel},\r\n {\"YTD\", YTD, defFormatString, \"Year-to-date\", YTDlabel},\r\n {\"ITD\", ITD, defFormatString, \"Inception-to-date\", ITDlabel},\r\n {\"T3M\", T3M, defFormatString, \"Trailing 3-months\", T3Mlabel},\r\n {\"TTM\", TTM, defFormatString, \"Trailing 12-months\", TTMlabel},\r\n {\"PMTD\", PMTD, defFormatString, \"Previous Month-to-date\", PMTDlabel},\r\n {\"PQTD\", PQTD, defFormatString, \"Previous Quarter-to-date\", PQTDlabel},\r\n {\"PYTD\", PYTD, defFormatString, \"Previous Year-to-date\", PYTDlabel},\r\n {\"PYMTD\", PYMTD, defFormatString, \"Previous year Month-to-date\", PYMTDlabel},\r\n {\"PYQTD\", PYQTD, defFormatString, \"Previous year Quarter-to-date\", PYQTDlabel},\r\n {\"PYITD\", PYITD, defFormatString, \"Previous year Inception-to-date\", PYITDlabel},\r\n {\"ΔMoM\", ΔMoM, defFormatString, \"Month-over-month\", ΔMoMlabel},\r\n {\"ΔQoQ\", ΔQoQ, defFormatString, \"Quarter-over-quarter\", ΔQoQlabel},\r\n {\"ΔYoY\", ΔYoY, defFormatString, \"Year-over-year\", ΔYoYlabel},\r\n {\"ΔMoM%\", MOMTDpct, pctFormatString, \"Month-over-month %\", MOMTDpctLabel},\r\n {\"ΔQoQ%\", QOQTDpct, pctFormatString, \"Quarter-over-quarter %\", QOQTDpctLabel},\r\n {\"ΔYoY%\", YOYTDpct, pctFormatString, \"Year-over-year %\", YOYTDpctLabel},\r\n {\"ΔMoM (PY)\", ΔMoM_PY, defFormatString, \"Month-over-previous-year-month\", ΔMoM_PYlabel},\r\n {\"ΔQoQ (PY)\", ΔQoQ_PY, defFormatString, \"Quarter-over-previous-year-quarter\", ΔQoQ_PYlabel},\r\n {\"ΔYoY (PY)\", ΔYoY_PY, defFormatString, \"Year-over-previous-year\", ΔYoY_PYlabel},\r\n {\"ΔMoM% (PY)\", MOMTD_PYpct, pctFormatString, \"Month-over-previous-year-month %\", MOMTD_PYpctLabel},\r\n {\"ΔQoQ% (PY)\", QOQTD_PYpct, pctFormatString, \"Quarter-over-previous-year-quarter %\", QOQTD_PYpctLabel},\r\n {\"ΔYoY% (PY)\", YOYTD_PYpct, pctFormatString, \"Year-over-previous-year %\", YOYTD_PYpctLabel},\r\n \r\n\r\n \r\n };\r\n\r\n \r\nint j = 0;\r\n\r\n\r\n//create calculation items for each calculation with formatstring and description\r\nforeach(var cg in Model.CalculationGroups) {\r\n if (cg.Name == calcGroupName) {\r\n for (j = 0; j < calcItems.GetLength(0); j++) {\r\n \r\n string itemName = calcItems[j,0];\r\n \r\n string itemExpression = calcItemProtection.Replace(\"<CODE>\",calcItems[j,1]);\r\n itemExpression = itemExpression.Replace(\"<LABELCODE>\",calcItems[j,4]); \r\n \r\n string itemFormatExpression = calcItemFormatProtection.Replace(\"<CODE>\",calcItems[j,2]);\r\n itemFormatExpression = itemFormatExpression.Replace(\"<LABELCODEFORMATSTRING>\",\"\\\"\\\"\\\"\\\" & \" + calcItems[j,4] + \" & \\\"\\\"\\\"\\\"\");\r\n \r\n //if(calcItems[j,2] != defFormatString) {\r\n // itemFormatExpression = calcItemFormatProtection.Replace(\"<CODE>\",calcItems[j,2]);\r\n //};\r\n\r\n string itemDescription = calcItems[j,3];\r\n \r\n if (!cg.CalculationItems.Contains(itemName)) {\r\n var nCalcItem = cg.AddCalculationItem(itemName, itemExpression);\r\n nCalcItem.FormatStringExpression = itemFormatExpression;\r\n nCalcItem.FormatDax();\r\n nCalcItem.Ordinal = j; \r\n nCalcItem.Description = itemDescription;\r\n \r\n };\r\n\r\n\r\n\r\n\r\n };\r\n\r\n \r\n };\r\n};",
"Tooltip": "",
"ValidContexts": "Model, Measure, CalculationGroupTable, CalculationItem"
},
{
"Name": "Macros\\Contango\\Create measures from columns ($)",
"Enabled": "true",
"Execute": "// Creates a SUM measure for every currently selected column and hide the column.\r\nforeach(var c in Selected.Columns)\r\n{\r\n var newMeasure = c.Table.AddMeasure(\r\n c.Name + \" (CAD/m3)\", // Name\r\n \"SUMX( 'Fact Table' , \" + c.DaxObjectFullName + \" * 'Fact Table'[Volume])\", // DAX expression\r\n c.DisplayFolder // Display Folder\r\n );\r\n \r\n // Set the format string on the new measure:\r\n newMeasure.FormatString = \"$#,0\";\r\n\r\n // Provide some documentation:\r\n newMeasure.Description = \"CAD\" + c.DaxObjectFullName;\r\n\r\n // Hide the base column:\r\n c.IsHidden = true;\r\n}",
"Tooltip": "Create measures from columns",
"ValidContexts": "Model, Measure"
},
{
"Name": "Macros\\Field Parameter\\Create Parameters from Measures",
"Enabled": "true",
"Execute": "// Before running the script, select the measures or columns that you\r\n// would like to use as field parameters (hold down CTRL to select multiple\r\n// objects). If you do not select measures, all measure will be added to the selection. \r\n\r\n//Also, you may change the name of the field parameter table\r\n// below. NOTE: If used against Power BI Desktop, you must enable unsupported\r\n// features under File > Preferences (TE2) or Tools > Preferences (TE3).\r\n// originally sourced from https://docs.tabulareditor.com/common/CSharpScripts/Beginner/script-create-field-parameter.html and edited by R.Mason\r\n// this generates the field parameter, but you can go edit the results in Power BI or Tabular editor after the fact\r\n\r\nvar name = \"Parameter - Measure Selection\";\r\n\r\n// Construct the DAX for the calculated table based on the current selection:\r\n//var objects = Model.AllMeasures ;\r\n\r\n// If no measures have been selected in Tabular Editor, the return all measures otherwise return only the selected measures.\r\n\r\nvar objects = Selected.Measures.Count == 0 ? Model.AllMeasures : Selected.Measures;\r\n\r\n\r\nvar dax = \"{\\n \" + string.Join(\",\\n \", objects.Select((c,i) => string.Format(\"(\\\"{0}\\\", NAMEOF('{1}'[{0}]), {2})\", c.Name, c.Table.Name, i))) + \"\\n}\";\r\n\r\n// Add the calculated table to the model:\r\nvar table = Model.AddCalculatedTable(name, dax);\r\n\r\n// In TE2 columns are not created automatically from a DAX expression, so \r\n// we will have to add them manually:\r\nvar te2 = table.Columns.Count == 0;\r\nvar nameColumn = te2 ? table.AddCalculatedTableColumn(name, \"[Value1]\") : table.Columns[\"Value1\"] as CalculatedTableColumn;\r\nvar fieldColumn = te2 ? table.AddCalculatedTableColumn(name + \" Fields\", \"[Value2]\") : table.Columns[\"Value2\"] as CalculatedTableColumn;\r\nvar orderColumn = te2 ? table.AddCalculatedTableColumn(name + \" Order\", \"[Value3]\") : table.Columns[\"Value3\"] as CalculatedTableColumn;\r\n\r\nif(!te2) {\r\n // Rename the columns that were added automatically in TE3:\r\n nameColumn.IsNameInferred = false;\r\n nameColumn.Name = name;\r\n fieldColumn.IsNameInferred = false;\r\n fieldColumn.Name = name + \" Fields\";\r\n orderColumn.IsNameInferred = false;\r\n orderColumn.Name = name + \" Order\";\r\n}\r\n// Set remaining properties for field parameters to work\r\n// See: https://twitter.com/markbdi/status/1526558841172893696\r\nnameColumn.SortByColumn = orderColumn;\r\nnameColumn.GroupByColumns.Add(fieldColumn);\r\nfieldColumn.SortByColumn = orderColumn;\r\nfieldColumn.SetExtendedProperty(\"ParameterMetadata\", \"{\\\"version\\\":3,\\\"kind\\\":2}\", ExtendedPropertyType.Json);\r\nfieldColumn.IsHidden = true;\r\norderColumn.IsHidden = true;\r\n",
"Tooltip": "",
"ValidContexts": "Model, Table, Measure"
},
{
"Name": "Macros\\Model Optimization\\Check Blank Relationships",
"Enabled": "true",
"Execute": "var sb = new System.Text.StringBuilder();\r\nstring newline = Environment.NewLine;\r\n\r\nsb.Append(\"FromTable\" + '\\t' + \"ToTable\" + '\\t' + \"BlankRowCount\" + newline);\r\n\r\nforeach (var r in Model.Relationships.ToList())\r\n{\r\n bool act = r.IsActive;\r\n string fromTable = r.FromTable.Name;\r\n string toTable = r.ToTable.Name;\r\n string fromTableFull = r.FromTable.DaxObjectFullName; \r\n string fromObject = r.FromColumn.DaxObjectFullName;\r\n string toObject = r.ToColumn.DaxObjectFullName;\r\n string dax;\r\n \r\n if (act)\r\n {\r\n dax = \"SUMMARIZECOLUMNS(\\\"test\\\",CALCULATE(COUNTROWS(\"+fromTableFull+\"),ISBLANK(\"+toObject+\")))\";\r\n }\r\n else\r\n {\r\n dax = \"SUMMARIZECOLUMNS(\\\"test\\\",CALCULATE(COUNTROWS(\"+fromTableFull+\"),USERELATIONSHIP(\"+fromObject+\",\"+toObject+\"),ISBLANK(\"+toObject+\")))\";\r\n }\r\n \r\n var daxResult = EvaluateDax(dax);\r\n string blankRowCount = daxResult.ToString();\r\n \r\n if (blankRowCount != \"Table\")\r\n {\r\n sb.Append(fromTable + '\\t' + toTable + '\\t' + blankRowCount + newline); \r\n }\r\n}\r\n\r\nsb.Output();",
"Tooltip": "",
"ValidContexts": "Model, Table, Column"
},
{
"Name": "Macros\\Simple\\Change Measure Names",
"Enabled": "true",
"Execute": "var FromString = \"Fixed Assets (Net)\";\r\nvar ToString = \"Net Fixed Assets\";\r\nforeach (var m in Selected.Measures)\r\n {\r\n m.Name = m.Name.Replace(FromString,ToString);\r\n /* Cycle over all measures in model and replaces the \r\n FromString with the ToString in the measure names*/\r\n }",
"Tooltip": "Change Text in All Measure Names",
"ValidContexts": "Model, Measure"
},
{
"Name": "Macros\\Simple\\Create Calculation Group",
"Enabled": "true",
"Execute": "var cg = Model.AddCalculationGroup(\"Value Presentation\");\r\n\r\ncg.AddCalculationItem(\"IFERROR( DIVIDE( SELECTEDMEASURE() , [Total] , 0 ) , SELECTEDMEASURE())\");\r\n\r\ncg.AddCalculationItem(\"Base\", \"SELECTEDMEASURE()\");\r\n\r\ncg.AddCalculationItem(\"Thousands's\", \"IFERROR( DIVIDE ( SELECTEDMEASURE (), 1000, 0 ) , SELECTEDMEASURE())\");\r\n\r\ncg.AddCalculationItem(\"Million's\", \"IFERROR( DIVIDE ( SELECTEDMEASURE (), 10000000, 0 ) , SELECTEDMEASURE())\");",
"Tooltip": "",
"ValidContexts": "Model, Measure, CalculationGroupTable, CalculationItem"
},
{
"Name": "Macros\\Simple\\Create Measure based on Selection",
"Enabled": "true",
"Execute": "foreach(var t in Selected.Tables)\r\n{\r\n var newMeasure = t.AddMeasure(\r\n \"Selected Measure\" , // Name\r\n @\"VAR SELECTED_VALUE_ =\r\n SELECTEDMEASURENAME ()\r\n = SELECTEDVALUE ( 'Sort Parameter - Measure Selection (Calculation Group)'[Name] )\r\nRETURN\r\n CALCULATE ( SELECTED_VALUE_ )\" // DAX expression\r\n // Display Folder\r\n );\r\n \r\n // Set the format string on the new measure:\r\n newMeasure.FormatString = \"#,0\";\r\n\r\n // Provide some documentation:\r\n newMeasure.Description = \"N/A\" ;\r\n}",
"Tooltip": "",
"ValidContexts": "Model, Measure"
},
{
"Name": "Macros\\Simple\\Create measures from columns",
"Enabled": "true",
"Execute": "// Creates a SUM measure for every currently selected column and hide the column.\r\nforeach(var c in Selected.Columns)\r\n{\r\n var newMeasure = c.Table.AddMeasure(\r\n \"Sum of \" + c.Name, // Name\r\n \"SUM(\" + c.DaxObjectFullName + \")\", // DAX expression\r\n c.DisplayFolder // Display Folder\r\n );\r\n \r\n // Set the format string on the new measure:\r\n newMeasure.FormatString = \"0.00\";\r\n\r\n // Provide some documentation:\r\n newMeasure.Description = \"This measure is the sum of column \" + c.DaxObjectFullName;\r\n\r\n // Hide the base column:\r\n c.IsHidden = true;\r\n}",
"Tooltip": "Create measures from columns",
"ValidContexts": "Model, Measure"
},
{
"Name": "Macros\\Simple\\Create Relationship",
"Enabled": "true",
"Execute": "var fromColumn = Model.Tables[\"Export\"].Columns[\"Date\"]; // Enter the 'from' part of the relationship\r\nvar toColumn = Model.Tables[\"Calendar\"].Columns[\"Date\"]; // Enter the 'to' part of the relationship\r\n\r\n{\r\n var r = Model.AddRelationship();\r\n r.FromColumn = fromColumn;\r\n r.ToColumn = toColumn;\r\n r.FromCardinality = RelationshipEndCardinality.Many;\r\n r.ToCardinality = RelationshipEndCardinality.One;\r\n r.CrossFilteringBehavior = CrossFilteringBehavior.OneDirection; //CrossFilteringBehavior.BothDirections\r\n}",
"Tooltip": "",
"ValidContexts": "Model, Measure, CalculationGroupTable, CalculationItem"
},
{
"Name": "Macros\\Simple\\Create Simple Measures",
"Enabled": "true",
"Execute": "foreach(var t in Selected.Tables)\r\n{\r\n var newMeasure = t.AddMeasure(\r\n \"Sum of \" , // Name\r\n @\"VAR TEST_ = \r\n SELECTEDMEASURENAME () = \r\n SELECTEDVALUE ( 'Sort Parameter - Measure Selection (Calculation Group)'[Name] ) \r\n RETURN CALCULATE ( TEST_ )\" // DAX expression\r\n // Display Folder\r\n );\r\n \r\n // Set the format string on the new measure:\r\n newMeasure.FormatString = \"0.00\";\r\n\r\n // Provide some documentation:\r\n newMeasure.Description = \"This measure is the sum of column \" ;\r\n}",
"Tooltip": "",
"ValidContexts": "Model, Measure"
},
{
"Name": "Macros\\Simple\\Edit/Replace Code Inside All DAX Measures ",
"Enabled": "true",
"Execute": "/*Warning! Take a backup copy first. \r\nThis script will operate over every measure in the model. It is \r\nessential that your FromString and ToString are set to change only the\r\nspecific usage of the string that you need to change across the entire model. Selected.Measures will alter for selected measures*/\r\nvar FromString = \"CALCULATE(SUM(Sales[ExtendedAmount])\";\r\nvar ToString = \"CALCULATE([Total Sales]\";\r\nforeach (var m in Selected.Measures)\r\n {\r\n m.Expression = m.Expression.Replace(FromString,ToString);\r\n /* Cycle over all measures in model and replaces the \r\n FromString with the ToString */\r\n }",
"Tooltip": "Edit/Replace Code Inside All DAX Measures ",
"ValidContexts": "Model, Measure"
},
{
"Name": "Macros\\Simple\\Edit/Replace Code Inside All DAX Measures and Rename Measure",
"Enabled": "true",
"Execute": "/*Warning! Take a backup copy first. \r\nThis script will operate over every measure in the model. It is \r\nessential that your FromString and ToString are set to change only the\r\nspecific usage of the string that you need to change across the entire model. Selected.Measures will alter for selected measures*/\r\nvar FromString = \"AES\";\r\nvar ToString = \"SWP\";\r\nvar OneString = \"1\";\r\nvar BlankString = \"\";\r\n\r\nforeach (var m in Selected.Measures)\r\n {\r\n m.Expression = m.Expression.Replace(FromString,ToString);\r\n /* Cycle over all measures in model and replaces the \r\n FromString with the ToString */\r\n\r\n m.Name = m.Name.Replace(FromString,ToString);\r\n /* Cycle over all measures in model and replaces the \r\n FromString with the ToString in the measure names*/\r\n \r\n m.Name = m.Name.Replace(OneString,BlankString);\r\n \r\n }",
"Tooltip": "Edit/Replace Code Inside All DAX Measures ",
"ValidContexts": "Model, Measure"
},
{
"Name": "Macros\\Simple\\Format DAX",
"Enabled": "true",
"Execute": "foreach(var m in Model.AllMeasures)\r\n{\r\n m.FormatDax();\r\n}",
"Tooltip": "",
"ValidContexts": "Model"
},
{
"Name": "Macros\\Simple\\Measure detail in description",
"Enabled": "true",
"Execute": "foreach (var m in Model.AllMeasures)\r\n{ m.Description = m.Expression; }",
"Tooltip": "",
"ValidContexts": "Model"
}
]
}