23
1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary The following paper should help to get a quick start on how to access the ODS BAPI in SAP BW using the new SAP .Net Connector 2.0. The main focus is to demonstrate how easy it became to call the BAPI functions as SAP .NET Connector generates all the code which is necessary to handle the RFC ( Remote Function Call ) part. What’s still left to the programmer is the connection to the BW system and processing BAPI result sets which of course might be still quite some work. Applies to SAP BW 3.0B, Basis SP 39, ABAP SP 39, BW SP 21 SAP .NET Connector 2.0 Microsoft Visual Studio .NET 2003 Keywords ODS BAPI, SAP .NET Connector, C# Level of difficulty Technical consultants, Developers Contact For feedback or questions you can contact the Collaboration Technology Support Center at [email protected] . Please check the .NET interoperability area in the SAP Developer Network http://www.sdn.sap.com/sdn/developerareas/dotnet.sdn for any updates or futher information . Collaboration Technology Support Center - Microsoft - Collaboration Brief September 2004

Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

  • Upload
    others

  • View
    82

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

1

Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation

Summary The following paper should help to get a quick start on how to access the ODS BAPI in

SAP BW using the new SAP .Net Connector 2.0. The main focus is to demonstrate how

easy it became to call the BAPI functions as SAP .NET Connector generates all the

code which is necessary to handle the RFC ( Remote Function Call ) part. What’s still

left to the programmer is the connection to the BW system and processing BAPI result

sets which of course might be still quite some work.

Applies to SAP BW 3.0B, Basis SP 39, ABAP SP 39, BW SP 21 SAP .NET Connector 2.0 Microsoft Visual Studio .NET 2003

Keywords ODS BAPI, SAP .NET Connector, C#

Level of difficulty Technical consultants, Developers

Contact For feedback or questions you can contact the Collaboration Technology Support Center at [email protected]. Please check the .NET interoperability area in the SAP Developer Network http://www.sdn.sap.com/sdn/developerareas/dotnet.sdn for any updates or futher information .

Collaboration Technology Support Center - Microsoft - Collaboration Brief September 2004

Page 2: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

2

Copyright 2004 SAP AG. All rights reserved. All other product and service names mentioned are the trademarks of their respective companies No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of SAP AG. The information contained herein may be changed without prior notice.. Some software products marketed by SAP AG and its distributors contain proprietary software components of other software vendors. Microsoft, Windows, Outlook, and PowerPoint are registered trademarks of Microsoft Corporation. IBM, DB2, DB2 Universal Database, OS/2, Parallel Sysplex, MVS/ESA, AIX, S/390, AS/400, OS/390, OS/400, iSeries, pSeries, xSeries, zSeries, z/OS, AFP, Intelligent Miner, WebSphere, Netfinity, Tivoli, and Informix are trademarks or registered trademarks of IBM Corporation in the United States and/or other countries. Oracle is a registered trademark of Oracle Corporation. UNIX, X/Open, OSF/1, and Motif are registered trademarks of the Open Group. Citrix, ICA, Program Neighborhood, MetaFrame, WinFrame, VideoFrame, and MultiWin are trademarks or registered trademarks of Citrix Systems, Inc. HTML, XML, XHTML and W3C are trademarks or registered trademarks of W3C®, World Wide Web Consortium, Massachusetts Institute of Technology. Java is a registered trademark of Sun Microsystems, Inc. JavaScript is a registered trademark of Sun Microsystems, Inc., used under license for technology invented and implemented by Netscape. MaxDB is a trademark of MySQL AB, Sweden. SAP, R/3, mySAP, mySAP.com, xApps, xApp, SAP NetWeaver, and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and in several other countries all over the world. All other product and service names mentioned are the trademarks of their respective companies. Data contained in this document serves informational purposes only. National product specifications may vary. These materials are subject to change without notice. These materials are provided by SAP AG and its affiliated companies ("SAP Group") for informational purposes only, without representation or warranty of any kind, and SAP Group shall not be liable for errors or omissions with respect to the materials. The only warranties for SAP Group products and services are those that are set forth in the express warranty statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional warranty.

