Skip to content
Archive of posts filed under the Reporting category.

SSRS Report Viewer Error

I was working on a particular production problem yesterday. Sometimes when a user clicked on print button in SSRS Web Report Viewer control, and error was shown, and report is only partially printed, maybe 2 pages out of 4 are printed. Specific error that is shown to the user stated “An error occurred during printing (0×80004005)”.
Don’t you hate problems that start with “it only breaks sometimes”? Moreover, those that have totally nondescript errors?

One thing I learned a while ago, is that is web farm environment these types of problems are often related to configuration issues on one server vs. the other. So, I took a look at all the servers, and they all had SSRS Report Viewer redistributable installed. What was also interesting, is that preview worked fine, the error only occured when print button is pushed.
It took me a bit to replicate the problem, and then I did what I often do when debugging web problems – I fired up Fiddler. What Fiddler was reporting is that I was getting 404 Not Found error for Reserved.ReportViewerWebControl.axd. I could not understand why because report viewer redistributable should have installed the HTTP handler for me. I checked first production machine, and it was there. So, I checked the rest of the production servers. I found one that was missing the handler. No idea why, the same install was run on all the servers.
So, I added the handler in IIS 7 Management IIS Console -> root server node -> Handler Mapping -> Add Managed Handler with the following entries:
Request Path: Reserved.ReportViewerWebControl.axd
Type:Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Name=ReportViewerWebControlHandler
Note: I am using SQL Server 2008 R2, hence the assembly version is 10.0

And voila, the problem went away!
Thanks.

Post to Twitter

Getting Started with PowerPivot

Last week I took a stab at creating my first PowerPivot spreadsheet, and I wanted to document the steps.  Maybe this post will help someone, but it will help me remember, that is for sure!

Before you get started, you will need to download all the software required.  Here is my list:

Of course, you will need and instance of SQL Server 2008.  You can just use Express edition if you do not have one installed.

Now that I have everything installed and configured, I can start with PowerPivot.  One note – look for Hand shaped cursor in the screens below.s

Step 1 – Start up Excel 2010 and look for PowerPivot menu, then click on PowerPivot Window to launch pivot.

image

Step 2 – click on From Database in the window, then Select from SQL Server

image

Step 3 – Fill in SQL Server details.  I am choosing to use Data Warehouse DB.  Click Next when done.  On the next screen select an option to Select for a list of tables and views.

image

Step 4 – Select dimension tables and fact table to analyze.  Here is my list in alphabetical order

  • DimCustomer
  • DimDate
  • DimProductCategory
  • DimSalesTerritory
  • FactInternetSales

You can select any tables you like of course.  Wait while data is imported into PowerPivot, then click Close.  PowerPivot window will now have five tabs with data and columns directly imported from the database.  Here is what it looks like.

image

Now click on PivotTable menu and select  Chart and Table – Vertical option.  We will simply create a chart and an analysis table to go with it.  Click on New Worksheet when prompted.  This step will return you back to main Excel window.  You will see chart, table and on the left hand side Gemini task pane – listing of imported data.  Gemini used to be Microsoft code name for this product/functionality.

image

Step 5 – Building a chart.  We are going to analyze sales based on customer marital status by linking it to sales amount.  Click on the chart first, then in Gemini pane expand DimCustomer table and select MaritalStatus.  Then, expand FactInternetSales and select SalesAmount.  PowerPivot will guess what we are trying to do and MaritalStatus as Axis field and Sum(SalesAmount) as Values.  Here is what it looks like:

image

 

Step 6 – building table with filters. 

Click on table first, then check the following tables/fields in Gemini pane:

  • DimCustomer – MaritalStatus and Gender
  • DimDte – CalendarYear
  • DimProductCategory – EnglishProductCategoryName
  • DimSalesTerritory – SalesTerritoryCountry
  • FactInternetSales – SalesAmount

At this point your bottom of Gemini pane should look like this:

image

if you have anything else in Values, click on that item and select “Move to Row labels”.  What you will see also is that your have a report built for you in table area that uses all the analysis points.  You could leave it as is, but I will do more.

 

Step 7 Now I can analyze the data by “slicing it”.  To do this we will create two groups of slices – horizontal and vertical.  We will split our analysis categories as follows:

  • Horizontal Slices: Marital Status and Gender
  • Vertical Slices –English Product Category and Calendar Year.

