<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ORAYLIS Blog</title>
	<atom:link href="http://blog.oraylis.de/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.oraylis.de</link>
	<description>ORAYLIS - Einfach mehr Wissen</description>
	<lastBuildDate>Wed, 15 Feb 2012 08:56:08 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Zugriff auf Excel Services einschr&#228;nken</title>
		<link>http://blog.oraylis.de/2012/02/zugriff-auf-excel-services-einschrnken-2/</link>
		<comments>http://blog.oraylis.de/2012/02/zugriff-auf-excel-services-einschrnken-2/#comments</comments>
		<pubDate>Wed, 15 Feb 2012 08:50:34 +0000</pubDate>
		<dc:creator>Daniel Snellen</dc:creator>
				<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[Excel Service]]></category>
		<category><![CDATA[Lizenzen]]></category>
		<category><![CDATA[SharePoint 2010]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2012/02/zugriff-auf-excel-services-einschrnken-2/</guid>
		<description><![CDATA[<p>Für die Excel Services auf den SharePoint Server 2010 werden Enterprise CAL’s benötigt.    <br />Leider bietet der SharePoint Server 2010 aktuell nur die Möglichkeit, Enterprise Features FARM weit zu aktivieren. Aus technologischer Sicht ist es für den SharePoint Server 2010 irrelevant, ob für alle Benutzer Enterprise CAL’s zur Verfügung stehen da jeder User bspw. Excel Services nutzen kann.</p>
<p>Sobald eine Service Application für den Excel Service angelegt wurde, versucht der SharePoint 2010 alle Excel Dateien (ab Excel 2007 aufwärts) im Browser zu öffnen. Für den SharePoint 2010 ist es irrelevant, ob die Enterprise Features für eine SiteCollention aktiviert oder deaktiviert sind. Falls die Features jedoch nicht aktiviert sind, bekommt der Benutzer eine Fehlermeldung.</p>
<p>Dieses Verhalten ist in einigen Szenarien hinderlich, wenn z.B. der SharePoint als Fileserver genutzt wird und es jedoch nur eine begrenze Anzahl an Enterprise Lizenzen für ausgewählte Benutzer gibt.</p>
<p>In diesem Fall muss der SharePoint Server 2010 daran gehindert werden, die „normalen“ Excel Dateien im Browser zu öffnen, indem die Websitesammlungs-Feature „<strong>Dokumente standardmäßig in Clientanwendungen öffnen“, </strong>aktiviert wird. </p>
<p>Sobald diese aktiv ist, werden alle Dokumente nur noch mit den lokal installieren Anwendungen geöffnet, z.B. Excel 2010 oder Word 2010.</p>
<p>Um dem ausgewählten Benutzer-Kreis dennoch das Öffnen von Excel Dateien über Excel Service im Browser zu ermöglichen, muss eine Dokumenten Bibliothek angelegt werden. In dieser Bibliothek werden nun die „speziellen“ Excel Dateien gespeichert. Die Berechtigung für diese Dokumenten Bibliothek sollte so eingestellt werden, dass nur Benutzer mit einer Enterprise CAL Zugriff haben.    <br />Letztendlich muss in den erweiterten Einstellungen dieser Dokumenten Bibliothek noch die Funktion „Dokumente im Browser öffnen“ aktiviert werden.</p>
<p>Nachfolgend die detaillierte Beschreibung für beide Einstellungen: </p>
<hr />
<h4>Webseiten Einstellungen</h4>
<p>1. Klickt in der SharePoint-Zentraladministration auf <b>Websiteaktionen</b> und anschließend auf <b>Websiteeinstellungen</b>.</p>
<p>2. Klickt auf der Seite <b>Websiteeinstellungen</b> im Abschnitt <b>Websitesammlungsverwaltung</b> auf <b>Websitesammlungs-Features</b>.</p>
<p>3. Klickt auf der Seite <b>Features</b> für das Feature <b>Dokumente standardmäßig in Clientanwendungen öffnen</b> auf <b>Aktivieren</b> (OpenInClient-Feature ist aktiviert), um Dokumente in der Clientanwendung zu öffnen. Klickt auf <b>Deaktivieren</b> (OpenInClient-Feature ist deaktiviert), um Dokumente im Browser zu öffnen.</p>
<hr />
<h4>Dokumenten Bibliothek</h4>
<p>1. Klickt auf der Bibliothekssymbolleiste auf Bibliothekseinstellungen.</p>
<p>2. Klickt auf der Seite Dokumentbibliothekseinstellungen auf Erweiterte Einstellungen.</p>
<p>3. Wählt nun auf der Seite Erweiterte Einstellungen unter Öffnen von Dokumenten im Browser eine der folgenden Optionen aus:</p>
<p><b>In der Clientanwendung öffnen</b>: Klickt ein Benutzer auf ein Dokument in dieser Bibliothek, wird das Dokument in der entsprechenden Clientanwendung geöffnet (sofern verfügbar). </p>
<p><b>Im Browser öffnen</b>: Klickt ein Benutzer auf ein Dokument in dieser Bibliothek, wird das Dokument in der Webbrowserwebanwendung für diesen Dokumenttyp geöffnet. Wenn das Dokument in der Webanwendung geöffnet wird, kann der Benutzer auswählen, ob das das Dokument in der Clientanwendung geöffnet werden soll. </p>
<p><b>Serverstandardeinstellung verwenden</b>: Klickt ein Benutzer auf ein Dokument in dieser Bibliothek, wird das Dokument gemäß dem Standardöffnungsverhalten geöffnet, welches für den Server vorgesehen ist, auf dem die SharePoint 2010-Produkte installiert sind.</p>
<div style="display:block"><small><em>by Daniel Snellen <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2012%2F02%2Fzugriff-auf-excel-services-einschrnken-2%2F&amp;linkname=Zugriff%20auf%20Excel%20Services%20einschr%26auml%3Bnken"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p>Für die Excel Services auf den SharePoint Server 2010 werden Enterprise CAL’s benötigt.    <br />Leider bietet der SharePoint Server 2010 aktuell nur die Möglichkeit, Enterprise Features FARM weit zu aktivieren. Aus technologischer Sicht ist es für den SharePoint Server 2010 irrelevant, ob für alle Benutzer Enterprise CAL’s zur Verfügung stehen da jeder User bspw. Excel Services nutzen kann.</p>
<p>Sobald eine Service Application für den Excel Service angelegt wurde, versucht der SharePoint 2010 alle Excel Dateien (ab Excel 2007 aufwärts) im Browser zu öffnen. Für den SharePoint 2010 ist es irrelevant, ob die Enterprise Features für eine SiteCollention aktiviert oder deaktiviert sind. Falls die Features jedoch nicht aktiviert sind, bekommt der Benutzer eine Fehlermeldung.</p>
<p>Dieses Verhalten ist in einigen Szenarien hinderlich, wenn z.B. der SharePoint als Fileserver genutzt wird und es jedoch nur eine begrenze Anzahl an Enterprise Lizenzen für ausgewählte Benutzer gibt.</p>
<p>In diesem Fall muss der SharePoint Server 2010 daran gehindert werden, die „normalen“ Excel Dateien im Browser zu öffnen, indem die Websitesammlungs-Feature „<strong>Dokumente standardmäßig in Clientanwendungen öffnen“, </strong>aktiviert wird. </p>
<p>Sobald diese aktiv ist, werden alle Dokumente nur noch mit den lokal installieren Anwendungen geöffnet, z.B. Excel 2010 oder Word 2010.</p>
<p>Um dem ausgewählten Benutzer-Kreis dennoch das Öffnen von Excel Dateien über Excel Service im Browser zu ermöglichen, muss eine Dokumenten Bibliothek angelegt werden. In dieser Bibliothek werden nun die „speziellen“ Excel Dateien gespeichert. Die Berechtigung für diese Dokumenten Bibliothek sollte so eingestellt werden, dass nur Benutzer mit einer Enterprise CAL Zugriff haben.    <br />Letztendlich muss in den erweiterten Einstellungen dieser Dokumenten Bibliothek noch die Funktion „Dokumente im Browser öffnen“ aktiviert werden.</p>
<p>Nachfolgend die detaillierte Beschreibung für beide Einstellungen: </p>
<hr />
<h4>Webseiten Einstellungen</h4>
<p>1. Klickt in der SharePoint-Zentraladministration auf <b>Websiteaktionen</b> und anschließend auf <b>Websiteeinstellungen</b>.</p>
<p>2. Klickt auf der Seite <b>Websiteeinstellungen</b> im Abschnitt <b>Websitesammlungsverwaltung</b> auf <b>Websitesammlungs-Features</b>.</p>
<p>3. Klickt auf der Seite <b>Features</b> für das Feature <b>Dokumente standardmäßig in Clientanwendungen öffnen</b> auf <b>Aktivieren</b> (OpenInClient-Feature ist aktiviert), um Dokumente in der Clientanwendung zu öffnen. Klickt auf <b>Deaktivieren</b> (OpenInClient-Feature ist deaktiviert), um Dokumente im Browser zu öffnen.</p>
<hr />
<h4>Dokumenten Bibliothek</h4>
<p>1. Klickt auf der Bibliothekssymbolleiste auf Bibliothekseinstellungen.</p>
<p>2. Klickt auf der Seite Dokumentbibliothekseinstellungen auf Erweiterte Einstellungen.</p>
<p>3. Wählt nun auf der Seite Erweiterte Einstellungen unter Öffnen von Dokumenten im Browser eine der folgenden Optionen aus:</p>
<p><b>In der Clientanwendung öffnen</b>: Klickt ein Benutzer auf ein Dokument in dieser Bibliothek, wird das Dokument in der entsprechenden Clientanwendung geöffnet (sofern verfügbar). </p>
<p><b>Im Browser öffnen</b>: Klickt ein Benutzer auf ein Dokument in dieser Bibliothek, wird das Dokument in der Webbrowserwebanwendung für diesen Dokumenttyp geöffnet. Wenn das Dokument in der Webanwendung geöffnet wird, kann der Benutzer auswählen, ob das das Dokument in der Clientanwendung geöffnet werden soll. </p>
<p><b>Serverstandardeinstellung verwenden</b>: Klickt ein Benutzer auf ein Dokument in dieser Bibliothek, wird das Dokument gemäß dem Standardöffnungsverhalten geöffnet, welches für den Server vorgesehen ist, auf dem die SharePoint 2010-Produkte installiert sind.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2012/02/zugriff-auf-excel-services-einschrnken-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Darstellung herausgefilterter Zeit-Kategorien</title>
		<link>http://blog.oraylis.de/2012/01/darstellung-herausgefilterter-zeit-kategorien/</link>
		<comments>http://blog.oraylis.de/2012/01/darstellung-herausgefilterter-zeit-kategorien/#comments</comments>
		<pubDate>Sun, 29 Jan 2012 12:39:37 +0000</pubDate>
		<dc:creator>Arno Cebulla</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[MS SSRS]]></category>
		<category><![CDATA[Microsoft BI]]></category>
		<category><![CDATA[Technologie]]></category>
		<category><![CDATA[AdventureWorks]]></category>
		<category><![CDATA[Lookup]]></category>
		<category><![CDATA[Reporting]]></category>
		<category><![CDATA[SQL 2008 R2]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/?p=1427</guid>
		<description><![CDATA[<p>Ein typisches Verhalten in Reporting-Services ist es, dass Daten, die mit Parametern herausgefiltert werden, auch im Bericht nicht dargestellt werden. Beispiel: In diesem Chart werden die Umsätze für ein Jahr dargestellt: </p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit1.gif"><img class="size-full wp-image-1428 alignnone" src="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit1.gif" alt="" width="460" height="214" /></a></p>
<p> Wenn nun nur noch die Monate Januar-April im Month-Parameter ausgewählt werden, erscheint folgendes Chart:</p>
<p> <a href="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit2.gif"><img class="alignleft size-full wp-image-1429" src="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit2.gif" alt="" width="669" height="305" /></a></p>
<p>Die Daten werden per MDX aus einem Cube gelesen und im Dataset mit einem Subselect oder in der WHERE-Bedingung gefiltert:</p>
<p><span style="color: #888888">SELECT</span></p>
<p><span style="color: #888888"> {[Measures].[Sales Amount]} ON 0,</span></p>
<p><span style="color: #888888"> NON EMPTY</span></p>
<p><span style="color: #888888"> {([Date].[Calendar].[Date].ALLMEMBERS )} ON 1</span></p>
<p><span style="color: #888888"> FROM</span></p>
<p><span style="color: #888888"> (SELECT ( STRTOSET(@DateCalendarYear, CONSTRAINED) ) ON 0</span></p>
<p><span style="color: #888888"> FROM</span></p>
<p><span style="color: #888888"> (SELECT ( STRTOSET(@DateMonthofYear, CONSTRAINED) ) ON 0</span></p>
<p><span style="color: #888888"> FROM [Adventure Works]))</span></p>
<p>Der Kunde wünscht nun, dass die übrigen Monate aber dennoch (mit dem Wert 0) angezeigt werden sollen. Hierfür gibt es zum einen die Möglichkeit, dieses bereits im MDX-Query zu lösen. Dies geschieht über einen String-Vergleich in einem IIF-Block. Leider ist diese Methode recht unperformant.</p>
<p>Ein besseres Ergebnis kann man mit dieser Methode erzielen, vorausgesetzt man verwendet SQL Server ab Version 2008 R2:</p>
<p>Im Dataset werden zunächst <strong>alle </strong>Daten für das Jahr geholt:</p>
<p><span style="color: #888888">SELECT</span></p>
<p><span style="color: #888888"> {[Measures].[Sales Amount]} ON 0,</span></p>
<p><span style="color: #888888"> NON EMPTY</span></p>
<p><span style="color: #888888"> {([Date].[Calendar].[Date].ALLMEMBERS )} ON 1</span></p>
<p><span style="color: #888888"> FROM</span></p>
<p><span style="color: #888888"> (SELECT ( STRTOSET(@DateCalendarYear, CONSTRAINED) ) ON 0</span></p>
<p><span style="color: #888888"> FROM [Adventure Works])</span></p>
<p>Dann wird ein zweites Dataset „GueltigeMonate“ erstellt, in dem die Monate anhand des Parameters gefiltert werden:</p>
<p><span style="color: #888888">WITH</span></p>
<p><span style="color: #888888">MEMBER [Measures].[ParameterCaption] AS [Date].[Month of Year].CURRENTMEMBER.MEMBER_CAPTION</span></p>
<p><span style="color: #888888">MEMBER [Measures].[ParameterValue] AS [Date].[Month of Year].CURRENTMEMBER.UNIQUENAME</span></p>
<p><span style="color: #888888">MEMBER [Measures].[ParameterLevel] AS [Date].[Month of Year].CURRENTMEMBER.LEVEL.ORDINAL</span></p>
<p><span style="color: #888888">SELECT</span></p>
<p><span style="color: #888888">{[Measures].[ParameterCaption], [Measures].[ParameterValue], [Measures].[ParameterLevel]} ON COLUMNS ,</span></p>
<p><span style="color: #888888">[Date].[Month of Year].ALLMEMBERS ON ROWS</span></p>
<p><span style="color: #888888">FROM</span></p>
<p><span style="color: #888888">(SELECT STRTOSET(@Monate,CONSTRAINED) ON 0</span></p>
<p><span style="color: #888888">FROM [Adventure Works])</span></p>
<p>Nun müssen beide Datasets miteinander verbunden werden. Hierzu werden die Eigenschaften der Serie geöffnet:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit3.png"><img class="size-medium wp-image-1430 alignnone" src="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit3-300x157.png" alt="" width="330" height="188" /></a></p>
<p>Im Feld für die Daten (Value) wird nun der Lookup gegen das Dataset „GueltigeMonate“  hergestellt. Hierfür wird die Funktion „Lookup“ benötigt. Die Syntax sieht so aus:</p>
<p><span style="color: #888888">=IIF(LEFT(Fields!Month.Value,LEN(Fields!Month.Value)-5)=</span></p>
<p><span style="color: #888888">LOOKUP(LEFT(Fields!Month.Value,LEN(Fields!Month.Value)-5), Fields!ParameterCaption.Value,Fields!ParameterCaption.Value,&#8221;GueltigeMonate&#8221;),</span></p>
<p><span style="color: #888888">Sum(Fields!Sales_Amount.Value),0)</span></p>
<p>Diese Syntax bewirkt folgendes:</p>
<p>Wenn der Monatsname im Haupt-Dataset gleich einem Monatsnamen ist, der im gefilterten Monats-Dataset vorhanden ist, so wird der Wert angezeigt, ansonsten wird die Zahl 0 angezeigt.</p>
<p>Wenn nun im Bericht die gleiche Selektion wie am Anfang beschreiben durchgeführt wird, ergibt sich das gewünschte Bild: </p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit41.png"><img class="size-full wp-image-1432 alignnone" src="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit41.png" alt="" width="671" height="322" /></a></p>
<p>Die Anzeige-Geschwindigkeit konnte mit der Lookup-Methode gegenüber der Behandlung im Query halbiert werden. In einem der nächsten Blog-einträge werde ich die Lookup-Funktion dann nochmal näher beleuchten.</p>
<div style="display:block"><small><em>by Arno Cebulla <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2012%2F01%2Fdarstellung-herausgefilterter-zeit-kategorien%2F&amp;linkname=Darstellung%20herausgefilterter%20Zeit-Kategorien"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p>Ein typisches Verhalten in Reporting-Services ist es, dass Daten, die mit Parametern herausgefiltert werden, auch im Bericht nicht dargestellt werden. Beispiel: In diesem Chart werden die Umsätze für ein Jahr dargestellt: </p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit1.gif"><img class="size-full wp-image-1428 alignnone" src="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit1.gif" alt="" width="460" height="214" /></a></p>
<p> Wenn nun nur noch die Monate Januar-April im Month-Parameter ausgewählt werden, erscheint folgendes Chart:</p>
<p> <a href="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit2.gif"><img class="alignleft size-full wp-image-1429" src="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit2.gif" alt="" width="669" height="305" /></a></p>
<p>Die Daten werden per MDX aus einem Cube gelesen und im Dataset mit einem Subselect oder in der WHERE-Bedingung gefiltert:</p>
<p><span style="color: #888888">SELECT</span></p>
<p><span style="color: #888888"> {[Measures].[Sales Amount]} ON 0,</span></p>
<p><span style="color: #888888"> NON EMPTY</span></p>
<p><span style="color: #888888"> {([Date].[Calendar].[Date].ALLMEMBERS )} ON 1</span></p>
<p><span style="color: #888888"> FROM</span></p>
<p><span style="color: #888888"> (SELECT ( STRTOSET(@DateCalendarYear, CONSTRAINED) ) ON 0</span></p>
<p><span style="color: #888888"> FROM</span></p>
<p><span style="color: #888888"> (SELECT ( STRTOSET(@DateMonthofYear, CONSTRAINED) ) ON 0</span></p>
<p><span style="color: #888888"> FROM [Adventure Works]))</span></p>
<p>Der Kunde wünscht nun, dass die übrigen Monate aber dennoch (mit dem Wert 0) angezeigt werden sollen. Hierfür gibt es zum einen die Möglichkeit, dieses bereits im MDX-Query zu lösen. Dies geschieht über einen String-Vergleich in einem IIF-Block. Leider ist diese Methode recht unperformant.</p>
<p>Ein besseres Ergebnis kann man mit dieser Methode erzielen, vorausgesetzt man verwendet SQL Server ab Version 2008 R2:</p>
<p>Im Dataset werden zunächst <strong>alle </strong>Daten für das Jahr geholt:</p>
<p><span style="color: #888888">SELECT</span></p>
<p><span style="color: #888888"> {[Measures].[Sales Amount]} ON 0,</span></p>
<p><span style="color: #888888"> NON EMPTY</span></p>
<p><span style="color: #888888"> {([Date].[Calendar].[Date].ALLMEMBERS )} ON 1</span></p>
<p><span style="color: #888888"> FROM</span></p>
<p><span style="color: #888888"> (SELECT ( STRTOSET(@DateCalendarYear, CONSTRAINED) ) ON 0</span></p>
<p><span style="color: #888888"> FROM [Adventure Works])</span></p>
<p>Dann wird ein zweites Dataset „GueltigeMonate“ erstellt, in dem die Monate anhand des Parameters gefiltert werden:</p>
<p><span style="color: #888888">WITH</span></p>
<p><span style="color: #888888">MEMBER [Measures].[ParameterCaption] AS [Date].[Month of Year].CURRENTMEMBER.MEMBER_CAPTION</span></p>
<p><span style="color: #888888">MEMBER [Measures].[ParameterValue] AS [Date].[Month of Year].CURRENTMEMBER.UNIQUENAME</span></p>
<p><span style="color: #888888">MEMBER [Measures].[ParameterLevel] AS [Date].[Month of Year].CURRENTMEMBER.LEVEL.ORDINAL</span></p>
<p><span style="color: #888888">SELECT</span></p>
<p><span style="color: #888888">{[Measures].[ParameterCaption], [Measures].[ParameterValue], [Measures].[ParameterLevel]} ON COLUMNS ,</span></p>
<p><span style="color: #888888">[Date].[Month of Year].ALLMEMBERS ON ROWS</span></p>
<p><span style="color: #888888">FROM</span></p>
<p><span style="color: #888888">(SELECT STRTOSET(@Monate,CONSTRAINED) ON 0</span></p>
<p><span style="color: #888888">FROM [Adventure Works])</span></p>
<p>Nun müssen beide Datasets miteinander verbunden werden. Hierzu werden die Eigenschaften der Serie geöffnet:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit3.png"><img class="size-medium wp-image-1430 alignnone" src="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit3-300x157.png" alt="" width="330" height="188" /></a></p>
<p>Im Feld für die Daten (Value) wird nun der Lookup gegen das Dataset „GueltigeMonate“  hergestellt. Hierfür wird die Funktion „Lookup“ benötigt. Die Syntax sieht so aus:</p>
<p><span style="color: #888888">=IIF(LEFT(Fields!Month.Value,LEN(Fields!Month.Value)-5)=</span></p>
<p><span style="color: #888888">LOOKUP(LEFT(Fields!Month.Value,LEN(Fields!Month.Value)-5), Fields!ParameterCaption.Value,Fields!ParameterCaption.Value,&#8221;GueltigeMonate&#8221;),</span></p>
<p><span style="color: #888888">Sum(Fields!Sales_Amount.Value),0)</span></p>
<p>Diese Syntax bewirkt folgendes:</p>
<p>Wenn der Monatsname im Haupt-Dataset gleich einem Monatsnamen ist, der im gefilterten Monats-Dataset vorhanden ist, so wird der Wert angezeigt, ansonsten wird die Zahl 0 angezeigt.</p>
<p>Wenn nun im Bericht die gleiche Selektion wie am Anfang beschreiben durchgeführt wird, ergibt sich das gewünschte Bild: </p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit41.png"><img class="size-full wp-image-1432 alignnone" src="http://blog.oraylis.de/wp-content/uploads/2012/01/Zeit41.png" alt="" width="671" height="322" /></a></p>
<p>Die Anzeige-Geschwindigkeit konnte mit der Lookup-Methode gegenüber der Behandlung im Query halbiert werden. In einem der nächsten Blog-einträge werde ich die Lookup-Funktion dann nochmal näher beleuchten.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2012/01/darstellung-herausgefilterter-zeit-kategorien/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sparse Snapshots in DAX / BISM Tabular</title>
		<link>http://blog.oraylis.de/2012/01/sparse-snapshots-in-dax-bism-tabular/</link>
		<comments>http://blog.oraylis.de/2012/01/sparse-snapshots-in-dax-bism-tabular/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 12:35:03 +0000</pubDate>
		<dc:creator>Hilmar Buchta</dc:creator>
				<category><![CDATA[MS SSAS]]></category>
		<category><![CDATA[BISM]]></category>
		<category><![CDATA[DAX]]></category>
		<category><![CDATA[PowerPivot]]></category>
		<category><![CDATA[Tabular]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2012/01/sparse-snapshots-in-dax-bism-tabular/</guid>
		<description><![CDATA[<p align="right">SQL Server 2012/Denali | PowerPivot</p>
<p>In <font style="background-color: #ffff00"></font><a href="http://ms-olap.blogspot.com/2011/11/sql-server-denali-powerpivot-common-way.html">my last post</a><font style="background-color: #ffff00"></font> I wrote about using delta values instead of full snapshots. However, the amount of data is identical if we using a sparse snapshots instead. For this purpose, the source data from my last post has just to be converted to absolute values as shown below:</p>
<table border="1" cellspacing="0" cellpadding="2" width="627">
<tbody>
<tr>
<td valign="top" width="241">
<p align="center"><strong>Only delta values</strong></p>
</td>
<td valign="top" width="101">&nbsp;</td>
<td valign="top" width="283">
<p align="center"><strong>Only snapshots (changes)</strong></p>
</td>
</tr>
<tr>
<td valign="top" width="241"><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t3" border="0" alt="t3" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t3_thumb.png" width="221" height="285" /></a></td>
<td width="101"><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/image.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://blog.oraylis.de/wp-content/uploads/2012/01/image_thumb.png" width="72" height="48" /></a></td>
<td valign="top" width="283"><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t2" border="0" alt="t2" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t2_thumb.png" width="222" height="287" /></a></td>
</tr>
</tbody>
</table>
<p>So the amount of data is not really changed. But with the sparse snapshots the computations get a lot more difficult. If we have delta values (left table) we can simply sum up all deltas to a given date and this works for all of our related tables (for example products). With sparse snapshots (right table) we have to find out the last value per product and then add the results up to the total, so we have to do a calculation per product before.</p>
<p>Before we get to the calculation, here is the very simple source data model that I used:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t7.png"><img style="display: inline" title="t7" alt="t7" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t7_thumb.png" width="563" height="171" /></a></p>
<p>It took me some time to figure out the following solution and I’m pretty sure that there must be an easier method. So feel free to experiment and write comments.</p>
<p>Here is the final code:</p>
<p><font face="Courier New">Stock:=      <br />&#160;&#160;&#160; SumX(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Product&#8217;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; &#8216;Product&#8217;[Product]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;LastStock&quot;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , calculate(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[StockLevel])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , dateadd(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,-floor(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; MaxX(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , 1       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,DAY       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; [LastStock]       <br />&#160;&#160;&#160; )</font></p>
<p>This is how are data looks like <em>without</em> the computation from above:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t5.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t5" border="0" alt="t5" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t5_thumb.png" width="334" height="202" /></a></p>
<p>Since the data is sparse we only see the stock at dates where there are changes. For the aggregation I used the Sum function (which doesn’t make much sense here for the date aggregates) and you also see that the row total over the products only takes products into account when there are changes.</p>
<p>And here is the resulting Excel pivot table using the calculation from above:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t6.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t6" border="0" alt="t6" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t6_thumb.png" width="333" height="565" /></a></p>
<p>As you can see the value for Quickerstill starts with 20 then drops to 18 at January 3, then to 15 at January 5 etc. Also the totals are correct now.</p>
<p>The remaining part of this post is about the formula from above, so it’s up to you to decide if you want to continue reading. The most important point here is that the calculation is much easier when working with delta rows or delta rows with intermediate snapshots (for example each first day of a month, quarter, year).</p>
<p>&#160;</p>
<p><strong><u>Details of the calculation</u></strong></p>
<p>The first question is about the way we’re doing the calculation. Wouldn’t it be easier and faster to have them on the rows and therefore persisted (is ‘persisted’ the right term when talking about an in-memory database??)? Well, if you look at the screenshots above, the only reason we’re doing all this is because we need calculated values on “rows” that do not exist. In the last screenshot there is no row for January 31, but the value has to be computed: For Notate it’s the value of January 1 and for Quickerstill it’s the value of January 21. So we have to use a calculated measure in the model.</p>
<p>To makes things easier here, let’s start with a single product (Quickerstill). I want to calculate the last date for which I have a value. To do this I filter the date range from a very early date (2000/1/1 here) to the last date in the current context to those values, where the sum of the stock amount (any aggregate would do) is not blank, then take the biggest date (max function). This is the code:</p>
<p><font color="#0000ff" face="Courier New"><font color="#000000">Step1:=</font>       <br /><font color="#333333">&#160;&#160;&#160; MaxX(        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160; )</font></font></p>
<p>If I include the original measure and this calculation in a pivot table, this is the result:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t8.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t8" border="0" alt="t8" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t8_thumb.png" width="264" height="537" /></a></p>
<p>For each day our calculation returns the last date with data. For example the calculated date for January 12 is January 6 as this was the last day with data before January 12. It seems we are already close to the solution but please keep in mind that the calculation from above would not work for more than one product (for example if the products are not filtered) as the date for each product has to be different. If we filter the pivot table from above for product Notate, the results would look totally different. Here are the first rows:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t9.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t9" border="0" alt="t9" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t9_thumb.png" width="265" height="289" /></a></p>
<p>But let’s ignore this for a second and keep the filter on Quickerstill. The next task would be to calculate the stock level at the calculated date. This sounds easy and the following formula was my first approach:</p>
<p><font face="Courier New">Step2 (with error):=      <br />&#160;&#160;&#160; calculate(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[StockLevel])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,<font color="#0000ff">MaxX(        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br /></font>&#160;&#160;&#160; )</font></p>
<p>The code in blue is the exactly the code from above which gives the filter context for the calculation of the sum of the stock level values. However, this results in an error:</p>
<p><strong><font color="#ff0000">Semantic Error: A function ‘MAXX‘ has been used in a True/False expression that is used as a table filter expression. This is not allowed.</font></strong></p>
<p>I love the ‘This is not allowed’ here. Actually there is no reason why it isn’t and I’m not feeling like I’m doing something illegal here. Maybe it’s also just a limitation of the CTP 3 beta release that I am currently working with. I also tried to wrap the MaxX function in a DateAdd with 0 days but this is also ‘not allowed’.</p>
<p>But there is a way which can be found after some time of experimenting. I take the number of days between the last date from the context and the date from the calculation in blue and use this result to correct my last date. Sounds confusing? Let’s start with the number of days. Here is the next step of the calculation:</p>
<p><font face="Courier New"><font color="#000000">Step2:=        <br />&#160;&#160;&#160; floor(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; -</font><font color="#00ff00">        <br /></font><font color="#0000ff">&#160;&#160;&#160;&#160;&#160;&#160;&#160; MaxX(        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )</font>       <br /><font color="#000000">&#160;&#160;&#160;&#160;&#160;&#160;&#160; , 1        <br />&#160;&#160;&#160; )</font></font></p>
<p>Again the code in blue is the last date calculation from above (step 1). Let’s take a look at the result of this calculation:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t10.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t10" border="0" alt="t10" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t10_thumb.png" width="312" height="472" /></a></p>
<p>As you see, the new calculation tells us, how many days we have to go back in time to find a value. For example for January 14 we get a value of 8 meaning we have to go back 8 days to January 6 to find a value. Now we can wrap this in the calculation of the stock value and for some reason that I don’t understand, this is not illegal anymore although I’m doing exactly the same as I did before. Here is the calculation:</p>
<p><font face="Courier New">Step3:=      <br />&#160;&#160;&#160; calculate(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[StockLevel])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , dateadd(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,-<font color="#0000ff">floor(        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; MaxX(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , 1         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br /></font>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,DAY       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160; )</font></p>
<p>Again the code from the last step is colored blue (step 2). Now we’re pretty close to the final formula. Let’s check the result when including both products:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t11.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t11" border="0" alt="t11" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t11_thumb.png" width="395" height="302" /></a></p>
<p>Now the result for each product is already working correctly. But the total is still not correct as you can see from the line marked in red. For January 2 the last date with data is the same for both products (January 1), therefore the value is correct. But for January 3 there are different days for the last stock value, so we only see one product in the total.</p>
<p>However, the remaining part is not difficult. We simply summarize (group) by product and take the sum. Again, the code in blue is the last code from the step before (step 3):</p>
<p><font face="Courier New">Stock:=      <br />&#160;&#160;&#160; SumX(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Product&#8217;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; &#8216;Product&#8217;[Product]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;LastStock&quot;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , <font color="#0000ff">calculate(        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[StockLevel])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , dateadd(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,-floor(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; MaxX(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , 1         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,DAY         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br /></font>&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; [LastStock]       <br />&#160;&#160;&#160; )</font></p>
<p>Now, this does the trick and we end up with the final screenshot as shown at the beginning of this post.</p>
<p>If you like you can play with the formula by downloading the sample work book <a href="https://skydrive.live.com/view.aspx?cid=61F98448A5E17D57&amp;resid=61F98448A5E17D57%21743" target="_blank">here</a> (right click on the link, then choose ‘Save as…’). You will need the <a href="http://www.microsoft.com/download/en/details.aspx?id=26721" target="_blank">PowerPivot Add-In CTP 3</a> or later in order to open the workbook.</p>
<div style="display:block"><small><em>by Hilmar Buchta <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2012%2F01%2Fsparse-snapshots-in-dax-bism-tabular%2F&amp;linkname=Sparse%20Snapshots%20in%20DAX%20%2F%20BISM%20Tabular"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p align="right">SQL Server 2012/Denali | PowerPivot</p>
<p>In <font style="background-color: #ffff00"></font><a href="http://ms-olap.blogspot.com/2011/11/sql-server-denali-powerpivot-common-way.html">my last post</a><font style="background-color: #ffff00"></font> I wrote about using delta values instead of full snapshots. However, the amount of data is identical if we using a sparse snapshots instead. For this purpose, the source data from my last post has just to be converted to absolute values as shown below:</p>
<table border="1" cellspacing="0" cellpadding="2" width="627">
<tbody>
<tr>
<td valign="top" width="241">
<p align="center"><strong>Only delta values</strong></p>
</td>
<td valign="top" width="101">&nbsp;</td>
<td valign="top" width="283">
<p align="center"><strong>Only snapshots (changes)</strong></p>
</td>
</tr>
<tr>
<td valign="top" width="241"><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t3" border="0" alt="t3" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t3_thumb.png" width="221" height="285" /></a></td>
<td width="101"><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/image.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://blog.oraylis.de/wp-content/uploads/2012/01/image_thumb.png" width="72" height="48" /></a></td>
<td valign="top" width="283"><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t2" border="0" alt="t2" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t2_thumb.png" width="222" height="287" /></a></td>
</tr>
</tbody>
</table>
<p>So the amount of data is not really changed. But with the sparse snapshots the computations get a lot more difficult. If we have delta values (left table) we can simply sum up all deltas to a given date and this works for all of our related tables (for example products). With sparse snapshots (right table) we have to find out the last value per product and then add the results up to the total, so we have to do a calculation per product before.</p>
<p>Before we get to the calculation, here is the very simple source data model that I used:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t7.png"><img style="display: inline" title="t7" alt="t7" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t7_thumb.png" width="563" height="171" /></a></p>
<p>It took me some time to figure out the following solution and I’m pretty sure that there must be an easier method. So feel free to experiment and write comments.</p>
<p>Here is the final code:</p>
<p><font face="Courier New">Stock:=      <br />&#160;&#160;&#160; SumX(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Product&#8217;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; &#8216;Product&#8217;[Product]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;LastStock&quot;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , calculate(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[StockLevel])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , dateadd(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,-floor(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; MaxX(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , 1       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,DAY       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; [LastStock]       <br />&#160;&#160;&#160; )</font></p>
<p>This is how are data looks like <em>without</em> the computation from above:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t5.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t5" border="0" alt="t5" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t5_thumb.png" width="334" height="202" /></a></p>
<p>Since the data is sparse we only see the stock at dates where there are changes. For the aggregation I used the Sum function (which doesn’t make much sense here for the date aggregates) and you also see that the row total over the products only takes products into account when there are changes.</p>
<p>And here is the resulting Excel pivot table using the calculation from above:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t6.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t6" border="0" alt="t6" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t6_thumb.png" width="333" height="565" /></a></p>
<p>As you can see the value for Quickerstill starts with 20 then drops to 18 at January 3, then to 15 at January 5 etc. Also the totals are correct now.</p>
<p>The remaining part of this post is about the formula from above, so it’s up to you to decide if you want to continue reading. The most important point here is that the calculation is much easier when working with delta rows or delta rows with intermediate snapshots (for example each first day of a month, quarter, year).</p>
<p>&#160;</p>
<p><strong><u>Details of the calculation</u></strong></p>
<p>The first question is about the way we’re doing the calculation. Wouldn’t it be easier and faster to have them on the rows and therefore persisted (is ‘persisted’ the right term when talking about an in-memory database??)? Well, if you look at the screenshots above, the only reason we’re doing all this is because we need calculated values on “rows” that do not exist. In the last screenshot there is no row for January 31, but the value has to be computed: For Notate it’s the value of January 1 and for Quickerstill it’s the value of January 21. So we have to use a calculated measure in the model.</p>
<p>To makes things easier here, let’s start with a single product (Quickerstill). I want to calculate the last date for which I have a value. To do this I filter the date range from a very early date (2000/1/1 here) to the last date in the current context to those values, where the sum of the stock amount (any aggregate would do) is not blank, then take the biggest date (max function). This is the code:</p>
<p><font color="#0000ff" face="Courier New"><font color="#000000">Step1:=</font>       <br /><font color="#333333">&#160;&#160;&#160; MaxX(        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160; )</font></font></p>
<p>If I include the original measure and this calculation in a pivot table, this is the result:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t8.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t8" border="0" alt="t8" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t8_thumb.png" width="264" height="537" /></a></p>
<p>For each day our calculation returns the last date with data. For example the calculated date for January 12 is January 6 as this was the last day with data before January 12. It seems we are already close to the solution but please keep in mind that the calculation from above would not work for more than one product (for example if the products are not filtered) as the date for each product has to be different. If we filter the pivot table from above for product Notate, the results would look totally different. Here are the first rows:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t9.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t9" border="0" alt="t9" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t9_thumb.png" width="265" height="289" /></a></p>
<p>But let’s ignore this for a second and keep the filter on Quickerstill. The next task would be to calculate the stock level at the calculated date. This sounds easy and the following formula was my first approach:</p>
<p><font face="Courier New">Step2 (with error):=      <br />&#160;&#160;&#160; calculate(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[StockLevel])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,<font color="#0000ff">MaxX(        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br /></font>&#160;&#160;&#160; )</font></p>
<p>The code in blue is the exactly the code from above which gives the filter context for the calculation of the sum of the stock level values. However, this results in an error:</p>
<p><strong><font color="#ff0000">Semantic Error: A function ‘MAXX‘ has been used in a True/False expression that is used as a table filter expression. This is not allowed.</font></strong></p>
<p>I love the ‘This is not allowed’ here. Actually there is no reason why it isn’t and I’m not feeling like I’m doing something illegal here. Maybe it’s also just a limitation of the CTP 3 beta release that I am currently working with. I also tried to wrap the MaxX function in a DateAdd with 0 days but this is also ‘not allowed’.</p>
<p>But there is a way which can be found after some time of experimenting. I take the number of days between the last date from the context and the date from the calculation in blue and use this result to correct my last date. Sounds confusing? Let’s start with the number of days. Here is the next step of the calculation:</p>
<p><font face="Courier New"><font color="#000000">Step2:=        <br />&#160;&#160;&#160; floor(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; -</font><font color="#00ff00">        <br /></font><font color="#0000ff">&#160;&#160;&#160;&#160;&#160;&#160;&#160; MaxX(        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )</font>       <br /><font color="#000000">&#160;&#160;&#160;&#160;&#160;&#160;&#160; , 1        <br />&#160;&#160;&#160; )</font></font></p>
<p>Again the code in blue is the last date calculation from above (step 1). Let’s take a look at the result of this calculation:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t10.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t10" border="0" alt="t10" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t10_thumb.png" width="312" height="472" /></a></p>
<p>As you see, the new calculation tells us, how many days we have to go back in time to find a value. For example for January 14 we get a value of 8 meaning we have to go back 8 days to January 6 to find a value. Now we can wrap this in the calculation of the stock value and for some reason that I don’t understand, this is not illegal anymore although I’m doing exactly the same as I did before. Here is the calculation:</p>
<p><font face="Courier New">Step3:=      <br />&#160;&#160;&#160; calculate(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[StockLevel])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , dateadd(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,-<font color="#0000ff">floor(        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; MaxX(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , 1         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br /></font>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,DAY       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160; )</font></p>
<p>Again the code from the last step is colored blue (step 2). Now we’re pretty close to the final formula. Let’s check the result when including both products:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2012/01/t11.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t11" border="0" alt="t11" src="http://blog.oraylis.de/wp-content/uploads/2012/01/t11_thumb.png" width="395" height="302" /></a></p>
<p>Now the result for each product is already working correctly. But the total is still not correct as you can see from the line marked in red. For January 2 the last date with data is the same for both products (January 1), therefore the value is correct. But for January 3 there are different days for the last stock value, so we only see one product in the total.</p>
<p>However, the remaining part is not difficult. We simply summarize (group) by product and take the sum. Again, the code in blue is the last code from the step before (step 3):</p>
<p><font face="Courier New">Stock:=      <br />&#160;&#160;&#160; SumX(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Product&#8217;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; &#8216;Product&#8217;[Product]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;LastStock&quot;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , <font color="#0000ff">calculate(        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[StockLevel])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , dateadd(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,-floor(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; MaxX(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Filter(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DatesBetween(&#8216;Date&#8217;[Date], date(2000,1,1), LastDate(&#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;X&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#160; calculate(Sum(&#8216;Stock&#8217;[StockLevel]), ALLEXCEPT(&#8216;Date&#8217;, &#8216;Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , not isblank([X])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , 1         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,DAY         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br /></font>&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; [LastStock]       <br />&#160;&#160;&#160; )</font></p>
<p>Now, this does the trick and we end up with the final screenshot as shown at the beginning of this post.</p>
<p>If you like you can play with the formula by downloading the sample work book <a href="https://skydrive.live.com/view.aspx?cid=61F98448A5E17D57&amp;resid=61F98448A5E17D57%21743" target="_blank">here</a> (right click on the link, then choose ‘Save as…’). You will need the <a href="http://www.microsoft.com/download/en/details.aspx?id=26721" target="_blank">PowerPivot Add-In CTP 3</a> or later in order to open the workbook.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2012/01/sparse-snapshots-in-dax-bism-tabular/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eine Schaltfl&#228;che in die SharePoint Ribbon Leiste integrieren</title>
		<link>http://blog.oraylis.de/2011/11/eine-schaltflche-in-die-sharepoint-ribbon-leiste-integrieren/</link>
		<comments>http://blog.oraylis.de/2011/11/eine-schaltflche-in-die-sharepoint-ribbon-leiste-integrieren/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 18:12:05 +0000</pubDate>
		<dc:creator>Sandra Erb</dc:creator>
				<category><![CDATA[Allgemein]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2011/11/eine-schaltflche-in-die-sharepoint-ribbon-leiste-integrieren/</guid>
		<description><![CDATA[<p>&#160;</p>
<p>Die wohl auffälligste Änderung in SharePoint 2010 zu den vorherigen Versionen, ist die Integration der bereits aus den Office Produkten bekannten Ribbon Leiste. Wie so vieles im SharePoint kann auch diese von Entwicklern erweitert und angepasst werden.</p>
<p>Im Folgenden wird ein Beispiel gezeigt, um eine eigene Schaltfläche in die Ribbon Leiste zu integrieren.</p>
<p>Zur Anpassung der Ribbon Leiste wird ein neues Feature mit Visual Studio 2010 erstellt. Dies vereinfacht das spätere Deployment durch die Erstellung einer wsp Datei.</p>
<p> <span id="more-1402"></span>
<p>Es empfiehlt sich immer mit einem Projekt vom Typ “Empty SharePoint Project” zu beginnen. Dieses ist flexibel und ermöglicht es, mehrere Features, Webparts etc. zu bündeln.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_NewProject.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="Neues Empty SharePoint Project" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_NewProject_thumb.png" width="339" height="215" /></a></p>
<p>Bei der Erstellung fragt Visual Studio ab, ob eine Sandboxed Solution oder eine Farm Solution erstellt werden soll. Für dieses Beispiel ist eine Sandboxed Solution vollkommen ausreichend. Eine Farm Solution sollte nur dann erstellt werden, wenn die Möglichkeiten der Sandboxed Solution nicht mehr ausreichen.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_2_SolutionType.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="Sandboxed Solution" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_2_SolutionType_thumb.png" width="329" height="262" /></a></p>
<p>Mit dem Visual Studio 2010 wurde das Entwickeln von SharePoint Solutions um ein Vielfaches vereinfacht. Es gibt mehr Templates und eine sehr gute Integration von Standard-Aufgaben in die Oberfläche. So wird beim Erstellen des neuen Projektes z.B. direkt ein “Feature” Verzeichnis angelegt. Mit einem Rechtsklick auf dieses Verzeichnis kann ein neues Feature erstellt werden.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_3_NewFeature.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="Feature hinzufuegen" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_3_NewFeature_thumb.png" width="244" height="152" /></a> </p>
<p>Die nun erstellte “Feature1.feature” Datei ist eine Art grafische Oberfläche für die Feature.xml Datei. Diese muss also nicht noch zusätzlich erstellt werden, im Gegensatz zur Elements.xml Datei, welche noch immer selbst geschrieben werden muss. Ein Template für die Elements.xml bekommt man z.B. durch das Hinzufügen eines “Empty Elements”. Ich empfehle an dieser Stelle die Elements.xml Datei immer über diesen Weg einzubinden, das macht die Solution übersichtlich.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/image.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="New Item" src="http://blog.oraylis.de/wp-content/uploads/2011/11/image_thumb.png" width="383" height="197" /></a></p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_5_EmptyElement.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="Empty Element" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_5_EmptyElement_thumb.png" width="384" height="243" /></a></p>
<p>Ein Blick auf das Feature zeigt, dass die Elements.xml Datei automatisch referenziert wurde.</p>
<p><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="Feature" src="http://blog.oraylis.de/wp-content/uploads/2011/11/image_thumb1.png" width="382" height="116" /></p>
<p>Nachdem nun alle für das Feature erforderlichen Dateien vorhanden sind, muss die Elements.xml Datei noch mit Leben gefüllt werden.</p>
<p>In der MSDN findet man viele Beispiele zum Anpassen der Ribbon Bar. Darunter auch diese einfache Elements.xml Datei:</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;Elements xmlns=&quot;http://schemas.microsoft.com/sharepoint/&quot;&gt;
&lt;CustomAction
  Id=&quot;DemoHelloWorldButton&quot;
  RegistrationType=&quot;List&quot;
  RegistrationId=&quot;101&quot;
  Location=&quot;CommandUI.Ribbon&quot;&gt;
    &lt;CommandUIExtension&gt;
      &lt;CommandUIDefinitions&gt;
        &lt;CommandUIDefinition
         Location=&quot;Ribbon.Documents.New.Controls._children&quot;&gt;
          &lt;Button
           Id=&quot;Ribbon.Documents.New.Controls.DemoHelloWorldButton&quot;
           Alt=&quot;Hello World Ribbon Button&quot;
           Sequence=&quot;10&quot;
           Image32by32=&quot;/_layouts/images/PPEOPLE.GIF&quot;
           Command=&quot;Demo_HelloWorld&quot;
           LabelText=&quot;Hello World Demo&quot;
           TemplateAlias=&quot;o2&quot;/&gt;
        &lt;/CommandUIDefinition&gt;
      &lt;/CommandUIDefinitions&gt;
      &lt;CommandUIHandlers&gt;
        &lt;CommandUIHandler
         Command=&quot;Demo_HelloWorld&quot;
         CommandAction=&quot;javascript:alert('Hello World!');&quot; /&gt;
      &lt;/CommandUIHandlers&gt;
    &lt;/CommandUIExtension&gt;
  &lt;/CustomAction&gt;
&lt;/Elements&gt;</code></pre>
<p>&#160;</p>
<p>Das <strong>CustomAction</strong> Element zeigt an, dass eine neue CustomAction hinzugefügt werden soll. Als CustomAction werden z.B. die Erweiterung der SharePoint Oberfläche mit Schaltflächen oder neuen Links in den Settings Seiten bezeichnet.</p>
<p>Über die Attribute <strong>RegistrationType</strong> und <strong>RegistrationId</strong> wird bestimmt, für welche Elemente die Custom Action (in diesem Fall die Schaltfläche) sichtbar sein soll. Das Attribut RegistrationType kann die folgenden Werte enthalten:</p>
<ul>
<li>None </li>
<li>List </li>
<li>ContentType </li>
<li>ProgId </li>
<li>FileType </li>
</ul>
<p>
  <br />Damit wird der Typ angegeben, an den die CustomAction gebunden wird. Die RegistrationId bestimmt dann das konkrete Element. In obigem Beispiel wird die Schaltfläche nur in Dokumentenbibliotheken angezeigt (Typ List und RegistrationId 101).</p>
<p>Eine sehr gute Übersicht über die verschiedenen Registration IDs findet sich z.B. in Mike Smith Blog unter <a title="http://techtrainingnotes.blogspot.com/2008/01/sharepoint-registrationid-list-template.html" href="http://techtrainingnotes.blogspot.com/2008/01/sharepoint-registrationid-list-template.html">http://techtrainingnotes.blogspot.com/2008/01/sharepoint-registrationid-list-template.html</a>.</p>
<p>Im <strong>CommandUIExtension</strong> Element wird die eigentliche Schaltfläche definiert. Das <strong>CommandUID</strong><strong>efinition</strong> Element beinhaltet hierbei die Definition der Darstellung und das <strong>CommandUIHandler</strong> Element beinhaltet die eigentliche Funktionalität hinter der Schaltfläche. </p>
<p>Das <strong>Location</strong> Attribut im CommandUIDefinition Element gibt an, an welcher Stelle die Anpassung in der Oberfläche dargestellt werden soll. Im obigen Beispiel wird die Schaltfläche in der Ribbon Leiste auf dem “Document” Tab in der Gruppe “New” angezeigt. Der folgenden MSDN Seite können einige Standardpfade für die Ribbon Elemente entnommen werden: <a title="http://msdn.microsoft.com/en-us/library/ee537543.aspx" href="http://msdn.microsoft.com/en-us/library/ee537543.aspx">http://msdn.microsoft.com/en-us/library/ee537543.aspx</a></p>
<p>Das <strong>Id</strong> Attribut im <strong>Button</strong> Element muss immer einen eindeutigen Wert haben. Hier empfiehlt sich eine GUID oder eine Mischung aus der Location der Schaltfläche und dem Namen des Features.</p>
<p>Das <strong>Sequence</strong> Attribut gibt an, in welcher Reihenfolge die Schaltflächen innerhalb einer Gruppe auf der Ribbon Leiste dargestellt werden sollen.</p>
<p>Über die beiden Attribute <strong>Image32by32</strong> und <strong>Image16by16</strong> werden die Grafiken definiert, welche für die Schaltfläche angezeigt werden sollen. Diese Bilder müssen im Verzeichnis <strong>/_layouts/images</strong> auf dem Server vorhanden sein (z.B. C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\1033\IMAGES bei einer englischen Standardinstallation).</p>
<p>Das <strong>Command</strong> Attribut im CommandUIDefinition Element identifiziert später die im CommandUIExtension/CommandUIHandler Element definierte Funktion, welche von der Schaltfläche aufgerufen wird. Es ist wichtig, an beiden Stellen den selben Wert für das Command Attribut einzutragen.</p>
<p>Der <strong>LabelText</strong> ist der Text, der unterhalb der Schaltfläche auf der Ribbon Leiste angezeigt wird. Es empfiehlt sich diese Texte von vornherein zu lokalisieren.</p>
<p>Das <strong>TemplateAlias</strong> Attribut definiert die Größe und Darstellung der Schaltfläche.</p>
<p>Die Definition des <strong>CommanUIHandler</strong> Elements ist sehr einfach. Über das <strong>Command</strong> Attribut wird die Verbindung zur Schaltfläche hergestellt. Daher muss dieses den selben Wert enthalten wie das Command Attribut des Button Elements. Im <strong>CommandAction</strong> Attribut wird z.B. eine Javascript Funktion angegeben, welche beim Anklicken der Schaltfläche ausgeführt werden soll.</p>
<p>Mehr braucht es nicht. Das Feature kann nun deployed werden. Dies kann auf einer Entwicklungsumgebung direkt aus dem Visual Studio heraus, oder mit Hilfe der Power Shell erfolgen.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_9_deploy.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="VS Deployment" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_9_deploy_thumb.png" width="347" height="164" /></a> </p>
<p>Soll das Feature über die Power Shell deployed werden, so muss zunächst eine wsp Datei erstellt werden. Auch dies kann nun über das Visual Studio 2010 selbst geschehen, es sind keine zusätzlichen Tools mehr nötig. Dazu aus dem Kontextmenü des Projektes den Punkt “Package” auswählen.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_10_package.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="20111020_10_package" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_10_package_thumb.png" width="350" height="164" /></a> </p>
<p>Ist die wsp Datei erstellt, erfolgt das Deployment über die folgenden PowerShell Befehle:</p>
<ol>
<li>
<pre><code>Add-SPSolution “&lt;Pfad&gt;\CustomRibbonButton.wsp”</code></pre>
</li>
<li>
<pre><code>Install-SPSolution –Identity CustomRibbonButton.wsp –GACDeployment</code></pre>
</li>
</ol>
<p>
  <br />Das Feature kann dann wie gewohnt über die Site Features (Site Settings –&gt; Site Features) oder über den PowerShell Befehl “<code>Enable-SPFeature</code>” aktiviert werden.</p>
<p>Die neue Schaltfläche ist jetzt in der Gruppe “New” auf dem “Documents” Tab aller Dokumentenbibliotheken vorhanden und führt wie gewünscht ein einfaches Java Script aus.</p>
</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_11_works.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="20111020_11_works" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_11_works_thumb.png" width="365" height="272" /></a></p>
<div style="display:block"><small><em>by Sandra Erb <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2011%2F11%2Feine-schaltflche-in-die-sharepoint-ribbon-leiste-integrieren%2F&amp;linkname=Eine%20Schaltfl%26auml%3Bche%20in%20die%20SharePoint%20Ribbon%20Leiste%20integrieren"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p>&#160;</p>
<p>Die wohl auffälligste Änderung in SharePoint 2010 zu den vorherigen Versionen, ist die Integration der bereits aus den Office Produkten bekannten Ribbon Leiste. Wie so vieles im SharePoint kann auch diese von Entwicklern erweitert und angepasst werden.</p>
<p>Im Folgenden wird ein Beispiel gezeigt, um eine eigene Schaltfläche in die Ribbon Leiste zu integrieren.</p>
<p>Zur Anpassung der Ribbon Leiste wird ein neues Feature mit Visual Studio 2010 erstellt. Dies vereinfacht das spätere Deployment durch die Erstellung einer wsp Datei.</p>
<p> <span id="more-1402"></span>
<p>Es empfiehlt sich immer mit einem Projekt vom Typ “Empty SharePoint Project” zu beginnen. Dieses ist flexibel und ermöglicht es, mehrere Features, Webparts etc. zu bündeln.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_NewProject.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="Neues Empty SharePoint Project" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_NewProject_thumb.png" width="339" height="215" /></a></p>
<p>Bei der Erstellung fragt Visual Studio ab, ob eine Sandboxed Solution oder eine Farm Solution erstellt werden soll. Für dieses Beispiel ist eine Sandboxed Solution vollkommen ausreichend. Eine Farm Solution sollte nur dann erstellt werden, wenn die Möglichkeiten der Sandboxed Solution nicht mehr ausreichen.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_2_SolutionType.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="Sandboxed Solution" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_2_SolutionType_thumb.png" width="329" height="262" /></a></p>
<p>Mit dem Visual Studio 2010 wurde das Entwickeln von SharePoint Solutions um ein Vielfaches vereinfacht. Es gibt mehr Templates und eine sehr gute Integration von Standard-Aufgaben in die Oberfläche. So wird beim Erstellen des neuen Projektes z.B. direkt ein “Feature” Verzeichnis angelegt. Mit einem Rechtsklick auf dieses Verzeichnis kann ein neues Feature erstellt werden.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_3_NewFeature.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="Feature hinzufuegen" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_3_NewFeature_thumb.png" width="244" height="152" /></a> </p>
<p>Die nun erstellte “Feature1.feature” Datei ist eine Art grafische Oberfläche für die Feature.xml Datei. Diese muss also nicht noch zusätzlich erstellt werden, im Gegensatz zur Elements.xml Datei, welche noch immer selbst geschrieben werden muss. Ein Template für die Elements.xml bekommt man z.B. durch das Hinzufügen eines “Empty Elements”. Ich empfehle an dieser Stelle die Elements.xml Datei immer über diesen Weg einzubinden, das macht die Solution übersichtlich.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/image.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="New Item" src="http://blog.oraylis.de/wp-content/uploads/2011/11/image_thumb.png" width="383" height="197" /></a></p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_5_EmptyElement.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="Empty Element" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_5_EmptyElement_thumb.png" width="384" height="243" /></a></p>
<p>Ein Blick auf das Feature zeigt, dass die Elements.xml Datei automatisch referenziert wurde.</p>
<p><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="Feature" src="http://blog.oraylis.de/wp-content/uploads/2011/11/image_thumb1.png" width="382" height="116" /></p>
<p>Nachdem nun alle für das Feature erforderlichen Dateien vorhanden sind, muss die Elements.xml Datei noch mit Leben gefüllt werden.</p>
<p>In der MSDN findet man viele Beispiele zum Anpassen der Ribbon Bar. Darunter auch diese einfache Elements.xml Datei:</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;Elements xmlns=&quot;http://schemas.microsoft.com/sharepoint/&quot;&gt;
&lt;CustomAction
  Id=&quot;DemoHelloWorldButton&quot;
  RegistrationType=&quot;List&quot;
  RegistrationId=&quot;101&quot;
  Location=&quot;CommandUI.Ribbon&quot;&gt;
    &lt;CommandUIExtension&gt;
      &lt;CommandUIDefinitions&gt;
        &lt;CommandUIDefinition
         Location=&quot;Ribbon.Documents.New.Controls._children&quot;&gt;
          &lt;Button
           Id=&quot;Ribbon.Documents.New.Controls.DemoHelloWorldButton&quot;
           Alt=&quot;Hello World Ribbon Button&quot;
           Sequence=&quot;10&quot;
           Image32by32=&quot;/_layouts/images/PPEOPLE.GIF&quot;
           Command=&quot;Demo_HelloWorld&quot;
           LabelText=&quot;Hello World Demo&quot;
           TemplateAlias=&quot;o2&quot;/&gt;
        &lt;/CommandUIDefinition&gt;
      &lt;/CommandUIDefinitions&gt;
      &lt;CommandUIHandlers&gt;
        &lt;CommandUIHandler
         Command=&quot;Demo_HelloWorld&quot;
         CommandAction=&quot;javascript:alert('Hello World!');&quot; /&gt;
      &lt;/CommandUIHandlers&gt;
    &lt;/CommandUIExtension&gt;
  &lt;/CustomAction&gt;
&lt;/Elements&gt;</code></pre>
<p>&#160;</p>
<p>Das <strong>CustomAction</strong> Element zeigt an, dass eine neue CustomAction hinzugefügt werden soll. Als CustomAction werden z.B. die Erweiterung der SharePoint Oberfläche mit Schaltflächen oder neuen Links in den Settings Seiten bezeichnet.</p>
<p>Über die Attribute <strong>RegistrationType</strong> und <strong>RegistrationId</strong> wird bestimmt, für welche Elemente die Custom Action (in diesem Fall die Schaltfläche) sichtbar sein soll. Das Attribut RegistrationType kann die folgenden Werte enthalten:</p>
<ul>
<li>None </li>
<li>List </li>
<li>ContentType </li>
<li>ProgId </li>
<li>FileType </li>
</ul>
<p>
  <br />Damit wird der Typ angegeben, an den die CustomAction gebunden wird. Die RegistrationId bestimmt dann das konkrete Element. In obigem Beispiel wird die Schaltfläche nur in Dokumentenbibliotheken angezeigt (Typ List und RegistrationId 101).</p>
<p>Eine sehr gute Übersicht über die verschiedenen Registration IDs findet sich z.B. in Mike Smith Blog unter <a title="http://techtrainingnotes.blogspot.com/2008/01/sharepoint-registrationid-list-template.html" href="http://techtrainingnotes.blogspot.com/2008/01/sharepoint-registrationid-list-template.html">http://techtrainingnotes.blogspot.com/2008/01/sharepoint-registrationid-list-template.html</a>.</p>
<p>Im <strong>CommandUIExtension</strong> Element wird die eigentliche Schaltfläche definiert. Das <strong>CommandUID</strong><strong>efinition</strong> Element beinhaltet hierbei die Definition der Darstellung und das <strong>CommandUIHandler</strong> Element beinhaltet die eigentliche Funktionalität hinter der Schaltfläche. </p>
<p>Das <strong>Location</strong> Attribut im CommandUIDefinition Element gibt an, an welcher Stelle die Anpassung in der Oberfläche dargestellt werden soll. Im obigen Beispiel wird die Schaltfläche in der Ribbon Leiste auf dem “Document” Tab in der Gruppe “New” angezeigt. Der folgenden MSDN Seite können einige Standardpfade für die Ribbon Elemente entnommen werden: <a title="http://msdn.microsoft.com/en-us/library/ee537543.aspx" href="http://msdn.microsoft.com/en-us/library/ee537543.aspx">http://msdn.microsoft.com/en-us/library/ee537543.aspx</a></p>
<p>Das <strong>Id</strong> Attribut im <strong>Button</strong> Element muss immer einen eindeutigen Wert haben. Hier empfiehlt sich eine GUID oder eine Mischung aus der Location der Schaltfläche und dem Namen des Features.</p>
<p>Das <strong>Sequence</strong> Attribut gibt an, in welcher Reihenfolge die Schaltflächen innerhalb einer Gruppe auf der Ribbon Leiste dargestellt werden sollen.</p>
<p>Über die beiden Attribute <strong>Image32by32</strong> und <strong>Image16by16</strong> werden die Grafiken definiert, welche für die Schaltfläche angezeigt werden sollen. Diese Bilder müssen im Verzeichnis <strong>/_layouts/images</strong> auf dem Server vorhanden sein (z.B. C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\1033\IMAGES bei einer englischen Standardinstallation).</p>
<p>Das <strong>Command</strong> Attribut im CommandUIDefinition Element identifiziert später die im CommandUIExtension/CommandUIHandler Element definierte Funktion, welche von der Schaltfläche aufgerufen wird. Es ist wichtig, an beiden Stellen den selben Wert für das Command Attribut einzutragen.</p>
<p>Der <strong>LabelText</strong> ist der Text, der unterhalb der Schaltfläche auf der Ribbon Leiste angezeigt wird. Es empfiehlt sich diese Texte von vornherein zu lokalisieren.</p>
<p>Das <strong>TemplateAlias</strong> Attribut definiert die Größe und Darstellung der Schaltfläche.</p>
<p>Die Definition des <strong>CommanUIHandler</strong> Elements ist sehr einfach. Über das <strong>Command</strong> Attribut wird die Verbindung zur Schaltfläche hergestellt. Daher muss dieses den selben Wert enthalten wie das Command Attribut des Button Elements. Im <strong>CommandAction</strong> Attribut wird z.B. eine Javascript Funktion angegeben, welche beim Anklicken der Schaltfläche ausgeführt werden soll.</p>
<p>Mehr braucht es nicht. Das Feature kann nun deployed werden. Dies kann auf einer Entwicklungsumgebung direkt aus dem Visual Studio heraus, oder mit Hilfe der Power Shell erfolgen.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_9_deploy.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="VS Deployment" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_9_deploy_thumb.png" width="347" height="164" /></a> </p>
<p>Soll das Feature über die Power Shell deployed werden, so muss zunächst eine wsp Datei erstellt werden. Auch dies kann nun über das Visual Studio 2010 selbst geschehen, es sind keine zusätzlichen Tools mehr nötig. Dazu aus dem Kontextmenü des Projektes den Punkt “Package” auswählen.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_10_package.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="20111020_10_package" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_10_package_thumb.png" width="350" height="164" /></a> </p>
<p>Ist die wsp Datei erstellt, erfolgt das Deployment über die folgenden PowerShell Befehle:</p>
<ol>
<li>
<pre><code>Add-SPSolution “&lt;Pfad&gt;\CustomRibbonButton.wsp”</code></pre>
</li>
<li>
<pre><code>Install-SPSolution –Identity CustomRibbonButton.wsp –GACDeployment</code></pre>
</li>
</ol>
<p>
  <br />Das Feature kann dann wie gewohnt über die Site Features (Site Settings –&gt; Site Features) oder über den PowerShell Befehl “<code>Enable-SPFeature</code>” aktiviert werden.</p>
<p>Die neue Schaltfläche ist jetzt in der Gruppe “New” auf dem “Documents” Tab aller Dokumentenbibliotheken vorhanden und führt wie gewünscht ein einfaches Java Script aus.</p>
</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_11_works.png"><img style="border-right-width: 0px;float: none;border-top-width: 0px;border-bottom-width: 0px;margin-left: auto;border-left-width: 0px;margin-right: auto" border="0" alt="20111020_11_works" src="http://blog.oraylis.de/wp-content/uploads/2011/11/20111020_11_works_thumb.png" width="365" height="272" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2011/11/eine-schaltflche-in-die-sharepoint-ribbon-leiste-integrieren/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stock levels as delta rows in DAX / BISM Tabular</title>
		<link>http://blog.oraylis.de/2011/11/stock-levels-as-delta-rows-in-dax-bism-tabular/</link>
		<comments>http://blog.oraylis.de/2011/11/stock-levels-as-delta-rows-in-dax-bism-tabular/#comments</comments>
		<pubDate>Sat, 19 Nov 2011 11:35:37 +0000</pubDate>
		<dc:creator>Hilmar Buchta</dc:creator>
				<category><![CDATA[MS SSAS]]></category>
		<category><![CDATA[BISM]]></category>
		<category><![CDATA[DAX]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2011/11/stock-levels-as-delta-rows-in-dax-bism-tabular/</guid>
		<description><![CDATA[<p align="right">SQL Server Denali | PowerPivot</p>
<p>A common way to compress large amounts of snap shot data is to store delta values instead of each snapshot value. This makes sense, if the data does not change every day. But for a good query performance you might not want to aggregate data over long periods.Therefore it makes sense to have a regular absolute snapshot value in the data and to use deltas between those snapshots. The work needed to create the periodic snapshots is usually done in the ETL process.</p>
<p>For my example, I’m using the following data table with absolute snapshot values as the first row of the month and deltas afterwards:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/p1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p1" border="0" alt="p1" src="http://blog.oraylis.de/wp-content/uploads/2011/11/p1_thumb.png" width="251" height="415" /></a></p>
<p>For example, for our product Quickerstill we start with a stock level of 20 boxes at the beginning of January 2011. Then, at January 3, 2011 we sold two of them (-2) and again on January 5 another 3 boxes (-3).</p>
<p>The goal is to create a measure that gives us the current stock level at each date (also on the dates between the delta rows).</p>
<p>In order to do so, we need a ‘real’ date dimension, so we have a separate date table that is linked to our facts. This is how this simple model looks like:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/p2.png"><img style="display: inline" title="p2" alt="p2" src="http://blog.oraylis.de/wp-content/uploads/2011/11/p2_thumb.png" width="591" height="234" /></a></p>
<p>&#160;</p>
<p>The measure DeltaStock is the original stock value from our table above (mixture of snapshots and deltas). </p>
<p>In order to perform the desired computation we can simply use the month-to-date formula as each day’s value computes as the sum from the first day of the month to the current day (including all deltas).</p>
<p>This is the simple formula we’re using to compute the stock at each day:</p>
<p><font face="Courier New">Stock:=TOTALMTD(SUM([DeltaStock]),&#8217;Date&#8217;[Date])</font></p>
<p>It’s amazing how simple this calculation is. Let’s take a look at the result. In order to see the effect, I added the original stock column together with the new computed column.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/p3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p3" border="0" alt="p3" src="http://blog.oraylis.de/wp-content/uploads/2011/11/p3_thumb.png" width="206" height="555" /></a></p>
<p>As you can see, we now have a stock for each day that computes correctly from the mixture of snapshot and deltas values.</p>
<p>Of course we could also do the calculation without the absolute snapshot values in between. In this case we have to aggregate the values from the very beginning up to the current date. First let’s take a look at the source data without the absolute snapshots:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/t1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t1" border="0" alt="t1" src="http://blog.oraylis.de/wp-content/uploads/2011/11/t1_thumb.png" width="260" height="311" /></a></p>
<p>The data is pretty much the same as in the first approach. Only the rows for the absolute snapshots are missing (apart from the first initial values).</p>
<p>In this case the calculation would look like this:</p>
<p><font face="Courier New">Stock:=      <br />&#160; SumX(       <br />&#160;&#160;&#160;&#160; DATESBETWEEN(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , date(2000,1,1)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , lastdate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160; ,calculate(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[DeltaStock])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160; )       <br />&#160; )</font></p>
<p>The calculation is still pretty simple. However I would prefer the option with the snapshot values in between for performance reasons and because these snapshots can be easily created in ETL (if they are not delivered from the source system).</p>
<p>Just two more remarks before I finish this post. The first one is about the DatesBetween range in the formula above. I’m using 2000/1/1 as the start date. However if you take a look at the returned dates only the existing rows from our date table are returned if they are matching this date range. So we could also write 1900/1/1 without risking to end up with a lot of rows.</p>
<p>The other remark is about the future time. Since our calculation takes the last value as the value for all the future, you will find values for all entries of the date dimension. This might not be wanted. In this case you can wrap the calculation from above inside an if statement to check the date:</p>
<p><font face="Courier New">StockClipped:=      <br />&#160; if(       <br />&#160;&#160;&#160; firstdate(&#8216;Date&#8217;[Date])&gt;Now()       <br />&#160;&#160;&#160; , Blank()       <br />&#160;&#160;&#160; ,SumX(       <br />&#160;&#160;&#160;&#160;&#160;&#160; DATESBETWEEN(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , date(2000,1,1)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , lastdate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,calculate(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[DeltaStock])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160; )       <br />&#160; )</font></p>
<p>With this modification (which also works with the formula for the absolute intermediate snapshots from above) values are only shown for periods that are over or have at least started. So the formula would return a value for the full year 2011 once the year has started. If you only want to see values for periods that have ended, you can replace the function ‘firstdate’ with a ‘lastdate’.</p>
<div style="display:block"><small><em>by Hilmar Buchta <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2011%2F11%2Fstock-levels-as-delta-rows-in-dax-bism-tabular%2F&amp;linkname=Stock%20levels%20as%20delta%20rows%20in%20DAX%20%2F%20BISM%20Tabular"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p align="right">SQL Server Denali | PowerPivot</p>
<p>A common way to compress large amounts of snap shot data is to store delta values instead of each snapshot value. This makes sense, if the data does not change every day. But for a good query performance you might not want to aggregate data over long periods.Therefore it makes sense to have a regular absolute snapshot value in the data and to use deltas between those snapshots. The work needed to create the periodic snapshots is usually done in the ETL process.</p>
<p>For my example, I’m using the following data table with absolute snapshot values as the first row of the month and deltas afterwards:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/p1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p1" border="0" alt="p1" src="http://blog.oraylis.de/wp-content/uploads/2011/11/p1_thumb.png" width="251" height="415" /></a></p>
<p>For example, for our product Quickerstill we start with a stock level of 20 boxes at the beginning of January 2011. Then, at January 3, 2011 we sold two of them (-2) and again on January 5 another 3 boxes (-3).</p>
<p>The goal is to create a measure that gives us the current stock level at each date (also on the dates between the delta rows).</p>
<p>In order to do so, we need a ‘real’ date dimension, so we have a separate date table that is linked to our facts. This is how this simple model looks like:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/p2.png"><img style="display: inline" title="p2" alt="p2" src="http://blog.oraylis.de/wp-content/uploads/2011/11/p2_thumb.png" width="591" height="234" /></a></p>
<p>&#160;</p>
<p>The measure DeltaStock is the original stock value from our table above (mixture of snapshots and deltas). </p>
<p>In order to perform the desired computation we can simply use the month-to-date formula as each day’s value computes as the sum from the first day of the month to the current day (including all deltas).</p>
<p>This is the simple formula we’re using to compute the stock at each day:</p>
<p><font face="Courier New">Stock:=TOTALMTD(SUM([DeltaStock]),&#8217;Date&#8217;[Date])</font></p>
<p>It’s amazing how simple this calculation is. Let’s take a look at the result. In order to see the effect, I added the original stock column together with the new computed column.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/p3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p3" border="0" alt="p3" src="http://blog.oraylis.de/wp-content/uploads/2011/11/p3_thumb.png" width="206" height="555" /></a></p>
<p>As you can see, we now have a stock for each day that computes correctly from the mixture of snapshot and deltas values.</p>
<p>Of course we could also do the calculation without the absolute snapshot values in between. In this case we have to aggregate the values from the very beginning up to the current date. First let’s take a look at the source data without the absolute snapshots:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/11/t1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t1" border="0" alt="t1" src="http://blog.oraylis.de/wp-content/uploads/2011/11/t1_thumb.png" width="260" height="311" /></a></p>
<p>The data is pretty much the same as in the first approach. Only the rows for the absolute snapshots are missing (apart from the first initial values).</p>
<p>In this case the calculation would look like this:</p>
<p><font face="Courier New">Stock:=      <br />&#160; SumX(       <br />&#160;&#160;&#160;&#160; DATESBETWEEN(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , date(2000,1,1)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , lastdate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160; ,calculate(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[DeltaStock])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160; )       <br />&#160; )</font></p>
<p>The calculation is still pretty simple. However I would prefer the option with the snapshot values in between for performance reasons and because these snapshots can be easily created in ETL (if they are not delivered from the source system).</p>
<p>Just two more remarks before I finish this post. The first one is about the DatesBetween range in the formula above. I’m using 2000/1/1 as the start date. However if you take a look at the returned dates only the existing rows from our date table are returned if they are matching this date range. So we could also write 1900/1/1 without risking to end up with a lot of rows.</p>
<p>The other remark is about the future time. Since our calculation takes the last value as the value for all the future, you will find values for all entries of the date dimension. This might not be wanted. In this case you can wrap the calculation from above inside an if statement to check the date:</p>
<p><font face="Courier New">StockClipped:=      <br />&#160; if(       <br />&#160;&#160;&#160; firstdate(&#8216;Date&#8217;[Date])&gt;Now()       <br />&#160;&#160;&#160; , Blank()       <br />&#160;&#160;&#160; ,SumX(       <br />&#160;&#160;&#160;&#160;&#160;&#160; DATESBETWEEN(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , date(2000,1,1)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , lastdate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,calculate(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sum(&#8216;Stock&#8217;[DeltaStock])       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160; )       <br />&#160; )</font></p>
<p>With this modification (which also works with the formula for the absolute intermediate snapshots from above) values are only shown for periods that are over or have at least started. So the formula would return a value for the full year 2011 once the year has started. If you only want to see values for periods that have ended, you can replace the function ‘firstdate’ with a ‘lastdate’.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2011/11/stock-levels-as-delta-rows-in-dax-bism-tabular/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamisierung von Gruppen</title>
		<link>http://blog.oraylis.de/2011/10/dynamisierung-von-gruppen/</link>
		<comments>http://blog.oraylis.de/2011/10/dynamisierung-von-gruppen/#comments</comments>
		<pubDate>Sun, 30 Oct 2011 17:10:00 +0000</pubDate>
		<dc:creator>Arno Cebulla</dc:creator>
				<category><![CDATA[MS SSRS]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/?p=1367</guid>
		<description><![CDATA[<p>&#160;</p>
<p>In Reporting Service lässt sich die Gruppierung einer Tabelle, einer Matrix oder eines Charts extrem dynamisch gestalten. Als Grundlage für dieses Beispiel dient die Datenbank „AdventureWorksDW2008R2“.</p>
<p>Das Ergebnis sollte in etwa so aussehen:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image002.jpg"><img style="border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="clip_image002" src="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image002_thumb.jpg" width="592" height="298" /></a></p>
<p>1. DataSet mit folgendem Query anlegen:</p>
<p>SELECT </p>
<p>PC.EnglishProductCategoryName AS Category</p>
<p>,PSC.EnglishProductSubcategoryName AS Subcategory</p>
<p>,P.EnglishProductName AS ProductName</p>
<p>,G.EnglishCountryRegionName AS Country</p>
<p>,G.StateProvinceName AS State </p>
<p>,FIS.SalesAmount </p>
<p>FROM dbo.FactInternetSales FIS</p>
<p>INNER JOIN dbo.DimProduct P </p>
<p>ON FIS.ProductKey = P.ProductKey</p>
<p>INNER JOIN dbo.DimProductSubcategory PSC</p>
<p>ON P.ProductSubcategoryKey = PSC.ProductSubcategoryKey</p>
<p>INNER JOIN dbo.DimProductCategory PC</p>
<p>ON PSC.ProductCategoryKey = PC.ProductCategoryKey</p>
<p>INNER JOIN dbo.DimCustomer C </p>
<p>ON FIS.CustomerKey = C.CustomerKey </p>
<p>INNER JOIN dbo.DimGeography G </p>
<p>ON C.GeographyKey = G.GeographyKey</p>
<p>2. Matrix aus Toolbar hinzufügen</p>
<p>3. Feld „Category“ auf RowGroups ziehen</p>
<p>4. Feld „Country“ auf ColumnGroups ziehen</p>
<p>5. Feld „SalesAmount“ in Data-Feld der Matrix ziehen</p>
<p>6. Feld „Subcategory“ auf RowGroups unter Gruppe „Category“ ziehen</p>
<p>7. RowGroup „Category“ umbenennen in „ParentRowGroup“</p>
<p>8. RowGroup „Subcategory“ umbenennen in „ChildRowGroup“</p>
<p>9. ColumnGroup „Country“ umbenennen in ColumnGroup</p>
<p>10. Die Textboxen der Matrix entsprechend benennen</p>
<p>11. Parameter „ParentGroupParam“ anlegen:</p>
<p>&#160;<a href="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image004.jpg"><img style="border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="clip_image004" src="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image004_thumb.jpg" width="368" height="303" /></a></p>
<p>12. Zwei weitere Parameter anlegen:<br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="255">
<p><b>NAME</b></p>
</td>
<td valign="top" width="255">
<p><b>PROMPT</b></p>
</td>
</tr>
<tr>
<td valign="top" width="255">
<p>ChildRowGroupParam</p>
</td>
<td valign="top" width="255">
<p>Select Child Row Group</p>
</td>
</tr>
<tr>
<td valign="top" width="255">
<p>ColumnGroupParam</p>
</td>
<td valign="top" width="255">
<p>Select Column Group</p>
</td>
</tr>
</tbody>
</table>
<p>13. Eigenschaften von „ParentGroupParam“ öffnen und unter „Available Values“ folende Einträge vornehmen:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image006.jpg"><img style="border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="clip_image006" src="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image006_thumb.jpg" width="379" height="312" /></a></p>
<p>14. Auf gleiche Weise werden die Einträge in „ChildGroupParam“ vorgenommen:<br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="236">
<p><b>LABEL</b></p>
</td>
<td valign="top" width="284">
<p><b>VALUE</b></p>
</td>
</tr>
<tr>
<td valign="top" width="236">
<p>Country</p>
</td>
<td valign="top" width="284">
<p>Country</p>
</td>
</tr>
<tr>
<td valign="top" width="236">
<p>State/Province</p>
</td>
<td valign="top" width="284">
<p>State</p>
</td>
</tr>
</tbody>
</table>
<p>15. Im Parameter „ChildRowGroupParam“ wird eine Anzeige-Logik hinterlegt. Dabei wird dieser Parameter in Abhängigkeit zum Parameter „ParentRowGroupParam“ gebracht:<br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="232">
<p><b>LABEL</b></p>
</td>
<td valign="top" width="394">
<p><b>VALUE</b></p>
</td>
</tr>
<tr>
<td valign="top" width="232">
<p>=IIF(Parameters!ParentRowGroupParam.Value= &quot;Category&quot;,&quot;ProductSubcategory&quot;,Nothing)</p>
</td>
<td valign="top" width="394">
<p>=IIF(Parameters!ParentRowGroupParam.Value= &quot;Category&quot;,&quot;Subcategory&quot;,Nothing)</p>
</td>
</tr>
<tr>
<td valign="top" width="232">
<p>Product Name</p>
</td>
<td valign="top" width="394">
<p>ProductName</p>
</td>
</tr>
</tbody>
</table>
<p>16. Eigenschaften von „ParentRowGroup“ öffnen und den Expression-Button neben „Group on:“ drücken und folgende Expression eingeben:</p>
<p>=Fields(Parameters!ParentRowGroupParam.Value).Value </p>
<p>17. In gleicher Weise werden auch die anderen Gruppen behandelt:<br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="160">
<p><b>GROUP</b></p>
</td>
<td valign="top" width="468">
<p><b>GROUP ON EXPRESSION</b></p>
</td>
</tr>
<tr>
<td valign="top" width="160">
<p>ChildRowGroup</p>
</td>
<td valign="top" width="468">
<p>=Fields(Parameters!ChildRowGroupParam.Value).Value</p>
</td>
</tr>
<tr>
<td valign="top" width="160">
<p>ColumnRowGroup</p>
</td>
<td valign="top" width="468">
<p>=Fields(Parameters!ColumnGroupParam.Value).Value</p>
</td>
</tr>
</tbody>
</table>
<p>18. In den Textboxen werden die gleichen Expressions wie in der „Group on“ – Expression verwendet:<br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="197">
<p><b>TextboxName</b></p>
</td>
<td valign="top" width="471">
<p><b>Expression</b></p>
</td>
</tr>
<tr>
<td valign="top" width="197">
<p>ParentRowGroup</p>
</td>
<td valign="top" width="471">
<p>=Fields(Parameters!ParentRowGroupParam.Value).Value </p>
</td>
</tr>
<tr>
<td valign="top" width="197">
<p>ChildRowGroup</p>
</td>
<td valign="top" width="471">
<p>=Fields(Parameters!ChildRowGroupParam.Value).Value</p>
</td>
</tr>
<tr>
<td valign="top" width="197">
<p>ColumnRowGroup</p>
</td>
<td valign="top" width="471">
<p>=Fields(Parameters!ColumnGroupParam.Value).Value</p>
</td>
</tr>
</tbody>
</table>
<p>Der Bericht kann nun nach verschiedenen Kriterien gruppiert werden.</p>
<div style="display:block"><small><em>by Arno Cebulla <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2011%2F10%2Fdynamisierung-von-gruppen%2F&amp;linkname=Dynamisierung%20von%20Gruppen"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p>&#160;</p>
<p>In Reporting Service lässt sich die Gruppierung einer Tabelle, einer Matrix oder eines Charts extrem dynamisch gestalten. Als Grundlage für dieses Beispiel dient die Datenbank „AdventureWorksDW2008R2“.</p>
<p>Das Ergebnis sollte in etwa so aussehen:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image002.jpg"><img style="border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="clip_image002" src="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image002_thumb.jpg" width="592" height="298" /></a></p>
<p>1. DataSet mit folgendem Query anlegen:</p>
<p>SELECT </p>
<p>PC.EnglishProductCategoryName AS Category</p>
<p>,PSC.EnglishProductSubcategoryName AS Subcategory</p>
<p>,P.EnglishProductName AS ProductName</p>
<p>,G.EnglishCountryRegionName AS Country</p>
<p>,G.StateProvinceName AS State </p>
<p>,FIS.SalesAmount </p>
<p>FROM dbo.FactInternetSales FIS</p>
<p>INNER JOIN dbo.DimProduct P </p>
<p>ON FIS.ProductKey = P.ProductKey</p>
<p>INNER JOIN dbo.DimProductSubcategory PSC</p>
<p>ON P.ProductSubcategoryKey = PSC.ProductSubcategoryKey</p>
<p>INNER JOIN dbo.DimProductCategory PC</p>
<p>ON PSC.ProductCategoryKey = PC.ProductCategoryKey</p>
<p>INNER JOIN dbo.DimCustomer C </p>
<p>ON FIS.CustomerKey = C.CustomerKey </p>
<p>INNER JOIN dbo.DimGeography G </p>
<p>ON C.GeographyKey = G.GeographyKey</p>
<p>2. Matrix aus Toolbar hinzufügen</p>
<p>3. Feld „Category“ auf RowGroups ziehen</p>
<p>4. Feld „Country“ auf ColumnGroups ziehen</p>
<p>5. Feld „SalesAmount“ in Data-Feld der Matrix ziehen</p>
<p>6. Feld „Subcategory“ auf RowGroups unter Gruppe „Category“ ziehen</p>
<p>7. RowGroup „Category“ umbenennen in „ParentRowGroup“</p>
<p>8. RowGroup „Subcategory“ umbenennen in „ChildRowGroup“</p>
<p>9. ColumnGroup „Country“ umbenennen in ColumnGroup</p>
<p>10. Die Textboxen der Matrix entsprechend benennen</p>
<p>11. Parameter „ParentGroupParam“ anlegen:</p>
<p>&#160;<a href="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image004.jpg"><img style="border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="clip_image004" src="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image004_thumb.jpg" width="368" height="303" /></a></p>
<p>12. Zwei weitere Parameter anlegen:<br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="255">
<p><b>NAME</b></p>
</td>
<td valign="top" width="255">
<p><b>PROMPT</b></p>
</td>
</tr>
<tr>
<td valign="top" width="255">
<p>ChildRowGroupParam</p>
</td>
<td valign="top" width="255">
<p>Select Child Row Group</p>
</td>
</tr>
<tr>
<td valign="top" width="255">
<p>ColumnGroupParam</p>
</td>
<td valign="top" width="255">
<p>Select Column Group</p>
</td>
</tr>
</tbody>
</table>
<p>13. Eigenschaften von „ParentGroupParam“ öffnen und unter „Available Values“ folende Einträge vornehmen:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image006.jpg"><img style="border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="clip_image006" src="http://blog.oraylis.de/wp-content/uploads/2011/10/clip_image006_thumb.jpg" width="379" height="312" /></a></p>
<p>14. Auf gleiche Weise werden die Einträge in „ChildGroupParam“ vorgenommen:<br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="236">
<p><b>LABEL</b></p>
</td>
<td valign="top" width="284">
<p><b>VALUE</b></p>
</td>
</tr>
<tr>
<td valign="top" width="236">
<p>Country</p>
</td>
<td valign="top" width="284">
<p>Country</p>
</td>
</tr>
<tr>
<td valign="top" width="236">
<p>State/Province</p>
</td>
<td valign="top" width="284">
<p>State</p>
</td>
</tr>
</tbody>
</table>
<p>15. Im Parameter „ChildRowGroupParam“ wird eine Anzeige-Logik hinterlegt. Dabei wird dieser Parameter in Abhängigkeit zum Parameter „ParentRowGroupParam“ gebracht:<br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="232">
<p><b>LABEL</b></p>
</td>
<td valign="top" width="394">
<p><b>VALUE</b></p>
</td>
</tr>
<tr>
<td valign="top" width="232">
<p>=IIF(Parameters!ParentRowGroupParam.Value= &quot;Category&quot;,&quot;ProductSubcategory&quot;,Nothing)</p>
</td>
<td valign="top" width="394">
<p>=IIF(Parameters!ParentRowGroupParam.Value= &quot;Category&quot;,&quot;Subcategory&quot;,Nothing)</p>
</td>
</tr>
<tr>
<td valign="top" width="232">
<p>Product Name</p>
</td>
<td valign="top" width="394">
<p>ProductName</p>
</td>
</tr>
</tbody>
</table>
<p>16. Eigenschaften von „ParentRowGroup“ öffnen und den Expression-Button neben „Group on:“ drücken und folgende Expression eingeben:</p>
<p>=Fields(Parameters!ParentRowGroupParam.Value).Value </p>
<p>17. In gleicher Weise werden auch die anderen Gruppen behandelt:<br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="160">
<p><b>GROUP</b></p>
</td>
<td valign="top" width="468">
<p><b>GROUP ON EXPRESSION</b></p>
</td>
</tr>
<tr>
<td valign="top" width="160">
<p>ChildRowGroup</p>
</td>
<td valign="top" width="468">
<p>=Fields(Parameters!ChildRowGroupParam.Value).Value</p>
</td>
</tr>
<tr>
<td valign="top" width="160">
<p>ColumnRowGroup</p>
</td>
<td valign="top" width="468">
<p>=Fields(Parameters!ColumnGroupParam.Value).Value</p>
</td>
</tr>
</tbody>
</table>
<p>18. In den Textboxen werden die gleichen Expressions wie in der „Group on“ – Expression verwendet:<br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="197">
<p><b>TextboxName</b></p>
</td>
<td valign="top" width="471">
<p><b>Expression</b></p>
</td>
</tr>
<tr>
<td valign="top" width="197">
<p>ParentRowGroup</p>
</td>
<td valign="top" width="471">
<p>=Fields(Parameters!ParentRowGroupParam.Value).Value </p>
</td>
</tr>
<tr>
<td valign="top" width="197">
<p>ChildRowGroup</p>
</td>
<td valign="top" width="471">
<p>=Fields(Parameters!ChildRowGroupParam.Value).Value</p>
</td>
</tr>
<tr>
<td valign="top" width="197">
<p>ColumnRowGroup</p>
</td>
<td valign="top" width="471">
<p>=Fields(Parameters!ColumnGroupParam.Value).Value</p>
</td>
</tr>
</tbody>
</table>
<p>Der Bericht kann nun nach verschiedenen Kriterien gruppiert werden.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2011/10/dynamisierung-von-gruppen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Excel Services Scorecard as Windows Desktop Gadget</title>
		<link>http://blog.oraylis.de/2011/10/excel-services-scorecard-as-windows-desktop-gadget/</link>
		<comments>http://blog.oraylis.de/2011/10/excel-services-scorecard-as-windows-desktop-gadget/#comments</comments>
		<pubDate>Sun, 23 Oct 2011 13:59:38 +0000</pubDate>
		<dc:creator>Hilmar Buchta</dc:creator>
				<category><![CDATA[MS SSAS]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[Desktop Gadget]]></category>
		<category><![CDATA[Excel]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2011/10/excel-services-scorecard-as-windows-desktop-gadget/</guid>
		<description><![CDATA[<p align="right">SharePoint 2010 | SQL Server 2008 | SQL Server 2008R2 | SQL Server 2012 (Denali)</p>
<p align="left">Early this year I stumbled across a very interesting Windows desktop gadget, that is capable of showing an Excel Services <em>element</em> on the Windows desktop. Here, <em>element</em> can be a certain named region, a pivot table or a chart in an Excel Services document. The technology for showing this element is the Excel Services REST API (REST stands for Representational State Transfer).</p>
<p align="left">You can find the article about the desktop gadget as well as the download link for the gadget itself <a href="http://blogs.msdn.com/b/cumgranosalis/archive/2009/11/03/interoducing-the-excel-services-gadget.aspx" target="_blank">here</a>. Installation and configuration of the gadget is pretty well explained on the linked site, so I can keep this short here.</p>
<p>After adding the gadget to your desktop, the gadget still needs to be configured. </p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p1" border="0" alt="p1" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p1_thumb.png" width="198" height="189" /></a></p>
<p>By clicking on the gadget configuration icon, the configuration dialog is displayed:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p2" border="0" alt="p2" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p2_thumb.png" width="202" height="244" /></a></p>
<table border="1" cellspacing="0" cellpadding="2" width="798">
<tbody>
<tr>
<td valign="top" width="144">Workbook</td>
<td valign="top" width="652">The URL to your Excel Services workbook, for example          <br />http://srv1/PowerPivot/Gadget.xlsx</td>
</tr>
<tr>
<td valign="top" width="144">Show in gadget</td>
<td valign="top" width="652">Here you can pick from any named region, pivot table or chart that should be displayed in the “expanded” state of the gadget (flyout)</td>
</tr>
<tr>
<td valign="top" width="144">Thumbnail</td>
<td valign="top" width="652">Here you can pick from any named region, pivot table or chart that should be displayed in the normal state of the gadget. This is what you see on your desktop first</td>
</tr>
<tr>
<td valign="top" width="144">Refresh</td>
<td valign="top" width="652">refresh interval of the gadget </td>
</tr>
</tbody>
</table>
<p>So the simple idea is to create a nice pivot table and to use this as the basis for the gadget. For my example I created a simple pivot table based on the Finance perspective of the Adventure Works OLAP cube. For the pivot table I have the year on the filter, the sales amount and the operating profit KPI as the data and the departments on the rows.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p3" border="0" alt="p3" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p3_thumb.png" width="478" height="180" /></a></p>
<p>If we use this large table in our gadget, the thumbnail view gets pretty much “microscopic”:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p6.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p6" border="0" alt="p6" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p6_thumb.png" width="226" height="167" /></a></p>
<p>So, for the thumbnail (default) view you should choose a much smaller area. The flyout (detail view) is much better, but the KPI indicators and the filters are not shown:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p5.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p5" border="0" alt="p5" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p5_thumb.png" width="388" height="150" /></a></p>
<p>So, here are a few tips and tricks you can use to make the gadget look nicer.</p>
<p>&#160;</p>
<p><strong><u>1. Use time filters for current year, current month etc.</u></strong></p>
<p>Of course we want our gadget to always show the latest values. Because of the auto refresh interval, we don’t have to care about this. But usually we will also use a time filter to restrict the data to a specific week, month etc. Since we don’t see the filter, the idea is to have this set automatically to the current time.</p>
<p>This can be easily done in the Excel Pivot Table by using date filters. Unfortunately, these filters don’t work in the filter area, so we have to place the time hierarchy on the rows or columns. Then we can apply a filter (for example current year) as shown here:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p7.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p7" border="0" alt="p7" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p7_thumb.png" width="326" height="417" /></a></p>
<p>For Adventure Works this would not result in any data since the sample date is only available for the years shown in the screenshot. However, in real life scenarios, this would be a good choice for the filter.</p>
<p>&#160;</p>
<p><strong><u>2. For thumbnail view, convert the pivot table to formulas</u></strong></p>
<p>Formulas are much easier to handle and to format, compared to a pivot table. Remembering the very narrow available space for the thumbnail view, having full control of the layout is important. You may even want to hard-code the thumbnail view. Let me explain what I mean. In order to have the connection name at a single place, we start in a blank sheet by putting the connection name in a named cell called “OLAPConnection” (feel free to choose a different name):</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p8.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p8" border="0" alt="p8" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p8_thumb.png" width="592" height="87" /></a></p>
<p>As the next step, let’s construct the current date member. From Management Studio, we can see that the MDX name of the time members looks like this (may be different in your cube, this example is taken from the Adventure Works sample database):</p>
<ul>
<li><font face="Courier New">[Date].[Calendar].[Calendar Year].&amp;[2001]</font> </li>
<li><font face="Courier New">[Date].[Calendar].[Month].&amp;[2001]&amp;[1]</font> </li>
<li><font face="Courier New">[Date].[Calendar].[Date].&amp;[20010101]</font> </li>
</ul>
<p>Here we have January 1, 2001. This is easily constructed using Excel’s time functions. So we simply add these fields to our Excel sheet</p>
<table border="1" cellspacing="0" cellpadding="2" width="791">
<tbody>
<tr>
<td valign="top" width="91"><strong>Label/Name</strong></td>
<td valign="top" width="40"><strong>Cell</strong></td>
<td valign="top" width="658"><strong>Formula</strong></td>
</tr>
<tr>
<td valign="top" width="91">Today</td>
<td valign="top" width="40">B3</td>
<td valign="top" width="658"><font face="Courier New">=Now()</font></td>
</tr>
<tr>
<td valign="top" width="91">Year</td>
<td valign="top" width="40">B4</td>
<td valign="top" width="658"><font face="Courier New">=&quot;[Date].[Calendar].[Calendar Year].&amp;[&quot; &amp; Year(B3) &amp; &quot;]&quot;</font></td>
</tr>
<tr>
<td valign="top" width="91">Month</td>
<td valign="top" width="40">B5</td>
<td valign="top" width="658"><font face="Courier New">=&quot;[Date].[Calendar].[Month].&amp;[&quot; &amp; Year(B3) &amp; &quot;]&amp;[&quot; &amp; Month(B3) &amp; &quot;]&quot;</font></td>
</tr>
<tr>
<td valign="top" width="91">Day</td>
<td valign="top" width="40">B6</td>
<td valign="top" width="658"><font face="Courier New">=&quot;[Date].[Calendar].[Date].&amp;[&quot; &amp; 10000*Year(B3)+100*Month(B3)+Day(B3) &amp;&quot;]&quot;</font></td>
</tr>
</tbody>
</table>
<p>Of course you could also add fields for the previous month, the week etc., just depending on the needs of your scorecard. I named the cells B4 as MDXYear, B5 as MDXMonth, B6 as MDXDay. This is how the result looks like:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p9.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p9" border="0" alt="p9" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p9_thumb.png" width="554" height="137" /></a></p>
<p>I had to fake the current date in order to see some values. Therefore I replaced the formula for today with this one:</p>
<p><font face="Courier New">=Date(2004, Month(Now()), Day(Now()))</font></p>
<p>Of course, you won’t want to do this in a real life scenario but since the sample dataset contains no data for 2011 I had to use this “time machine formula”.</p>
<p>Before you start wondering what all this is good for, let’s query some data. For example, let’s assume that we want to see the operating profit (which is on the account ‘Operating Profit’) for the current year. So this would by our Excel formula:</p>
<p><font face="Courier New">=CUBEVALUE(OLAPConnection,&quot;[Measures].[Amount]&quot;,&quot;[Account].[Accounts].[Operating Profit]&quot;,MDXYear)</font></p>
<p>In order to show this value in our gadget, I placed it on a new sheet and adjusted the column width and height a little bit.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p10.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p10" border="0" alt="p10" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p10_thumb.png" width="168" height="83" /></a></p>
<p>In order to get a nice flyout, I also created a simple pivot chart in the Excel sheet, showing the operational profit during the year. After saving the Excel file, our gadget now looks like this:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p12.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p12" border="0" alt="p12" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p12_thumb.png" width="213" height="154" /></a></p>
<p>And here is the flyout:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p13.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p13" border="0" alt="p13" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p13_thumb.png" width="298" height="270" /></a></p>
<p>&#160;</p>
<p><strong><u>3. (Conditional) background colors and fonts are preserved in the REST API</u></strong></p>
<p>In order to include a kind of traffic light approach, we already found out that Excel indicators are not yet supported in the REST API. However, conditional formatting is supported, so you can easily create a scorecard like the follow:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p14.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p14" border="0" alt="p14" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p14_thumb.png" width="170" height="209" /></a></p>
<p>Also KPI indicators can be created using special characters, for example from the WingDings font as shown in the following example:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p15.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p15" border="0" alt="p15" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p15_thumb.png" width="155" height="200" /></a></p>
<p>For this example, I used a separate table of banding ranges and an Excel VLookup to find the appropriate color for the indictor. Here, 1=green, 2=yellow, 3=red. In the Excel cell I used conditional formatting to choose the text color appropriately. But as we always want to display a certain element (here, the diamond from the WingDings font), I used a custom format for each of the cells, so the number (1, 2 or 3) is not shown but only one character. The corresponding character for the diamond is “u”, so the custom format looks like this:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p20.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p20" border="0" alt="p20" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p20_thumb.png" width="365" height="327" /></a></p>
<p>And of course, there is a lot more you can do with all these formatting, cube functions etc.</p>
<p>&#160;</p>
<p><strong><u>3. Make changes to the source code of the gadget</u></strong></p>
<p>You can extract the gadget or modify the source code of the gadget yourself. After installing the gadget, the extracted sources can be found here: </p>
<p>%LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgets</p>
<p>After modifying the sources, the gadgets need to be switched off and on in order for the changes to apply. The main file is the gadget.html here. For example you could change the link “By Excel Services” to point on your SharePoint server. To do so, a simple change in the source is needed:</p>
<p>Before:    <br /><font face="Courier New">&lt;tr&gt;&lt;td id=&quot;dockedTitle&quot; width=&quot;100%&quot;&gt;      <br />&lt;a id=&quot;leftDockedTitleLink&quot; href=&quot;</font><font face="Courier New">http://blogs.msdn.com/cumgranosalis/pages/excel-services-windows-7-gadget.aspx&quot;</font><font face="Courier New">&gt;By Excel Services&lt;/a&gt;      <br />&lt;/td&gt;&lt;td&gt;</font></p>
<p>After:    <br /><font face="Courier New">&lt;tr&gt;&lt;td id=&quot;dockedTitle&quot; width=&quot;100%&quot;&gt;      <br />&lt;a id=&quot;leftDockedTitleLink&quot; href=&quot;</font><font face="Courier New">http://srv1/PowerPivot/Forms/AllItems.aspx&quot;</font><font face="Courier New">&gt;All reports&lt;/a&gt;      <br />&lt;/td&gt;&lt;td&gt;</font></p>
<p>I also changed the background color here, so this is how the result looks like:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p17.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p17" border="0" alt="p17" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p17_thumb.png" width="198" height="244" /></a></p>
<p>As you can see, you can do a lot of interesting things with this simple but very powerful desktop gadget.</p>
<p>&#160;</p>
<p><strong><u>4. Use parameters</u></strong></p>
<p>If you want to use the same Excel Services file for more than one user you may want to pass parameters from each individual instance of the desktop gadget to the Excel Services file. This is also possible, however there are some things to take care of.</p>
<p>The syntax for passing a parameter is </p>
<p><font face="Courier New">Ranges(&#8216;cellname&#8217;)=value</font></p>
<p>Here, cellname is a named cell in Excel that we want to pass the value to. This is how it is entered in the desktop gadget, if our named cell is named ‘value1’ and we want to pass ‘xyz’:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/z1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="z1" border="0" alt="z1" src="http://blog.oraylis.de/wp-content/uploads/2011/10/z1_thumb.png" width="244" height="214" /></a></p>
<p>Multiple parameters may be passed by separating them with an ampersand, for example</p>
<p><font face="Courier New">Ranges(&#8216;value1&#8242;)=xyz&amp;Ranges(&#8216;value2&#8242;)=42&amp;Ranges(&#8216;value3&#8242;)=01</font></p>
<p>This could be our corresponding view in the desktop gadget:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/z2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="z2" border="0" alt="z2" src="http://blog.oraylis.de/wp-content/uploads/2011/10/z2_thumb.png" width="102" height="109" /></a></p>
<p>I just added a field that concatenates all three parameters to show that the Excel Services sheet is recomputed based on the passed values.</p>
<p>As you can see, all parameters are passed to the gadget. However, numeric parameters are considered as numbers in Excel, so 01 was changed to 1. If you want to prevent this, add a &#8216; in front of each text. </p>
<p>This is how the parameters should look like when you want to make sure, text is passed as text (and not converted to a number or date) in Excel:</p>
<p><font face="Courier New">Ranges(&#8216;value1&#8242;)=<font color="#ff0000">&#8216;</font>xyz&amp;Ranges(&#8216;value2&#8242;)=42&amp;Ranges(&#8216;value3&#8242;)=<font color="#ff0000">&#8216;</font>01</font></p>
<p>You should also be aware, that this string is passed to the URL “as it is”. So you have to encode all characters that are not allowed in a URL.</p>
<p>For example, if you want to pass the year 2006 from AdventureWorks, the unique name of the date member would be:</p>
<p><font face="Courier New">[Date].[Calendar].[Calendar Year].&amp;[2006]</font></p>
<p>In order to pass this to the gadget, you have to encode blanks, the square brackets and the ampersand. So the result would look like this:</p>
<p><font face="Courier New">Ranges(&#8216;parDate&#8217;)=%5BDate%5D.%5BCalendar%5D.%5BCalendar%20Year%5D.%26%5B2006%5D</font></p>
<p>This is very difficult to read. Therefore I recommend just to pass the key (2006 in this case) as the parameter and to construct the unique name in Excel using a formula like </p>
<p><font face="Courier New">=&quot;[Date].[Calendar].[Calendar Year].&amp;[&quot; &amp; parDate &amp; &quot;]&quot;</font></p>
<p>Of course, there are a lot more things you can do with this simple, yet powerful Windows desktop gadget. Like with most other gadget you may also place more than one instance of the gadget on your desktop, so you can have different scorecards. You can also add links to your Excel sheet, so that you can jump directly to a dashboard for a specific key performance indicator. Just start playing with the gadget and see how powerful und useful it is.</p>
<div style="display:block"><small><em>by Hilmar Buchta <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2011%2F10%2Fexcel-services-scorecard-as-windows-desktop-gadget%2F&amp;linkname=Excel%20Services%20Scorecard%20as%20Windows%20Desktop%20Gadget"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p align="right">SharePoint 2010 | SQL Server 2008 | SQL Server 2008R2 | SQL Server 2012 (Denali)</p>
<p align="left">Early this year I stumbled across a very interesting Windows desktop gadget, that is capable of showing an Excel Services <em>element</em> on the Windows desktop. Here, <em>element</em> can be a certain named region, a pivot table or a chart in an Excel Services document. The technology for showing this element is the Excel Services REST API (REST stands for Representational State Transfer).</p>
<p align="left">You can find the article about the desktop gadget as well as the download link for the gadget itself <a href="http://blogs.msdn.com/b/cumgranosalis/archive/2009/11/03/interoducing-the-excel-services-gadget.aspx" target="_blank">here</a>. Installation and configuration of the gadget is pretty well explained on the linked site, so I can keep this short here.</p>
<p>After adding the gadget to your desktop, the gadget still needs to be configured. </p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p1" border="0" alt="p1" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p1_thumb.png" width="198" height="189" /></a></p>
<p>By clicking on the gadget configuration icon, the configuration dialog is displayed:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p2" border="0" alt="p2" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p2_thumb.png" width="202" height="244" /></a></p>
<table border="1" cellspacing="0" cellpadding="2" width="798">
<tbody>
<tr>
<td valign="top" width="144">Workbook</td>
<td valign="top" width="652">The URL to your Excel Services workbook, for example          <br />http://srv1/PowerPivot/Gadget.xlsx</td>
</tr>
<tr>
<td valign="top" width="144">Show in gadget</td>
<td valign="top" width="652">Here you can pick from any named region, pivot table or chart that should be displayed in the “expanded” state of the gadget (flyout)</td>
</tr>
<tr>
<td valign="top" width="144">Thumbnail</td>
<td valign="top" width="652">Here you can pick from any named region, pivot table or chart that should be displayed in the normal state of the gadget. This is what you see on your desktop first</td>
</tr>
<tr>
<td valign="top" width="144">Refresh</td>
<td valign="top" width="652">refresh interval of the gadget </td>
</tr>
</tbody>
</table>
<p>So the simple idea is to create a nice pivot table and to use this as the basis for the gadget. For my example I created a simple pivot table based on the Finance perspective of the Adventure Works OLAP cube. For the pivot table I have the year on the filter, the sales amount and the operating profit KPI as the data and the departments on the rows.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p3" border="0" alt="p3" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p3_thumb.png" width="478" height="180" /></a></p>
<p>If we use this large table in our gadget, the thumbnail view gets pretty much “microscopic”:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p6.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p6" border="0" alt="p6" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p6_thumb.png" width="226" height="167" /></a></p>
<p>So, for the thumbnail (default) view you should choose a much smaller area. The flyout (detail view) is much better, but the KPI indicators and the filters are not shown:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p5.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p5" border="0" alt="p5" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p5_thumb.png" width="388" height="150" /></a></p>
<p>So, here are a few tips and tricks you can use to make the gadget look nicer.</p>
<p>&#160;</p>
<p><strong><u>1. Use time filters for current year, current month etc.</u></strong></p>
<p>Of course we want our gadget to always show the latest values. Because of the auto refresh interval, we don’t have to care about this. But usually we will also use a time filter to restrict the data to a specific week, month etc. Since we don’t see the filter, the idea is to have this set automatically to the current time.</p>
<p>This can be easily done in the Excel Pivot Table by using date filters. Unfortunately, these filters don’t work in the filter area, so we have to place the time hierarchy on the rows or columns. Then we can apply a filter (for example current year) as shown here:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p7.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p7" border="0" alt="p7" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p7_thumb.png" width="326" height="417" /></a></p>
<p>For Adventure Works this would not result in any data since the sample date is only available for the years shown in the screenshot. However, in real life scenarios, this would be a good choice for the filter.</p>
<p>&#160;</p>
<p><strong><u>2. For thumbnail view, convert the pivot table to formulas</u></strong></p>
<p>Formulas are much easier to handle and to format, compared to a pivot table. Remembering the very narrow available space for the thumbnail view, having full control of the layout is important. You may even want to hard-code the thumbnail view. Let me explain what I mean. In order to have the connection name at a single place, we start in a blank sheet by putting the connection name in a named cell called “OLAPConnection” (feel free to choose a different name):</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p8.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p8" border="0" alt="p8" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p8_thumb.png" width="592" height="87" /></a></p>
<p>As the next step, let’s construct the current date member. From Management Studio, we can see that the MDX name of the time members looks like this (may be different in your cube, this example is taken from the Adventure Works sample database):</p>
<ul>
<li><font face="Courier New">[Date].[Calendar].[Calendar Year].&amp;[2001]</font> </li>
<li><font face="Courier New">[Date].[Calendar].[Month].&amp;[2001]&amp;[1]</font> </li>
<li><font face="Courier New">[Date].[Calendar].[Date].&amp;[20010101]</font> </li>
</ul>
<p>Here we have January 1, 2001. This is easily constructed using Excel’s time functions. So we simply add these fields to our Excel sheet</p>
<table border="1" cellspacing="0" cellpadding="2" width="791">
<tbody>
<tr>
<td valign="top" width="91"><strong>Label/Name</strong></td>
<td valign="top" width="40"><strong>Cell</strong></td>
<td valign="top" width="658"><strong>Formula</strong></td>
</tr>
<tr>
<td valign="top" width="91">Today</td>
<td valign="top" width="40">B3</td>
<td valign="top" width="658"><font face="Courier New">=Now()</font></td>
</tr>
<tr>
<td valign="top" width="91">Year</td>
<td valign="top" width="40">B4</td>
<td valign="top" width="658"><font face="Courier New">=&quot;[Date].[Calendar].[Calendar Year].&amp;[&quot; &amp; Year(B3) &amp; &quot;]&quot;</font></td>
</tr>
<tr>
<td valign="top" width="91">Month</td>
<td valign="top" width="40">B5</td>
<td valign="top" width="658"><font face="Courier New">=&quot;[Date].[Calendar].[Month].&amp;[&quot; &amp; Year(B3) &amp; &quot;]&amp;[&quot; &amp; Month(B3) &amp; &quot;]&quot;</font></td>
</tr>
<tr>
<td valign="top" width="91">Day</td>
<td valign="top" width="40">B6</td>
<td valign="top" width="658"><font face="Courier New">=&quot;[Date].[Calendar].[Date].&amp;[&quot; &amp; 10000*Year(B3)+100*Month(B3)+Day(B3) &amp;&quot;]&quot;</font></td>
</tr>
</tbody>
</table>
<p>Of course you could also add fields for the previous month, the week etc., just depending on the needs of your scorecard. I named the cells B4 as MDXYear, B5 as MDXMonth, B6 as MDXDay. This is how the result looks like:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p9.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p9" border="0" alt="p9" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p9_thumb.png" width="554" height="137" /></a></p>
<p>I had to fake the current date in order to see some values. Therefore I replaced the formula for today with this one:</p>
<p><font face="Courier New">=Date(2004, Month(Now()), Day(Now()))</font></p>
<p>Of course, you won’t want to do this in a real life scenario but since the sample dataset contains no data for 2011 I had to use this “time machine formula”.</p>
<p>Before you start wondering what all this is good for, let’s query some data. For example, let’s assume that we want to see the operating profit (which is on the account ‘Operating Profit’) for the current year. So this would by our Excel formula:</p>
<p><font face="Courier New">=CUBEVALUE(OLAPConnection,&quot;[Measures].[Amount]&quot;,&quot;[Account].[Accounts].[Operating Profit]&quot;,MDXYear)</font></p>
<p>In order to show this value in our gadget, I placed it on a new sheet and adjusted the column width and height a little bit.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p10.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p10" border="0" alt="p10" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p10_thumb.png" width="168" height="83" /></a></p>
<p>In order to get a nice flyout, I also created a simple pivot chart in the Excel sheet, showing the operational profit during the year. After saving the Excel file, our gadget now looks like this:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p12.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p12" border="0" alt="p12" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p12_thumb.png" width="213" height="154" /></a></p>
<p>And here is the flyout:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p13.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p13" border="0" alt="p13" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p13_thumb.png" width="298" height="270" /></a></p>
<p>&#160;</p>
<p><strong><u>3. (Conditional) background colors and fonts are preserved in the REST API</u></strong></p>
<p>In order to include a kind of traffic light approach, we already found out that Excel indicators are not yet supported in the REST API. However, conditional formatting is supported, so you can easily create a scorecard like the follow:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p14.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p14" border="0" alt="p14" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p14_thumb.png" width="170" height="209" /></a></p>
<p>Also KPI indicators can be created using special characters, for example from the WingDings font as shown in the following example:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p15.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p15" border="0" alt="p15" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p15_thumb.png" width="155" height="200" /></a></p>
<p>For this example, I used a separate table of banding ranges and an Excel VLookup to find the appropriate color for the indictor. Here, 1=green, 2=yellow, 3=red. In the Excel cell I used conditional formatting to choose the text color appropriately. But as we always want to display a certain element (here, the diamond from the WingDings font), I used a custom format for each of the cells, so the number (1, 2 or 3) is not shown but only one character. The corresponding character for the diamond is “u”, so the custom format looks like this:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p20.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p20" border="0" alt="p20" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p20_thumb.png" width="365" height="327" /></a></p>
<p>And of course, there is a lot more you can do with all these formatting, cube functions etc.</p>
<p>&#160;</p>
<p><strong><u>3. Make changes to the source code of the gadget</u></strong></p>
<p>You can extract the gadget or modify the source code of the gadget yourself. After installing the gadget, the extracted sources can be found here: </p>
<p>%LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgets</p>
<p>After modifying the sources, the gadgets need to be switched off and on in order for the changes to apply. The main file is the gadget.html here. For example you could change the link “By Excel Services” to point on your SharePoint server. To do so, a simple change in the source is needed:</p>
<p>Before:    <br /><font face="Courier New">&lt;tr&gt;&lt;td id=&quot;dockedTitle&quot; width=&quot;100%&quot;&gt;      <br />&lt;a id=&quot;leftDockedTitleLink&quot; href=&quot;</font><font face="Courier New">http://blogs.msdn.com/cumgranosalis/pages/excel-services-windows-7-gadget.aspx&quot;</font><font face="Courier New">&gt;By Excel Services&lt;/a&gt;      <br />&lt;/td&gt;&lt;td&gt;</font></p>
<p>After:    <br /><font face="Courier New">&lt;tr&gt;&lt;td id=&quot;dockedTitle&quot; width=&quot;100%&quot;&gt;      <br />&lt;a id=&quot;leftDockedTitleLink&quot; href=&quot;</font><font face="Courier New">http://srv1/PowerPivot/Forms/AllItems.aspx&quot;</font><font face="Courier New">&gt;All reports&lt;/a&gt;      <br />&lt;/td&gt;&lt;td&gt;</font></p>
<p>I also changed the background color here, so this is how the result looks like:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/p17.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="p17" border="0" alt="p17" src="http://blog.oraylis.de/wp-content/uploads/2011/10/p17_thumb.png" width="198" height="244" /></a></p>
<p>As you can see, you can do a lot of interesting things with this simple but very powerful desktop gadget.</p>
<p>&#160;</p>
<p><strong><u>4. Use parameters</u></strong></p>
<p>If you want to use the same Excel Services file for more than one user you may want to pass parameters from each individual instance of the desktop gadget to the Excel Services file. This is also possible, however there are some things to take care of.</p>
<p>The syntax for passing a parameter is </p>
<p><font face="Courier New">Ranges(&#8216;cellname&#8217;)=value</font></p>
<p>Here, cellname is a named cell in Excel that we want to pass the value to. This is how it is entered in the desktop gadget, if our named cell is named ‘value1’ and we want to pass ‘xyz’:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/z1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="z1" border="0" alt="z1" src="http://blog.oraylis.de/wp-content/uploads/2011/10/z1_thumb.png" width="244" height="214" /></a></p>
<p>Multiple parameters may be passed by separating them with an ampersand, for example</p>
<p><font face="Courier New">Ranges(&#8216;value1&#8242;)=xyz&amp;Ranges(&#8216;value2&#8242;)=42&amp;Ranges(&#8216;value3&#8242;)=01</font></p>
<p>This could be our corresponding view in the desktop gadget:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/10/z2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="z2" border="0" alt="z2" src="http://blog.oraylis.de/wp-content/uploads/2011/10/z2_thumb.png" width="102" height="109" /></a></p>
<p>I just added a field that concatenates all three parameters to show that the Excel Services sheet is recomputed based on the passed values.</p>
<p>As you can see, all parameters are passed to the gadget. However, numeric parameters are considered as numbers in Excel, so 01 was changed to 1. If you want to prevent this, add a &#8216; in front of each text. </p>
<p>This is how the parameters should look like when you want to make sure, text is passed as text (and not converted to a number or date) in Excel:</p>
<p><font face="Courier New">Ranges(&#8216;value1&#8242;)=<font color="#ff0000">&#8216;</font>xyz&amp;Ranges(&#8216;value2&#8242;)=42&amp;Ranges(&#8216;value3&#8242;)=<font color="#ff0000">&#8216;</font>01</font></p>
<p>You should also be aware, that this string is passed to the URL “as it is”. So you have to encode all characters that are not allowed in a URL.</p>
<p>For example, if you want to pass the year 2006 from AdventureWorks, the unique name of the date member would be:</p>
<p><font face="Courier New">[Date].[Calendar].[Calendar Year].&amp;[2006]</font></p>
<p>In order to pass this to the gadget, you have to encode blanks, the square brackets and the ampersand. So the result would look like this:</p>
<p><font face="Courier New">Ranges(&#8216;parDate&#8217;)=%5BDate%5D.%5BCalendar%5D.%5BCalendar%20Year%5D.%26%5B2006%5D</font></p>
<p>This is very difficult to read. Therefore I recommend just to pass the key (2006 in this case) as the parameter and to construct the unique name in Excel using a formula like </p>
<p><font face="Courier New">=&quot;[Date].[Calendar].[Calendar Year].&amp;[&quot; &amp; parDate &amp; &quot;]&quot;</font></p>
<p>Of course, there are a lot more things you can do with this simple, yet powerful Windows desktop gadget. Like with most other gadget you may also place more than one instance of the gadget on your desktop, so you can have different scorecards. You can also add links to your Excel sheet, so that you can jump directly to a dashboard for a specific key performance indicator. Just start playing with the gadget and see how powerful und useful it is.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2011/10/excel-services-scorecard-as-windows-desktop-gadget/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Windows Phone 7.5 Mango</title>
		<link>http://blog.oraylis.de/2011/10/windows-phone-7-5-mango/</link>
		<comments>http://blog.oraylis.de/2011/10/windows-phone-7-5-mango/#comments</comments>
		<pubDate>Sun, 09 Oct 2011 19:12:46 +0000</pubDate>
		<dc:creator>Jörg Plümacher</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Mango]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Windows Phone 7]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2011/10/windows-phone-7-5-mango/</guid>
		<description><![CDATA[<p>Ich bin seit letzter Woche glücklicher Gewinner eines HTC Mozart mir Windows Phone 7. Das Gerät wurde auf der Microsoft Partnerkonferenz an die ersten 800 Teilnehmer verteilt. Aufgespielt war von Anfang an das neue Update auf Windows Phone 7.5 Mango.</p>
<p>Bislang war ich Nutzer eines iPhone 4 und durh das Gerät auch ziemlich verwöhnt. Gerade im privaten Bereich unterstützt mich das iPhone bei vielen Dingen des Alltags. </p>
<ul>
<li>Meine Musik verwalte ich über iTunes. Es ist mir möglich die Musik über verschiedene Geräte im Haus abzuspielen (AirPort und Apple TV).</li>
<li>Die zahlreichen Apps lassen einen immer wieder auf das Gerät schauen, ob Nachrichten, Sportergebnisse oder die neusten Facebook Nachrichten.</li>
</ul>
<p>Dem neuen HTC Gerät mit Windows Phone 7 wollte ich eine Chance geben, also setzte ich die SIM Karte ein und legte los. Der erste Eindruck war durchaus positiv. Die Bedienung per Touch ist mindestens genauso folgsam wie beim iPhone. Sicher braucht man zunächst eine kurze Zeit, um sich an die geänderte Navigation zu gewöhnen. Die Startseite macht einen sehr guten Eindruck. Die neuen Kacheln des Metros Designs gefallen mir sehr gut. Inhalte werden direkt auf den Kacheln dargestellt, Dokumente oder Internet Seiten können auch direkt als Kachel auf der Startseite angebracht werden.   </p>
<p>Interessant war für mich vor allem die Integration der Microsoft Programme. Hier sehe ich für mich die eigentliche Stärke gegenüber dem iPhone. Hier die Vorteile im Überblick:</p>
<ul>
<li>Mails lassen sich mit der Kennzeichnung flaggen. Durch diese Kennzeichnung lassen sich Mails im Outlook dann später leichter wiederfinden und nachbearbeiten.</li>
<li>Es lassen sich Aufgaben darstellen und bearbeiten. Das ist im iPhone leider gar nicht möglich.</li>
<li>Bei Aufgaben lässt sich ein Erinnerungsdatum hinterlegen. Dann wird die Aufgabe auch im Kalender angezeigt.</li>
<li>Dokumente (Word, Excel und OneNote) lassen sich direkt im Gerät bearbeiten. Ideal ist das vor allem in Verbindung mit SharePoint oder dem eigenen Live Account. Die Dokumente werden übersichtlich dargestellt und können auch direkt auf einer Kachel dargestellt werden. Bei der Dokumentation der Beiträge der Partnerkonferenz wurden so meine Notizen direkt in unserem SharePoint gespeichert. Zurück am Arbeitsplatz waren so die Inhalte direkt verfügbar.</li>
<li>Aufgaben lassen sich auch als “Privat” kennzeichnen. Eigentlich selbstverständlich, aber im iPhone leider nicht möglich.</li>
<li>Abgesagte Termine lassen sich kommentieren. Auch das ist beim iPhone nicht möglich.</li>
<li>Bei Teilnehmern eines Termins lassen sich auch optionale Teilnehmer hinzunehmen.</li>
<li>Das zusammenlegen der Kontaktinformationen aus allen verfügbaren Konten (Outlook, Windows Live, Facebook) ist ein tolles Features. Insgesamt ist die Integration der Social Media Daten sehr gelungen.</li>
<li>Die Kamerataste an der Seite erlaubt das Fotografieren auch bei gesperrtem Gerät.</li>
<li>Auch die Sync Software Zune macht einen prima Eindruck.</li>
<li>Apps im Marketplace sind noch nicht ganz in der Fülle verfügbar, können aber die wichtigsten Themen auch sehr gut abdecken.</li>
<li>Bing Suche hat mich positiv überrascht. Vor allem die Musiksuche und die Möglichkeit Texte einzuscannen und diese unmittelbar zu übersetzen. Das kann sicherlich im nächsten Urlaub von großem Nutzen sein. </li>
</ul>
<p>Insgesamt macht das Telefon und das Betriebssystem einen sehr guten und gelungenen Eindruck. Ich habe Spaß an dem Gerät und werde es in Verbindung mit meinem iPhone (eher privater Nutzen) weiter nutzen. Bei dem Gerät steht eher der geschäftliche Einsatz im Vordergrund. </p>
<div style="display:block"><small><em>by Jörg Plümacher <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2011%2F10%2Fwindows-phone-7-5-mango%2F&amp;linkname=Windows%20Phone%207.5%20Mango"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p>Ich bin seit letzter Woche glücklicher Gewinner eines HTC Mozart mir Windows Phone 7. Das Gerät wurde auf der Microsoft Partnerkonferenz an die ersten 800 Teilnehmer verteilt. Aufgespielt war von Anfang an das neue Update auf Windows Phone 7.5 Mango.</p>
<p>Bislang war ich Nutzer eines iPhone 4 und durh das Gerät auch ziemlich verwöhnt. Gerade im privaten Bereich unterstützt mich das iPhone bei vielen Dingen des Alltags. </p>
<ul>
<li>Meine Musik verwalte ich über iTunes. Es ist mir möglich die Musik über verschiedene Geräte im Haus abzuspielen (AirPort und Apple TV).</li>
<li>Die zahlreichen Apps lassen einen immer wieder auf das Gerät schauen, ob Nachrichten, Sportergebnisse oder die neusten Facebook Nachrichten.</li>
</ul>
<p>Dem neuen HTC Gerät mit Windows Phone 7 wollte ich eine Chance geben, also setzte ich die SIM Karte ein und legte los. Der erste Eindruck war durchaus positiv. Die Bedienung per Touch ist mindestens genauso folgsam wie beim iPhone. Sicher braucht man zunächst eine kurze Zeit, um sich an die geänderte Navigation zu gewöhnen. Die Startseite macht einen sehr guten Eindruck. Die neuen Kacheln des Metros Designs gefallen mir sehr gut. Inhalte werden direkt auf den Kacheln dargestellt, Dokumente oder Internet Seiten können auch direkt als Kachel auf der Startseite angebracht werden.   </p>
<p>Interessant war für mich vor allem die Integration der Microsoft Programme. Hier sehe ich für mich die eigentliche Stärke gegenüber dem iPhone. Hier die Vorteile im Überblick:</p>
<ul>
<li>Mails lassen sich mit der Kennzeichnung flaggen. Durch diese Kennzeichnung lassen sich Mails im Outlook dann später leichter wiederfinden und nachbearbeiten.</li>
<li>Es lassen sich Aufgaben darstellen und bearbeiten. Das ist im iPhone leider gar nicht möglich.</li>
<li>Bei Aufgaben lässt sich ein Erinnerungsdatum hinterlegen. Dann wird die Aufgabe auch im Kalender angezeigt.</li>
<li>Dokumente (Word, Excel und OneNote) lassen sich direkt im Gerät bearbeiten. Ideal ist das vor allem in Verbindung mit SharePoint oder dem eigenen Live Account. Die Dokumente werden übersichtlich dargestellt und können auch direkt auf einer Kachel dargestellt werden. Bei der Dokumentation der Beiträge der Partnerkonferenz wurden so meine Notizen direkt in unserem SharePoint gespeichert. Zurück am Arbeitsplatz waren so die Inhalte direkt verfügbar.</li>
<li>Aufgaben lassen sich auch als “Privat” kennzeichnen. Eigentlich selbstverständlich, aber im iPhone leider nicht möglich.</li>
<li>Abgesagte Termine lassen sich kommentieren. Auch das ist beim iPhone nicht möglich.</li>
<li>Bei Teilnehmern eines Termins lassen sich auch optionale Teilnehmer hinzunehmen.</li>
<li>Das zusammenlegen der Kontaktinformationen aus allen verfügbaren Konten (Outlook, Windows Live, Facebook) ist ein tolles Features. Insgesamt ist die Integration der Social Media Daten sehr gelungen.</li>
<li>Die Kamerataste an der Seite erlaubt das Fotografieren auch bei gesperrtem Gerät.</li>
<li>Auch die Sync Software Zune macht einen prima Eindruck.</li>
<li>Apps im Marketplace sind noch nicht ganz in der Fülle verfügbar, können aber die wichtigsten Themen auch sehr gut abdecken.</li>
<li>Bing Suche hat mich positiv überrascht. Vor allem die Musiksuche und die Möglichkeit Texte einzuscannen und diese unmittelbar zu übersetzen. Das kann sicherlich im nächsten Urlaub von großem Nutzen sein. </li>
</ul>
<p>Insgesamt macht das Telefon und das Betriebssystem einen sehr guten und gelungenen Eindruck. Ich habe Spaß an dem Gerät und werde es in Verbindung mit meinem iPhone (eher privater Nutzen) weiter nutzen. Bei dem Gerät steht eher der geschäftliche Einsatz im Vordergrund. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2011/10/windows-phone-7-5-mango/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom Aggregates in DAX / BISM Tabular (part 2)</title>
		<link>http://blog.oraylis.de/2011/09/custom-aggregates-in-dax-bism-tabular-part-2/</link>
		<comments>http://blog.oraylis.de/2011/09/custom-aggregates-in-dax-bism-tabular-part-2/#comments</comments>
		<pubDate>Sun, 25 Sep 2011 13:41:39 +0000</pubDate>
		<dc:creator>Hilmar Buchta</dc:creator>
				<category><![CDATA[Allgemein]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2011/09/custom-aggregates-in-dax-bism-tabular-part-2/</guid>
		<description><![CDATA[<p align="right">SQL Server Danali | PowerPivot</p>
<p align="left">This post combines two ideas</p>
<ol>
<li>
<div align="left">The calculation of a moving average (last 30 days) as shown in a <font style="background-color: #ffff00"></font><a href="http://ms-olap.blogspot.com/2011/08/moving-average-in-dax-bism-tabular.html" target="_blank">previous post</a><font style="background-color: #ffff00"></font></div>
</li>
<li>
<div align="left">Custom aggregations</div>
</li>
</ol>
<p align="left">What I want to show here today, is how we can influence the way our calculation works on higher levels. For this purpose I’m showing three different approaches:</p>
<ol>
<li>
<div align="left">The monthly (quarterly, yearly) total is defined as the last day’s moving average of the given date range.        <br />This corresponds to the original approach from my post about <font style="background-color: #ffff00"></font><a href="http://ms-olap.blogspot.com/2011/08/moving-average-in-dax-bism-tabular.html" target="_blank">moving averages</a><font style="background-color: #ffff00"></font></div>
</li>
<li>
<div align="left">The monthly (quarterly, yearly) total is defined as the average of all the moving averages on day level.</div>
</li>
<li>
<div align="left">The monthly (quarterly, yearly) total is defined as the average of the sales amount of all days of that period (the moving average is only to be calculated on date level)</div>
</li>
</ol>
<p align="left">Of course, there are many more possibilities but I think the methods shown here, can be used for many other aggregation requirements.</p>
<p align="left">Here are the three aggregations side by side. </p>
<p align="left"><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/image5.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.oraylis.de/wp-content/uploads/2011/09/image_thumb5.png" width="499" height="557" /></a></p>
<p align="left">Although the values on higher levels of aggregation differ a lot, the daily values are identical (we just wanted to change the rollup method, not the calculation on a detail level).</p>
<p align="left">Let’s start with the first one:</p>
<p align="left">&#160;</p>
<p><strong><u>1. The monthly (quarterly, yearly) total is defined as the last day’s moving average of the given date range</u></strong></p>
<p>This is shown here for our measure “Sales Amount(30 avg)”:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/image6.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.oraylis.de/wp-content/uploads/2011/09/image_thumb6.png" width="457" height="455" /></a></p>
<p>As shown in my <font style="background-color: #ffff00"></font><a href="http://ms-olap.blogspot.com/2011/08/moving-average-in-dax-bism-tabular.html" target="_blank">previous post</a><font style="background-color: #ffff00"></font>, the formula may look like this:</p>
<p><font face="Courier New">Sales Amount (30d avg):=      <br />AverageX(       <br />&#160; Summarize(       <br />&#160;&#160;&#160; datesinperiod(       <br />&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160;&#160; , LastDate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160; , -30       <br />&#160;&#160;&#160;&#160;&#160;&#160; , DAY       <br />&#160;&#160;&#160; )       <br />&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]       <br />&#160;&#160;&#160; , &quot;SalesAmountSum&quot;       <br />&#160;&#160;&#160; , calculate(Sum(&#8216;Internet Sales&#8217;[Sales Amount]), ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date]))       <br />&#160; )       <br />&#160; ,[SalesAmountSum]       <br />)</font></p>
<p>Since we use the expression LastDate(‘Date’[Date]) the last date of each period is used for the moving average – exactly what we wanted.</p>
<p>&#160;</p>
<p><strong><u>Average at month level as the average of the moving averages (day level)</u></strong></p>
<p>In this approach, the monthly aggregate has to be calculated as the average of all the daily moving averages of that month. The picture shows what this means:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/image7.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.oraylis.de/wp-content/uploads/2011/09/image_thumb7.png" width="464" height="445" /></a></p>
<p>This might look pretty difficult. However, for our calculation we simply have to wrap the existing calculation in another Summarize – function. </p>
<p>This is the formula I used:</p>
<p><font face="Courier New">Sales Amount (30d avg 2):=      <br />AverageX(       <br />&#160; summarize(       <br />&#160;&#160;&#160; &#8216;Date&#8217;       <br />&#160;&#160;&#160; , &#8216;Date&#8217;[Date]       <br />&#160;&#160;&#160; , &quot;DayAvg&quot;       <br />&#160;&#160;&#160; </font><font face="Courier New"><font color="#0000ff">AverageX(        <br />&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; datesinperiod(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , -30         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , DAY         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;SalesAmountSum&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , calculate(Sum(&#8216;Internet Sales&#8217;[Sales Amount]), ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160; ,[SalesAmountSum]         <br />&#160;&#160;&#160; )         <br /></font>&#160; )       <br />&#160; ,[DayAvg]       <br />)</font></p>
<p>The blue part of the formula is exactly the same is in the first calculation. We’re just wrapping this in an additional Average function. Why does this still work on a day-level? Simply because the outer average computes the average of a single value in this case.</p>
<p>So, with just a minor change to the formula, we changed the method of aggregation quite a lot.</p>
<p>&#160;</p>
<p><strong><u>3. The monthly (quarterly, yearly) total is defined as the average of the sales amount of all days of that period</u></strong></p>
<p>This sounds quite simple but in this case we have to distinguish two calculation paths:</p>
<ul>
<li>day level </li>
<li>month level and above </li>
</ul>
<p>The following picture shows the calculation for the monthly aggregate:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/image8.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.oraylis.de/wp-content/uploads/2011/09/image_thumb8.png" width="462" height="436" /></a></p>
<p>In order to split our computation paths we need to find out if we are on day level or not. Usually the IsFiltered(…) DAX function can be used for this purpose. However, since we have some columns with date granularity (date, day of month, day of year) in our date dimension, we would have to write something like IsFiltererd(‘Date’[Date]) || IsFiltered(‘Date’[Day of Month]) || …</p>
<p>To simplify this, I simple used a count of days in the following code. If we count only one day, we’re on day level. Of course, the count is the more expensive operation, but for this example, I leave it that way (the date table is not really big). </p>
<p>&#160;</p>
<p><font face="Courier New">Sales Amount (30d avg 3):=      <br />if (       <br />&#160; Count(&#8216;Date&#8217;[Date])=1,       <br />&#160; <font color="#0000ff">AverageX(        <br />&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160; datesinperiod(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , –30         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , DAY         <br />&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160; , &quot;SalesAmountSum&quot;         <br />&#160;&#160;&#160;&#160;&#160; , calculate(Sum(&#8216;Internet Sales&#8217;[Sales Amount]), ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date]))         <br />&#160;&#160;&#160; )         <br />&#160;&#160;&#160; ,[SalesAmountSum]         <br />&#160; )         <br /></font>&#160; ,&#160; <br />&#160; AverageX(       <br />&#160;&#160;&#160; Summarize(       <br />&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;       <br />&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160; ,&quot;SalesAmountAvg&quot;       <br />&#160;&#160;&#160;&#160;&#160; , calculate(Sum(&#8216;Internet Sales&#8217;[Sales Amount]), ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date]))       <br />&#160;&#160;&#160; )       <br />&#160;&#160;&#160; ,[SalesAmountAvg]       <br />&#160; )       <br />)       <br /></font></p>
<p>Again the blue part of the formula is exactly the same as in our first approach. This part is taken whenever we’re on a day level. On higher levels, the aggregate is computed as a simple (not moving) average of all daily values.</p>
<p>So, using the concepts of my previous post we were able to change the aggregation method to meet very sophisticated requirements. </p>
<div style="display:block"><small><em>by Hilmar Buchta <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2011%2F09%2Fcustom-aggregates-in-dax-bism-tabular-part-2%2F&amp;linkname=Custom%20Aggregates%20in%20DAX%20%2F%20BISM%20Tabular%20%28part%202%29"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p align="right">SQL Server Danali | PowerPivot</p>
<p align="left">This post combines two ideas</p>
<ol>
<li>
<div align="left">The calculation of a moving average (last 30 days) as shown in a <font style="background-color: #ffff00"></font><a href="http://ms-olap.blogspot.com/2011/08/moving-average-in-dax-bism-tabular.html" target="_blank">previous post</a><font style="background-color: #ffff00"></font></div>
</li>
<li>
<div align="left">Custom aggregations</div>
</li>
</ol>
<p align="left">What I want to show here today, is how we can influence the way our calculation works on higher levels. For this purpose I’m showing three different approaches:</p>
<ol>
<li>
<div align="left">The monthly (quarterly, yearly) total is defined as the last day’s moving average of the given date range.        <br />This corresponds to the original approach from my post about <font style="background-color: #ffff00"></font><a href="http://ms-olap.blogspot.com/2011/08/moving-average-in-dax-bism-tabular.html" target="_blank">moving averages</a><font style="background-color: #ffff00"></font></div>
</li>
<li>
<div align="left">The monthly (quarterly, yearly) total is defined as the average of all the moving averages on day level.</div>
</li>
<li>
<div align="left">The monthly (quarterly, yearly) total is defined as the average of the sales amount of all days of that period (the moving average is only to be calculated on date level)</div>
</li>
</ol>
<p align="left">Of course, there are many more possibilities but I think the methods shown here, can be used for many other aggregation requirements.</p>
<p align="left">Here are the three aggregations side by side. </p>
<p align="left"><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/image5.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.oraylis.de/wp-content/uploads/2011/09/image_thumb5.png" width="499" height="557" /></a></p>
<p align="left">Although the values on higher levels of aggregation differ a lot, the daily values are identical (we just wanted to change the rollup method, not the calculation on a detail level).</p>
<p align="left">Let’s start with the first one:</p>
<p align="left">&#160;</p>
<p><strong><u>1. The monthly (quarterly, yearly) total is defined as the last day’s moving average of the given date range</u></strong></p>
<p>This is shown here for our measure “Sales Amount(30 avg)”:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/image6.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.oraylis.de/wp-content/uploads/2011/09/image_thumb6.png" width="457" height="455" /></a></p>
<p>As shown in my <font style="background-color: #ffff00"></font><a href="http://ms-olap.blogspot.com/2011/08/moving-average-in-dax-bism-tabular.html" target="_blank">previous post</a><font style="background-color: #ffff00"></font>, the formula may look like this:</p>
<p><font face="Courier New">Sales Amount (30d avg):=      <br />AverageX(       <br />&#160; Summarize(       <br />&#160;&#160;&#160; datesinperiod(       <br />&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160;&#160; , LastDate(&#8216;Date&#8217;[Date])       <br />&#160;&#160;&#160;&#160;&#160;&#160; , -30       <br />&#160;&#160;&#160;&#160;&#160;&#160; , DAY       <br />&#160;&#160;&#160; )       <br />&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]       <br />&#160;&#160;&#160; , &quot;SalesAmountSum&quot;       <br />&#160;&#160;&#160; , calculate(Sum(&#8216;Internet Sales&#8217;[Sales Amount]), ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date]))       <br />&#160; )       <br />&#160; ,[SalesAmountSum]       <br />)</font></p>
<p>Since we use the expression LastDate(‘Date’[Date]) the last date of each period is used for the moving average – exactly what we wanted.</p>
<p>&#160;</p>
<p><strong><u>Average at month level as the average of the moving averages (day level)</u></strong></p>
<p>In this approach, the monthly aggregate has to be calculated as the average of all the daily moving averages of that month. The picture shows what this means:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/image7.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.oraylis.de/wp-content/uploads/2011/09/image_thumb7.png" width="464" height="445" /></a></p>
<p>This might look pretty difficult. However, for our calculation we simply have to wrap the existing calculation in another Summarize – function. </p>
<p>This is the formula I used:</p>
<p><font face="Courier New">Sales Amount (30d avg 2):=      <br />AverageX(       <br />&#160; summarize(       <br />&#160;&#160;&#160; &#8216;Date&#8217;       <br />&#160;&#160;&#160; , &#8216;Date&#8217;[Date]       <br />&#160;&#160;&#160; , &quot;DayAvg&quot;       <br />&#160;&#160;&#160; </font><font face="Courier New"><font color="#0000ff">AverageX(        <br />&#160;&#160;&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; datesinperiod(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , -30         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; , DAY         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , &quot;SalesAmountSum&quot;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , calculate(Sum(&#8216;Internet Sales&#8217;[Sales Amount]), ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date]))         <br />&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160; ,[SalesAmountSum]         <br />&#160;&#160;&#160; )         <br /></font>&#160; )       <br />&#160; ,[DayAvg]       <br />)</font></p>
<p>The blue part of the formula is exactly the same is in the first calculation. We’re just wrapping this in an additional Average function. Why does this still work on a day-level? Simply because the outer average computes the average of a single value in this case.</p>
<p>So, with just a minor change to the formula, we changed the method of aggregation quite a lot.</p>
<p>&#160;</p>
<p><strong><u>3. The monthly (quarterly, yearly) total is defined as the average of the sales amount of all days of that period</u></strong></p>
<p>This sounds quite simple but in this case we have to distinguish two calculation paths:</p>
<ul>
<li>day level </li>
<li>month level and above </li>
</ul>
<p>The following picture shows the calculation for the monthly aggregate:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/image8.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.oraylis.de/wp-content/uploads/2011/09/image_thumb8.png" width="462" height="436" /></a></p>
<p>In order to split our computation paths we need to find out if we are on day level or not. Usually the IsFiltered(…) DAX function can be used for this purpose. However, since we have some columns with date granularity (date, day of month, day of year) in our date dimension, we would have to write something like IsFiltererd(‘Date’[Date]) || IsFiltered(‘Date’[Day of Month]) || …</p>
<p>To simplify this, I simple used a count of days in the following code. If we count only one day, we’re on day level. Of course, the count is the more expensive operation, but for this example, I leave it that way (the date table is not really big). </p>
<p>&#160;</p>
<p><font face="Courier New">Sales Amount (30d avg 3):=      <br />if (       <br />&#160; Count(&#8216;Date&#8217;[Date])=1,       <br />&#160; <font color="#0000ff">AverageX(        <br />&#160;&#160;&#160; Summarize(         <br />&#160;&#160;&#160;&#160;&#160; datesinperiod(         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,LastDate(&#8216;Date&#8217;[Date])         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , –30         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; , DAY         <br />&#160;&#160;&#160;&#160;&#160; )         <br />&#160;&#160;&#160;&#160;&#160; , &#8216;Date&#8217;[Date]         <br />&#160;&#160;&#160;&#160;&#160; , &quot;SalesAmountSum&quot;         <br />&#160;&#160;&#160;&#160;&#160; , calculate(Sum(&#8216;Internet Sales&#8217;[Sales Amount]), ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date]))         <br />&#160;&#160;&#160; )         <br />&#160;&#160;&#160; ,[SalesAmountSum]         <br />&#160; )         <br /></font>&#160; ,&#160; <br />&#160; AverageX(       <br />&#160;&#160;&#160; Summarize(       <br />&#160;&#160;&#160;&#160;&#160; &#8216;Date&#8217;       <br />&#160;&#160;&#160;&#160;&#160; ,&#8217;Date&#8217;[Date]       <br />&#160;&#160;&#160;&#160;&#160; ,&quot;SalesAmountAvg&quot;       <br />&#160;&#160;&#160;&#160;&#160; , calculate(Sum(&#8216;Internet Sales&#8217;[Sales Amount]), ALLEXCEPT(&#8216;Date&#8217;,'Date&#8217;[Date]))       <br />&#160;&#160;&#160; )       <br />&#160;&#160;&#160; ,[SalesAmountAvg]       <br />&#160; )       <br />)       <br /></font></p>
<p>Again the blue part of the formula is exactly the same as in our first approach. This part is taken whenever we’re on a day level. On higher levels, the aggregate is computed as a simple (not moving) average of all daily values.</p>
<p>So, using the concepts of my previous post we were able to change the aggregation method to meet very sophisticated requirements. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2011/09/custom-aggregates-in-dax-bism-tabular-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom Aggregates in DAX / BISM Tabular (part 1)</title>
		<link>http://blog.oraylis.de/2011/09/custom-aggregates-in-dax-bism-tabular-part-1/</link>
		<comments>http://blog.oraylis.de/2011/09/custom-aggregates-in-dax-bism-tabular-part-1/#comments</comments>
		<pubDate>Sun, 11 Sep 2011 13:33:32 +0000</pubDate>
		<dc:creator>Hilmar Buchta</dc:creator>
				<category><![CDATA[MS SSAS]]></category>
		<category><![CDATA[BISM]]></category>
		<category><![CDATA[DAX]]></category>
		<category><![CDATA[PowerPivot]]></category>
		<category><![CDATA[Tabular]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2011/09/custom-aggregates-in-dax-bism-tabular-part-1/</guid>
		<description><![CDATA[<p align="right">SQL Server Denali | PowerPivot</p>
<p>Custom aggregates can be created using cube scripts in BISM multidimensional (SSAS OLAP cubes). How can we do this with BISM tabular? In many cases, simple DAX calculations can solve this for us.</p>
<p>I’m referring to<font style="background-color: #ffff00"></font> the example of my <a href="http://ms-olap.blogspot.com/2011/08/semi-additive-measures-in-dax-bism.html" target="_blank">previous post</a> about semi additive measures. Let’s say we’re monitoring the stock of two products we’re selling. For the totals we want to see the average stock over time. At least once a month we’re taking a snapshot of the stock. If we have more than one snapshot per month, the monthly total computes as the average of those snapshot. For aggregation above the month level we want to take the average of the monthly averages. At first, this looks like we only have to use average as the aggregation function. But the average of averaged values is not identical to the average of all values. Let’s take a look at this source data table:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/t11.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t1" border="0" alt="t1" src="http://blog.oraylis.de/wp-content/uploads/2011/09/t1_thumb1.png" width="244" height="233" /></a></p>
<p>For product Notate we have a single measurement of 50 pieces in February. For product Quickerstill we have 8 distinct measurements with an average of 50 pieces in February. However, when we look at the total average for Quickerstill, the 8 distinct measurements in February result in a higher weight of the February average and therefore in a higher total average of 44 instead of 30:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/t21.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t2" border="0" alt="t2" src="http://blog.oraylis.de/wp-content/uploads/2011/09/t2_thumb1.png" width="393" height="135" /></a></p>
<p>The Average Stock measure in this example is the same semi additive measure as in <font style="background-color: #ffff00"></font><a href="http://ms-olap.blogspot.com/2011/08/semi-additive-measures-in-dax-bism.html" target="_blank">my previous post</a> and computed like this:</p>
<p><font face="Courier New">AVG Stock:=Sum([Stocklevel])/DISTINCTCOUNT([Date])</font></p>
<p>The requirement for the custom aggregate means, that we also want to see a total average of 30 for product Quickerstill (20+50+20=90, 90/3=30). This requirement is somewhat unusual as the computation above gives the “correct” average of all values. One interpretation is that the weight for computing the average of two or more months is not influenced by the number of measurements within the month. </p>
<p>We can achieve this in a way that is very similar to the semi additive calculations from my last post. Here is the resulting formula:</p>
<p><font face="Courier New">Special AVG Stock:=AVERAGEX(SUMMARIZE(&#8216;Stock&#8217;,[Year],[Month],&quot;AvgStock&quot;,AVERAGE([Stocklevel])),[AvgStock])</font></p>
<p>This formula simply summarizes the average stock at a grouping level of year and month. Then, in a second step, it takes these values and computes the average of them. By doing so, we have broken the aggregation into two layers. First we average by month, then we take the average of those values.</p>
<p>Here is the resulting table using the new aggregate:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/t3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t3" border="0" alt="t3" src="http://blog.oraylis.de/wp-content/uploads/2011/09/t3_thumb.png" width="460" height="146" /></a></p>
<p>And after expanding the February values (2nd month) we clearly see the how our custom aggregate works:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/p1.png"><img style="display: inline" title="p1" alt="p1" src="http://blog.oraylis.de/wp-content/uploads/2011/09/p1_thumb.png" width="570" height="278" /></a></p>
<p>Of course, this is just a simple custom aggregate but it is remarkable that we didn’t need any kind of cube script with scope-statements to achieve this but only a very simple DAX expression.</p>
<div style="display:block"><small><em>by Hilmar Buchta <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2011%2F09%2Fcustom-aggregates-in-dax-bism-tabular-part-1%2F&amp;linkname=Custom%20Aggregates%20in%20DAX%20%2F%20BISM%20Tabular%20%28part%201%29"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p align="right">SQL Server Denali | PowerPivot</p>
<p>Custom aggregates can be created using cube scripts in BISM multidimensional (SSAS OLAP cubes). How can we do this with BISM tabular? In many cases, simple DAX calculations can solve this for us.</p>
<p>I’m referring to<font style="background-color: #ffff00"></font> the example of my <a href="http://ms-olap.blogspot.com/2011/08/semi-additive-measures-in-dax-bism.html" target="_blank">previous post</a> about semi additive measures. Let’s say we’re monitoring the stock of two products we’re selling. For the totals we want to see the average stock over time. At least once a month we’re taking a snapshot of the stock. If we have more than one snapshot per month, the monthly total computes as the average of those snapshot. For aggregation above the month level we want to take the average of the monthly averages. At first, this looks like we only have to use average as the aggregation function. But the average of averaged values is not identical to the average of all values. Let’s take a look at this source data table:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/t11.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t1" border="0" alt="t1" src="http://blog.oraylis.de/wp-content/uploads/2011/09/t1_thumb1.png" width="244" height="233" /></a></p>
<p>For product Notate we have a single measurement of 50 pieces in February. For product Quickerstill we have 8 distinct measurements with an average of 50 pieces in February. However, when we look at the total average for Quickerstill, the 8 distinct measurements in February result in a higher weight of the February average and therefore in a higher total average of 44 instead of 30:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/t21.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t2" border="0" alt="t2" src="http://blog.oraylis.de/wp-content/uploads/2011/09/t2_thumb1.png" width="393" height="135" /></a></p>
<p>The Average Stock measure in this example is the same semi additive measure as in <font style="background-color: #ffff00"></font><a href="http://ms-olap.blogspot.com/2011/08/semi-additive-measures-in-dax-bism.html" target="_blank">my previous post</a> and computed like this:</p>
<p><font face="Courier New">AVG Stock:=Sum([Stocklevel])/DISTINCTCOUNT([Date])</font></p>
<p>The requirement for the custom aggregate means, that we also want to see a total average of 30 for product Quickerstill (20+50+20=90, 90/3=30). This requirement is somewhat unusual as the computation above gives the “correct” average of all values. One interpretation is that the weight for computing the average of two or more months is not influenced by the number of measurements within the month. </p>
<p>We can achieve this in a way that is very similar to the semi additive calculations from my last post. Here is the resulting formula:</p>
<p><font face="Courier New">Special AVG Stock:=AVERAGEX(SUMMARIZE(&#8216;Stock&#8217;,[Year],[Month],&quot;AvgStock&quot;,AVERAGE([Stocklevel])),[AvgStock])</font></p>
<p>This formula simply summarizes the average stock at a grouping level of year and month. Then, in a second step, it takes these values and computes the average of them. By doing so, we have broken the aggregation into two layers. First we average by month, then we take the average of those values.</p>
<p>Here is the resulting table using the new aggregate:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/t3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="t3" border="0" alt="t3" src="http://blog.oraylis.de/wp-content/uploads/2011/09/t3_thumb.png" width="460" height="146" /></a></p>
<p>And after expanding the February values (2nd month) we clearly see the how our custom aggregate works:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/09/p1.png"><img style="display: inline" title="p1" alt="p1" src="http://blog.oraylis.de/wp-content/uploads/2011/09/p1_thumb.png" width="570" height="278" /></a></p>
<p>Of course, this is just a simple custom aggregate but it is remarkable that we didn’t need any kind of cube script with scope-statements to achieve this but only a very simple DAX expression.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2011/09/custom-aggregates-in-dax-bism-tabular-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

