Skip to Content

This article will provide a step-by-step implementation for finding and exporting reports from the SAP BI platform server to your application.  The code requires SAP BI platform 4.0 SP05 or later.

You will need to have a valid logon token to use these REST methods.  Please read first the server logon article if you have not already implemented it yet.

You can find that article here:  https://scn.sap.com/community/restful-sdk/blog/2012/11/17/using-web-intelligence-rest-web-services-to-log-into-the-bi-platform-server-javascript-and-c

Once we have our logon token, we can now access all of the Web Intelligence documents within the BI platform server.  In order to export a report, we need to know its document ID and report ID.  In this article, we will get these IDs using the REST API.

Getting the document list

To get a list of Web Intelligence documents on the server, we will use the REST method ‘GET’ to the following URI:

URI

http:// <Server IP> :<port>/biprws/raylight/v1/documents/

JavaScript Implementation

Here we use AJAX to send the REST method to the server.  We set the “Accept Header” to ‘application/xml’ or ‘application/json’ depending on the format we want.  Finally, we set a custom header “X-SAP-LogonToken” to our logon token variable.

Javascript Function

function getDocs(){                     

                ajaxRequest = $.ajax({url: server + ‘/biprws/raylight/v1/documents’, type: ‘get’,

                                complete: function(xhr) {

                                                json = jQuery.parseJSON(xhr.responseText).documents.document;

                                                                 },

                                                                 beforeSend: function(xhr) {

                                                                                xhr.setRequestHeader(‘Accept’, ‘application/json’);

                                                                                xhr.setRequestHeader(‘X-SAP-LogonToken’, logonToken);

                                                                                }

                                });

}

C# Implementation

In C#, we first create an HttpWebRequest object which takes the URI as a parameter.  Then we set the REST method to ‘GET’, the “Accept Headers” to either ‘application/xml’ or ‘application/json’, and a custom header “X-SAP-LogonToken” to our logontoken variable.  Then we create an HttpWebResponse object to collect the server response. Finally, we use the stream class to read the input.

REST Request

string server = http:// + IP + “:” + port + “/biprws/raylight/v1/documents”;

HttpWebRequest GetRequest = (HttpWebRequest)WebRequest.Create(server);

GetRequest.Method = “GET”;

GetRequest.Accept = “application/”+dformat;

GetRequest.Headers.Set(“X-SAP-LogonToken”, ltoken);

HttpWebResponse GETResponse = (HttpWebResponse)GetRequest.GetResponse();

Stream GETResponseStream = GETResponse.GetResponseStream();

StreamReader sr = new StreamReader(GETResponseStream);

Console.WriteLine(sr.ReadToEnd());

The server will respond with a list of all documents in XML or JSON format.

Getting the report list

Once we decide on the document, we must also find out which report within that document we want to export.

We do this by using the REST method ‘GET’ to the URI:

URI

http:// <Server IP> :<port>/biprws/raylight/v1/documents/+ docID +/reports/

Be sure to enter the document ID into the URI as shown above.

JavaScript Implementation

Similar to retrieving a document, we set the header to ‘GET’ and the “Accept Header” to either ‘application/xml’ or ‘application/json’, and set a custom header “X-SAP-LogonToken” to our logontoken variable.

Javascript Function

function listReports(id)                {

                                var documentID = id;

                                ajaxRequest = $.ajax({url: server + ‘/biprws/raylight/v1/documents/’+id+’/reports’, type: ‘get’,

                                                complete: function(xhr) {

                                                json = jQuery.parseJSON(xhr.responseText).reports.report;

                                                                 },

                                                                 beforeSend: function(xhr) {

                                                                                                xhr.setRequestHeader(‘Accept’, ‘application/json’);

                                                                                                xhr.setRequestHeader(‘X-SAP-LogonToken’, logonToken);

                                                                                                console.log(“Requesting a complete list of documents”);

                                                                                                }

                                });

                }

C# Implementation

This is very similar to the implementation for retrieving the document list.

REST Request

string server = http:// + IP + “:” + port + “/biprws/raylight/v1/documents/” + DocID + “/reports/”;

HttpWebRequest GetRequest = (HttpWebRequest)WebRequest.Create(server);

GetRequest.Method = “GET”;

GetRequest.Accept = “application/”+dformat;

GetRequest.Headers.Set(“X-SAP-LogonToken”, ltoken);

