Вы находитесь на странице: 1из 17

Customizing SAP for Dummies: ABAP Tutorial for Students with some Programming Experience Part 1

As you know, I am going through some kind of ABAP training right now with the help of one of the team members. I have spend the last two weeks reading the documentation of help.sap.com and feel I am starting to get a better grip of what ABAP is and how you can use it. The goal of this tutorial is to give any person with the basic knowledge of procedural programming, object-oriented programming (OOP) and SQL, a good overview of what the possibilities of the language are and how to understand a basic ABAP program. So lets start. Programs in SAP are created, edited and debugged in the same presentation framework you normally use to access the SAP programs. These programs are called Transactions and are either local programs or belong to a package. The only reason for using packages is to group different files that belong together and make the transportation phase easier. Transportation meaning changing the status of a program, from the programing phase to the testing phase, to finally transporting the program to the SAP master. Any program written in ABAP begins with one of the following introductory statements, a space and the name of the program:

REPORT PROGRAM FUNCTION-POOL CLASS-POOL INTERFACE-POOL TYPE-POOL

What you normaly use is a report. A report is nothing more than an executable programm. Function pools are, as its name says, pools of functions you can include in your executable program. The same for type pools, which contains definitions of types to use in executable programs. Class pools are used in OOP, so we will come to that later (when I get to the topic in my training :-) ) Once you have defined the type of program and its name, you can start with the types and data definitions. I will explain both together as their similarities are many. To define a new type you have following syntax

TYPES new_type {TYPE {REF TO} defined_type} | {LIKE {REF TO} defined_variable}.

This code defines a new type new_type based on the already defined type defined_type or based on the type of the variable defined_variable. If you use the keyword REF TO the new type will be only a pointer to a variable of that type. Analogous we can use following syntax to define a variable:

DATA new_type{(c)} {TYPE {REF TO} defined_type} | {LIKE {REF TO} defined_variable} {VALUE d}.
Just notice that if you use the option (c) you will create an array of c elements of the defined type, and using the keyword VALUE you can assign a value d to the variable. And for the end of this part I just want to show you the predefined types in ABAP you can use when defining new types or variables. Numeric Types Type Integer Floating point number Packed number Character Types Type Characters Date Time Hexadecimal field Identifier C D T X Initial Value 00000000 000000 0 Lenght (in Bytes) 1 65535 8 6 1 65535 Format YYYYMMDD HHMMSS X0000..000 Identifier I F P Initial Value 0 0 0 Lenght (in Bytes) 4 8 1-16 Format 0000- (negative) / 0000 (positive)

Customizing SAP for Dummies: ABAP Tutorial for Students with some Programming Experience Part 2
In the first part of this tutorial I explained the basics of programs and types in ABAP. Today I will introduce you to the a first ABAP program, which in a way is a Hello World program for ABAP, using the possible features of ABAP in a single simple report. As I said last time a report is nothing more than an executable file. So here it is: view source print?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 *&--------------------------------------------* *& Report ZSER1301 *& *&--------------------------------------------* *& *& *&--------------------------------------------* REPORT zser1301. * Declarative Section TYPES: BEGIN OF zsf_type, carrid LIKE sflight-carrid, carrname LIKE scarr-carrname, currcode LIKE scarr-currcode, minpay LIKE sflight-paymentsum, maxpay LIKE sflight-paymentsum, avgpay LIKE sflight-paymentsum, totpay LIKE sflight-paymentsum, END OF zsf_type. DATA: i_tab_fl TYPE STANDARD TABLE OF zsf_type, wa_tab_fl TYPE zsf_type, time_beg TYPE i, time_end TYPE i, time_tot TYPE i. * Program Statements GET RUN TIME FIELD time_beg. SELECT MIN( MAX( AVG( SUM( FROM sflight~carrid scarr~carrname paymentsum ) AS minpay paymentsum ) AS maxpay paymentsum ) AS avgpay paymentsum ) AS totpay sflight JOIN scarr

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

