Passing parameters without refreshing the page

Recently a reader had an interesting problem. Her client needed a prompt page from which they could open different reports. As it stands now, the client needed to select their prompts, hit the finish button, and then click on the links. She wanted a way to skip the second step – select the prompts, and have those values pass in the drill through.

With the prompt API, and a bit of JS, this is incredibly easy.

The first step is to identify the target report. You can get the report search path through the properties. Click on the “View the search path, ID and URL Location” link, and a window will pop up with the path and other details.
1. Get search path

Notice the double quotes? That can potentially cause trouble with the JavaScript, so I recommend using a URL Encoder: /content/folder[@name=’JavaScript Examples’]/folder[@name=’Drill Target’]/report[@name=’Target’] becomes %2Fcontent%2Ffolder%5B%40name%3D%27JavaScript%20Examples%27%5D%2Ffolder%5B%40name%3D%27Drill%20Target%27%5D%2Freport%5B%40name%3D%27Target%27%5D

The example I’m posting will be using the URL Encoded version.

The next step will be the JavaScript:

<script>

  var paulScripts = {}
    , oCR = cognos.Report.getReport("_THIS_")
    , gateway = window['oCV_THIS_'].getRV().getCV().sGateway
    , report1 = decodeURIComponent("%2Fcontent%2Ffolder%5B%40name%3D%27JavaScript%20Examples%27%5D%2Ffolder%5B%40name%3D%27Drill%20Target%27%5D%2Freport%5B%40name%3D%27Target%27%5D%0A%0A");
 

  /* function paulScripts.URLEncode - Paul Mendelson = 2013-10-21
   * Based on the JSONEncode function, this will return the use/display values of
   * a prompt in a format that can be based via POST or GET.
   * usage: 'p_Parameter1='+paulScripts.URLEncode(paulScripts.getControl('MyPrompt'))
   */
  paulScripts.URLEncode = function(promptControl){
    var urlData = '<selectChoices>'
      , aPromptValues = promptControl.getValues()
      , nonRange = []
      , range =[];

    if (aPromptValues.length == 0) {return false}
   
    for (var j=0; j< aPromptValues.length; j++) {
      var promptValue =  aPromptValues[j];
     
      if (promptValue.use) {// Non Range value
        nonRange.push("<selectOption useValue='"+promptValue.use + "' displayValue='"+ promptValue.display + "'/>");
        }
      else { // Range value   
        var rangeStart = promptValue.start
          , rangeEnd = promptValue.end
          , start, end, startDisp, endDisp;
        if (rangeStart && rangeEnd) { //has both Start and End (bounded)
          rangeStart.display?startDisp = " displayValue='"+ rangeStart.display+"'":"";
          rangeEnd.display?endDisp = " displayValue='"+ rangeEnd.display+"'":"";
          range.push("<selectBoundRange><start useValue='"+rangeStart.use +"'" + startDisp +"/><end useValue='"+rangeEnd.use +"'" + endDisp +"/></selectBoundRange>")
        }
        else if (rangeStart && !rangeEnd) {//unboundedEndRange
          rangeStart.display?startDisp = " displayValue='"+ rangeStart.display+"'":"";
          range.push("<selectUnboundedEndRange><start useValue='"+rangeStart.use +"'" + startDisp +"/></selectUnboundedEndRange>");
        }
        else if (!rangeStart && rangeEnd) {
          rangeEnd.display?endDisp = " displayValue='"+ rangeEnd.display+"'":"";
          range.push("<selectUnboundedStartRange><end useValue='"+rangeEnd.use +"'" + endDisp +"/></selectUnboundedStartRange>");
        }
        else {
          alert ("Range not set.");
        } // end if
      } // end if
    } // end for
    if(nonRange.length>0) urlData += nonRange.join();
    if(range.length>0) urlData += range.join();
    urlData+='</selectChoices>';
    return urlData.replace(/&/g,'&amp;');
  }

  /* function paulScripts.getPrompts
   * Paul Mendelson - 2013-10-21
   * Retrieves all the prompts on the page and returns the parameter values
   */
  paulScripts.getPrompts = function(){
  //find all of the controls and stick them in aPromptControls.
    var aPromptControls = oCR.prompt.getControls( ),
    prompts = [];

  //loop through the controls - finding the name and values and sticking them into the names array
    for(i=0;i<aPromptControls.length;i++)
    {
      if(aPromptControls[i].getValues().length == 0) continue;
      prompts.push(aPromptControls[i].getParameterName());
      prompts.push(paulScripts.URLEncode (aPromptControls[i]));
    }
   
  return  prompts;
  }

