Characteristics of the CIS ABAP interface

The CIS ABAP interface is easy to use and a fast way to read SAP data via an ABAP routine. The further processing and the visualization of the data can then be implemented in VB.NET and HTML.

In VB.NET we call an ABAP routine of the function module /GUIXT/CISADDON_INTERFACE. All input parameters are strings in a predefined order, e.g.

Parameter 1: Customer number
Parameter 2: Order number

The ABAP routine returns a table where each row is a string. The string can contain multiple values, separated from each other by a tab character. Alternatively you may return a long text or data in XML format.

Pros and cons:

  • Requires ABAP knowledge
  • Excellent performance achievable
  • Complex select statements and SAP standard module calls are possible
  • Authorization checks, if necessary, implemented in ABAP
  • Quick implementation
  • Very versatile
  • Well suited for CIS report implementation

In the called routine you can read all data needed in your application. In particular, it often makes sense to add the language dependent texts for the given keys that you wish to display.

Example 1:
Retrieving stock overview data

For a given material number we want to display a stock overview:

The documentation Example "Stock overview" describes how you integrate this add-on into CIS mobile. Here we concentrate on the data retrieval part.

We know the material number and want to return a table with plant and stock number, texts for plant and stock and various availability figures.

The name of our routine is  "MaterialStock"  and its interface is as follows:

Input: Material number

Output: For each plant and stock one row with plant and stock id, plant and stock text and 4 stock numbers: "Freely available", "Rearrangement", "Q-Text" and "Returns."

Next we need to figure out how we can retrieve these data in ABAP. If the SAP database contains the information we can use an ABAP Select statement. If complex logic is necessary to build up the data we need to look for existing SAP functions  e.g. BAPIs.

In our case we can retrieve tha data directly form the database:

  • The four stock figures are stored in table MARD
  • The plant text is in table T001W
  • The stock text is in table T001L

For performance reasons we try to minimize the number of database calls. The ABAP Select statement provides various ways to formulate complex queries such as joins and subqueries that often can replace a series of simple Select commands.

When we read tables that are kept in the SAP application server cache (e.g. small customizing tables), multiple Select statements are no problem since they are executed locally on the application server in a very short period of time.

In our case we assume that the tables T001W and T001L are in the SAP cache, in contrast to table MARD which can be big and probably will not be cached. For this reason we first read table MARD and then use single Select calls to read the texts for each plant and stock. The alternative is to use a complex "join" for the three tables, but in our case this would not be faster.

In total our ABAP coding looks as follows:

ABAP
* Stock quantities for each plant
*
* In
* 1 MATNR Material number
*
* Out
*  Stok quantities

form MaterialStock tables reqparm resparm   
                        changing   rc type c   msg type c.

  data: wa(8000).
  data: parmatnr like mard-matnr.

  Read Table reqparm index 1 into parmatnr.

* Stock quantities
  data: begin of stock occurs 10,
          werks like mard-werks,
          lgort like mard-lgort,
          labst like mard-labst,
          umlme like mard-umlme,
          insme like mard-insme,
          retme like mard-retme,
       end of stock.

* Texts
  Data: werks_text like t001w-name1,
        lgort_text like t001l-lgobe.

* Quantities, character format
  Data: labst_char(16),
        umlme_char(16),
        insme_char(16),
        retme_char(16).

  select *  from mard into corresponding fields of table stock
                    where matnr = parmatnr and labst > 0.


  Sort stock.
  Loop at stock.

* Authority check
    AUTHORITY-CHECK OBJECT 'M_MATE_WRK'
      ID 'WERKS' FIELD STOCK-WERKS
      ID 'ACTVT' FIELD '03'.

* not authorized?
    if sy-subrc NE 0.
      UNPACK 4 to rc.
      if msg = space.
        Concatenate 'Missing authorization for plant:' STOCK-WERKS 
                                      into msg separated by space.
      else.
        Concatenate MSG STOCK-WERKS into msg separated by ','.
      endif.

    else.
* read texts
      Select single name1 from t001w into werks_text
               where werks = stock-werks.

      Select single lgobe from t001l into lgort_text
                where werks = stock-werks and lgort = stock-lgort.

* character format of quantities

      Write:
        stock-labst to labst_char decimals 0,
        stock-umlme to umlme_char decimals 0,
        stock-insme to insme_char decimals 0,
        stock-retme to retme_char decimals 0.


* output result
      Concatenate
          stock-werks
          werks_text
          stock-lgort
          lgort_text
          labst_char
          umlme_char
          insme_char
          retme_char
               into wa 
                separated by cl_abap_char_utilities=>horizontal_tab.

      Append wa to resparm.

    endif.
  Endloop.
Endform.

We have added an "Authority-Check" statement in order to check the user authorization needed to display plant data.
Description of the ABAP part of the interface