HttpWebResponse GETResponse = (HttpWebResponse)GetRequest.GetResponse();

Stream GETResponseStream = GETResponse.GetResponseStream();

StreamReader sr = new StreamReader(GETResponseStream);

Console.WriteLine(sr.ReadToEnd());

Exporting the report

Finally, we have all the information we need to export the report data.  We do this by using the REST method ‘GET’ to the URI:

URI

http:// <Server IP> :<port>/biprws/raylight/v1/documents/+ docID +/reports/ +reportID

Again, we need to include the chosen docID and reportID in the above URI.

JavaScript Implementation

The only difference between this code and the two previous examples is that we can set the “Accept Headers” to either ‘text/xml’ or ‘text/html’.  If you choose xml, you can store it by using the parseXML method coming from the JQuery library.

Javascript Function

function exportReport(docId,reportId){

                var x = docId;

                var y = reportId;

                ajaxRequest = $.ajax({url: server + ‘/biprws/raylight/v1/documents/’+x+’/reports/’+y, type: ‘get’,

                                                complete: function(xhr) {

                                                                                response = $.parseXML(xhr.responseText);

                                                                                 },

                                                                                beforeSend: function(xhr) {

                                                                                                xhr.setRequestHeader(‘Accept’, ‘text/xml’);

                                                                                                xhr.setRequestHeader(‘X-SAP-LogonToken’, logonToken);

                                                                                                }

                                                });

}

C# Implementation

Again, the only differences here are between choosing your response data in either ‘text/xml’ or ’text/html’ formats.

REST Request

string server = http:// + IP + “:” + port + “/biprws/raylight/v1/documents/” + CUID + “/reports/” + reportID;

HttpWebRequest GetRequest = (HttpWebRequest)WebRequest.Create(server);

GetRequest.Method = “GET”;

GetRequest.Accept = “text/”+dformat;

GetRequest.Headers.Set(“X-SAP-LogonToken”, ltoken);

HttpWebResponse GETResponse = (HttpWebResponse)GetRequest.GetResponse();

Stream GETResponseStream = GETResponse.GetResponseStream();

StreamReader sr = new StreamReader(GETResponseStream);

string output = sr.ReadToEnd();

The server will respond with the report data in either XML or HTML format depending on whether you set the “Accept Header” to ‘text/html’ or ‘text/xml’, respectively.  If you wish to display the report in a browser, then HTML would be your preferred format.  On the other hand, if you would like to extract and parse through the report data, then XML format would be your best bet.

With the above implementation, you should be able to export your Web Intelligence data to any application.  From there, you can mash it up with other web services data to provide new insights or simply customize it to better suit your business context.

Questions? Comments? Please let me know what you think!

By Brian Park, Product Management Intern, brian.park@sap.com

To report this post you need to login first.

14 Comments

