Two Variables You Should Have In Every Report Studio Report

There is an old joke that tells us that hard work pays in the long run, but that laziness pays off right now. However, in the world of software development, I think that laziness done right can pay off in the long run even better than hard work. Now there are a lot of developers who would prefer to skip the task of documenting a report they’ve developed. Sure it’s lazy, but that’s short term lazy.

I prefer long-term lazy, where I document the report now so that when I go to edit it a year later, I don’t have to spend an hour re-learning all the details of the report design. The first variable I want to talk about allows report documentation right in the report.

ShowDocumentation

Few reports are so simple that new Cognos developers can understand them intuitively. In fact, I suspect that most of your reports take even experienced developers a little time to understand. Sadly, Cognos does not give us a place to document the report, however they do give us the tools necessary to easily create one ourselves.

Report documentation can come in many forms. Maybe you have a large list of items that need to be completed (developer name, date, time, parameters, query descriptions, ,modifications, etc.), or perhaps you just have a bit of information on the design that you really need to remind yourself or another developer, the next time the report is being modified. Either way, you can put this information right in the report and use variable ShowDocumentation to hide it from the report consumers.

Create ShowDocumentation as a string variable with the expression of “0” (zero), and set the values allowed to be either 0 or 1 (I never use boolean variables, but that’s a topic for another time).

Then add text items to your report and set the render variable so that it’s only rendered if ShowDocumentation is “1” (which it never is). If you’re just trying to call out something, you can put the text item right in the report where it will be seen by every developer. You could even color it red, or make it bold, or give it a yellow background (or all of these) if you really need to get their attention. If the text is long, put it in a block with a fixed width (say 800px) and set the render variable on it. Then, any text you put inside will be word-wrapped for the developer, but still hidden to the report consumer.

If you have a lot of documentation , then you could create a report page called “Documentation“with ShowDocumentation of “1” as the render variable. Within that report page you could use tables and blocks to create a form you could fill out. Use small text variables with the render variable, placed in the actual report page (not the Documentation report page) to serve as call-outs that you could then reference in the Documentation page.

Debug

Often, while we are in the process of developing or testing a report we need information that the report consumer should not see. Perhaps it’s some information on the layout, or just numbers that are used in a calculation. To do this the lazy way, you want to be able to add this information to the report once, and be able to turn it on and off at will. That’s where variable Debug comes in.

As with ShowDocumentation, create a text variable called Debug with a hard-coded value of “0” (zero) and possible values of 0 or 1. You can then use Debug either as a render variable or a style variable to hide the items you only want the developer to see.

Then, all you need to do is change the Debug variable’s value to “1” when you are testing so that the items are visible, and then change it back to 0 when you’re ready to put the report back into production.

Here are some examples:

  • In a list, you can add columns used in a calculation for validation. Use the ancestor button to navigate to the column’s List Column object and set the render variable there.
  • If you are having trouble with layout, you can use the style variable to turn on an object’s border when in “debug mode”. I like to use the color fuchsia because it really stands out. Besides, how often do you see fuchsia in a report?
  • Debugging a chart? Add a list using the same data source as the chart with the render variable set to Debug = 1.

Okay, you should only have to use one of these in every report (ShowDocumentation), but I find myself using Debug in a large percentage of the reports I develop.
Have you used something similar? If so, let me know.

Advertisements

Creating JavaScript Functions in Active Reports

For those of us who love to (of just need to) expand Cognos beyond it’s built-in capabilities, one of the fundamental tools we use is the JavaScript function.  We use JavaScript to perform all kinds of reporting sorcery, and we create functions for those things that we call over and over again.For years this worked well.  Even after major releases, most of our functions continued to work with little or no modifications.

Then, one day IBM came out with Active Reports.  We were awed by it’s ability to make reports portable, and the fact that data was embedded into the reports also meant that the reports were super-fast when users changed filters or parameters.  But all of this came with a cost.  We lost the ability to create JavaScript functions and the <script> tags that should execute as soon as the report opened no longer functioned. We were still able to execute in-line JavaScript, but this had significant limitations.

Recently, I was reading a comment in LinkedIn by Paul Mendelson (aka CognosPaul) where he talked about creating a function when a user clicked a button.  Within the inline JavaScript, it checked to see if the function existed.  If it didn’t exist, it created it, otherwise it went on with the rest of the actions that the button-click demanded.  This did not satisfy my immediate requirement because I needed something to happen the moment the screen opened up, but it set me in the right direction.

How To Create Functions and Run JavaScript When the Report Opens

The key to this technique is the <img> tag which is one of the few to include an onLoad event.  This event fires as soon as the image is displayed.

Add an HTML item anywhere on the report, just make sure it’s somewhere that will always be rendered (on the page, but not inside any decks). Give the HTML item the following text:

<img src="hal/imagesirot/progress.gif" width="1" height="1" onload="
     while( ! alert) {} 
     /* Define the function */ 
     if (!document.testFunction ) { 
          testFunction = function() { 
               alert('We are running the test function'); 
          } 
     } 
     /* Run any startup actions */ 
     testFunction(); 