paulScripts.runReport = function(reportName,reportPath,gateway, prompts){
  var basicInfo = [
          reportName, "toolbar=no,height=200,width=400"
        , 'ui.gateway' , gateway
        , 'ui.tool' , 'CognosViewer'
        , 'ui.action' , 'run'
        , 'ui.object' , reportPath
        , "run.prompt" ,"false"
        , "cv.toolbar" ,"false"
        , "cv.header" ,"false"
        , "run.prompt", "false"
    ];

    basicInfo=basicInfo.concat(prompts);
  return cognosLaunchInWindow.apply(this,basicInfo);
  }



</script>
 

Let’s go through the functions.

var paulScripts = {}
, oCR = cognos.Report.getReport(“_THIS_”)
, gateway = window[‘oCV_THIS_’].getRV().getCV().sGateway
, report1 = decodeURIComponent(“%2Fcontent%2Ffolder%5B%40name%3D%27JavaScript%20Examples%27%5D%2Ffolder%5B%40name%3D%27Drill%20Target%27%5D%2Freport%5B%40name%3D%27Target%27%5D%0A%0A”);

We’re defining the variables on the page. Notice that I’m hardcoding the report search path into a variable here. There’s actually no reason to do that, we could put it directly into the function, or put it into another prompt, or even insert it into a table and build a list with each row calling another report.

The gateway variable is pulling the gateway from the report you’re running. Another gateway could be entered here, if needed.

The paulScripts.URLEncode will take a prompt control, process the selected values, and spit out a string that Cognos can use to populate parameters.

paulScripts.getPrompts will look for every prompt on the page, and create an array of the parameter names and the selected strings. This makes updating the report simple – you won’t need to modify and JavaScript when adding or removing prompts.

paulScripts.runReport is the last function. It uses the cognosLaunchInWindow function to run a report in the specified window, using the specified search path, on the specified gateway, with the results of the paulScripts.getPrompts function.

To use it, all you need to do is creating an onclick event like this:

<input type="button" onclick="paulScripts.runReport('_blank',report1,gateway, paulScripts.getPrompts())" value="Run Report 1"/>

And finally, we can test it:
passingPrompts

This report was built on 10.2.1, but should work on all versions 10.2 and up.
Passing Parameters Without Refresh (4818 downloads)

Export all report XMLs to file system – Updated

2 years ago, I posted a method for exporting all of the reports to the file system, using the same folder path. I was never happy with that method, as it required adding a UDF to the content store, and large reports would fail. Since getting these reports was a requirement at one of my clients, I finally had the time to tweak it.

Unlike the previous version, I don’t have access to Oracle, so this is on SQL server. The connection string to the server is handled from inside the script (row 151), all you need to do is change the data source and catalog details to connect.

The reports will be saved under c:\temp\reports. You may want to change that as well (row 244), but don’t forget that windows has an absolute limit in the number of characters in a file path.

Unlike the old version, this will also pull reports from users’ My Folders, including orphaned reports from deleted users. The user reports will be saved under \users\<user name>\my folders\. This will also generate a log file including the sql query sent to the db, and all of the reports generated.

Due to security concerns, the file has been renamed to getreports.vbs.txt. Simply rename that to getreports.vbs to enable it.

I tested this on Cognos 10.2, on SQL Server 2005. If anyone has access to Oracle and wants to adapt the SQL, I’ll  gladly amend the post to include it.

 

getreports.vbs (1612 downloads)

Quick and painless way of accessing users’ folders

As part of my administrative duties for my various clients, I periodically trawl through the logs. Many times I’ll want to see exactly what the users are doing in the reports on my server. It becomes a headache when these reports are in the users’ “My Folders”. I need to go into the administration page, find the user, go into their “My Folders”, copy out the report, paste it into mine then run it. It’s a mess and I’m far too lazy for that.

Fortunately Cognos allows us to access objects through URL parameters. On my laptop, I’m using OpenDJ as my authentication provider, so the CAMID is slightly different than Active Directory. My CAMID here is CAMID(“OpenDJ:u:cn=administrator”). In AD, it might be CAMID(“AD:u:r7a1n7d8o8m3l1e4t9t2e2r4s01234567)

My user

I can just copy that CAMID and paste it into the URL as:
http://server/cognos/cgi-bin/cognosisapi.dll?b_action=xts.run&m=portal/cc.xts&m_path=CAMID(“OpenDJ:u:cn=administrator”)

2. Accessing my user

Obviously this is still predicated on the security in place. A user who doesn’t have permission to access another user’s folder will get an “Access Denied”

3. Thwarted again

UPDATE!
In the comments below, Ryan shared that a users’ folders can be accessed directly with the username:
http://server/cognos/cgi-bin/cognosisapi.dll?b_action=xts.run&m=portal/cc.xts&m_path=//account[@userName=’john.doe’]/folder[@name=’My Folders’]