Page 3: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

3

Contents Summary .............................................................................................................1 Applies to ............................................................................................................1 Keywords.............................................................................................................1 Level of difficulty ................................................................................................1 Contact ................................................................................................................1 Contents ..............................................................................................................3 Introduction.........................................................................................................4 SAP BW Demo Cube 0D_DECU.........................................................................5

Activating demo cube 0D_DECU ............................................................................................ 5 Loading data into the demo cube 0D_DECU ......................................................................... 6 Issues loading the demo cube 0D_DECU .............................................................................. 6

Creating an ODSObject ......................................................................................7 SAP BW ODS BAPI ...........................................................................................10 Code sample .....................................................................................................11

Use SAP BW ODS BAPI methods to retrieve metadata and extract data......................... 11 Source listing of C# sample ( shows all ODS objects and extracts data from ODS object ODSDECU ) ............................................................................................................................. 15

Conclusion ........................................................................................................22 Limitations.........................................................................................................22 References ........................................................................................................23

Page 4: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

4

Introduction

It might be useful in certain customer scenarios to extract data from SAP BW using a

self-written program instead of a full-blown reporting tool. This paper shows how easy it

is to call the SAP BW ODS BAPI functions with the help of SAP .NET Connector 2.0.

ODSObjects are not based on a star or snowflake schema. They are “flat” structures

without separate dimension tables. But it might be still necessary to join to the master

data tables in order to get text data or to work with hierarchies. Due to this flat structure

no MDX ( Multidimensional eXpression ) language is needed ( like for the OLAP BAPI )

to retrieve data from an ODSObject which makes life easier. What needs to be done is

just to specify all the parameters for the read call of the ODS BAPI.

The sample is based on a SAP demo cube which is part of the business content

in SAP BW. Therefore it should be possible for every SAP BW 3.0B customer

to setup the same environment which was used for the sample.

Page 5: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

5

SAP BW Demo Cube 0D_DECU

To use exactly the same test environment which was used for the sample it’s

necessary to activate the 0D_DECU demo cube.

Activating demo cube 0D_DECU The cube can be activated in the administrator workbench ( transaction RSA1 )

under section “Business Content” :

Figure 1 : demo cube activation

Page 6: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

6

Loading data into the demo cube 0D_DECU When the demo cube is activated you will find several .CSV load files in the SAP work

directory. Use the appropriate InfoSources and InfoPackages to load the master data

and the InfoCube ( fact table ) :

Figure 2 : load files for demo cube

Issues loading the demo cube 0D_DECU SAP Note 370397 provides some hints regarding loading the SAP demo cubes. There

were two issues related to loading the .CSV files. A few files contained some additional

character after the last data row which confused BW. A simple workaround was to open

the .CSV file in Notepad and delete any additional ‘newline’ or whatever at the end ( just

use DEL or BACKSPACE until the cursor stands directly next to the last visible

character in the data file ).

The second issue was more difficult to solve. For whatever reason the order of the

columns in two .CSV files ( master data for 0D_SOLD_TO and trans data for the fact

table ) was different than the transfer structure which was generated. The solution was

to change the order of the columns in the DataSource/Transfer Structure.

Page 7: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

7

For 0D_SOLD_TO it has to be :

0D_SOLD_TO, 0D_COUNTRY, 0D_INDUSTRY, 0LONGITUDE, 0LATITUDE,

0ALTITUDE, 0SRCID, 0PRECISID, 0D_REGION, 0D_CITY, 0D_STREET, 0D_PHONE

For the fact table it has to be :

D_CO_CODE, D_DIS_CHAN, D_DIV, D_MATERIAL, D_PROD_HIE, D_SALE_EMP,

D_SALE_ORG, D_SOLD_TO, D_VERSION, D_INV_QTY, SALES_UNIT, D_COST,

DOC_CURRCY, D_NETVLINV, D_TAXAMOUN, CALDAY, D_VTYPE