ON sflight~carrid = scarr~carrid INTO CORRESPONDING FIELDS OF TABLE tab_fl GROUP BY sflight~carrid scarr~carrname ORDER BY sflight~carrid. GET RUN TIME FIELD time_end. time_tot = ( time_end - time_beg ). WRITE:/ 'Carriers Data'. ULINE. WRITE:/(8) 'CARRIER', (20) 'NAME',(23) 'MIN PAY', (23) 'MAX PAY', (23) 'AVG PAY', (23) 'SUM PAY'. ULINE. LOOP AT i_tab_fl INTO wa_tab_fl. WRITE:/(8) wa_tab_fl-carrid, (20) wa_tab_fl-carrname, (17) wa_tab_fl-minpay, wa_tab_fl-currcode, (17) wa_tab_fl-maxpay, wa_tab_fl-currcode, (17) wa_tab_fl-avgpay, wa_tab_fl-currcode, (17) wa_tab_fl-totpay, wa_tab_fl-currcode. ENDLOOP. WRITE: /, / 'Runtime = ', time_tot.

Now lets go through it and I will try to explain how all this code works. Lines 11-19: Here we declare the structure type we will use in the program. sflight and scarr are two tables declared in the ABAP dictionary. All tables declared in this dictionary are global and may be used in any program. In scarr information about different airlines in store, and in sflight that about flights of these airlines. Lines 21-25: We declare an internal table, which is of type of this structure. This means we have one or more entries, and in each entry such an structure. After this we declare a work area, of the same type as the table entry. And declare three integer variables, which we use to calculate the runtime of the report. Lines 28, 41, 43: We get the user time before the logic, after it, and then calculate the total. Lines 30-39: SQL query. I asume you have some idea of SQL, so I am just going to explain all the ABAP related stuff. We select diferent fields and use some aggregate functions on the paymentsum field of sflight. In order to do this we use group by, and use order by just

to have a better output. We are selecting from a join of two different tables. Pay attention to line 37. In this line we tell the database to store the result of the SQL query into the internal table tab_fl, and to only store the fields of the select, which exist in the internal table. Lines 45-49: We display the title and fields of the table. Lines 51-58: We display the data store in our internal table. To do this we use a loop at the internal table into the work area. This means that in each iteration of the loop we will get another entry of the internal table in the work area. We use the syntax workareafieldname to access the field values. We let the program run, and get the following screen:

Screen of Report ZSER1301 That was not so difficult, was it? I know you are probably thinking this is not the kind of program you program in every language, but it is the most typical report in ABAP. Actually, a report is call this way, because you get information and report it back. So now that we have written a program that works, lets try to write the same thing and use the right tools for it. In the next example we will do exactly the same. For it we will declare the structure type in the ABAP dictionary and create a function module (FM), which works like a subroutine, to get the information from the database. This way we make use of the principle of modularity, reusability and continuity. So the first thing we do, is create the structure type, using the object explorer:

ZSF_TYPE Structure We rewrite the report: view source print?


01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 *&--------------------------------------------* *& Report ZSER1300 *& *&--------------------------------------------* *& *& *&--------------------------------------------* REPORT zser1300. * Declarative Section *TABLES: scarr, sflight. DATA: i_tab_fl TYPE STANDARD TABLE OF zsf_type, wa_tab_fl TYPE zsf_type, time_tot TYPE i. * Program Statements CALL FUNCTION 'ZSER1300_FM' IMPORTING time_tot = time_tot TABLES tab_fl = i_tab_fl. WRITE:/ 'Carriers Data'. ULINE. WRITE:/(8) 'CARRIER', (20) 'NAME',(23) 'MIN PAY',

29 30 31 32 33 34 35 36 37 38 39 40 41

(23) 'MAX PAY', (23) 'AVG PAY', (23) 'SUM PAY'. ULINE. LOOP AT i_tab_fl INTO wa_tab_fl. WRITE:/(8) wa_tab_fl-carrid, (20) wa_tab_fl-carrname, (17) wa_tab_fl-minpay, wa_tab_fl-currcode, (17) wa_tab_fl-maxpay, wa_tab_fl-currcode, (17) wa_tab_fl-avgpay, wa_tab_fl-currcode, (17) wa_tab_fl-totpay, wa_tab_fl-currcode. ENDLOOP. WRITE: /, / 'Runtime = ', time_tot.