You must be Logged on to comment or reply to a post.

  1. Abhi SAP

    Hi Brian,

    Thanks for posting this interesting document.Its actually inspired me to do something similiar to this using javascript. I’m a newbie to javascript but tried my best to put some code to open a webi report without prompting it for credentials. I’m able to retrieve the token successfully but was not able call the function to open a webi report. Can you take a look of my javascript code and let me know where I’m doing wrong.

    Thanks in Advance.

    <html>

    <head>

    <script src=”http://code.jquery.com/jquery-latest.js“></script>

    <script src=”scripts/jquery.json2html-3.0.js” type=”text/javascript”></script>

    <script>

    // Logs into the platform

    var logon = new XMLHttpRequest();

        var url = ‘server/biprws/logon/long’;

        var action = ‘logon/long’;

        var body = ‘<?xml version=”1.0″?><attrs xmlns=”http://www.sap.com/rws/bip“><attr name=”userName” type=”string”>UserName</attr><attr name=”password” type=”string”>Password</attr><attr name=”auth” type=”string” possibilities=”secEnterprise,secLDAP,secWinAD”>secLDAP</attr></attrs>’;

        var response;

        var logonToken;

        logon.open(‘POST’, url, false);

        logon.setRequestHeader(‘X-PINGARUNER’, ‘pingpong’);

        logon.setRequestHeader(‘Content-Type’, ‘application/xml’);

        logon.setRequestHeader(‘Accept’, ‘application/xml’);

        logon.send(body);

       logonToken = logon.getResponseHeader(‘X-SAP-LogonToken’);

    function exportReport(docId,reportId){

                    var x = ‘AZxcbgtrty’;

                    var y = ‘123456’;

                    ajaxRequest = $.ajax({url: ‘server’ + ‘/biprws/raylight/v1/documents/’+x+’/reports/’+y, type: ‘get’,

                                                    complete: function(xhr) {

                                                                                    response = $.parseXML(xhr.responseText);

                                                                                     },

                                                                                    beforeSend: function(xhr) {

                                                                                                    xhr.setRequestHeader(‘Accept’, ‘text/html’);

                                                                                                    xhr.setRequestHeader(‘X-SAP-LogonToken’, logonToken);

                                                                                                    }

                                                    });

    }

      

       

    </script>

    </head>

      <body>

        <div id=”id” style=”width: 900px; height: 500px;”></div>

      </body>

    </html>

    (0) 
      1. Abhi SAP

        Hi Anthony,

        thanks for your reply.I get a blank page.

        I also tried to verify my token is correct or not. So what I did is captured the token value from X-SAP-LogonToken and did the url encode to capture url encoded Token value. I tied this token to the open document link to open a webi report. But still it asks me the credentials.

        So, not sure whether token is passed to the function defined in Javascript to view webi report in html format.

        Abhi

        (0) 
          1. Daniel Paulsen

            I’ll venture a guess that it has to do with pulling the X-SAP-LogonToken from the headers instead of the response body.  The Token in the header has double quotes around it whereas the returned token in the response body does not.

            Try removing the quotes and then encode the token before using it in openDocument.

            I saw similar results and tried the following:

               logon.send(body);

               logonToken = logon.getResponseHeader(‘X-SAP-LogonToken’);
               window.alert(“Logon Token: ” + logonToken);          //has double quotes
             

               logonToken = logonToken.replace(/”/g,””);               // remove all double quotes

               logonToken =  encodeURIComponent(logonToken);
               window.alert(“Logon Token: ” + logonToken);       //encoded with double quotes removed

               window.open(‘http://BIPW08R2:8080/BOE/OpenDocument/opendoc/openDocument.jsp?sIDType=InfoObjectID&iDocID=5547&token=‘ + logonToken);

            Dan

            (0) 
            1. Rogerio Plank

              Hi,

              how are you calling your javascript application ? Is it through a regular HTML file ?

              If so, where the file located, cause you can be facing a CORS issue. Reading through your code, I noticed that you use the ‘X-PINGARUNER to get the logon token, but not in the second call. Try adding it to your code, like in:

              xhr.setRequestHeader(‘X-PINGARUNER’‘, ‘pingpong’)

              Regards,

              Rogerio

              (0) 
              1. Abhi SAP

                Rogerio- I’m calling using regular HTML.  I tried keeping xhr.setrequestheader like you said it didn’t worked.

                Daniel – I tried removing the quotes from logon token and add it to the open document link then also no luck.

                We use open AM for authentication, do you think I need to do anything to make it work.

                (0) 
  2. Harini Deepak

    Hi Brian.

    Thanks for sharing this. I am trying to retrieve query from each report using the below request

    http://<cms>:<port>/biprws/raylight/v1/documents/<Report id>/dataproviders/DP0/.

    I am able to retrieve query from each report, but if the query used in the report is a combined query with union, the above request does not return the query. Could you please share how to retrieve combined queries from webi report?


    Thanks in Advance,

    Harini

    (0) 
    1. Eric FESTINGER

      hi Harini,

      I just tested your call on our latest development branch, and it returns the combined query as expected. For example:

      <dataprovider>

        <id>DP2</id> 

        <name>Requête combinée</name> 

        <dataSourceId>6727</dataSourceId> 

        <dataSourcePrefix>DS0</dataSourcePrefix> 

        <dataSourceType>unv</dataSourceType> 

        <updated>2016-03-02T13:33:14.000Z</updated> 

        <duration>1</duration> 

        <isPartial>false</isPartial> 

        <rowCount>22</rowCount> 

        <flowCount>1</flowCount> 

        <dictionary>

        <expression dataType=”String” qualification=”Dimension”>

        <id>DP2.DO88</id> 

        <name>Customer Full Name</name> 

        <description>/Customer/Customer Full Name Customer’s first name + ‘ – ‘ +Customer’s last name</description> 

        <dataSourceObjectId>DS0.DO88</dataSourceObjectId> 

        <formulaLanguageId>[Requête combinée].[Customer Full Name]</formulaLanguageId>

        </expression> 

        <expression dataType=”Numeric” qualification=”Measure” highPrecision=”false”>

        <id>DP2.DO95</id> 

        <name>Number Of Customer Country</name> 

        <description>/Resort Measure/Number Of Customer Country Number Of Country (Aggregation Function is Sum) (On Table Country)</description> 

        <dataSourceObjectId>DS0.DO95</dataSourceObjectId> 

        <formulaLanguageId>[Requête combinée].[Number Of Customer Country]</formulaLanguageId> 

        <aggregationFunction>Sum</aggregationFunction>

        </expression>

        </dictionary> 

        <query>SELECT CUSTOMER.FIRST_NAME || ‘ – ‘ || CUSTOMER.LAST_NAME, Count (Distinct CUSTOMER.COUNTRY_ID) FROM CUSTOMER WHERE TO_NUMBER(TO_CHAR(CUSTOMER.BIRTHDATE,’SYYYY’)) IN @prompt(‘Saisir une ou plusieurs valeurs pour Year of Customer Birthdate’,’N’,,Multi,Free,Persistent,,User:0) GROUP BY CUSTOMER.FIRST_NAME || ‘ – ‘ || CUSTOMER.LAST_NAME UNION SELECT CUSTOMER.FIRST_NAME || ‘ – ‘ || CUSTOMER.LAST_NAME, Count (Distinct CUSTOMER.COUNTRY_ID) FROM CUSTOMER WHERE TO_NUMBER(TO_CHAR(CUSTOMER.BIRTHDATE,’Q’)) IN @prompt(‘Saisir une ou plusieurs valeurs pour Quarter of Customer Birthdate’,’N’,,Multi,Free,Persistent,,User:1) GROUP BY CUSTOMER.FIRST_NAME || ‘ – ‘ || CUSTOMER.LAST_NAME</query>

      </dataprovider>

      1. Which version are you using? (‘GET …/raylight/v1/about’)

      2. To avoid mixing subjects, it would be preferable you open, if needed, a new discussion instead.

      Thanks and regards,

      eric

      (0) 
      1. Harini Deepak

        Thanks a lot for your reply Eric.After seeing your response I understood my question was wrong.I am able to retrieve combined query,but I’m not able to retrieve full outer join query.

        Capture.JPG

        (0) 
        1. Eric FESTINGER

          hi Harini,

          This is indeed missing from the “data provider details” call when there are multiple flows, but you may ask directly for the query execution plan.

          For example:

          [GET] raylight/v1/documents/9308/dataproviders/DP0/queryplan

          Accept: application/xml

          Content-Type: application/xml

          Response:

          <?xml version=”1.0″ encoding=”UTF-8″?>

          <queryplan custom=”false” editable=”true”>

            <multipleFlows>

            <statement index=”1″>SELECT CITY.CITY_NAME, CUSTOMER.COMPANY_NAME FROM CITY INNER JOIN CUSTOMER ON (CUSTOMER.CITY_ID=CITY.CITY_ID) /* User: @Variable(‘BOUSER’) Universe: @Variable(‘UNVNAME’) */</statement> 

            <statement index=”2″>SELECT INVENTORY.STOCK_LEVEL FROM INVENTORY /* User: @Variable(‘BOUSER’) Universe: @Variable(‘UNVNAME’) */</statement>

            </multipleFlows>

          </queryplan>

          Regards,

          eric

          PS : next time, please do create a new discussion so that other people may look for that topic more easily.

          (0) 
  3. Eric FESTINGER

    hello Michael

    This behavior is not specific to the BO REST services, but to the C# implementation of web requests.

    The Microsoft documentation is quite clear about it!

    Quoting https://msdn.microsoft.com/en-us/library/system.net.webexception.response(v=vs.110).aspx:

    Some Internet protocols, such as HTTP, return otherwise valid responses indicating that an error has occurred at the protocol level. When the response to an Internet request indicates an error, WebRequest.GetResponse sets the Status property to WebExceptionStatus.ProtocolError and provides the WebResponse that contains the error message in the Response property of the WebException that was thrown. The application can examine the WebResponse to determine the actual error.


    Regards,

    eric

    (0) 
  4. Murali Nadadhur

    Thanks Brian. My use case is to export the Business Object reports to a CSV file. Is there an automated way or an API to do this? Our framework is in Java, so it would be great if you could help me with the Java solution on this regard.

    (0) 

Leave a Reply