Category Archives: SDK

BusinessObjects SDK

How to determine date pattern for a Webi document using Java RE SDK

...

// Determine preferred locale for the user
Locale locale = null;
try {
    IUserInfo userInfo;
    try {
        userInfo = enterpriseSession.getUserInfo();
    }
    catch (SDKException e) {
        userInfo = null;
    }
    if (null != userInfo) {
        try {
            if (userInfo.getPreferredViewingLocale() != null) {
                locale = userInfo.getPreferredViewingLocale();
            }
        }
        catch (SDKException.PropertyNotFound e) {
            locale = Locale.getDefault();
        }
    }
    System.out.println("Locale: " + locale);
}
catch(Exception e) {
    System.out.println(e.toString());
}
if (locale != null) {
    // Open the document
    OpenDocumentParameters odp = new OpenDocumentParameters(-1, true, false);
    odp.getMultilingualOptions().enableMultilingual(locale.toString());
    DocumentInstance doc = reportEngine.openDocument(infoObject.getID(), odp);

    // Determine the pattern
    FormatNumber formatNumber = doc.getDefaultFormatNumber(FormatNumberType.DATE_TIME);
    System.out.println("Date pattern: " + formatNumber.getPositive());

    // Close the document
    doc.closeDocument();
}

How to refresh Deski report and export it as PDF and XLS using COM SDK

Here is an example how to open Deski report and refresh it and export as PDF using COM SDK.

You will need Visual Studio 2010 Express, BusinessObjects Enterprise XI 3.1 client tools.

1) Create a Deski report (here C:\Users\dmytro\Desktop\Document1.rep)
2) Create a new Project “RunDeski” in VS
3) Add reference to the Deski COM SDK, Project > Add Reference > BusinessObjects 12.0 Object Library
4) Paste the code.
5) Run it.

using busobj;
namespace RunDeski
{
    class Program
    {
        static void Main(string[] args)
        {
            Application application = new Application();
            try 
            {
                application.Interactive = false;
                application.Logon("Administrator", "", "localhost", "secEnterprise", false, true);
                IDocument doc = application.Documents.Open(@"C:\Users\dmytro\Desktop\Document1.rep");
                doc.Refresh();
                doc.ExportAsPDF(@"C:\Users\dmytro\Desktop\Document1.pdf"); 
                doc.SaveAs(@"C:\Users\dmytro\Desktop\Document1.xls");
                doc.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            finally
            {
                application.Quit();
            }
        }
    }
}

How to print SQL queries of Webi 4.0 document using Java

The current public BO BI 4.0 SDK does not include functionality that allows to print SQL queries of a Webi 4.0 document, but this is still possible.

UPDATE: BO BI 4.1 SDK contains RESTful web services for Webi. It allows you to do the below without hacks.

Disclaimer: Use it on your own risk.

The necessary libraries:

  • C:\Program Files (x86)\SAP BusinessObjects\Tomcat6\webapps\BOE\WEB-INF\eclipse\plugins\webpath.AnalyticalReporting\web\WEB-INF\lib\adv_ivcdzview.jar
  • C:\Program Files (x86)\SAP BusinessObjects\Tomcat6\webapps\BOE\WEB-INF\eclipse\plugins\webpath.AnalyticalReporting\web\WEB-INF\lib\webi_client_toolkit.jar
  • C:\Program Files (x86)\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\java\lib\*
    (without subfolders)

The program has two classes: Program and Processor. Program is a main class that iterates through infoobjects of Webi type. Processor is printing SQL of the Webi documents. The most interesting part is Processor which uses BI 4.0 functionality for accessing data providers.

Main (Program.java)

import com.crystaldecisions.sdk.exception.SDKException;
import com.crystaldecisions.sdk.framework.CrystalEnterprise;
import com.crystaldecisions.sdk.framework.IEnterpriseSession;
import com.crystaldecisions.sdk.framework.ISessionMgr;
import com.crystaldecisions.sdk.occa.infostore.IInfoObject;
import com.crystaldecisions.sdk.occa.infostore.IInfoObjects;
import com.crystaldecisions.sdk.occa.infostore.IInfoStore;

public class Program {
   public static void main(String[] args) throws Exception {

      IEnterpriseSession enterpriseSession = null;
      try {
         // Establish connection
         System.out.println("Connecting...");
         ISessionMgr sessionMgr = CrystalEnterprise.getSessionMgr();
         enterpriseSession = sessionMgr.logon(
               "Administrator", "", "localhost", "secEnterprise");
         IInfoStore infoStore = (IInfoStore) enterpriseSession.getService("InfoStore");

         // Initialize processor (see below)
         Processor processor = new Processor(enterpriseSession);

         // Get list of Webi documents
         String cmsQuery = "select SI_NAME, SI_ID from CI_INFOOBJECTS "
               + "where SI_KIND = 'Webi' and SI_INSTANCE=0";
         IInfoObjects infoObjects = (IInfoObjects) infoStore.query(cmsQuery);

         // Process all Webi documents from a folder (root here)
         for (Object object : infoObjects) {
            IInfoObject infoObject = (IInfoObject) object;
            String path = getInfoObjectPathAndTitle(infoObject); 
            if (path.startsWith("/")) {
               System.out.println(path);
               processor.process(infoObject);
               System.out.println();
            }
         }
      } catch (SDKException ex) {
         ex.printStackTrace();
      } finally {
         if (enterpriseSession != null)
            enterpriseSession.logoff();
      }
      System.out.println("Finished!");
   }

