Monday, March 12, 2012

Display the No Row Information in the SSRS Report Footer

Recently there is a reader asked about how to display row count information in page footer if no data returned.  Since RowNumber() function can only be used in the report body to retrieve the number of rows in the specified scope, we could not use it in either the Header or Footer area.

We could use other counting function such as CountRows() or Count() to retrieve the number of rows retuned for the dataset.

Here is what we can do:

  • Add a textbox in the report footer

image

  • Use CountRows() function passing in the dataset name in the expression for the textbox as:

image

Result

AS you could see, the report footer shows the number of row returned by the dataset now.

image

image

Reference:

http://msdn.microsoft.com/en-us/library/dd255237(v=sql.110).aspx

http://msdn.microsoft.com/en-us/library/ms157163(v=sql.110).aspx

http://msdn.microsoft.com/en-us/library/ms156330(v=sql.110).aspx

Tuesday, March 6, 2012

Use DAX Earlier Function in Calculated Column to Mimic Group By Clause

It is very easy to group or slice the measures in the Pivot table by adding a attribute to the row or slicer.  But, how do we create the same effect in the Calculated Column?

image

Here is the Sample Data

image

If we treat this table as a SQL table, we could use the following T-SQL query to find the total queued time for each queue per date.

SELECT [Date], [QueueName], SUM([QueuedTime]) AS [TotalQueuedTime]
FROM CallDetail
GROUP BY [Date], [QueueName]

In PowerPivot, we could use the EARLIER function to achieve the same effect.  EARLIER is a very useful DAX function when you want to use a certain value as input to produce a calculation.


Syntax:



EARLIER(<column>, <number>) 

Solution:


Step 1: Calculate the total of the QueuedTime by using SUM(), and then use FILTER() to obtain the subset of the table for the Date and the QueueName needed.



=CALCULATE(
    SUM(CallDetail[QueuedTime]), 
    FILTER(CallDetail, CallDetail[Date] = ?) 
           && CallDetail[QueueName]= ?
            )
    )

Step 2: In the question mark area, we need to plug in a value/expression to restrict the rows been returned.


If we set they to the static value as “2012-02-18” and “Queue A”, the Sum of QueuedTime will be 900 for all the rows which won’t be correct for the Queue not equal to “Queue A” or the Date not equal to “2012-02-18”.


image

Step 3: To pass in correct expression, we could use the EARLIER() as the input for the certain value (i.e. Date or Queue name) that the calculation will be based on it. 


=CALCULATE(
    SUM(CallDetail[QueuedTime]), 
    FILTER(CallDetail, CallDetail[Date] = EARLIER(CallDetail[Date])
           && CallDetail[QueueName]= EARLIER(CallDetail[QueueName])
            )
    )

You can see the result now is correct based on the Date and QueueName

image

The EARLIER function is based on the current row context. If there is no row context, it will return an error.

Implementation Example:


Here is a scenario that I have encountered: Create a measure that contains the cumulated Queued Time only for the last queue.


image


To solve it, I add the following condition to the pervious formula based on the LastQueue flag



=IF(CallDetail[LastQueue] = 1, 
    CALCULATE(
        SUM(CallDetail[QueuedTime]), 
        FILTER(CallDetail, CallDetail[Date] = EARLIER(CallDetail[Date]) 
           && CallDetail[CallID]=EARLIER(CallDetail[CallID])
            )
        )
     ,BLANK()
    )

This way, only the last queue will have the total queued time in the column. image


When summing up in the Pivot table, the total of QueueTimeHandled per day will now match the total of QueuedTime.


image


My colleague Javier Guillen has another nice blog entry to discuss how to use the EARLIER() in DAX measure. You may want to check it out.


Reference:


http://technet.microsoft.com/en-us/library/ee634551.aspx

Sunday, February 26, 2012

Using Page and CAML Query to Extract SharePoint List in SSIS

 

There are several ways to read SharePoint List as data source in SSIS.  The easiest way is using the SharePoint List Adapter.  You could download it from the Codeplex site.  However, you may want to have more control during extracting the list to avoid failure, to manipulate data before sent to the output rows, or you are experiencing timeout issue with lots of item in the list. 

Here is the solution I used:

Add For Loop Container in Task Component with a Data Flow

  • Since the SharePoint list could be large, use the for loop container to loop through the paging.

image

  • Set InitExpression to the Page number @PageCount = 1
  • Set the EvalExpression to a Variable: @LoopNext  which will be determine in the data flow.
  • Set the AssignExpression to be @PageCount = @PageCount + 1

image 

Create a Script Component  with Source Type to Read SharePoint List

  • In the data flow, add a Script Component with Source type.

image

  • Pass in @LoopNext  and @SharePointPageInfo variables as Read Write Variables.
  • Pass in @SharePointSite, @SharepointListname, @SharePoinbtView, @SharePointRowLimit variables as Read Variables.
  • Create two Outputs. One for the default SharePoint list data set, the other will hold the error data.
  • Click Edit Script… button to add .net code
  • Right click the project to add Server Reference that point to the SharePoint Site