All ABAP routines are part of the function module  /GUIXT/CISADDON_INTERFACE. Formally, the interfaces of all these routines are the same:

form xxxx tables reqparm resparm   changing   rc type c   msg type c.

Here reqparm is the input table and resparm is the output table. With return code rc=0 we indicate normal processing and with rc>0 an error situation; in this case we can set an error text into parameter msg.

All input parameters are read using their parameter number. For example, when we pass three keys VKORG, VTWEG and SPART from VB.NET, we read the three key values with

   Read Table reqparm index into vkorg.
  Read Table reqparm index into vtweg.
  Read Table reqparm index into spart.

into the the ABAP variables vkorg, vtweg and spart.

The output table resparm consists of rows of ABAP type C (character) with a maximum length of 8000. The content can be arbitrary. A very practical format is to put multiple values into one row, separated by a tab character. When we return long texts we use a different format; see example 3.
 

Description of the VB.NET part of the interface

In order to execute the ABAP routine from VB.NET we build up the input table, call the routine with ic.RfcRequest() and then process the output table. For our example "MaterialStock" above this looks as follows:
 
VB.net
    ' Stock overview 
    Public Function BuildMaterialStock(ByVal keys _ 
                  As Dictionary(Of String, String), ByRef buttons As String) As String

        ' We use CIS addon ABAP function to read the stock quantities

        ' Clear input/output
        rfc_input.Clear()
        rfc_output.Clear()

        ' Build up input
        Dim s As addonsimplestring = DirectCast(rfc_input.AddNew(), addonsimplestring)
        s.content = GetItem(keys, "MATNR")

        ' Request data
        ic.RfcRequest("CISADDON.MATERIALSTOCK", "S", rfc_input, rfc_output, deferred:=True)

        ' execute all requests (one only in our case)
        ic.RfcExecuteDeferredCalls(rfcmessages)

       
        For Each line As addonsimplestring In rfc_output

           ...

        Next

        

    End Function

You can find the full VB.NET source in the documentation Example "Stock overview" and in the VB.NET add-on-Project contained in the CIS installation.

 

Example 2:
Retrieving customer pricing information

Our next example is the data retrieval for the "Pricing" report:

We proceed as in example 1. The name of our new routine is "PRICING" and its interface is as follows:

Input:
Sales organization, distribution channel, division, customer numbers (one customer number per row)

Output: For each customer one row with customer number, price group with text, pricing scheme with text, price list with text.

Next we determine how to read the data in ABAP::

  • The keys for the pricing information are stored in table KNVV
  • The texts for price group, pricing scheme and price list are stored in the tables T188T, TVKDT und T189T.

How can you obtain these table names? One approach is to search in internet to see whether other people have already looked for this information. A second way is to use the F1 help function in SAP which provides the technical field name, domain name and hopefully a database table name. A third approach is to use the SAP database trace. This trace often contains many table names for a single screen display which results in a longer search for the right table. Finally, there are books available that describe SAP transactions and database layout.

If you think that a particular table is the right one, display its structure and its content with transaction SE11.

For performance reasons try to avoid making a separate database call for each customer, e.g. 100 database calls if the list contains 1000 customers. Instead use the option of passing a whole set of keys to a single ABAP Select command (option "FOR ALL ENTRIES IN ...").

Our ABAP coding then looks as follows:

ABAP
* Pricing
* In
* 1 VKORG
* 2 VTWEG
* 3 SPART
* 4 KUNNR and following: customer numbers
*
* Out
*  KUNNR  KONDA KONDATEXT  KALKS KALKSTEXT  PLTYP PLTYPTEXT
form PRICING tables reqparm resparm   
                   changing   rc type c   msg type c.

  data: wa(8000).
  data: vkorg like knvv-vkorg,
        vtweg like knvv-vtweg,
        spart like knvv-spart.




  Read Table reqparm index 1 into vkorg.
  Read Table reqparm index 2 into vtweg.
  Read Table reqparm index 3 into spart.
  Read Table reqparm index 4 into wa.

* Customer numbers
  data: begin of customers occurs 10,
          kunnr like kna1-kunnr,
        end of customers.

  Data: k type i value 4.
  Read Table reqparm index k into customers-kunnr.
  While sy-subrc EQ 0.
    Append customers.

    k = k + 1.
    Read Table reqparm index k into customers-kunnr.
  Endwhile.

* no customers?
  if   customers[] is initial.
    exit.
  endif.