Creating an ODSObject The ODSObject in the sample was created manually. The idea was to use the same

InfoObjects which were used in the sample query of the “OLAP BAPI white paper” in

order to make the output of the ODS query comparable. See the following screenshot

regarding the definition of the ODSObject.

Figure 3 : structure of the ODSObject

Page 8: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

8

To load the ODSObject with the same data as the demo InfoCube the InfoSource of

0D_DECU was copied. When creating the default update rules an error message

showed up which complained about a missing InfoObject ( 0RECORDMODE ) in the

communication structure. This is needed in an ODSObject. But it doesn’t exist in the

load files for the demo InfoCube. Therefore the solution was to add this InfoObject to the

communication structure and set a constant value in the transfer structure. There was a

little issue as the selection list for a constant didn’t show any values :

Figure 4 : no selection of constant values for InfoObject 0RECORDMODE

The workaround was to choose a formula ( called it “recmodeconst” ) and then select a

constant in the formula screen. Here the selection list of possible constants worked fine.

The value ‘ ‘ ( blank ) which means “After-Image” was selected :

Page 9: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

9

Figure 5 : selection of constant value ‘After-Image’ for InfoObject 0RECORDMODE in the “formula screen”

After the ODSObject was created the standard procedures followed to load and activate

an ODSObject ( not covered in this document ). Just don’t forget to set the update type

of the data fields in the ODSObject to “Addition” ( change update rules ). The default is

“Overwrite” which finally leads to a different query result than the sample query in the

“OLAP BAPI white paper”. The reason is that there are duplicate values for the key

columns. In case of “Overwrite” you would get only the data values of the last row which

was loaded for a certain combination of keys.

Page 10: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

10

SAP BW ODS BAPI You will find infos about the ODS BAPI in the function module documentation using

transaction SE37. The following screenshot shows the info for the function

BAPI_ODSO_READ_DATA_UC. The sample uses the non-Unicode version. But it

turned out that the docu for the Unicode version includes a more detailed description

of the function. There you will find e.g. the list of possible function parameters.

Figure 6 : function module documentation of ‘BAPI_ODSO_READ_DATA_UC’ Two function calls are basically necessary to read data from an ODSObject :

BAPI_ODSO_GETLIST() to find an ODSObject ( in case the name shouldn’t

be hard-coded ) and BAPI_ODSO_READ_DATA() to read data from it ( or

BAPI_ODSO_READ_DATA_UC() for Unicode systems ).

Page 11: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

11

Code sample Use SAP BW ODS BAPI methods to retrieve metadata and extract data After you installed SAP .NET Connector open a new C# Console Program Project in

Visual Studio .NET and add the SAP Connector Proxy ( in Solution Explorer right-click

on the project name and choose “Add”->”Add New Item …” ). More infos can be found

in the description and the samples which come with the SAP .NET Connector. After

adding the Proxy click on “Build”->”Build Solution”.

Figure 7 : SAP Connector Proxy

Configure the connection to the BW application server in the “Server Explorer” window.

In the folder BOR you can use the subfolder “Alphabetical” to find the OLAP BAPI

functions. :

Page 12: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

12

Figure 8 : looking for ODS BAPI methods

Under “ODSObject” choose GetList as well as ReadData and put it via “drag&drop” on

the design window of the generated SAPProxy. SAP .NET Connector generates code to

call the BAPI functions and to define the parameters which are needed. By “moving” the

BAPI methods to the design window it will automatically add icons for the additional

classes which are needed to handle the method parameters and result sets. In the

“code-view” of the SAPProxy1.cs file you will find the BAPI calls and which parameters

are used. SAP .NET Connector generated classes with slightly different names :

“GetList” became “Bapi_Odso_GetList()” and “ReadData” became

“Bapi_Odso_Read_Data”. Before you continue click on “Build”->”Build Solution”.

Page 13: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

13

Figure 9 : choosing ODS BAPI methods “GetList” and “ReadData”