image image

  • In CreateNewOutputRows(), instantiate the SharePoint Web Service List object
  • Create several XMLNode objects as the parameters to call System.Xml.XmlNode GetListItems()
//Retrieve the list of available fields from the GetList call to Sharepoint.
Lists SPS = new Lists();
SPS.UseDefaultCredentials = true;
SPS.Url = strSharepointURL;
 
//Create XML Node
XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");
XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query","");
 
 
XmlNode ndListItems = null;
ndListItems = SPS.GetListItems(strListName, strViewName, ndQuery, ndViewFields, strRowLimit, ndQueryOptions, null);



  • Once the result gets back, iterate through the XML nodes to populate the default output data row.
  • If there is an exception thrown

    • Set the @LoopNext to false which will stop the For Loop container
    • Add a row that contains the exception message to error output.


catch (System.Web.Services.Protocols.SoapException ex)
     {
         string strError = "Message:" + ex.Message + "\nDetail:" + ex.Detail.InnerText + "\nStackTrace:" + ex.StackTrace;
         
         ErrorBuffer.AddRow();
         ErrorBuffer.ErrorData = strError.ToString().Substring(0, strError.ToString().Length > 4000 ? 4000 : strError.ToString().Length);
         bLoopNext = false;
     }



  • In the data flow, sent the SharePoint list items to the destination table and the error data to error table. This way the SSIS package will not fail to execute with any SharePoint Site issue. Other process could utilize the data in the error table to recover it softly.
  • In the Add Metadata component, add the @PageCount as an output column. It could be used for recovery or debug purpose.

image 


Narrow Down the Needed Fields



Don’t select all the fields from the list. Sometime the list may contain binary data, meta data or image that may take long time to load. To narrow down the fields, just specify the fields in the ViewFields XML Node as:



XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
//Get List of Field needed
ndViewFields.InnerXml = "<FieldRef Name='ID' />";
ndViewFields.InnerXml += "<FieldRef Name='Created' />";
ndViewFields.InnerXml += "<FieldRef Name='Author' />";
ndViewFields.InnerXml += "<FieldRef Name='Editor' />";
ndViewFields.InnerXml += "<FieldRef Name='Modified' />";

Add CAML Query to Extract Only the Delta



To pull only the delta records in, just add filters in the query. The SharePoint list has a system field called “Modified” which will be time stamped when the record get changed. You could utilize the CAML query to get the items that have Modified Date greater than a Date value or within an arrange of date. If you don’t know the syntax of the CAML Query, you could use some SharePoint Utility such as U2U CAML Builder.


Here is a sample CAML Query that will filter the result by range of date:



<Where><And>
<Geq><FieldRef Name="Modified" IncludeTimeValue="TRUE" /><Value Type="DateTime">2012-01-01 00:00:00</Value></Geq>
<Leq><FieldRef Name="Modified" IncludeTimeValue="TRUE" /><Value Type="DateTime">2012-01-31 23:59:00</Value></Leq>
</And>
</Where>


Page though Large Number of List Items in the Script



Depend on the size of the item, you may set the row limit to 1000 while calling the GetListItems().  The function supports service-side paging. When the XML result returned, it includes a ListItemCollectionPositionNext attribute that contains the information to support the paging.  You need to save it for the next call.  Make sure you do not modify the string. 


In the example below, I set the ListItemCollectionPositionNext attribute to a local variable first and the bLoopNext to true. I then save the string to a SSIS Read/Write variable to be use for next loop.



//Get page related meta data
XDocument meta = XDocument.Parse(ndListItems.InnerXml);
if (meta.Root.Attribute("ListItemCollectionPositionNext") != null)
    {
       strPage = meta.Root.Attribute("ListItemCollectionPositionNext").Value;
       bLoopNext = true;
    }
else
    {
       strPage = string.Empty;
       bLoopNext = false;
    }

When next loop starts, I set the saved attribute string to the QueryOptions parameter to be used to fetch the next set data back.



//Set page Query option
if (strPage.Length > 0)
    {
       ndQueryOptions.InnerXml = @"<Paging ListItemCollectionPositionNext='' />";
       ndQueryOptions.ChildNodes[0].Attributes["ListItemCollectionPositionNext"].InnerText = strPage;
    }
else
    {
        ndQueryOptions.InnerXml = "";
    }
    

 Result



After executing the SSIS package, you can see the SharePoint List been extracted page by page as below:


image 


The PageCount column stores the SharePoint List page number.


Reference:



http://msmvps.com/blogs/ivansanders/archive/2011/07/24/ssis-sharepoint-list-adapters.aspx


http://msdn.microsoft.com/en-us/library/lists.lists.getlistitems(v=office.12).aspx


http://sqlsrvintegrationsrv.codeplex.com/releases/view/17652

Thursday, February 16, 2012

Tip to Change SSIS Variable Scope

Recently I work on a SSIS project that has a Sequence Container with lot of variables that I need for a data flow. Later on I want to change the sequence container to be a For Loop Container.   It is easy to copy and paste the the data flow in the container to the other. But, how to move the SSIS variables in the visual studio?

If you are familiar with the SSIS XML code, you may be able to copy or move the variables from one XML Node section to the other without corrupt it.  For others, recreating the variable with correct value or expression could be cumbersome.

