Article
· Jun 2, 2023 5m read

InterSystems Reports Migration - Generate Report to Stream

We are looking at what we need to do to migrate from our current usage of Zen reports to InterSystems Reports. One of the hurdles for us is figuring out ways to interact with InterSystems reports programmatically from ObjectScript routines. There is a Java API for it, but it is possible to generate a report from InterSystems reports to a stream object in ObjectScript without diving into Java by using a %Net.HttpRequest. Here is a code example, followed by an explanation:

#include %cspInclude
GetStream(catalog="",report="",type="2",paramnames,paramvalues,str) public{
     try{
        set namelist = $LFS(paramnames)
        set valuelist = $LFS(paramvalues)
        if $LL(valuelist) '= $LL(namelist){
            $$$ThrowStatus($$$ERROR(5001,"Mismatched parameter name and value list sizes."))
        }
        if report = ""{
            $$$ThrowStatus($$$ERROR(5001,"No report name provided"))
        }
        if catalog = ""{
            $$$ThrowStatus($$$ERROR(5001,"No catalog name provided"))
        }
        set myreq = ##class(%Net.HttpRequest).%New()
        set myreq.Server = "127.0.0.1"
        set myreq.Port = "8888"
        set myreq.Location = "jinfonet/tryView.jsp"
        set myreq.Username = "MyUserName"
        set myreq.Password = "MyPassword"
        do myreq.SetParam("jrs.report",$$$URLENCODE(report))
        do myreq.SetParam("jrs.catalog",$$$URLENCODE(catalog))
        do myreq.SetParam("jrs.result_type",type)
        for i=1:1:$LL(namelist){
            do myreq.SetParam($$$URLENCODE("jrs.param$"_$LG(namelist,i)),$$$URLENCODE($LG(valuelist,1)))
        }
        set sc = myreq.Get()
        if $$$ISERR(sc) {$$$ThrowStatus(sc)}
        set response = myreq.HttpResponse.Data
        if $ISOBJECT(response){
            set sc = response.Rewind()
            if $$$ISERR(sc) {$$$ThrowStatus(sc)}
            while 'response.AtEnd{
                set sc = str.Write(response.Read())
                if $$$ISERR(sc) {$$$ThrowStatus(sc)}
            }
        }
        else{
            set sc = str.Write(response)
            if $$$ISERR(sc) {$$$ThrowStatus(sc)}
        }
    }
    catch ex{
        do ex.Log()
        return ex.AsStatus()
    }
    return $$$OK
}

This routine takes the following arguments:

catalog - The catalog name in InterSystems reports, including directory (i.e. /MyCatalog/Catalog.cat)

report - The report name in InterSystems reports, including directory (i.e. /MyCatalog/MyReport.cls)

type - The file type to create. I have set 2 as the default because that's the type for PDF, which is what we typically use. 1 is HTML, 2 is PDF, 3 is TEXT, 4 is Excel, 5 is PostScript, 6 is RTF, and 7 is XML.

paramnames - If the report has parameters, this is a comma-separated list of report parameters

paramvalues - The values to use for those parameters, in the same order as the names.

str - A %Stream.Object (or any class that inherits from it) which should be passed by reference. This is the stream that will eventually hold the report.

I have some initial checking at the top for a few things that will cause a problem. The type has to be 1-7, so I throw an error if it's not. (Side Note: I apologize for my overuse of the throw/catch error checking; it's a construct I'm used to from other languages!) The lists of parameter names and values should be the same size. There must be a catalog and a report provided.

The server and port for the request must be the domain/IP and port of your InterSystems report server. This assumes it's running on the same server as your IRIS instance at its default port. If not, adjust accordingly. The location is /jinfonet/tryView.jsp. This is a web page on the report server that uses accepts a GET request. It's also a handy one to redirect a browser to if you want to link to a report. If the user is not authenticated, it redirects to a login prompt. If the report has parameters and they are not provided, it will then prompt for parameters. I'm going to set some parameters on the request to handle all of that so we can get straight to the report. That's why we're setting the Username and Password properties on the HttpRequest object; they must be a valid username and password for your InterSystems Reports server.

The tryView.jsp can accept quite a few parameters. They are fully documented by Logi here, but for purposes of this example, I'm keeping it pretty basic. We set a parameter called jrs.report that contains the URL encoded report name, jrs.catalog which contains the url encoded catalog name, and jrs.result_type which uses our type argument to tell the JSP what kind of file to generate.

After that, I loop through the parameter name and value lists to send the parameters to the report. The name of the HttpRequest parameter is jrs.param$ followed by the report parameter name, and is set to whatever value needs passed to this parameter. So my report has a parameter called "OrderNumber" the HTTP request parameter must be named jrs.param$OrderNumber and be set to whatever order number the report parameter should be set to. At that point, we're ready to send the request off using the Get() method.

Once the response comes back, the report's stream is now in the request object's HttpResponse.Data, which depending on length, can sometimes be a string and sometimes be a stream, so I've got some steps to check that, then write that data to the %Stream.Object that was passed by reference.

And there you have it; an InterSystems Report generated to a stream.

Discussion (0)1
Log in or sign up to continue