Skip to content

Commit 5545650

Browse files
authored
Adding new documentation (#286)
1 parent 2471ee2 commit 5545650

4 files changed

Lines changed: 458 additions & 0 deletions

File tree

content/features/views/user-interface.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,28 @@ Use the **Window > Capture current layout..." option to save a customized layout
4949

5050
![Manage Layouts](~/content/assets/images/manage-layouts.png)
5151

52+
### Window docking options
53+
54+
When rearranging views and documents in Tabular Editor 3, you can choose to dock windows in different areas of the interface. When dragging a window to a new position, docking indicators will appear showing you the available docking locations.
55+
56+
![Window Docking Options](~/content/assets/images/window-docking-options.png)
57+
58+
There are two primary ways to dock windows, each serving a different purpose:
59+
60+
**Document tab docking (center indicator)**: When you drag a window to the center docking indicator, it will be placed in the main document area. Windows docked this way become document tabs that:
61+
- Can be cycled through using **Ctrl+Tab**
62+
- Are displayed in the main working area alongside other documents like DAX queries, scripts, and diagrams
63+
- Do not have auto-hide functionality
64+
65+
**Tool window docking (edge indicators)**: When you drag a window to the left, right, top, or bottom docking indicators, it will be docked as a tool window. Tool windows:
66+
- Are not accessible via **Ctrl+Tab**
67+
- Display a pin icon that enables auto-hide functionality (making the window collapse when not in use)
68+
- Behave similarly to other tool windows such as the TOM Explorer and Messages view
69+
- Can be docked at various positions around the main document area
70+
71+
> [!TIP]
72+
> The size of a docked window is determined by the available space in the area you choose to dock it, not by the docking option itself. You can resize windows by dragging the dividers between them.
73+
5274
### Changing themes and palettes
5375

5476
The visual appearance of Tabular Editor 3 can be changed by choosing a different theme and/or palette. Tabular Editor 3 ships with five different themes (sometimes called "skins"), available through the **Window > Themes** menu:

content/references/shortcuts3.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ applies_to:
3131
|Close Document|Ctrl+W|
3232
|Exit|Alt+F4|
3333
|Deployment wizard|Ctrl+Shift+D|
34+
|Switch In-Focus Window|Ctrl+Tab|
3435

3536
## Edit
3637

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
---
2+
uid: composite-model-measure-formatting
3+
title: Measure Format Properties in Composite Models
4+
author: Support Team
5+
updated: 2026-01-26
6+
applies_to:
7+
products:
8+
- product: Tabular Editor 2
9+
full: true
10+
- product: Tabular Editor 3
11+
editions:
12+
- edition: Desktop
13+
full: true
14+
- edition: Business
15+
full: true
16+
- edition: Enterprise
17+
full: true
18+
---
19+
20+
# Measure Format Properties in Composite Models
21+
22+
When working with composite models that use a Live connection to Analysis Services (SSAS/AAS), you may encounter validation errors or confusing behavior when editing measure formatting properties. A common error message is:
23+
24+
**"A measure is not allowed to have both FormatString and Format Expression."**
25+
26+
This article explains why this occurs and how to resolve it.
27+
28+
---
29+
30+
## Understanding the Issue
31+
32+
Composite models combine local Power BI tables with remote tables from an SSAS/AAS semantic model via a Live connection. In this architecture, measure formatting can be ambiguous:
33+
34+
- **FormatString**: A static format definition (e.g., "0.00" for currency).
35+
- **Format String Expression**: A dynamic format string evaluated at query time.
36+
37+
The error occurs because the model ends up with both a static format and a dynamic format expression simultaneously—a state that is not allowed by the Tabular Object Model (TOM).
38+
39+
### Why this happens
40+
41+
In composite models:
42+
43+
1. **Ownership ambiguity**: Remote measures are owned by the remote SSAS/AAS model. When you edit formatting in Tabular Editor, you may be trying to override remote metadata, which creates conflicts.
44+
45+
2. **Metadata synchronization**: When a Format String Expression is present on a measure, the FormatString often appears as "Custom" to indicate dynamic formatting is active. If you then try to set a static FormatString simultaneously, both properties become populated, triggering the validation error.
46+
47+
3. **Persistence constraints**: Changes to remote measure metadata may not persist cleanly because the remote model retains authoritative control. This leaves the local composite model in an inconsistent state.
48+
49+
---
50+
51+
## Root Causes
52+
53+
### Remote measure formatting
54+
55+
If the problematic measure is defined in the remote SSAS/AAS model:
56+
57+
- Formatting should be managed in the source model, not in the Power BI composite model.
58+
- Attempting to override remote measure formatting in Power BI can result in both FormatString and Format String Expression being populated, leading to the validation error.
59+
60+
### Script or automation setting both properties
61+
62+
- If you are using C# scripts, Power Query transformations, or BPA rules to apply formatting, ensure they target only one approach per measure (either static or dynamic, not both).
63+
64+
### Calculation groups with format expressions
65+
66+
- Calculation groups can define Format String Expressions that override measure formats. If a calc item's format expression is active, the UI may still display the measure's static FormatString, creating the appearance of both being set.
67+
68+
### Version or environment constraints
69+
70+
- Dynamic format strings for measures have limited availability and may not be fully supported in certain Power BI versions or deployment modes (Report Server).
71+
- If you are on Power BI Desktop prior to 2025 or Power BI Report Server prior to January 2025, dynamic measure formats may not be supported.
72+
73+
---
74+
75+
## Resolution
76+
77+
The solution depends on whether the measure is **remote** (from SSAS/AAS) or **local** (created in the composite model).
78+
79+
### If the measure is remote (from SSAS/AAS)
80+
81+
This is the most common scenario. Remote measures are owned by the source semantic model.
82+
83+
**Recommended approach:**
84+
85+
1. **Manage formatting in the source model.** Open SSAS/AAS in SQL Server Management Studio or Tabular Editor connected to the source model, and set the formatting there.
86+
87+
2. **If report-specific formatting is required,** create a local "wrapper" measure in your Power BI composite model:
88+
- Define a new measure in the local model that references the remote measure.
89+
- Apply the desired format string to the wrapper measure.
90+
- Use the wrapper measure in your report instead of the remote measure.
91+
92+
**Trade-off:** This approach creates duplicates and adds maintenance overhead, but it is the most reliable way to apply report-specific formatting in a Live connection scenario.
93+
94+
### If the measure is local (created in the composite model)
95+
96+
**For static formatting (most common):**
97+
98+
1. Select the measure in Tabular Editor.
99+
2. Clear the **Format String Expression** field (set it to empty/null).
100+
3. Set the measure's **Format String** to the desired static format (e.g., `"0.00%"` for percentage, `"$#,##0.00"` for currency).
101+
4. Save the model.
102+
103+
**For dynamic formatting:**
104+
105+
1. Select the measure.
106+
2. Keep or set the **Format String Expression** to your desired DAX expression (this is the only formatting property you should use).
107+
3. Leave the **Format String** as "Custom" (do not attempt to also set a static format string).
108+
4. Verify that your environment supports dynamic format strings (Power BI Desktop 2025 or later, or Power BI Report Server January 2025 or later).
109+
110+
---
111+
112+
## Quick Troubleshooting Checklist
113+
114+
- [ ] **Determine measure ownership**: Is the measure remote (SSAS/AAS) or local (composite model)?
115+
- [ ] **Check Format String Expression**: Even if you didn't set it, verify whether it is populated. In the property grid, look for a non-empty "Format String Expression" field.
116+
- [ ] **Review scripts and rules**: If you use C# scripts or BPA rules to set measure formats, ensure they do not set both FormatString and Format String Expression in the same pass.
117+
- [ ] **Check calculation groups**: Confirm whether any calculation group items define a Format String Expression that might be overriding or conflicting with the measure's format.
118+
- [ ] **Verify environment version**: Confirm your Power BI Desktop (2025 or later) or Power BI Report Server (January 2025 or later) version, especially if using dynamic formats.
119+
120+
---
121+
122+
## Step-by-Step Examples
123+
124+
### Example 1: Fixing a remote measure with static formatting
125+
126+
**Scenario:** You have a "Sales Amount" measure in the remote SSAS model, and you want it formatted as currency in your Power BI report.
127+
128+
**Steps:**
129+
130+
1. In Tabular Editor, connect directly to the SSAS/AAS model (not to the Power BI composite model).
131+
2. Navigate to the "Sales Amount" measure.
132+
3. Set its **Format String** to `"$#,##0.00"`.
133+
4. Save the model back to SSAS/AAS.
134+
5. Return to Tabular Editor connected to the Power BI composite model; the formatting should now be inherited.
135+
136+
If formatting still does not appear correct in the report, create a local wrapper measure (see below).
137+
138+
### Example 2: Creating a wrapper measure for report-specific formatting
139+
140+
**Scenario:** You need the Sales Amount measure from SSAS formatted differently in this specific report.
141+
142+
**Steps:**
143+
144+
1. In Tabular Editor, connect to the Power BI composite model.
145+
2. Create a new measure in a local table (or in the measure table if you have one):
146+
```
147+
Sales Amount (Formatted) = [Sales Amount]
148+
```
149+
3. Set the **Format String** of the new measure to your desired format (e.g., `"$#,##0.00"`).
150+
4. Save the model.
151+
5. Update your report visuals to use the wrapper measure instead of the original remote measure.
152+
153+
### Example 3: Setting local measure with dynamic formatting
154+
155+
**Scenario:** You have a local measure in the composite model and want to apply conditional formatting based on a threshold.
156+
157+
**Steps:**
158+
159+
1. Select the measure in Tabular Editor.
160+
2. Ensure **Format String** is empty (do not set a static format).
161+
3. Set **Format String Expression** to your conditional expression:
162+
```dax
163+
IF(
164+
[YourMeasure] > 1000,
165+
"#,##0.00",
166+
"0.00"
167+
)
168+
```
169+
4. Do **not** also set a static FormatString.
170+
5. Save the model.
171+
6. Verify your Power BI version supports dynamic format strings (Desktop 2025+ or PBIRS Jan 2025+).
172+
173+
---
174+
175+
## Prevention Best Practices
176+
177+
1. **Decide on formatting strategy early**: Determine whether each measure should use static or dynamic formatting and stick to one approach per measure.
178+
179+
2. **Audit remote measures**: Before editing formatting in a composite model, check whether the measure is remote. If so, manage formatting in the source SSAS/AAS model.
180+
181+
3. **Use version-appropriate features**: If you're using dynamic format strings, ensure all relevant environments (Desktop, Report Server, Analysis Services) support them for your Power BI version.
182+
183+
4. **Script defensively**: If you write C# scripts or BPA rules to format measures, separate the logic so you only set one for mat property per measure, and include a guard to check whether the other property is already populated.
184+
185+
5. **Clear Format String Expression when switching to static**: If a measure previously used dynamic formatting, always clear the Format String Expression before attempting to set a static FormatString.
186+
187+
---
188+
189+
## Additional Resources
190+
191+
- **[Microsoft Docs - Measure Format Strings](https://learn.microsoft.com/en-us/analysis-services/tmsl/measures-object-tmsl)**: Official documentation on measure formatting in the Tabular Object Model.
192+
- **[Composite Models in Power BI](https://learn.microsoft.com/en-us/power-bi/transform-model/desktop-composite-models)**: Understanding Live connections and composite model architecture.
193+
- **[Dynamic Format Strings](https://learn.microsoft.com/en-us/power-bi/create-reports/desktop-dynamic-format-strings)**: Feature availability and usage guidance.
194+
195+
---
196+
197+
## Still Need Help?
198+
199+
If the steps above don't resolve your issue:
200+
201+
1. **Verify the measure is local**: Connect directly to your Power BI file (.pbix) in Tabular Editor to confirm the measure is defined locally, not remotely.
202+
203+
2. **Export diagnostic information**: Run the following Tabular Editor script to audit all measures:
204+
```csharp
205+
var measures = Model.AllMeasures;
206+
foreach (var m in measures)
207+
{
208+
var hasStaticFormat = !string.IsNullOrEmpty(m.FormatString);
209+
var hasDynamicFormat = !string.IsNullOrEmpty(m.FormatStringExpression);
210+
if (hasStaticFormat && hasDynamicFormat)
211+
{
212+
Output($"CONFLICT - {m.Name}: FormatString='{m.FormatString}', Expression='{m.FormatStringExpression}'");
213+
}
214+
else if (hasStaticFormat)
215+
{
216+
Output($"STATIC - {m.Name}: '{m.FormatString}'");
217+
}
218+
else if (hasDynamicFormat)
219+
{
220+
Output($"DYNAMIC - {m.Name}: '{m.FormatStringExpression}'");
221+
}
222+
}
223+
```
224+
225+
3. **Contact support**: Reach out with the diagnostic output and your Power BI and Tabular Editor version numbers.

0 commit comments

Comments
 (0)