Ich bin Prinzipal Consultant für BI und Dataware Housing mit den Microsoft Techniken.Für die Trivadis AG bin ich zusätzlich zu meiner Arbeit als Consultant auch als Trainer tätig. Dafür besitze ich alle notwendigen Microsoft Zertifizierungen.In diesen Blog veröffentliche ich ausschließlich meine Meinung. Diese Meinung kann von der offiziellen Meinung der Trivadis AG abweichen. ;-)
In der Regel werden Werte in einem Cube formatiert ausgegeben. Diese Formatierung wird direkt bei dem entsprechenden Measure angegeben. Hier finden Sie die Formatierungsauszeichnungen.
Damit wird erreicht dass bei Clientsoftware die diese Formatierungen unterstützen, die Werte so ausgegeben werden wie sie einheitlich im Cube formatiert wurden. Wichtig ist in diesem Kontext, dass die Clientsoftware serverseitige Formatierung unterstützt. Werden neuere Versionen von Excel verwendet – ab Excel 2007 und jünger – unterstützen diese die Übernahme der cubeseitigen Formatierung standardmäßig. Diese Funktionalität kann auch in Excel durch die Pivot Optionen ausgeschaltet werden.
Selbstverständlich ist es auch möglich innerhalb vom MDX Script die Werte mit einheitlichen Formatanweisungen zu versehen. Sollen zum Beispiel alle Werte einheitlich als Standardzahl mit Tausender Trennzeichen und zwei Nachkommastellen formatiert werden, kann das mit FORMAT_STRING(THIS) = "Standard"; erreicht werden. Diese Anweisung formatiert alle Measures, einschließlich der berechneten, einheitlich.
Wenn Sie das so verwenden wollen, dann sollten Sie dieses Formatierung am Ende des MDX Scripts durchführen. Das MDX Script wird in der Regel von oben nach unten abgearbeitet.
Jetzt bringen wir etwas Dynamik in die Darstellung; das geht natürlich auch.
Der Benutzer soll zum Beispiel in die Lage versetzt werden, die Formatierung über eine Dimension zu steuern.
Ich verwende für mein Beispiel eine sehr stark vereinfachte Anforderung eines Kunden.
Folgende MDX Abfrage liefert das entsprechende Ergebnis:
SELECT {[Measures].[Sales Amount]} * [Dim Measurement unit].[Unit].[Unit].members ON 0, Non Empty [Dim Product].[English Product Category Name].[English Product Category Name].members ON 1 FROM [SSAS_Overwrite]
Damit dieses Ergebnis erzielt werden kann, müssen wir im Cube eine zusätzliche Dimension Dim Measurement unit einfügen. Da diese Dimension keine Verbindung zu den Fakten hat, brauchen wir auch keine Verknüpfung in der Dimensionsmatix zur Measuregroup erzeugen.
Zusätzlich wird diese Formatierung noch im MDX Script hinterlegt
SCOPE([Dim Measurement unit].[Unit].[Tsd]); FORMAT_STRING(THIS) = "#,#0; - #,#0"; END SCOPE; SCOPE([Dim Measurement unit].[Unit].[Mio]); FORMAT_STRING(THIS) = "##0,,.000; - ##0,,.000"; END SCOPE;
In Abhängigkeit von der Selektion des Endbenutzers wird jedes Measure mittels Formatierung entsprechend dargestellt. Vielleicht fragen Sie sich, warum die Werte nicht entsprechend geteilt werden. Natürlich haben Sie Recht, aber für dieses Beispiel wählen wir diesen Weg. In der Realität sollte die Genauigkeit für weitere Berechnungen nicht verloren gehen.
Die beiden Kommas in der Formatanweisung sind keine Tippfehler. Das Komma steht für das Tausender Trennzeichen – in MDX wird immer die amerikanische Formatierungen verwendet. Zwei direkt hintereinander folgende Kommas sind dann 1000 x 1000 sprich eine Million.
Damit es nicht zu einfach wird kommt eine weitere Anforderung hinzu: Der Benutzer soll zusätzlich auch das Vorzeichen der Zahlen umschalten können. Das lässt sich nicht mit der bereits vorhanden Dimension erreichen. Wir brauchen eine weitere ungebundene Dimension Dim Prefix.
Die Dimensionsmatrix sieht dann so aus:
Hier sind die Anweisungen im MDX Script
CALCULATE; ALTER CUBE CURRENTCUBE UPDATE DIMENSION [Dim Prefix].[Prefix], Default_Member = [Dim Prefix].[Prefix].[Value] UPDATE DIMENSION [Dim Measurement unit].[Unit], Default_Member = [Dim Measurement unit].[Unit].[Value]; FORMAT_STRING(THIS) = "Standard"; SCOPE([Dim Measurement unit].[Unit].[Tsd]); FORMAT_STRING(THIS) = "#,#0; - #,#0"; END SCOPE;
SCOPE([Dim Measurement unit].[Unit].[Mio]); FORMAT_STRING(THIS) = "##0,,.000; - ##0,,.000"; END SCOPE;
SCOPE([Dim Prefix].[Prefix].[Negative]); FORMAT_STRING(THIS) = "- #,##0.00"; END SCOPE;
Zuerst werden für die beiden ungebundenen Dimensionen Default Members explizit festgelegt. Danach erfolgt die Formatierung aller angezeigter Measures.
Mit dieser MDX Abfrage bekommen wir folgendes Ergebnis:
SELECT {[Measures].[Sales Amount]} * [Dim Prefix].[Prefix].[Prefix].members ON 0, Non Empty [Dim Product].[English Product Category Name].[English Product Category Name].members * [Dim Measurement unit].[Unit].[Unit].members ON 1 FROM [SSAS_Overwrite]
Das Ergebnis ist ganz offensichtlich falsch. Die zweite Formatierungsanweisung hat die erste Formatierung komplett überschrieben.
So intuitiv der erste Ansatz war, so falsch war er auch.
Wenn wir den Wert in der Ergebnisausgabe doppelt anklicken, dann bekommen wir die Cell Properies dieser Zelle angezeigt. Wichtig sind die beiden Werte VALUE und FORMATTED_VALUE. In Value bekommen wir den ursprünglichen Wert ohne jede Formatierung. Dieser Wert ist immer die Basis für Berechnungen oder auch Formatierungen.
Beim Inhalt von FORMATTED_VALUE sehen wir den formatierten Wert.
In Reporting Services wird standardmäßig der unformatierte Wert – VALUE – verwendet. Das kann aber ganz einfach geändert werden. Statt Value einfach FormattedValue auswählen. Dafür müssen aber die CELL PROPERIES entsprechend ausgegeben werden.
Da diese Werte für Reporting Services Strings sind, können diese nicht aggregiert werden. Die Summe muss also mit VALUE gebildet und anschließend manuell formatiert werden.
Die Lösung für die Anforderung ist ganz einfach – der Basiswert muss im Fall der negativen Formatierung mit -1 multipliziert werden.
Sie sehen, ich habe die Reihenfolge im MDX Script und die Berechnungen geändert. Das Ergebnis ist jetzt so wie es gewünscht wurde.
Formatierung im Cube sind in der Regel genau das, was die Benutzer gerne haben. Bitte sind Sie aber trotzdem zurückhaltend mit diesen Möglichkeiten. Natürlich braucht dieser Vorgang auch Zeit.
Ich habe schon mal gesehen, dass die sehr aufwendige Formatierung der Werte mehr als zweimal soviel Zeit in Anspruch genommen hat, als die Ausgabe der Werte mit Basisformatierung. Es ist schon ein Unterschied ob ein Ergebnis in 2 Sekunden oder in 6 Sekunden angezeigt wird.