I will leave Sales Territory country as a column in my table. To perform this I will click on each of my slices and select “Move to Slices Horizontal (or Vertical) as appropriate.  Then I click on each slice and choose Move Up or down until my pane looks like this:

image

Now here is what my table looks:

image

I will go ahead and move things around to make spreadsheet look better:

image

 

Step 8 – Use slices for analysis.  This process is super simple – just click on a desired slice(s) to enact filter on rows of a table.

image

To clear the filter just click on a funnel picture with x across it:

image

As you do so, you will see the chart and table both updating with your filter values.  One thing I did notice at the end – Catergory is lon linked to internet sales, so category filter has no effect on data.  If you see similar behavior, your data has the same issue.  You can always manually build relationships in PowerPivot by click on Table tab in pivot and choosing Manage Relationships menu:

image

 

As you can see, using PowerPivot is extremely easy and the results are very powerful.  You can save your spreadsheet, open it later and refresh the data by clicking on a filter!  You also have an option to show or hide Gemini panels in Excel under PowerPivot menu.  In the same menu you also have an option to show or hide Gemini panels.

Thanks.

Post to Twitter

Webinar (Reporting in Silverlight) download

Recording of the webinar I presented is now up on Magenic web site.  Here is the address: http://www.magenic.com/Default.aspx?tabid=635

Since I am not sure if the sample project is available, I decided to post the zip file with the sample project here.

Please let me know if you have any questions. 

Post to Twitter

Webinar on reporting in Silverlight

I am presenting a webinar on July 28th on reporting in Silverlight.  This webinar is hosted by my employer, Magenic Technologies.  If you would like to register and watch this event, please follow this link: http://guest.cvent.com/EVENTS/Info/Invitation.aspx?e=6ca01a01-e2bd-4a77-a057-a63ab2208e81

There should be some tome allocated for questions and answers as well.

Thank you.

Post to Twitter

SSRS and “Unable to load client print control” issue

I was faced with a new (to me) problem today.  As part of testing of a Silverlight application that has SSRS based reports, the client reported an issue on some machines.  They are able to print a report, but clicking on export or print button was causing issues.  The actual error reported from Silverlight application was “Unable to load client print control.”  Apparently this is a know issue caused by a Microsoft issued patch a few month ago.  Here are the details of the issue and links to patches to address it: http://blogs.msdn.com/brianhartman/archive/2008/11/05/client-print-fails-to-load-after-microsoft-update-956391.aspx

Here is a direct link to SQL Server 2008 Report Viewer redistributable package:

http://www.microsoft.com/downloads/details.aspx?FamilyID=bb196d5d-76c2-4a0e-9458-267d22b6aac6&DisplayLang=en

Post to Twitter

Notes on SSRS deployment

I had to deploy and configure SSRS on Friday.  Getting it configured was an easy part.  Then I had to deploy about 50 reports for testing.  They all shared one data source.  One unfortunate part I found is that you cannot add multiple reports to report server at one time.  So, I had to pick one report at a time to add to SSRS installation.  Once that was done I discovered that data source did not translate properly.  At that point I had to pull up properties of each report and pick a data source yet again.  Once all that was done, I was able to preview reports on SSRS server.

Next step was to configure application server.  In my case I was using ASP.NET based SSRS report viewer.  All my settings were in web.config.  I updated them with the SSRS server location.  However, once I tried to preview a report there, I got a security exception.  What I had to do to resolve that is to note domain\appserver location that my web site was running on.  Then I had to go to SSRS configuration and add a user domain\appserver$ with the role of Browser.  At that point I was able to run and preview the reports.

I have the following notes:

1. Deployment tools (SSRS Management web site) is really lacking.  I was wishing that I could force the person to reply a few hundred reports using that.  I think the tool would be greatly improved after that :-).

2. Security is quite easy to setup.

Post to Twitter

Reporting in Silverlight

Reporting in Silverlight environment has one major problem.  Silverlight does not have a report viewer control for either SQL Server reporting services or Crystal reports.  As a result, one has to come up with a workaround that uses existing report viewer controls.  Luckily both Crystal and SSRS have report viewer controls designed for the web.  So, all we need to do is cleanly integrate these controls into a Silverlight application, using browser integration capabilities of Silverlight.  By cleanly, I mean as cleanly as possible :-).