Here is a easy way to handle it:

  • Install BIDS Helper from CodePlex site.
  • Select the variable you want to copy or move

image

  • Click on the Move/Copy Variables from SSIS Variables tool bar to open a new window

image

  • Click on the DTS executable that you want the variable scope to change to , then click OK

image

  • The variable shows up in the SSIS Variables Window with new Scope

Wednesday, February 15, 2012

SQL Dump After Either Upgrade or Downgrade the PowerPivot

Recently I upgraded the PowerPivot Excel add on to the version 2 to work with new DAX. I experienced excel crush when I opened the workbook.  The error message showed as:

SQLDUMPER.EXE
Unable to open file \\?\Program Files\Microsoft Analysis Services\AS OLEDB\10\FlightRecorderCurrent.trac error 2

I tried to uninstall and re-install the program, but it didn’t work.  I have to manually delete the directory C:\Program Files\Microsoft Analysis Services\AS OLEDB\ and repair the PowerPivot, then it works.

Same situation happened again when I downgrade my PowerPivot back to version 1 to be compatible with my client’s environment.  Once I manually remove the C:\Program Files\Microsoft Analysis Services\AS OLEDB\ directory and then repair the program, it works again.

Thursday, January 26, 2012

Publish a BISM Tabular Model Database Connection on SharePoint 2010

Once you built a BISM Tabular Model project and deployed to SSAS,  you may want to publish it on the SharePoint 2010. A BISM connection allows business end users to access the underline model on SharePoint with addtional security control. It could also utilize the SharePoint quick launch commands to open the Excel Workbook or Power View Report.  For more information about how to create a BISM Tubular Model project, see my previous blog entry Create a SSAS BISM Tabular Model Project.

 

Add the BI Semantic Model Connection Content Type to the SharePoint Library

  • Go to the SharePoint Library site that will host the connection file, click the Library in the Library Tools.
  • Click the Library Settings
  • In the General Settings section, select the Advanced settings
image
  • In the Content Types, Select the Allow management of content types to be Yes, then click OK
  • In the Content Types section, Click on the Add from existing site content types
  • Add the BI semantic Model Connection
image
  • After click on the OK button, you can see the BI Semantic Model Connection added in the Content type table
image

 

Set Up Permissions

  • Grant the Tubular Model Analysis Service administrative permissions to the SharePoint Service Account.
  • Grant the user who is going to use the connection with the Read permission on the Tabular Model database
    • Add a Role with Read permission
    • Adding the user to the Role

 

Create the Connection File on SharePoint

  • Go to the library page, click on the Documents in the Library Tools.
  • Click on the down arrow on the New Document and select the BI semantic Model Connection.
image
  • On the New BI Semantic Model Connection page, specify the server name and database name and then Click OK.
image
  • On the library page, you should be able to see the new connection file.

image


Use the BISM Connection in SharePoint

Now you may use Excel or Power View to consume the BISM connection file as the data source. 
  • If you create the file in PowerPivot Gallery, you could click on either the Open New Excel Workbook or Create Power View Report link on the right upper corner to open the application.
image
  • If you create the file in the Shared Documents page, you could click on the Down Arrow on the File Name to launch either the Excel or the Power View Report.

image

Additional Reference
http://technet.microsoft.com/en-us/library/hh230813(SQL.110).aspx
http://technet.microsoft.com/en-us/library/gg492136(SQL.110).aspx

Thursday, January 12, 2012

SQL Server 2012 – Integration Services Catalog

SSIS in SQL 2012 has a new Integration Services Catalog (SSISDB) that is used for monitoring and managing SSIS projects. The Catalog will store all the integration services objects and will automatically log all the package execution activities when the SSIS project is using the new Project Deployment Model.

In order to use the new Project Deployment Model, you need to create the Integration Services Catalog for the first time.  Otherwise you will get the following error message as:

An Integration Services catalog (SSISDB) was not found on this server instance ("LocalHost").
To deploy a project to this server, you must create the SSISDB catalog. Open the Create Catalog dialog box from the Integration Services node.

image

Steps to Create the Catalog:

  • Open SQL Server Management Studio
  • Right click on the Integration Services node
  • Click on the Create Catalog…..

image

  • The catalog name is SSISDB. Enter the password for encryption then hit the OK button.

image

  • The new SSISDB will be created and show in two places:
    • Database node
    • Integration Services node

image 

  • You may view or adjust the catalog properties using the property window or Catalog.Configure_Catalog stored procedure.

image

Monitor the Execution Activities

After deploy a SSIS project, the data will be collected by the SSISDB.  The build in Integration Service Dashboard could be used to monitor all the activities that executed by the SSIS packages for that project.

  • Right Click on the SSISDB node to open the Reports->Standard Reports->Integration Services Dashboard.

image

  • Dashboard Summary Report opened.

image

  • There are hyperlinks on the overview report to navigate to more detail information.

image

There is no need to create any custom logging in the SSIS packages at all.

Additional Reference:

http://msdn.microsoft.com/en-us/library/hh479588(v=SQL.110).aspx