   public static String getInfoObjectPath(IInfoObject infoObject) throws SDKException {
      String path = "";
      while (infoObject.getParentID() != 0) {
         infoObject = infoObject.getParent();
         path = "/" + infoObject.getTitle() + path;
      }
      return path;
   }

   public static String getInfoObjectPathAndTitle(IInfoObject infoObject) throws SDKException {
      return getInfoObjectPath(infoObject) + "/" + infoObject.getTitle();
   }
}

Printing (Processor.java)

import java.util.List;
import java.util.Locale;

import com.businessobjects.adv_ivcdzview.Utils;
import com.businessobjects.rebean.wi.model.engine.IDocumentInstance;
import com.businessobjects.rebean.wi.services.IDocumentInstanceManagementService;
import com.businessobjects.rebean.wi.services.IDocumentInstanceService;
import com.businessobjects.sdk.core.Core;
import com.businessobjects.sdk.core.context.IContext;
import com.crystaldecisions.sdk.exception.SDKException;
import com.crystaldecisions.sdk.framework.IEnterpriseSession;
import com.crystaldecisions.sdk.occa.infostore.IInfoObject;
import com.sap.sl.dataprovider.DataProvider;
import com.sap.sl.dataprovider.service.DataProviderService;
import com.sap.sl.queryexecutionplan.NativeQueryNode;
import com.sap.sl.queryexecutionplan.OperatorNode;
import com.sap.sl.queryexecutionplan.QueryExecutionPlan;
import com.sap.sl.queryexecutionplan.QueryExecutionPlanNode;
import com.sap.sl.sdk.workspace.service.WorkspaceContextualService;
import com.sap.sl.workspace.Workspace;
import com.sap.sl.workspace.service.WorkspaceService;
import com.sap.webi.client.toolkit.Deployment;
import com.sap.webi.client.toolkit.LoginKey;
import com.sap.webi.client.toolkit.SessionContext;
import com.sap.webi.client.toolkit.services.DSLServicesHelper;
import com.sap.webi.client.toolkit.services.ServicesHelper;

public class Processor {

   SessionContext sessionContext;
   Locale localLocale;
   IContext context;
   IDocumentInstanceManagementService dimService;
   IDocumentInstanceService diService;
   DataProviderService dpService;
   WorkspaceService wsService;

   public Processor(IEnterpriseSession enterpriseSession) throws SDKException {
      sessionContext = Utils.getSessionContextManager()
            .matchSessionContext(Deployment.DHTML, 
                  enterpriseSession.getSerializedSession(), true);

      localLocale = Locale.getDefault();
      sessionContext.getLoginInfo().set(LoginKey.LOCALE, localLocale);
      sessionContext.logonWithSerializedSession();

      context = sessionContext.getCoreContext();         
      dimService = Core.getService(IDocumentInstanceManagementService.class);
      diService = ServicesHelper.getDocumentInstanceService();

      dpService = DSLServicesHelper.getDataProviderService(context);
      wsService =  Core.getService(WorkspaceContextualService.class, context);
   }

