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 1 into vkorg.
Read Table reqparm index 2 into vtweg.
Read Table reqparm index 3 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.
|
|