The ODS BAPI method Bapi_Odso_Getlist() is very easy to handle. To list all ODSObjects in the BW system just call the function using the appropriate parameters and loop thru the result set to print all object names. The following screenshot shows the output of the first part of the C# sample :

Figure 10 : output of C# sample – retrieving BW metadata ( existing ODSObjects )

Page 14: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

14

The ODS BAPI method Bapi_Odso_Read_Data() is also pretty easy to use. The sample

code shows how to specify search conditions for the values of the fields in the

ODSobject as well as the possibility to extract only certain fields instead of all of them.

The function uses neither MDX nor SQL which makes life much easier. Also processing

of the result set isn’t as complex as in the OLAP BAPI sample. The result set is just a list

of rows. Every row comes back as one string. In case all the fields of the ODSObject

which were selected would sum up to a rowlength of more then 250 bytes a second

string would belong to the same row and so on. This adds a bit complexity to the

processing. Metadata ( structure of the string which represents a row ) is provided in a

separate structure. The following screenshot shows the output of the second part of the

C# sample. The values of the key figures ( data fields of the ODSObject ) are identical to

the MDX query output of the “OLAP BAPI white paper” sample. The big difference are

the key fields. Here we get only the IDs for 0D_CO_CODE and 0D_SOLD_TO. The text

info from the master data tables is not available thru the ODS BAPI.

Figure 11 : output of C# sample – extracting data from the ODSObject

Page 15: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

15

Source listing of C# sample ( shows all ODS objects and extracts data from ODS object ODSDECU )

IMPORTANT : if you just copy the following code into Visual Studio you will get

errors during compilation in case you chose a different name than

SDNC_SAMPLE03 for your C# project. So just change the

namespace in the source listing accordingly.

