2007/04/18

Partial multi-column reports in Reporting Services

Scenario. You need to create a multicolumn report in reporting services, but unfortunately, you just need the multicolumn behaviour in the details part of the report, not also on the master.

Suppose you have an invoice (master: invoice number, customer, total sum, etc, details: every item being invoiced), or any other type of report that has a master/details structure and you just need the multi column behaviour in the details part of it.

Problem. As stated in Writing Multi-Column Reports:

A multi-column layout applies to the entire report. It is not possible to specify a multi-column layout on the top half of the report, and a tabular layout on the bottom half of the report.

It seems you really have a problem... Microsoft says that it is impossible to do what you need to. Fortunately there is a...

Workaround. The idea behind this workaround is letting RS believe that the report is just a tabular report as usual. In fact, all you need to do is pure T-SQL behind the scenes, the final report just have one column, but will seem to have 2 columns (or any) where you need to. Let's see it with an example. Suppose you have your data:

Invoice Customer Item Description  Qty  Price    Sum
 394483 JOHN DOE    1 FRENCH FRIES  1    3.00  17.00
 394483 JOHN DOE    2 BISCUITS      1    4.00  17.00
 394483 JOHN DOE    3 BEERx6        1    5.00  17.00
 394483 JOHN DOE    4 MILK          2    2.00  17.00
 394483 JOHN DOE    5 HAM           1    1.00  17.00
And you want to make your invoice with the details (Item, Description, Qty and Price) displayed in two columns. We need to transform the data into something like:
Invoice Customer Item Description  Qty  Price    Sum Item2 Description2 Qty2 Price
 394483 JOHN DOE    1 FRENCH FRIES  1    3.00  17.00     2 BISCUITS      1    4.00
 394483 JOHN DOE    3 BEERx6        1    5.00  17.00     4 MILK          2    2.00
 394483 JOHN DOE    5 HAM           1    1.00  17.00  NULL NULL         NULL  NULL
Do yo see the point? You need to create new fields (ended with 2 suffix) that will store the next row of the needed data, and return half the rows (plus one if the count is not pair). Having transformed your underlying data in such a way, you can create your report as usual, placing a table where you need to and doubling (in case you want 2 columns) the number of columns:
Item Description  Qty  Price         Item2 Description2  Qty2  Price2

How can we do such a transormation using T-SQL?

Let's suppose you have prepared a stored procedure for retrieving the underlying data for RS to use. If you have not, you will need to because we will be doing a couple of transformations, not just a simple select query, so you cannot embed the query into the report itself. You will need to use a stored procedure for it, let's call it RS_MyCustomReport.

You might have RS_MyCustomReport defined as something like:

USE [mydatabase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[RS_MyCustomReport](@Filter1 int = NULL, @Filter2 varchar(8)=NULL)
AS
  SELECT {your list of fields}
  FROM {your tables or views}
  WHERE ({FieldX} = @Filter1 OR @Filter1 IS NULL) AND
        ({FieldY} = @Filter2 OR @Filter2 IS NULL)

Where FieldX and FieldY are the fields to use to filter using the optional parameters @Filter1 and @Filter2. All you need to do is the following (the changes are highlighted):

USE [mydatabase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[RS_MyCustomReport](@Filter1 int = NULL, @Filter2 varchar(8)=NULL)
AS
  SELECT IDENTITY(int,1,1) AS ID, AUX1.*
  INTO #TEMP
  FROM (
    SELECT {your list of fields}
    FROM {your tables or views}
    WHERE ({FieldX} = @Filter1 OR @Filter1 IS NULL) AND
          ({FieldY} = @Filter2 OR @Filter2 IS NULL)
  ) AUX1

  SELECT * FROM
   ( SELECT T1.*, T2.{FieldA} AS FieldA2, T2.{FieldB} AS FieldB2 {...}
     FROM #TEMP T1 LEFT OUTER JOIN #TEMP T2 ON (T1.ID+1 = T2.ID OR T2.ID IS NULL)
   ) AUX
  WHERE AUX.ID % 2 = 1
  ORDER BY AUX.ID

You can replace the number of joins and the % 2 operator if you need to create multi column reports of 3 or more columns. A whole running script that you can test follows:

SELECT IDENTITY(int,1,1) AS ID, AUX1.*
INTO #TEMP
FROM (SELECT 13 AS Col, 'one' AS Descr UNION
      SELECT 18, 'two' UNION
      SELECT 35, 'three' UNION
      SELECT 51, 'four' UNION
      SELECT 67, 'five') AS AUX1

SELECT * FROM #TEMP

SELECT * FROM (
  SELECT T1.*, T2.Col AS Col2, T2.Descr AS Descr2
  FROM #TEMP T1 LEFT OUTER JOIN #TEMP T2 ON (T1.ID+1 = T2.ID or T2.ID IS NULL)
) AUX WHERE AUX.ID % 2 = 1
ORDER BY AUX.ID

DROP TABLE #TEMP

2007/04/04

How to: Enable Remote Errors (Reporting Services Configuration)

Simple, but it took me a while to find it when I needed it. So here it is: How to: Enable Remote Errors (Reporting Services Configuration)
You can edit the ConfigurationInfo table in the report server database to set EnableRemoteError to True, but if the report server is actively used, you should use script to modify the settings.

2007/03/22

Error 0x8007007f: A problem is preventing Windows from accurately checking the license for this computer

SYMPTOMS After you install SP2 for Windows Server 2003 x64 you get the following error message when you try to login using local console or RDP:
A problem is preventing Windows from accurately checking the license for this computer: Error Code 0x8007007f
Un problema impide que Windows compruebe con precisión el estado de la licencia para este equipo. Código de error: 0x8007007f

RESOLUTION Some days after having approved SP2 for Windows Server 2003 x64 in WSUS and having it installed on several servers without any problem, I tried to log in using RDP on another one of them and noticed the former error message. Then I went to the local console and see a bunch of error messages on screen (without having anyone logged on) such as "not enough virtual memory...", "application xxxx will now terminate", and so on, poping up in front of the usual "press ctrl+alt+del to log in" dialog. So I needed to accept all those error messages before being able to actually log in the server from the console.

After having read and accepted 5 or 6 of them, I started to just press Ok without even read the messages... Finally I was able to press ctrl+alt+del and try to log in... and the same error regarding code 0x8007007f appeared, logging me off automatically (logging in process did not even finish).

So I went back to my XP client and used the Event Viewer to remotely connect to the server experiencing the problem and see the System event log. Quite near the top of the list of events I found:

Event Type: Information
Event Source: NtServicePack
Event Category: None
Event ID: 4371
Date:  21/03/2007
Time:  15:21:52
User:  NT AUTHORITY\SYSTEM
Computer: SERVERNAME
Description:
Windows Server 2003 Service Pack 2 was installed (Service Pack 1 was previously installed).
Event Type: Information
Event Source: Windows Update Agent
Event Category: Installation 
Event ID: 19
Date:  21/03/2007
Time:  15:21:59
User:  Not available
Computer: SERVERNAME
Description:
Installation Successful: Windows successfully installed the following update: Windows Server 2003 Service Pack 2 for x64 Editions
Event Type: Information
Event Source: Windows Update Agent
Event Category: Installation 
Event ID: 22
Date:  21/03/2007
Time:  15:21:59
User:  Not available
Computer: SERVERNAME
Description:
Restart Required: To complete the installation of the following updates, the computer will be restarted within 5 minutes: 
- Windows Server 2003 Service Pack 2 for x64 Editions

But no trace of the expected reboot was found at on the rest of the System event log. So I just used shutdown -i to interactively shutdown the server and restart it again. That solved the problem completely.

SCENARIO

  • Dell PowerEdge 2950 (Dual Xeon, 4Gb RAM)
  • Windows Server 2003 Standard x64 R2 + SP1
  • SQL Server 2005 Standard Edition
  • WSUS is used to deploy updates to computers in the domain
  • Windows Server 2003 Service Pack 2 (SP2) for x64 Editions is released and aproved in WSUS for automatic install

KEYWORDS Windows 2003 Server, R2, x64, 64 bits, SP2, Service Pack 2, WSUS, 0x8007007f, licence, problem, error, prevent, accurately, check, license

2007-03-27 UPDATE Only 5 days have passed since the original date of this post and I have noticed a big amount of traffic (compared to my historic) directed by Google regarding this Error 0x8007007f. It seems it is a relative common problem but I would like to have some feedback about it: If your problem is fixed only with a reboot, I would like to hear about it; if it does not, I would like you to drop some lines too; if you solved your problem in any other way, it would be interesting for everybody to know. Thanks.

2007-04-07 UPDATE Due to the limited feedback I have received, I am investigating this issue on myself (even though my servers do not show this error anymore). It seems there is a workaround for this error, in Microsoft's Knowledge Base 914232: You may receive error code 0x80004005 or other error codes when you try to start a Windows XP-based computer:

Error code 0x8007007f or error code 0x8007007e
This problem frequently occurs after you upgrade a service pack. After you upgrade, there appears to be a corrupted file, a missing file, or a file mismatch.
[...]
Workaround for error code 0x8007007f or error code 0x8007007e
To work around this problem, uninstall the service pack that you installed. Then, reinstall the service pack.

This does not seem to be in contradiction with what happened to me: If the server, for whatever the reason, did not reboot, it seems feasible that this error 0x8007007f appears because of a file mismatch (since the reboot did not occur the files that were in use were not replaced).

Before you uninstall and reinstall SP2, I would check if the reboot did take place and, if not, doing a remote reboot of the server might solve the problem.

2007/03/01