   public void process(IInfoObject infoObject) {
      IDocumentInstance doc = dimService.openDocument(context, infoObject.getID());               
      Workspace workspace = diService.getWorkspace(context, doc);            
      List<DataProvider> listDataProvider = wsService.getDataProviders(workspace); 
      for (DataProvider provider : listDataProvider) {
         QueryExecutionPlan plan = dpService.getQueryExecutionPlan(provider, true);
         print(plan.getQueryExecPlanTree());
      }
      dimService.closeDocument(context, doc);
   }

   private static void print(QueryExecutionPlanNode planNode) {
      if (planNode instanceof NativeQueryNode) {
         NativeQueryNode queryNode = (NativeQueryNode)planNode;
         System.out.println(queryNode.getNativeQueryString());         
      } else if (planNode instanceof OperatorNode) {
         OperatorNode operatorNode = (OperatorNode)planNode;      
         for (QueryExecutionPlanNode node : operatorNode.getChildren()) {
            print(node);
         }
      }
   }
}

Java code to list the objects used in a Webi 4.0 document

The current public BO BI 4.0 SDK does not include any features that allows to list objects used in a Webi 4.0 document or access variables. But this is still possible.

UPDATE: Please consider 4.1 RESTful Web Services SDK Developer Guides and API References http://scn.sap.com/docs/DOC-27465. It might be more convenient than hacking internal SDKs.

The necessary libraries:

  • C:\Program Files (x86)\SAP BusinessObjects\Tomcat6\webapps\BOE\WEB-INF\eclipse\plugins\webpath.AnalyticalReporting\web\WEB-INF\lib\adv_ivcdzview.jar
  • C:\Program Files (x86)\SAP BusinessObjects\Tomcat6\webapps\BOE\WEB-INF\eclipse\plugins\webpath.AnalyticalReporting\web\WEB-INF\lib\webi_client_toolkit.jar
  • C:\Program Files (x86)\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\java\lib\* (without subfolders)
Disclaimer: Use it on your own risk
import java.util.List;
import java.util.Locale;

import com.businessobjects.adv_ivcdzview.Utils;
import com.businessobjects.rebean.wi.model.engine.IDocumentInstance;
import com.businessobjects.rebean.wi.services.IDocumentInstanceManagementService;
import com.businessobjects.sdk.core.Core;
import com.businessobjects.sdk.core.context.IContext;
import com.crystaldecisions.sdk.exception.SDKException;
import com.crystaldecisions.sdk.framework.CrystalEnterprise;
import com.crystaldecisions.sdk.framework.IEnterpriseSession;
import com.crystaldecisions.sdk.framework.ISessionMgr;
import com.crystaldecisions.sdk.occa.infostore.IInfoObject;
import com.crystaldecisions.sdk.occa.infostore.IInfoObjects;
import com.crystaldecisions.sdk.occa.infostore.IInfoStore;
import com.sap.sl.dictionary.DictionaryExpression;
import com.sap.sl.dictionary.Variable;
import com.sap.webi.client.toolkit.Deployment;
import com.sap.webi.client.toolkit.LoginKey;
import com.sap.webi.client.toolkit.SessionContext;
import com.sap.webi.client.toolkit.reporting.ReportDictionaryHelper;

public class Program2 {
  public static void main(String[] args) throws Exception {

    IEnterpriseSession enterpriseSession = null;
    try {
      System.out.println("Connecting...");
      ISessionMgr sessionMgr = CrystalEnterprise.getSessionMgr();
      enterpriseSession = sessionMgr.logon(
          "Administrator", "", "localhost", "secEnterprise");

      // Do some magic
      String serializedSession = enterpriseSession.getSerializedSession();
      SessionContext sessionContext = Utils.getSessionContextManager()
          .matchSessionContext(Deployment.DHTML, serializedSession, true);
      Locale localLocale = Locale.getDefault();
      sessionContext.getLoginInfo().set(LoginKey.LOCALE, localLocale);
      sessionContext.logonWithSerializedSession();
      IContext context = sessionContext.getCoreContext();
      IDocumentInstanceManagementService documentInstanceManagementService =
          Core.getService(IDocumentInstanceManagementService.class);

      // Get the list of webi documents
      IInfoStore infoStore = (IInfoStore) enterpriseSession.getService("InfoStore");
      String query = "select SI_NAME, SI_ID from CI_INFOOBJECTS "
          + "where SI_KIND = 'Webi' and SI_INSTANCE=0";
      IInfoObjects infoObjects = (IInfoObjects) infoStore.query(query);

      for (Object object : infoObjects) {
        IInfoObject infoObject = (IInfoObject) object;
        if (getInfoObjectPathAndTitle(infoObject).startsWith("/")) {
          System.out.println("REPORT: " + infoObject.getTitle());

          IDocumentInstance doc = documentInstanceManagementService
              .openDocument(context, infoObject.getID());

          List list = ReportDictionaryHelper
              .getDictionaryObjectsFlatList(context, doc);
          if (list.size() > 0) {
            System.out.println("OBJECTS:");
            for (DictionaryExpression expr:list) {
              System.out.println(expr.getName());
            }
          }

          List vars = ReportDictionaryHelper.getDocumentVariables(context,doc);
          if (vars.size() > 0) {
            System.out.println("VARIABLES:");
            for (Variable var:vars) {
              System.out.println(var.getName());
            }
          }

          documentInstanceManagementService.closeDocument(context, doc);
          System.out.println();
        }
      }
    } catch (SDKException ex) {
      ex.printStackTrace();
    } finally {
      if (enterpriseSession != null)
        enterpriseSession.logoff();
    }
    System.out.println("Finished!");
  }

