Thursday, March 15, 2007

BIRT: Hide Report Table When No Data is Returned

Recently, a question came up on the BIRT newsgroup about hiding a table in a BIRT report when no data is returned. This is actually a very simple task to accomplish using the Hide Element expression in the property editor for BIRT.

In the following demonstration, I will use a scripted data source that will return data only if the user has a report parameter set to true. When no data is returned from the dataset, the Hide expression in the table will hide the table, and in a Label element, it will tell the user that no data was returned from the data set.

So I create a BIRT report called hideTable.rptdesign. In this report, the first thing I do is create a report parameter called rprmHideTable. I like to prefix my report parameters with rprm, which stands for Report Parameter, which differentiates report parameters from data set parameters. I set the data type to Boolean, the display type to Check Box, and set the default value to true.

Figure 1. Report Parameter rprmHideTable

Next, I create a new data source. I select scripted data source as my type, and name it dsrcScripted. Then I create a new data set called dsetScripted that is based off of dsrcScripted. It will have 1 column, which I will label as A, with a type of any. Now I need to put in my generic script to handle the generation of data. I open up the script tab in the report designer, select dsetScripted, and choose the Open event. I use the following code in the Open event to initialize my generic counter.

x = 0;

Now I go into the Fetch event. This is where I am going to generate my data returned from the data set. I use the following code to generate my data, which will be controlled by my report parameter.

if (params["rprmHideTable"] == true)
{
if (x < 4)
{
row["A"] = x;
x++;

return true;
}
}

return false;

Now, I can drag over my new data set into my report designer and do a test run to see the issue that was brought up. Sure enough, when I run the report with my parameter set to false, the header row of the table is still shown, even though no data is there. That’s obviously not what we want. Well, fixing this is easy enough.


Figure 2
. The report with parameter set to true

Figure 3. The report with parameter set to false. Oh no, that’s not what we want

To fix this, all we need to do is select the Table using either the report designer pane or using the outline, and under the Property Editor, under the Properties tab, choose visibility. Then we will check the Hide Element checkbox, and in the expression editor, use the following expression.

(Total.count() <>

What this will do is set the hide element value expression to true when the total number of detail rows in the table is less than 1, basically 0. And that’s all there is to hiding the table when no data is returned.

Figure 4. Hide the table expression

So then, how do we go about displaying a label letting the user no that no data was returned. This too is an easy enough task to accomplish, and works in a similar manner to hiding the table, but in reverse.

I am actually going to use a bit of scripting to do this, but there are a number of different ways this same task can be accomplished. First, I will switch over to the script editor, and in the outline I am going to choose the root report. In the Initialize event, I will use the following code to initialize a global variable called rowsReturned.

rowsReturned = 0;

Then I will go back into the Visibility expression for my table, and change the Expression to the following:

rowsReturned = Total.count();

(Total.count() <>

Now, I will drag over a label just below my table in the report designer. I will type in the message “No data was returned”. Then, in the Property Editor, I will select the Visibility property for this item. I will set the Hide checkbox to true, and I will use the following expression:

(rowsReturned > 0)

Now, when I preview the report, I see the table with data when data is returned, and the message “No data returned” when the data set returns nothing.

Figure 5. No Data Returned

This same principle can be applied to a number of different visual elements in BIRT. For example, lets say you wanted to hide a column based on some report parameter or environmental variable, you can. You can create a report parameter asking the user if they want to display the footer row in a table to avoid having to see aggregate numbers, and all sorts of different options to show or hide different aspects of a report. This allows a more savvy developer to think about things like row level and element security. So imagine being able to write one large report, and then, based on some value retrieved from an applications HTTPSession object such as user credentials, showing and hiding various elements of a report. This allows you to create one large report, and filter out elements based on security settings. It really allows you to get flexible with the possibilities of BIRT in an application.

7 comments:

Anonymous said...

A very well written article, was of great help.

Bahata said...

A very well written article, was of great help.

Cathy said...

Good one...

John Ward said...

We can even do this an easier way if we wanted... we can set the visibility expression of the table to Total.count() == 0, and skip the global variable. Always a few ways to do things in BIRT :)

John

Tim said...

Good Job! :)

Mike said...

Good Article was of real help. Thanks :)

seen said...

John, Great article thanks.
However It works in my Birt-developer but when I port the design to the server it's not working, the "No data" label sticks around all the time...(I am using BIRT 2.5)
Any help is appreciated.

Thanks,
mp