We have two options to do this.  We can launch another browser window from Silverlight and open the report in new ASPX page or we can embed a new web page that hosts report viewer control inside the web page that hosts Silverlight application.  I will demonstrate these options in the following manner.  Launch a new web page that hosts SSRS report viewer and embed a web page that hosts Crystal reports viewer.

This post builds on top of previous post I had about SSRS implementation.

SSRS implementation

Create ASPX page for report viewer:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReportViewerForm.aspx.cs"
    Inherits="MyWeb.ReportViewerForm" %>
<!–
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">–>
<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
<html xmlns="http://www.w3.org/1999/xhtml" style="height:100%;">
<head runat="server">
    <title>Report</title>
</head>
<body>
    <form id="form1" runat="server" style="height:100%" >
    <div style="height:100%" >
        <rsweb:ReportViewer ID="MainReportViewer" runat="server" 
            AsyncRendering="false"
            ProcessingMode="Remote"
            Width="100%"
            ShowExportControls="True"
            ShowFindControls="True"
            ShowParameterPrompts="False"
            ShowPromptAreaButton="False"
            ShowRefreshButton="False"
            BackColor="White">
            <ServerReport DisplayName="MainReport" ReportServerUrl="" />
        </rsweb:ReportViewer>
    </div>
    </form>
</body>
</html>

Create a class to launch a report with the following routine:

public static void LaunchReport(string reportName)
       {
           Uri sourceUri = new Uri(HtmlPage.Document.DocumentUri, Application.Current.Host.Source.ToString().Substring(0, Application.Current.Host.Source.ToString().IndexOf("ClientBin") – 1) + "/ReportViewerForm.aspx?ReportName=" + reportName);

           if (ArePopupsAllowed())
           {
               System.Text.StringBuilder codeToRun = new System.Text.StringBuilder();
               codeToRun.Append("window.open(");
               codeToRun.Append("\"");
               codeToRun.Append(sourceUri.ToString());
               codeToRun.Append("\",");
               codeToRun.Append("\"");
               codeToRun.Append("\",");
               codeToRun.Append("\"");
               codeToRun.Append("width=1100,height=900,scrollbars=yes,menubar=no,toolbar=no,resizable=yes");
               codeToRun.Append("\");");
               try
               {
                   HtmlPage.Window.Eval(codeToRun.ToString());
               }
               catch (Exception ex)
               {
                   // do something               }
           }

           else
              //inform the user that popups need to be enabled
       }

ArePopupsAllowed function tests if popups are allowed in the browser.  Contact me if you need this code.

If you need to pass in parameters, you can easily pass them in as query parameters and parse them inside  ReportViewerForm.aspx just like the report name itself.  Here is code in Load event for this web page:

protected void Page_Load(object sender, EventArgs e)
        {
            MainReportViewer.ProcessingMode = ProcessingMode.Remote;
            MainReportViewer.ServerReport.ReportPath = "/MySSRSReports/" + this.Request.QueryString["ReportName"];
            MainReportViewer.ServerReport.ReportServerUrl = new Uri("http://localhost:8080/ReportServer_SQL2008");
            List<ReportParameter> parameters = new List<ReportParameter>();
            List<string> values = new List<string>();
            values.Add("1");
            values.Add("2");
            values.Add("3");
            ReportParameter oneParamter = new ReportParameter("ParmeterName", values.ToArray());
            parameters.Add(oneParamter);
            MainReportViewer.ServerReport.SetParameters(parameters.ToArray());
            MainReportViewer.ShowParameterPrompts = false;
            MainReportViewer.ServerReport.Refresh();
        }

In the example above I do hard code parameter values, but you get the idea.  Just add your parameters to the URL for ReprotViewerForm and have the form add them to each report.

Of course you also need to create SSRS report as well, but this is a separate subject.

Crystal Reports implementation

First thing is to create a crystal report.  You do have the usual options here to have the report get data directly from database (which is what I am using) or you can write more code to get data into a DataSet for example, using additional .NET classes and pass DataSet to the report.  We have to create a web page here as well to host report viewer.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReportView.aspx.cs" Inherits="MyApp.Web.ReportView" %>

<%@ Register assembly="CrystalDecisions.Web, Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" namespace="CrystalDecisions.Web" tagprefix="CR" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <CR:CrystalReportViewer ID="CrystalReportViewer1" runat="server"
            AutoDataBind="true" />
    </div>
    </form>
</body>
</html>

Again, you have to put some code to Load event to interpret report name and parameters as well as setup connection information

protected void Page_Load(object sender, EventArgs e)
        {
            string filter = Request.Params["param"];
            CrystalReportViewer1.Attributes.Add("Width", "100%");
            CrystalReportViewer1.Attributes.Add("Width", "100%");

            CrystalDecisions.CrystalReports.Engine.ReportDocument doc = new CrystalDecisions.CrystalReports.Engine.ReportDocument();
            doc.Load(Server.MapPath("MyReport.rpt"));
            foreach (CrystalDecisions.CrystalReports.Engine.Table item in doc.Database.Tables)
            {
                CrystalDecisions.Shared.ConnectionInfo connection = new CrystalDecisions.Shared.ConnectionInfo();
                connection.ServerName = "(local)";
                connection.UserID = "myUser";
                connection.Password = "myPassword";
                connection.DatabaseName = "MyDatabase";
                CrystalDecisions.Shared.TableLogOnInfo logInfo = new CrystalDecisions.Shared.TableLogOnInfo();
                logInfo.ConnectionInfo = connection;
                item.ApplyLogOnInfo(logInfo);
            }

            CrystalDecisions.Shared.ParameterField param = new CrystalDecisions.Shared.ParameterField();

            CrystalDecisions.Shared.ParameterDiscreteValue discreteVal = new CrystalDecisions.Shared.ParameterDiscreteValue();

            discreteVal.Value = filter;
            param.ParameterFieldName = "@Test";
            param.CurrentValues.Add(discreteVal);
            doc.SetParameterValue(param.ParameterFieldName, param.CurrentValues);

            this.CrystalReportViewer1.ReportSource = doc;
        }

So far pretty easy.  How the Silverlight part.  In this case we do not want to have a popup, but instead have our page appear to be a part of Silverlight application.  Let’s see what web page looks like that hosts Silverlight application.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="MyApp.Web._Default" %>

<%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls"
    TagPrefix="asp" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%;">
<head id="Head1" runat="server">
    <title>Report</title>
</head>
<body style="height: 100%; margin: 0;">
    <form id="form2" runat="server" style="height: 100%;">
    <asp:ScriptManager ID="ScriptManager2" runat="server">
    </asp:ScriptManager>
    <div style="height: 100%;">
        <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/MySilverlightApp.xap" MinimumVersion="2.0.30523"
            Width="100%" Height="80%" Windowless="true"/>
    </div>
    <iframe id="reportFrame" style="position:absolute; width:0px; height:0px; visibility:hidden"></iframe>
    </form>
</body>

</html>

As you can see, we are using frames in this case to show the report.  Now, the Silverlight code to launch a report:

private void ShowReportButton()        {
            HtmlElement m = HtmlPage.Document.GetElementById("reportFrame");
            if (m != null)
            {
                int top, left, width, height;
                top = (int)this.outerGrid.RowDefinitions[0].ActualHeight;
                left = (int)(this.outerGrid.ColumnDefinitions[0].ActualWidth + this.outerGrid.ColumnDefinitions[1].ActualWidth);
                width = (int)this.outerGrid.ActualWidth – left;
                height = (int)this.outerGrid.ActualHeight – top;
                m.SetStyleAttribute("left", left.ToString());
                m.SetStyleAttribute("top", top.ToString());
                m.SetStyleAttribute("width", width.ToString());
                m.SetStyleAttribute("height", height.ToString());
                m.SetAttribute("src", "ReportView.aspx?param=P");
                m.SetStyleAttribute("visibility", "visible");
            }
        }

In the code about outerGrid is the control that hosts main Silverlight application.  So, since our Silverlight application is located at position (0,0) in the web page (top left corner), we can compute the coordinates and size of report frame by using actual height and width of our Silverlight controls.  Once that is done, we can control the location of the frame and its size to make it appear as part of Silverlight application.  You would also need to listen to resize events of the browser in order to control the size of the report window.

This is my attempt to write a comprehensive guide to Silverlight reporting.

Post to Twitter