  public static String getInfoObjectPath(IInfoObject infoObject)
      throws SDKException
  {
    String path = "";
    while (infoObject.getParentID() != 0) {
      infoObject = infoObject.getParent();
      path = "/" + infoObject.getTitle() + path;
    }
    return path;
  }

  public static String getInfoObjectPathAndTitle(IInfoObject infoObject)
      throws SDKException
  {
    return getInfoObjectPath(infoObject) + "/" + infoObject.getTitle();
  }
}

How to Change Expression in Report Cells using BO Java SDK

Problem

“I have nearly 500 reports, each report having logo on the right up corner in all tabs, in a cell having formula “boimg://logo.bmp” and read as image URL. Now i have come up with change in logo format. Now the same formula is to be changed to “boimg://logo.jpg””.

Code

private static int replaceExpression(DocumentInstance widoc, String from, String to) {
   ReportDictionary reportDictionary = widoc.getDictionary();
   ArrayList nodes = getListOfTreeNodes(widoc.getStructure(), false);
   int n = 0;
   for (TreeNode node : nodes) {
      if (node instanceof ReportCell) {
         ReportCell reportCell = (ReportCell)node;
         ReportExpression reportExpression = reportCell.getExpr();
         if (reportExpression instanceof FormulaExpression) {
            FormulaExpression formulaExpression = (FormulaExpression)reportExpression;
            if (formulaExpression.getValue().compareTo(from) == 0){
               FormulaExpression newFormulaExpression = reportDictionary.createFormula(to);
               reportCell.setExpr(newFormulaExpression);
               n += 1;
            }
         }
      }
   }
   widoc.applyFormat();
   return n;
}

public static ArrayList getListOfTreeNodes(TreeNode root, boolean onlyLeaves) {
   ArrayList nodes = new ArrayList();
   treeNodeTraversal(root, nodes, onlyLeaves);
   return nodes;
}

private static void treeNodeTraversal(TreeNode node, ArrayList nodes, boolean onlyLeaves) {
   if (!onlyLeaves || node.isLeaf()) {
      nodes.add(node);
   }
   for (int i = 0; i < node.getChildCount(); ++i) {
      treeNodeTraversal(node.getChildAt(i), nodes, onlyLeaves);
   }
}

Source

https://bukhantsov.org/tools/ReplaceInReportCell.java

How to get report drill filters

Here is an example how to get report drill filters.

DocumentInstance doc = reportEngine.openDocument(infoObject.getID());
Reports reports = doc.getReports();
for (int i = 0; i < reports.getCount(); i++)
{
    Report report = reports.getItem(i);
    DrillInfo drillInfo = (DrillInfo) report.getNamedInterface("DrillInfo");
    DrillBar drillBar = drillInfo.getDrillBar();
    for (int j = 0; j < drillBar.getCount(); ++j) {
        DrillBarObject drillBarObject = drillBar.getItem(j);
        System.out.println(
            String.format("%s='%s'", 
                drillBarObject.getName(), 
                drillBarObject.getFilter()));
    }
}
doc.closeDocument();

Result:

Service Line='Recreation'
Year=''

How to Test All Connection using BusinessObjects SDK

Problem

“I was doing some research in the past but could not find any solution out on the WEB, but think it would be helpful for BO admins. Tool, that can test all the universe connection from environment without using Designer tool, since in it you can test one connection at the time, but if you have 50 of them that is a lot of clicks. In our company , we often change database passwords and need to update connections setting, and sometimes we can miss 1-2 and few days later some reports will start failing or people will complain that they can run certain report (because database password was not been updated). So I was thinking about some utility that can use designer SDK that can go and loop through all the universe connections in the system and return pass or fail.”

Code

static void Main(string[] args)
{
   Application application = new Application();
   try
   {
      if (args.Length != 4)
      {
         application.LogonDialog();
      }

      Connections connections = application.Connections;
      foreach (Connection connection in connections)
      {
         Console.Write(connection.Name.PadRight(40));
         try
         {
            connection.Test();
            Console.WriteLine("OK");
         }
         catch (Exception ex)
         {
            Console.WriteLine(ex.Message.Replace("\n","").Replace("\r",""));
         }
      }
   }
   catch (Exception ex)
   {
      Console.WriteLine(ex.ToString());
   }
   finally
   {
      application.Quit();
   }
}

Downloads

download source Source
download executable Executable for BOE XI 3.1 SP3 FP3.2

The executable should be run from command line as the result is printed to standard output. The arguments are: username password server auth. E.g.

TestConnections.exe Administrator "" localhost secEnterprise > c:/connectionstest.txt

If you do not specify the arguments, the designer logon dialog will appear.

Printing LoV names with Designer COM SDK

Tutorial “Getting started with Designer SDK”

using System;
using Designer;
namespace ConsoleApplication1
{
    class Program
    {
        delegate void CleanUpMethod();