using System; using SAP.Connector; namespace SDNC_SAMPLE03 { class Class1 { [STAThread] static void Main(string[] args) { // variables for processing the result set // and formatting on the screen as well as // parameters for the BAPI call int nr_odsobj=0; int nr_rs_rows=0; int nr_rs_cols=0; int infobj_offset=2; int ods_col_length=0; int max_ods_col_length=12; int ods_col_offset=0; int ods_max_rows=0; int ods_lines_per_record=0; int ods_nr_rows=0; string ods_objname=""; string ods_colname=""; string rs_currency=""; string rs_salesunit=""; // parameters for BAPI call BAPIRET2 ods_ret2; BAPI6116LTable ods_ltab = new BAPI6116LTable(); BAPI6116L ods_lrow; BAPI6116SLTable ods_sl16tab = new BAPI6116SLTable(); BAPI6100SLTable ods_sl00tab = new BAPI6100SLTable(); BAPI6116DALOTable ods_dalotab = new BAPI6116DALOTable(); BAPI6116DALO ods_dalorow; BAPI6116IOLSTable ods_iolstab = new BAPI6116IOLSTable(); BAPI6116IOLS ods_iolsrow; BAPI6116IOLSTable ods_iolsotab = new BAPI6116IOLSTable();

Page 16: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

16

BAPI6116DATable ods_datab = new BAPI6116DATable(); BAPI6116DA ods_darow; BAPI6116SLIOTable ods_sliotab = new BAPI6116SLIOTable(); BAPI6116SLIO ods_sliorow; // assemble connection string Destination bw_system = new Destination(); bw_system.AppServerHost = "hdmbw30b"; bw_system.Username = "rosetta"; bw_system.Password = "obelix"; bw_system.Client = 900; bw_system.SystemNumber = 1; // establish connection to BW SAPProxy1 sap_bw_proxy = new SAPProxy1(bw_system.ConnectionString); // BAPI call to get the list of all ODS objects // in the BW system. The first parameter ( object version ) // is set to 'A' to look only for "active" objects. // No selection criteria is specified. See the function // module documentation using transaction SE37 in BW and // type in "BAPI_ODSO_GETLIST" for more infos. sap_bw_proxy.Bapi_Odso_Getlist("A", out ods_ret2, ref ods_ltab, ref ods_sl16tab, ref ods_sl00tab ); // process the result set Console.Write("Number of ODS objects found : "); Console.WriteLine(ods_ltab.Count); for( nr_odsobj=0; nr_odsobj<ods_ltab.Count; nr_odsobj++ ) { ods_lrow = ods_ltab[nr_odsobj]; Console.WriteLine(); Console.WriteLine("ODS object "+(nr_odsobj+1)); Console.WriteLine(); Console.WriteLine(" ODS Object : "+ods_lrow.Odsobject); Console.WriteLine(" Infoarea : "+ods_lrow.Infoarea); Console.WriteLine(" Long descr : "+ods_lrow.Textlong); Console.WriteLine(); } Console.WriteLine("Press RETURN"); Console.ReadLine(); // look for the demo ODS object ods_objname = "ODSDECU"; for( nr_odsobj=0; nr_odsobj<ods_ltab.Count; nr_odsobj++ ) { if( ods_ltab[nr_odsobj].Odsobject.Equals(ods_objname) ) break; } if( nr_odsobj >= ods_ltab.Count ) { Console.WriteLine("ODS object "+ods_objname+" not found !"); Console.WriteLine();

Page 17: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

17

Console.WriteLine("Press RETURN"); Console.ReadLine(); return; } ods_lrow = ods_ltab[nr_odsobj]; // instead of selecting all fields from the ODS // object just select certain InfoObjects. The // result set will deliver them in the same order // as they were added in the following list. // // One issue – ‘currency’ and ‘unit’ will be delivered // as separate InfoObjects ( columns in the result ). // But there are two key figures in the result which // need the ‘currency’ added at the end of the string // to get a nice output. Therefore ‘currency’ and ‘unit’ // are put at the beginning of the list to make processing // of the result set easier later on. ods_iolsrow = new BAPI6116IOLS(); ods_iolsrow.Infoobject = "0DOC_CURRCY"; ods_iolstab.Add(ods_iolsrow); ods_iolsrow = new BAPI6116IOLS(); ods_iolsrow.Infoobject = "0SALES_UNIT"; ods_iolstab.Add(ods_iolsrow); ods_iolsrow = new BAPI6116IOLS(); ods_iolsrow.Infoobject = "0D_CO_CODE"; ods_iolstab.Add(ods_iolsrow); ods_iolsrow = new BAPI6116IOLS(); ods_iolsrow.Infoobject = "0D_SOLD_TO"; ods_iolstab.Add(ods_iolsrow); ods_iolsrow = new BAPI6116IOLS(); ods_iolsrow.Infoobject = "0D_COST"; ods_iolstab.Add(ods_iolsrow); ods_iolsrow = new BAPI6116IOLS(); ods_iolsrow.Infoobject = "0D_NETVLINV"; ods_iolstab.Add(ods_iolsrow); ods_iolsrow = new BAPI6116IOLS(); ods_iolsrow.Infoobject = "0D_INV_QTY"; ods_iolstab.Add(ods_iolsrow); // define the selection criteria. It's possible // to specify certain restrictions for every // InfoObject in the result. // See the function module documentation in // transaction SE37 for more infos about the // available options. But use the function name // BAPI_ODSO_READ_DATA_UC. The docu for the // Unicode version of the function provides more // details. // In the following code "BT" means "between" // ( between high and low value ). "I" means // that the boundary values should be included. ods_sliorow = new BAPI6116SLIO(); ods_sliorow.Iobjnm = "0D_CO_CODE";

Page 18: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

18

ods_sliorow.Low = "1000"; ods_sliorow.High = "2000"; ods_sliorow.Opt = "BT"; ods_sliorow.Sign = "I"; ods_sliotab.Add(ods_sliorow); ods_sliorow = new BAPI6116SLIO(); ods_sliorow.Iobjnm = "0D_SOLD_TO"; ods_sliorow.Low = "0000002100"; ods_sliorow.High = "0000002500"; ods_sliorow.Opt = "BT"; ods_sliorow.Sign = "I"; ods_sliotab.Add(ods_sliorow); // call the BAPI function to read data from // the ODSObject. If the third parameter is // empty it means that the InfoObject list // should be considered. If set to 'X' means // to select ALL InfoObjects. sap_bw_proxy.Bapi_Odso_Read_Data( ods_max_rows, ods_lrow.Odsobject, "", out ods_lines_per_record, out ods_nr_rows, out ods_ret2, ref ods_dalotab, ref ods_iolstab, ref ods_iolsotab, ref ods_datab, ref ods_sliotab ); // process the result set // // IMPORTANT : // Every row is returned as a string. If the string is // longer than 250 characters it's split. Therefore the // BAPI call parameter "ods_lines_per_record" exists. // In the sample all InfoObjects fit in one string which // makes the processing easier. Console.WriteLine("Result Set : "); Console.WriteLine(); // go thru all rows in the result set for(nr_rs_rows=0; nr_rs_rows<ods_datab.Count; nr_rs_rows++) { ods_darow = ods_datab[nr_rs_rows]; if( ods_dalotab.Count > 0 ) { // get the currency text from the current result row. // Method get_rs_value() is defined further down. get_rs_value("0DOC_CURRCY",ref ods_dalotab, ref ods_darow, out rs_currency); // get the unit text from the current result row get_rs_value("0SALES_UNIT",ref ods_dalotab, ref ods_darow, out rs_salesunit); // before printing the first result row print a header // with the column/field names ( InfoObject names ) if( nr_rs_rows == 0 ) {

Page 19: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

19

// use a hard-coded offset to skip the first two // InfoObjects which are "currency" and "unit" // ( mentioned above when specifying the InfoObjects // which should be retrieved ). Print the other names // as the header line. for(nr_rs_cols=infobj_offset; nr_rs_cols < ods_dalotab.Count; nr_rs_cols++) { ods_dalorow = ods_dalotab[nr_rs_cols]; Console.Write(ods_dalorow.Infoobject.PadLeft (max_ods_col_length,' ') + " | "); } Console.WriteLine(); // print a line of dashes to make the output nicer. for(nr_rs_cols=infobj_offset; nr_rs_cols < ods_dalotab.Count-1; nr_rs_cols++) { Console.Write("".PadLeft(max_ods_col_length,'-') + "-+-"); } Console.Write("".PadLeft(max_ods_col_length,'-') + "-+"); Console.WriteLine(); } } // print the values of the result set. As every row is // sent back as a string it's necessary to use the // "ods_dalotab" structure which includes the meta data // to figure out which InfoObjects are included in the // result and what their offset and length are. This // info is used to find the correct substrings. for(nr_rs_cols=infobj_offset; nr_rs_cols < ods_dalotab.Count; nr_rs_cols++) { ods_dalorow = ods_dalotab[nr_rs_cols]; ods_col_offset = System.Convert.ToInt32(ods_dalorow.Offset); ods_col_length = System.Convert.ToInt32(ods_dalorow.Length); // the length info didn't fit for some reason for // the last column. The length was 3 and the offset // was 88. But the total length of the row string // was 90. As it's the unit string which was 'ST' // in the sample - the quick and dirty workaround was // to just correct the length for this last column. if( (ods_col_offset + ods_col_length) > ods_darow.Data.Length ) ods_col_length = ods_darow.Data.Length - ods_col_offset; // in case of the two key figures add the currency // text to the string if( ods_dalorow.Infoobject.Equals("0D_COST") || ods_dalorow.Infoobject.Equals("0D_NETVLINV") ) ods_colname = ods_darow.Data.Substring(ods_col_offset, ods_col_length ).Trim() + " " + rs_currency.Trim(); else // in case of the quantity column add the unit text

Page 20: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

20

// to the string if( ods_dalorow.Infoobject.Equals("0D_INV_QTY")) ods_colname = ods_darow.Data.Substring(ods_col_offset, ods_col_length ).Trim() +" "+ rs_salesunit.Trim(); else ods_colname = ods_darow.Data.Substring(ods_col_offset, ods_col_length ).Trim(); Console.Write( ods_colname.Trim().PadLeft(max_ods_col_length,' ') + " | "); } // end for-loop thru all InfoObjects within one result row Console.WriteLine(); } // end for-loop thru all rows in the result set // print again a line of dashes at the end to make the output // nicer for(nr_rs_cols=infobj_offset; nr_rs_cols < ods_dalotab.Count-1; nr_rs_cols++) { Console.Write("".PadLeft(max_ods_col_length,'-') + "-+-"); } Console.Write("".PadLeft(max_ods_col_length,'-') + "-+"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Press RETURN"); Console.ReadLine(); } // end main // method which searches in the meta data structure // for a certain InfoObject and gets the appropriate // substring ( value of the object ) from a result // row which is in fact one long string. static void get_rs_value(string inf_objname, ref BAPI6116DALOTable ods_dalotab, ref BAPI6116DA ods_darow, out string rs_value) { int i; int col_offset; int col_length; BAPI6116DALO ods_infobj; rs_value = ""; for(i=0; i<ods_dalotab.Count; i++) { ods_infobj = ods_dalotab[i]; if( ods_infobj.Infoobject.Equals(inf_objname) ) { col_offset = System.Convert.ToInt32(ods_infobj.Offset); col_length = System.Convert.ToInt32(ods_infobj.Length); // the length info didn't fit for some reason for // the last column. The length was 3 and the offset // was 88. But the total length of the row string // was 90. As it's the unit string which was 'ST'

Page 21: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

21

// in the sample - the quick and dirty workaround was // to just correct the length for this last column. if( (col_offset + col_length) > ods_darow.Data.Length ) col_length = ods_darow.Data.Length - col_offset; rs_value = ods_darow.Data.Substring(col_offset, col_length ); } // end if – InfoObject found } // end for-loop thru all InfoObjects } // end get_rs_value() – return value for an InfoObject } // end class } // end namespace

Page 22: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

22

Conclusion SAP .NET Connector 2.0 is a great tool which relieves developers from all the Remote

Function Call details in order to access the SAP BW BAPIs. What’s left are parameter

definitions / settings and processing the result sets. Depending on the BAPI method this

might be still some work. But it’s definitely an elegant and easy way to connect SAP BW

with the Microsoft .NET world.

It’s easier to select data from an ODSObject using the ODS BAPI than to send a MDX

query thru the OLAP BAPI. Depending on the project requirements it might be worth the

overhead and additional need of space inside BW to create an ODSObject just for the

task to access the data from an external program as the coding complexity would be

less compared to the OLAP BAPI.

Limitations The C# sample should just help to get a quick start on the topic. It cannot be used

unmodified for real application development ( e.g. no error handling included ). The

sample was tested with a simple ODSObject. It’s not guaranteed that it works 100%

correct with every ODSObject and all levels of complexity. Some changes would be

necessary anyway to work with a different ODSObject as the object name ODSDECU

as well as the InfoObject selection list and search conditions are hard-coded.

The SAP BW ODS BAPI was not made for unloading masses of data. OpenHubService

is the tool which should be used instead.

There is a difference between reporting and unloading. Imagine a BW query which

selects certain data from an ODSObject. If this data would be stored in an external

OLAP engine like Microsoft Analysis Services it’s no longer called reporting.

Whenever you extract data from the mySAP BI environment into 3rd-party target

systems your SAP BW Enterprise Data Warehouse functions as an ‘Open Hub Platform’.

Since extracting data from SAP BW by any means requires additional licensing, please

make sure to contact your SAP representative.

Page 23: Access to the SAP BW ODS BAPI using C# and SAP …...1 Access to the SAP BW ODS BAPI using C# and SAP .NET Connector 2.0 Hermann Däubler, Program Manager, Microsoft Corporation Summary

23

References ODSObject :

http://help.sap.com/saphelp_nw04/helpdata/en/f9/45503c242b4a67e10000000a114084/content.htm