and in line 20 we call the function module ZSER1300_FM and pass the variables which are going to be return. If you take a look at the interface of ZSER1300_FM, you will see the declaration of the variables used in the FM. All not optional will have to be assigned at the time of the FM call. view source print?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 FUNCTION ZSER1300_FM. *&--------------------------------------------* *"Local Interface: *" EXPORTING *" REFERENCE(TIME_TOT) TYPE *" TABLES *" TAB_FL STRUCTURE I

ZSF_TYPE I OPTIONAL

*" CHANGING *" REFERENCE(TIME_BEG) TYPE

*" REFERENCE(TIME_END) TYPE I OPTIONAL *&--------------------------------------------* GET RUN TIME FIELD time_beg. SELECT sflight~carrid scarr~carrname MIN( paymentsum ) AS minpay MAX( paymentsum ) AS maxpay AVG( paymentsum ) AS avgpay SUM( paymentsum ) AS totpay FROM sflight JOIN scarr ON sflight~carrid = scarr~carrid INTO CORRESPONDING FIELDS OF TABLE tab_fl GROUP BY sflight~carrid scarr~carrname ORDER BY sflight~carrid. GET RUN TIME FIELD time_end. time_tot = ( time_end - time_beg ).

28 ENDFUNCTION.

Customizing SAP for Dummies: ABAP Tutorial for Students with some Programming Experience Part 3
It is time to continue the ABAP tutorial. After the basics in Part 1 and the first report in Part 2, in this part we are going to take a look at the different events in ABAP used in what is called an Interactive Report. An Interactive Report is supposed to display information about a list of items, and each time we click on one of these items, to display the details of such item in a so called subscreen. As always lets start with the source code of the report and the source code of the different FMs: view source print?
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 *&------------------------------------------------* *& Report Z_TEST_INT_REP *& *&------------------------------------------------* *& *& *&------------------------------------------------* REPORT z_test_int_rep NO STANDARD PAGE HEADING.

DATA: vbak_input TYPE zvbak_input, vbak_output TYPE STANDARD TABLE OF ztabfm01, wa_vbak TYPE ztabfm01, vbap_input TYPE STANDARD TABLE OF ztabfm02, vbap_output TYPE STANDARD TABLE OF ztabfm02, wa_vbap TYPE ztabfm02, vbeln_n TYPE n LENGTH 10, vbep_output TYPE STANDARD TABLE OF ztabfm03, wa_vbep TYPE ztabfm03, box TYPE c. PARAMETERS: vbtyp LIKE OBLIGATORY auart LIKE OBLIGATORY vkorg LIKE OBLIGATORY vtweg LIKE vbak_input-vbtyp VALUE CHECK, vbak_input-auart VALUE CHECK, vbak_input-vkorg VALUE CHECK, vbak_input-vtweg

032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083

OBLIGATORY VALUE CHECK, spart LIKE vbak_input-spart OBLIGATORY VALUE CHECK. INITIALIZATION. vbtyp = 'C'. auart = 'TA'. vkorg = '1000'. vtweg = '10'. spart = '00'. TOP-OF-PAGE. WRITE:/ 'Sales Header'. ULINE. WRITE:/ 'Document', (10) 'Category', (12) 'Organization'. ULINE. TOP-OF-PAGE DURING LINE-SELECTION. CASE sy-lsind. WHEN 1. WRITE:/ 'Sales Item'. ULINE. WRITE:/(15) 'Document', (10) 'Item', (17) 'Material Number', (12) 'Price'. ULINE. WHEN 2. WRITE:/ 'Sales Schedule Line'. ULINE. WRITE:/(15) 'Document', (10) 'Item', (18) 'Schedule Number', (15) 'Order quantity', (15) 'Conf. quantity'. ULINE. ENDCASE. AT SELECTION-SCREEN. PERFORM vbak_in_to_out. IF vbak_output IS INITIAL. MESSAGE e888(sabapdocu) WITH 'No entries found'. ENDIF. START-OF-SELECTION. PERFORM vbak_in_to_out. PERFORM display_data_vbak. AT LINE-SELECTION. CASE sy-lsind. WHEN 1. CLEAR: vbap_input. DO. CLEAR: wa_vbap. READ LINE sy-index FIELD VALUE box