"/>

The first line of the onload event is sure to raise hairs on the back of your head. “while( ! alert) {}” will endlessly loop until it detects the existence of the “alert” function.  This is necessary because in Active Reports, the image will load (and the onload event of the image will fire) before the document has completed loading.  JavaScript developers usually avoid this type of loop because JavaScipt runs synchronously, so the browser locks up until the loop is satisfied.  In my testing, this loop has never caused a problem, however, if someone can suggest a better alternative, I’m certainly open to trying it.

The image is hidden (style=”display:none;”), so it won’t affect your layout. I chose to use the progress.gif image because it’s always loaded.  You can use your own image, however I would not recommend a 1×1 transparent gif.  I tested this and it worked fine on Windows (IE, Firefox and Chrome), but did not work correctly on Cognos Mobile (iPad or Android).  If you do use your own image, it must also be somewhere in the report using a standard Cognos Image element from the toolbox, so that the image is properly registered.  Otherwise the image will only work while you are online.

The first thing you should do following the “while” loop is to define any functions you need.  In the example above I’ve demonstrated the “testFunction”.After that you can run any JavaScript that needs to run when the report first opens.Coming soon… getElementById in Active Reports.

Revisions
2014-09-17 – Added details about the images that can be used and the placement of the HTML Item.

A List Prompt From an Actual List

A colleague recently used this technique on my current project, so I want to make sure that credit was given where credit is due.

From Paul’s Cognos Blog: Checkbox List Prompt

Changing a Value Prompt in Report Studio using JavaScript

There have been many occasions where I have needed to change the filters on a report by having the user click on data on the report.  For example if I had a listing of cars, class, and number sold, and the user clicked on “Sedan” under the Class column, I would want to filter the report to only show sedans.

In Cognos 8 Report Studio, I accomplished this by having  a drill-through on the Class column back to the same report, passing the data item into the Class prompt.  This was an imperfect solution for a number of reasons, but it was usually good enough.  However, Cognos 10’s introduction of Business Insight  made this technique a bit less than “good enough”.  If I were to add the report to a Business Insight workspace, clicking on “Sedan” would not update the report I was looking at.  Instead, it would open a new copy of the report in a new window.

So the drill-through technique is no longer an option. My new technique for accomplishing this is to use Javascript to change the prompt. The following technique works with Cognos 10.1.1 Report Studio and I believe it’ll work with Cognos 8 as well. However, remember that with any JavaScript used in Cognos, an update to another version of Cognos (even a minor one) could break it.

Set Up the Prompt

This technique requires that you add the prompt to your report page (regardless of whether or not you have a copy of the prompt on a  prompt page).  I like to put these near the top of the report so the user can immediately see what filters are being applied.  However, you can put it anywhere on the report page that you want. 

  1. Add the prompt to the report page
  2. Before the prompt, add an HTML item with the following HTML code:
    <div id=”VP_TestPrompt”>

    Give the div tag an appropriate ID.  If you have more than one prompt, give each one a unique name.

  3. After the prompt, add an HTML item to close the div tag:
    </div>
  4. After the closing div tag, add a third HTML item with the following function:
    <script type=”text/javascript”>
    function selectPromptByValue(divId, val) {
       var oVPCont = document.getElementById(divId);
       var oVP = oVPCont.getElementsByTagName(“select”);
       var i = oVP[0].options.length;
          while (i) {
          if (oVP[0].options[–i].value==val) {
             oVP[0].options[i].selected=1;
             promptAction(‘finish’);
             i=0;
          }
       }
    }
    </script>

    If you have multiple prompts, you will only need this HTML item once on the report page.  The first parameter tells it which prompt to reference.

Set Up the Link

Now you just need to call the function selectPromptByValue, passing in the name of the div tag (set in step 2 above) and the value you want to pass into the value prompt.
Ther are a couple of ways to do this.  For most reports you could use a hyperlink to call the function (ex: javascript:selectPromptByValue(“VP_TestPrompt”, “A”);).  However, this does not work when running the report from a Business Insight workspace because BI incorrectly assumes that the hyperlink (anchor tag) will be taking you to another web page.  This results in a warning about navigating away from the page.

Instead I use a simple text object and wrap it in another div tag with an onclick event.

  1. Add your text.  To make it look more like a hyperlink, you may wish to underline it and set the color to blue.
  2. Add an HTML item before the text:
     <div style=”cursor:pointer”; onclick=’javascript:selectPromptByValue(“VP_TestPrompt”, “A”);’>

    The first parameter should be the id of the div tag you set before the prompt.  The second parameter is the value in the prompt that you want to select.
    If the link is to be data driven (ex: in a list), then you will need to make the ULR Source Type a report expression and parse it together so that it looks like the above example.

  3. Add an HTML item after the text to close the div tag:
     </div>

Example Report

To see how this technique works, copy the text from this Word document into your clipboard, open Report Studio, and select Open Report from Clipboard.