* Result tables
  data: begin of r1 occurs 10,
          kunnr like knvv-kunnr,
          konda like knvv-konda,
          kalks like knvv-kalks,
          pltyp like knvv-pltyp,
       end of r1.


  Select kunnr konda kalks pltyp
           from knvv
             into corresponding fields of table r1
               for all entries in customers
              where vkorg = vkorg
    and vtweg = vtweg
    and spart = spart
    and kunnr = customers-kunnr.

  sort r1.

  Data: kondatext like t188t-vtext,
        kalkstext like tvkdt-vtext,
        pltyptext like t189t-ptext.

  Loop at r1.

    kondatext = ''.
    kalkstext = ''.
    pltyptext = ''.

    Select single vtext from t188t into kondatext 
                    where spras = sy-langu and konda = r1-konda.
    Select single vtext from tvkdt into kalkstext 
                    where spras = sy-langu and kalks = r1-kalks.
    Select single ptext from t189t into pltyptext 
                    where spras = sy-langu and pltyp = r1-pltyp.

* output result
    Concatenate
        r1-kunnr
        r1-konda
        kondatext
        r1-kalks
        kalkstext
        r1-pltyp
        pltyptext
         into wa separated by cl_abap_char_utilities=>horizontal_tab.

    Append wa to resparm.


  Endloop.
Endform.

 


Please note the follwowing detail in the ABAP coding:

* no customers?
  if   customers[] is initial.
    exit.
  endif

This is necessary since an empty key table in option  "FOR ALL ENTRIES IN ..:" results in a full table scan.
Example 3:
Reading a production order text

The following example shows how to read an SAP long text. We read the production order long text:

We start as in example 1 and define a name for the ABAP routine e.g.  "ADDON_AUFK_LONGTEXT" and the interface:

Input: Order number

Output: Long text, one text line in an output table line

Next we need to implement the long text reading in ABAP:

  • We use the function module READ_TEXT in order to read the text in internal SAP text format "ITF"
  • Then we use the function module CONVERT_ITF_TO_ASCII which returns the text as a simple text table

The text will be searched in the logon language and, if not found, then in English and finally in German.

ABAP

* Read longtext of productionorder (CO03)
form ADDON_AUFK_LONGTEXT tables reqparm resparm   
                      changing   rc type c   msg type c.


  DATA: AUFNR like aufk-aufnr.

* 1st parameter: document number
  Read Table reqparm index 1 into AUFNR.

* texts
  DATA: BEGIN OF T_HEAD.
          INCLUDE STRUCTURE THEAD.
  DATA: END OF T_HEAD.

* text lines
  DATA: BEGIN OF T_LINES OCCURS 0.
          INCLUDE STRUCTURE TLINE.
  DATA: END OF T_LINES.

* Order number with client
  DATA: BEGIN OF CLIENTAUFNR,
          CLIENT LIKE SY-MANDT,
          AUFNR LIKE AUFK-AUFNR,
        END OF CLIENTAUFNR.

  CLIENTAUFNR-CLIENT = SY-MANDT.
  CLIENTAUFNR-AUFNR  = AUFNR.


*  Read long text
  Perform set_textkeys using 'AUFK' CLIENTAUFNR 'KOPF'.

  T_HEAD-TDID = textkeys-tdid.
  T_HEAD-TDNAME = textkeys-tdname.
  T_HEAD-TDSPRAS = textkeys-tdspras.
  T_HEAD-TDOBJECT = textkeys-tdobject.

  CALL FUNCTION 'READ_TEXT'
    EXPORTING
      ID       = T_HEAD-TDID
      LANGUAGE = T_HEAD-TDSPRAS
      NAME     = T_HEAD-TDNAME
      OBJECT   = T_HEAD-TDOBJECT
    IMPORTING
      HEADER   = T_HEAD
    TABLES
      LINES    = T_LINES
    EXCEPTIONS
      OTHERS   = 1.


  CALL FUNCTION 'CONVERT_ITF_TO_ASCII'
    TABLES
      ITF_LINES = T_LINES.


  LOOP AT T_LINES.
    Append T_LINES-TDLINE TO RESPARM.
  ENDLOOP.



endform.

 


Here we use the helper function "set_textkeys":

Perform set_textkeys using 'AUFK' CLIENTAUFNR 'KOPF'.

It checks whether a text exists in the logon language, then in English and finally in German, and sets the text key appropriately:

ABAP
 
Form set_textkeys using tdobject tdname tdid.

  Clear textkeys.
  Select single * from stxh into corresponding fields of textkeys
      where tdobject = tdobject and tdname = tdname 
                and tdid = tdid and tdspras = sy-langu.

* try English
  if sy-subrc ne 0 and sy-langu ne 'E'.
    Select single * from stxh into corresponding fields of textkeys
    where tdobject = tdobject and tdname = tdname and tdid = tdid 
                               and tdspras = 'E'.
  endif.

* try German
  if sy-subrc ne 0 and sy-langu ne 'D'.
    Select single * from stxh into corresponding fields of textkeys
    where tdobject = tdobject and tdname = tdname 
                            and tdid = tdid and tdspras = 'D'.
  endif.


Endform.