084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136

wa_vbak-vbeln INTO vbeln_n. IF sy-subrc NE 0. EXIT. ELSEIF box = 'X'. MOVE vbeln_n TO wa_vbap-vbeln. APPEND wa_vbap TO vbap_input. ENDIF. ENDDO. IF vbap_input IS INITIAL. MESSAGE s888(sabapdocu) WITH 'No line selected'. sy-lsind = sy-lsind - 1. ELSE. CLEAR vbap_output. CALL FUNCTION 'Z_TEST_FUNCT_BE_INT2' TABLES vbeln_in = vbap_input vbap_det = vbap_output. IF vbap_output IS INITIAL. MESSAGE s888(sabapdocu) WITH 'No items to display'. sy-lsind = sy-lsind - 1. ELSE. PERFORM display_data_vbap. ENDIF. ENDIF. WHEN 2. CALL FUNCTION 'Z_TEST_FUNCT_BE_INT3' EXPORTING vbeln_in = wa_vbap-vbeln posnr_in = wa_vbap-posnr TABLES vbep_det = vbep_output. PERFORM display_data_vbep. WHEN 3. MESSAGE s888(sabapdocu) WITH 'No more subscreens available'. ENDCASE. *&------------------------------------------------* *& Form display_data_vbak *&------------------------------------------------* * text *&------------------------------------------------* FORM display_data_vbak. LOOP AT vbak_output INTO wa_vbak. WRITE:/ box AS CHECKBOX, wa_vbak-vbeln, (10) wa_vbak-vbtyp, (12) wa_vbak-vkorg. ENDLOOP. ENDFORM. "display_data_vbak

137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182

*&------------------------------------------------* *& Form display_data_vbap *&------------------------------------------------* * text *&------------------------------------------------* FORM display_data_vbap. LOOP AT vbap_output INTO wa_vbap. WRITE:/(15) wa_vbap-vbeln, (10) wa_vbap-posnr, (17) wa_vbap-matnr, (12) wa_vbap-netpr. HIDE wa_vbap. ENDLOOP. ENDFORM. "display_data_vbap *&------------------------------------------------* *& Form display_data_vbep *&------------------------------------------------* * text *&------------------------------------------------* FORM display_data_vbep. LOOP AT vbep_output INTO wa_vbep. WRITE:/(15) wa_vbep-vbeln, (10) wa_vbep-posnr, (17) wa_vbep-etenr, (15) wa_vbep-wmeng, (15) wa_vbep-bmeng. ENDLOOP. ENDFORM. "display_data_vbep *&------------------------------------------------* *& Form vbak_in_to_out *&------------------------------------------------* * text *&------------------------------------------------* FORM vbak_in_to_out. CLEAR: vbak_input, vbak_output. vbak_input-vbtyp = vbtyp. vbak_input-auart = auart. vbak_input-vkorg = vkorg. vbak_input-vtweg = vtweg. vbak_input-spart = spart. CALL FUNCTION 'Z_TEST_FUNCT_BE_INT1' EXPORTING vbak_input = vbak_input TABLES vbak_det = vbak_output. ENDFORM. "vbak_in_to_out

view source print?


01 FUNCTION Z_TEST_FUNCT_BE_INT1. 02 *"-----------------------------------------------03 *"*"Local Interface:

04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20

*" IMPORTING *" REFERENCE(VBAK_INPUT) TYPE

ZVBAK_INPUT

*" TABLES *" VBAK_DET STRUCTURE ZTABFM01 *"-----------------------------------------------SELECT vbeln erdat erzet ernam vbtyp auart vkorg vtweg spart FROM vbak INTO CORRESPONDING FIELDS OF TABLE vbak_det * UP TO 100 ROWS WHERE vbtyp = vbak_input-vbtyp AND auart = vbak_input-auart AND vkorg = vbak_input-vkorg AND vtweg = vbak_input-vtweg AND spart = vbak_input-spart. ENDFUNCTION.

view source print?