        static void Main(string[] args)
        {
            Application application = new Application();
            application.Interactive = false;

            CleanUpMethod cleanUp = delegate { application.Quit(); };
            Console.CancelKeyPress += delegate { cleanUp(); }; // to handle Ctrl+C

            try
            {
                application.Logon("Administrator", 
                    "", "localhost", "secEnterprise");                
                Universe universe =
                    application.Universes.OpenFromEnterprise(
                        "webi universes",
                        "Island Resorts Marketing",
                        false);
                PrintClasses(universe.Classes, "");
                universe.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                cleanUp();
            }
        }

        static void PrintClasses(Classes classes, String path)
        {
            foreach (Class theclass in classes)
            {
                String path2 = path + "/" + theclass.Name;
                foreach (Designer.Object theobject in theclass.Objects)
                {
                    if (theobject.HasListOfValues)
                    {
                        Console.WriteLine(path2 + ";" 
                            + theobject.Name + ";" 
                            + theobject.ListOfValues.Name);
                    }
                }
                PrintClasses(theclass.Classes, path2);
            }
        }

    }
}

Is the use of Enterprise SDKs in a thick-client/desktop application supported

Question:

BusinessObjects Enterprise XI, Crystal Reports Server XI, and Crystal Enterprise contain COM, .NET, and Java SDKs. Is the use of these SDKs in a thick-client or desktop application supported?

Answer:

No, the use of BusinessObjects Enterprise SDKs is not supported in a thick-client or desktop application because the BusinessObjects Enterprise SDK is only intended for use in web applications. To build BI platform thick-client or desktop applications, use Business Objects web services.

 Explanation:

  • Thick client applications are not supported because of the CORBA implementation we use with the Enterprise services.
  • Thick client applications are typically installed on many client systems. The large install base would put a strain on the CMS because an individual CORBA connection would be created for each client logon to the CMS server.
  • Web applications don’t present this problem because the application server will only create one CORBA connection to the CMS server for all the client sessions initiated.
  • While the thick client application will likely work without error, there is no escalation path to the technical development team for any issues specifically related to the thick client application. Any issue must be reproduceable in a web environment in order to be tracked as a bug.
  • Only the Enterprise Web Services SDK is supported in a thick client application.

Source:

SAP note 1219135 and related discussion