01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 FUNCTION z_test_funct_be_int2. *"-----------------------------------------------*"*"Local Interface: *" TABLES *" VBELN_IN STRUCTURE ZTABFM02

*" VBAP_DET STRUCTURE ZTABFM02 *"-----------------------------------------------SELECT vbeln posnr matnr kwmeng netpr werks INTO CORRESPONDING FIELDS OF TABLE vbap_det FROM vbap FOR ALL ENTRIES IN vbeln_in WHERE vbeln EQ vbeln_in-vbeln. ENDFUNCTION.

view source print?


01 02 03 04 05 06 07 08 09 10 11 12 13 FUNCTION z_test_funct_be_int3. *"-----------------------------------------------*"*"Local Interface: *" IMPORTING *" REFERENCE(VBELN_IN) TYPE *" *" REFERENCE(POSNR_IN) TYPE TABLES VBELN_VA

POSNR

*" VBEP_DET STRUCTURE ZTABFM03 *"-----------------------------------------------SELECT vbeln posnr etenr edatu wmeng bmeng FROM vbep INTO CORRESPONDING FIELDS OF TABLE vbep_det

14 WHERE vbeln = vbeln_in AND posnr = posnr_in. 15 16 ENDFUNCTION.

The way this report works is the following: When you run the report you are presented with a screen, called Selection Screen, where you can select the kind of Sales you want to display information about.

Selection Screen After choosing the kind and clicking continue (the green tick button on the upper left) you are presented with the sales headers, corresponding to what you have previously chosen.

First Display

After you have chosen the headers and clicked on the magnifying glass, the details of the chosen headers will be displayed, i.e. the sales items belonging to the chosen headers.

Second Display Finally, after double clicking any sales item, you will get information about the different schedules for the item.

Third and last display As you can see, there are many new things in this example. I am just going to go through it and try to explain them all. First of all, I am not declaring the types in the report anymore. I declare the types in the ABAP Data Dictionary. Any type declared here can be used in any report or FM in the SAP implementation, which is exactly what I do, using the same types for tables in the report and in the FM, as you can see at the declaration of the FMs. The following four types are declared:

ZTABFM01

ZTABFM02

ZTABFM03

ZVBAK_INPUT The next important thing is Forms. Forms are nothing more than function which you can call inside your report. These are called with the keyword PERFORM and declared between FORM and ENDFORM. They help structure the code and reuse it, as I am doing with vbak_in_to_out. You could probably identify most of the events used, now that you know how the report works. However, I will explain each one of them:

INITIALIZATION (line 36) This is how parameters are initialized for the display of the selection screen. The default values for the input, so to say. AT SELECTION-SCREEN (line 67) This happens exactly at the moment you click continue at the selection screen. In this example I am using a message code MESSAGE e888(sabapdocu) which means, if it is triggered, the selection is not finished, and the user is brought back to the selection screen. START-OF-SELECTION (line 73) Happens exactly after AT SELECTION-SCREEN. Is where you actually do the selection and prepare everything for display. TOP-OF-PAGE (line 43) Is the display at the top of the page when displaying the first selection. You normally write the page header here. AT LINE-SELECTION (line 77) This is the most complex of all events in this example. It is the event triggered by the double click on a line, or the click of the magnifying glass. sy-lsind is an important variable in this event, which tells you in which selection screen

the report is. If it is equal to 1 then you are selecting items of the first selection, if it is equal to 2 then from the second, etc. Lines 83 to 90 is the code used to check if there is any item selected. It goes through the lines of display and checks whether it is an item line and whether the box is checked. Lines 93 to 110 just checks if there is any items to display. Just remember that if there is nothing to display we have to set sy-lsind back and tell the report we are still at the first display screen. TOP-OF-PAGE DURING LINE-SELECTION (line 50) Uses the same logic of AT LINE-SELECTION to display headers for the subscreens.

One last important thing is line 147. The hide statement allow us to save a variable into memory when double clicking a line, so we can use it for display in the next event (line 115 wa_vbap). Please feel free to create this example yourself and make small changes to it. It will surely give you a much deeper understanding of events in ABAP, and about interactive reports. Until next time.

Вам также может понравиться