You are on page 1of 44

Starting the debugger in a modal screen Usually in ABAP, when you want to start the debugger from a certain

point, you just have to write "/H" in the command window. But if you are in a modal screen or in a message display, you cannot write the traditional "/H", here is how to do it : 1. Open notepad and paste these lines in a document : [FUNCTION] Command=/H Title=Debugger Type=SystemCommand 2. Save this document anywhere on your local pc. ex: c:\breakpoint.txt 3. Drag&drop this file from the explorer to your ABAP modal screen.... et voila !! Retrieving field names dynamically Sometimes you may have only a table name and want to retrieve the name of each field of the corresponding table. For example, when you want to use ASSIGN COMPONENT fieldname OF TABLE table. An ABAPer's first reaction is to read the standard ABAP basis tables DD02L, DD03L, etc This way of reading fields is very slow. Use methods from the class CL_ABAP_TYPEDESCR instead. Example: data: descr_struc_ref TYPE REF TO cl_abap_structdescr. descr_struc_ref ?= cl_abap_typedescr=>describe_by_name('SFLIGHT' ). Here is the result of descr_struct_ref after the execution of this piece of code ABSOLUTE_NAME C 200 \TYPE=SFLIGHT TYPE_KIND C 1 u LENGTH I 4 80 DECIMALS I 4 0 KIND C 1 S STRUCT_KIND C 1 F COMPONENTS h 8 Table[14x40]

HAS_INCLUDE C 1 The table COMPONENTS is filled with : LENGTH DECIMALS TYPE_KIND NAME 3 | 0 |C |MANDT 3 | 0 |C |CARRID 4 | 0 |N |CONNID 8 | 0 |D |FLDATE etc. You have the fields name and a lot more information about the table. This class can also handle structure, table type, etc. Note that this method is very fast because it uses the database layer directly thanks to SYSTEM CALLs. To have a look at the class, use transaction SE24. Restricting the selection screen When you create a select-option for an input to your program, for each field, the default selection screen looks like this:

And the default possible selections are:

but sometime you don't want to give the user the possibility to select a range, select values "greater than", etc. Here is a small example on how to do it: REPORT ZDANY_RESTRICT_SELECTION. * Include type pool SSCR TYPE-POOLS sscr. TABLES : sflight. * defining the selection-screen select-options : s_carrid for sflight-carrid, s_connid for sflight-connid. * Define the object to be passed to the RESTRICTION parameter DATA restrict TYPE sscr_restrict. * Auxiliary objects for filling RESTRICT DATA : optlist TYPE sscr_opt_list, ass type sscr_ass. INITIALIZATION. * Restricting the carrid selection to only EQ and 'BT'. optlist-name = 'OBJECTKEY1'. optlist-options-eq = 'X'. optlist-options-bt = 'X'. APPEND optlist TO restrict-opt_list_tab. ass-kind = 'S'. ass-name = 'S_carrid'. ass-sg_main = 'I'.

ass-sg_addy = space. ass-op_main = 'OBJECTKEY1'. APPEND ass TO restrict-ass_tab. * Restricting the connid selection to CP, GE, LT, NE. optlist-name = 'OBJECTKEY2'. optlist-options-cp = 'X'. optlist-options-ge = 'X'. optlist-options-lt = 'X'. optlist-options-ne = 'X'. APPEND optlist TO restrict-opt_list_tab. ass-kind = 'S'. ass-name = 'S_connid'. ass-sg_main = 'I'. ass-sg_addy = space. ass-op_main = 'OBJECTKEY2'. APPEND ass TO restrict-ass_tab. CALL FUNCTION 'SELECT_OPTIONS_RESTRICT' EXPORTING restriction = restrict EXCEPTIONS TOO_LATE = 1 REPEATED = 2 SELOPT_WITHOUT_OPTIONS = 3 SELOPT_WITHOUT_SIGNS = 4 INVALID_SIGN = 5 EMPTY_OPTION_LIST = 6 INVALID_KIND = 7 REPEATED_KIND_A = 8 OTHERS = 9. IF sy-subrc <> 0. MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. ENDIF. when you execute this piece of code, you will notice that for carrid, the selection screen is now restricted :

.Calling an external program You want to call a program on your PC from an ABAP program ? try this function : *This example calls the dos prompt DATA: i_returncode TYPE i.

CMD calls the DOS prompt but you can put any program here * PARAMETER = 'test' IMPORTING returncode = i_returncode. DATA: itab TYPE spfli_tab.. Another good example is when you create a correction in a function and you want to keep the installation of the OSS note automatic (if you add parameters in a note.CALL FUNCTION 'GUI_EXEC' EXPORTING command = 'CMD' <<==-. TABLES: spfli. there is a lot of other functions to communicate with the PC like: GUI_CREATE_DIRECTORY GUI_DELETE_FILE GUI_DOWNLOAD GUI_EXEC GUI_FILE_SAVE_DIALOG GUI_GET_DESKTOP_INFO GUI_GET_FILE_INFO etc. For example. This is very useful when you CANNOT add the field as a standard parameter. the user will have to install the note manually). when you want to use a variable in a BADI which is not already passed as a parameter.. Here is a short example on how to do this : REPORT zdany_test_var_from_fm. Using a variable from a calling program without passing it in parameter Did you ever try to use a variable from another program without passing this variable as a parameter. DATA dbcnt TYPE sy-dbcnt. .

LOOP AT <itab> INTO itab. FUNCTION zfunction. FIELD-SYMBOLS: <itab> TYPE spfli_tab. itab-connid. WRITE: / itab-carrid. FIELD-SYMBOLS: <dbcnt>. While on debug mode follow the menu path GOTO->Display condition->memory use 2. field = '(ZDANY_TEST_VAR_FROM_FM)dbcnt'. lets you see which table required a lot of memory 1. field = '(ZDANY_TEST_VAR_FROM_FM)ITAB[]'. The first method. * We want to use the DBCNT from the program ZDANY_TEST_VAR_FROM_FM DATA: field(50). ASSIGN (field) TO <dbcnt>. ENDFUNCTION List of internal tables while debugging There can be times when you need a list of active internal tables while you are debugging ABAP code. CALL FUNCTION 'ZFUNCTION'. * We want to use the internal table from the program ZDANY_TEST_VAR_FROM_FM DATA: itab TYPE spfli.SELECT * FROM spfli INTO TABLE itab UP TO 2 ROWS. dbcnt = sy-dbcnt. Select tabstrip: Memory use . ASSIGN (field) TO <itab>. ENDLOOP.ranked list The second method provides a very detailed list . WRITE <dbcnt>.

CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR' EXPORTING percentage = sy-index text = percentage_text. You will get a list of all the tables active in that program along with some other attributes. While in debug mode. DO 100 TIMES. You just have to call the ABAP FM SAPGUI_PROGRESS_INDICATOR. 3. add an hour 3. 2. .5' SECONDS. it is the slowest method you can use. convert the time stamp into a standard date and field 2. For example. convert back the date and time to a timestamp However. When we have to do some calculation on a time stamp is not as easy as on a date field. 7. DATA: percentage_text TYPE c LENGTH 5. give it a try !! REPORT zdany_progress_bar. WAIT UP TO '0. we should use time stamp in our abap programs instead of the traditional date and time fields. to add an hour to a timestamp. choose GOTO->System Areas->internal information A list appears on the debug screen By default the area editbox contains a ? Now enter DSEG in that field. ENDDO. You can play around and try the other area than DSEG. 4. some are interesting. 5. percentage_text(3) = sy-index. The type and size of the records determine if they are internal tables and how many records there are. at the appropriate points. Showing a progress bar in ABAP This process is very easy but a lot of programmers don't know how to do it.1. percentage_text+3 = '%'. Below is a simple example. Press Return . many people will: 1. Manipulating Timestamps Actually. 6.

. ENDTRY. process after input. call function module F4IF_FIELD_VALUE_REQUEST.. WRITE 'invalid range'... l_tstamp_out TYPE timestamp. EXIT. SKIP. use class CL_ABAP_TSTMP.. In the following example. * NOTE: * Tabname/fieldname is the name of the table and field . DATA : l_tstamp TYPE timestamp. EXIT. CATCH cx_parameter_invalid_range . 1 hour is added REPORT zdany_tstamp. WRITE l_tstamp_out time zone 'UTC '. MODULE f4_help_for_carrid INPUT. . insert the event PROCESS ON-VALUEREQUEST request in the program and add a field statement for the field that should trigger the F4 help. WRITE l_tstamp time zone 'UTC '. PROCESS ON VALUE-REQUEST. TRY. It enables you to make whatever calculation you want on a time stamp. FIELD sflight-carrid MODULE f4_help_for_carrid. . Example: process before output.1 hour = 3600 seconds RECEIVING r_tstmp = l_tstamp_out.. Generating your own standard F4 help To avoid the standard F4 help to be show. CALL METHOD cl_abap_tstmp=>add EXPORTING tstmp = l_tstamp secs = 3600 <<<===--.. GET TIME STAMP FIELD l_tstamp.. WRITE 'invalid type'. In the module called from PROCESS ON-VALUE-REQUEST request. CATCH cx_parameter_invalid_type .Instead.

ENDIF.* for which F4 should be shown. " F4_help_for_carrid INPUT To control F4 help in a selection screen use the AT SELECTION-SCREEN ON VALUEREQUEST FOR <field> event. ENDMODULE. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. * * Value: The value of the Dynpro field when calling the F4 help. Note that for ranges both the low and high value of the field must have there own ON VALUE-REQUEST . * * Dynprog/Dynpnr/Dynprofield are the names of the Progran/Dynpro/Field * in which the f4 value should be returned.g 'A*' to show only values beginning with A CALL FUNCTION 'F4IF_FIELD_VALUE_REQUEST' EXPORTING tabname = 'SFLIGHT' fieldname = 'CARRID' * SEARCHHELP = ' ' * SHLPPARAM = ' ' dynpprog = 'ZDANY_F4_OWN_CALL' dynpnr = '0100' dynprofield = 'SFLIGHT-CARRID' * STEPL = 0 value = 'A*' * MULTIPLE_CHOICE = ' ' * DISPLAY = ' ' * SUPPRESS_RECORDLIST = ' ' * CALLBACK_PROGRAM = ' ' * CALLBACK_FORM = ' ' * TABLES * RETURN_TAB = * EXCEPTIONS * FIELD_NOT_FOUND = 1 * NO_HELP_FOR_FIELD = 2 * INCONSISTENT_HELP = 3 * NO_VALUES_FOUND = 4 * OTHERS = 5 . * You can limit the values shown. by inseting a value in this parameter * e. IF sy-subrc <> 0.

you don't need to define a layout. * calling the display of the grid. the system will automatically create the fieldcatalog based * on the table name you pass in parameter CALL METHOD l_alv->set_table_for_first_display EXPORTING i_structure_name = 'SFLIGHT' CHANGING it_outtab = lt_sflight. put NOTHING in the layout and this is going to work CALL SCREEN 100 Instead of creating an empty screen 100. you can also define an empty selection screen in you program and use it. no more screen painter required ! SELECTION-SCREEN BEGIN OF SCREEN 1001. when we use cl_gui_container=>screen0 as parent. Creating an ALV Grid in 3 lines Did you know that you can create an ALV Grid very fast. NO CONTAINER DEFINITION IS REQUIRED ! CREATE OBJECT l_alv EXPORTING i_parent = cl_gui_container=>screen0. PERFORM f4_help_carrid. CALL SELECTION-SCREEN 1001. lt_sflight TYPE TABLE OF sflight. a container and all the other small things we usually define in an ALV Grid. SELECTION-SCREEN END OF SCREEN 1001. AT SELECTION-SCREEN ON VALUE-REQUEST FOR s_prctr-high.Example: AT SELECTION-SCREEN ON VALUE-REQUEST FOR s_prctr-low. the ALVGrid control will * automatically use the full screen to display the grid. * Creation of the ALV object. * You have to create an EMPTY screen. Modifying the F4 standard calendar . PERFORM f4_help_carrid. If we don't need to finetune the ALV Grid and just want to display a list on the screen or to the printer. SELECT * FROM sflight INTO TABLE lt_sflight. a fieldcatalog. here is a very simple way to proceed: DATA: l_alv TYPE REF TO cl_gui_alv_grid.

in table T001W. Here is an example of the result. here is a small example on how to call the calendar : CALL FUNCTION 'F4_DATE' EXPORTING date_for_first_month = '20031208' holiday_calendar_id = 'CA' "<<==-. Saving an internal table in Microsoft Excel format . When you do not want the user to choose a weekend day or a holiday. the holiday calendar and the factory calendar.Here is how you point on a holiday calendar * factory_calendar_id = T001W-FABKL "<<==-.. I tried to create the Dany's day in ISP but I'm stuck on a small access problem. you can do it.. or a factory one display = ' ' IMPORTING select_date = select_date EXCEPTIONS OTHERS = 4. stupid security ! Because a holiday can be different by country. a red square marks each holiday. Two different type of calendars are defined in SAP. These calendars are defined in the customizing under : SPRO -> General settings -> maintain calendar in this screen. all the default holidays are predefined by country.. field FABKL.. you can add or delete holiday as you want.When you press F4 on any date field the standard calendar opens in order for you to choose a date.. the factory calendar is stored for each plants.

you can use a range object . 4. Enter the From-index and To-index for the lines you want to save. Then press ctrl-F11 or right-mouse and click "Save As Excel Worksheet". 2.While you are debugging your program. Generating a number range automatically If you need a unique key in a table or a sequential number for any other purpose. 1. Choose folder/filename and save. Ranges are maintained in transaction SNRO After maintaining the first screen you have to maintain the intervals by clicking the button "number ranges" . Display the content of the internal table in the debugger. you can save the content of an internal table. 3.

CALL FUNCTION 'NUMBER_GET_NEXT' EXPORTING nr_range_nr = '01' object = 'ZTEST' quantity = '1' IMPORTING number = l_number * quantity = ' ' * RETURNCODE = EXCEPTIONS interval_not_found = 1 . Note: Field NRLEVEL Contains the last assigned number.NRIV Number range intervals. In you program you read the next number by using the function NUMBER_GET_NEXT DATA l_number TYPE i.TNRO Definition of number range objects .These informations are stored in tables : .

l_count type i. comp_fld type cl_abap_structdescr=>component. comp_tab type cl_abap_structdescr=>component_table. * We read information about each fields of SFLIGHT (see ABAP FAQ #2) struct_type ?= cl_abap_typedescr=>describe_by_name( 'SFLIGHT' ). field-symbols : <lt_dynamic> type any table. Here's how it goes: REPORT ZDANY_DYN_LOCAL_TYPES. . elem_type type ref to cl_abap_elemdescr. struct_type type ref to cl_abap_structdescr. types : end of typ_hardcoded. ****************** dynamic "new wave" local type ******************* types: typ_count type i. * create a table based on hardcoded type data : lt_hardcoded type table of typ_hardcoded. itab_type type ref to cl_abap_tabledescr. lt_sflight type sflight. ****************** hardcoded "old style" local type ******************* * This is a normal hardcoded local type types : begin of typ_hardcoded. You can also create the number range in your program instead of using SNRO with the functions: NUMBER_RANGE_INTERVAL_LIST : verify if a number range already exist NUMBER_RANGE_ENQUEUE : lock the specifier number range NUMBER_RANGE_INTERVAL_UPDATE : create the number range NUMBER_RANGE_UPDATE_CLOSE : commit changes NUMBER_RANGE_DEQUEUE : unlock Defining a local type dynamically You can now define a local type dynamically. This is only supported in 6.number_range_not_intern = 2 object_not_found = 3 quantity_is_0 = 4 quantity_is_not_1 = 5 interval_overflow = 6 OTHERS = 7.40. display l_number. data: dref type ref to data. each time you call NUMBER_GET_RANGE the number is automatically increased.

assign dref->* to <lt_dynamic>. * We add manually the counter comp_fld-name = 'L_COUNT'. * we finally assign a field symbol to the pointer because we cannot * directly access a pointer.. there is a lot of better way to do it. comp_fld-type = elem_type. Using macros First : DO NOT use macros in a new program. * The new thing here is the "type handle" which create a pointer to a * handle create data dref type handle itab_type. note that * we should use class cl_abap_elemdescr instead of cl_abap_typedescr elem_type ?= cl_abap_elemdescr=>describe_by_name( 'TYP_COUNT' ). . insert comp_fld into comp_tab index 1.. * we read all fleids of SFLIGHT and create a component table comp_tab = struct_type->get_components( ).* We also need the information about the type "typ_count". * we create the structure struct_type = cl_abap_structdescr=>create( comp_tab ). and the internal table itab_type = cl_abap_tabledescr=>create( struct_type ). * . internal table lt_hardcoded and * lt_dynamic are the same break-point. * At the end of this small program.

END-OF-DEFINITION. WRITE number1.corp/~sapidb/011000358700002805272003E . you can see a strange call to what it look like a function but it's not. In some old programs. REPORT zdany_dynamic_select. . no easy way of knowing this is a macro ZMULTIPLY number1 number2. for the sake of understanding what old programs do. One of the most used macros is "break". Here is an example of a fully dynamic select. number2 TYPE i VALUE 5. do not create new macros unless you absolutely must. If you have a look in table TRMAC. To put a break-point in your code that will break only for your user Again.Some people come to my desk and tell me they found a "magic" function which the code behind is invisible and it's impossible to trace this function. REPORT zdany_macro. For more information about the dynamic select. it's a macro. The macros are stored in table TRMAC. this is a PDF file. Using dynamic SELECT statements The very useful SELECT statement could be fully dynamic from release 6. MULTIPLY &1 BY &2. * calling the macro. you can read the document "Enhanced ABAP programming with Dynamic Open SQL" from Adrian Görler and Ulrich Koch. it's a macro.10 and up. DATA: number1 TYPE i VALUE 2. you will see : BREAK 000 * USER specific BREAK-POINT BREAK 001 if sy-uname = '&1' BREAK 002 break-point BREAK 003 endif Here is how to create a simple macro. you probably use "break my_user_name". Here is the link https://webphl07. *Macro definition DEFINE ZMULTIPLY. This is not part of the ABAP language despite what a lot of people think.phl.

ASSIGN dref->* TO <lt_outtab>. * We remove the unnecessary fields LOOP AT comp_tab INTO comp_fld. REF TO cl_abap_tabledescr. CREATE DATA dref TYPE HANDLE itab_type.* We use some parameters to dynamically control the select. REF TO cl_abap_elemdescr. TYPES: f_count TYPE i. <l_fld> TYPE ANY. TABLE OF edpline. p_selfl5 TYPE edpline DEFAULT 'CURRENCY'. cl_abap_structdescr=>component_table. <ls_outtab> TYPE ANY. comp_fld-type = elem_type. * Creation of the output table including a non standard field. DELETE TABLE comp_tab WITH TABLE KEY name = comp_fld-name. IF comp_fld-name <> p_selfl1 AND comp_fld-name <> p_selfl2 AND comp_fld-name <> p_selfl3 AND comp_fld-name <> p_selfl4 AND comp_fld-name <> p_selfl5. REF TO data. ENDIF. DATA: lt_where lt_sel_list lt_group l_having l_wa_name l_sel_list dref itab_type struct_type elem_type comp_tab comp_fld TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE TABLE OF edpline. ENDLOOP. p_where1 TYPE edpline DEFAULT 'PRICE > 300'. string. . string. REF TO cl_abap_structdescr. comp_tab = struct_type->get_components( ). ASSIGN dref->* TO <ls_outtab>. cl_abap_structdescr=>component. p_selfl1 TYPE edpline DEFAULT 'CARRID'. edpline. elem_type ?= cl_abap_elemdescr=>describe_by_name( 'F_COUNT' ). itab_type = cl_abap_tabledescr=>create( struct_type ). p_selfl3 TYPE edpline DEFAULT 'FLDATE'. p_selfl2 TYPE edpline DEFAULT 'CONNID'. comp_fld-name = 'F_COUNT'. TABLE OF edpline. APPEND comp_fld TO comp_tab. p_where2 TYPE edpline DEFAULT 'AND CURRENCY = ''EUR'''. p_selfl4 TYPE edpline DEFAULT 'PRICE'. f_count * see ABAP FAQ #14 for more information on this topic struct_type ?= cl_abap_typedescr=>describe_by_name( p_tabnam ). FIELD-SYMBOLS : <lt_outtab> TYPE ANY TABLE. l_wa_name = 'l_WA'. this is not very * clever but this is just a test program !! PARAMETER : p_tabnam TYPE tabname DEFAULT 'SFLIGHT'. struct_type = cl_abap_structdescr=>create( comp_tab ). CREATE DATA dref TYPE HANDLE struct_type.

If you want to do some JavaScript tests in ABAP there is a good program to use : DEMO_JAVA_SCRIPT_MINI_EDITOR.* Creation of the selection fields and the "group by" clause APPEND p_selfl1 TO lt_sel_list. APPEND 'COUNT(*) AS F_COUNT' TO lt_sel_list. WRITE: <l_fld>. compile and execute it to test the result. data: l_JS_PROCESSOR type ref to CL_JAVA_SCRIPT. APPEND p_selfl2 TO lt_sel_list. SKIP. APPEND p_selfl2 TO lt_group. ENDLOOP. l_RETURN_VALUE type STRING. * Creation of the "having" clause l_having = 'count(*) >= 1'. APPEND p_selfl5 TO lt_group. LOOP AT comp_tab INTO comp_fld. When you run this program. * display of the results LOOP AT <lt_outtab> ASSIGNING <ls_outtab>. here is a small example on how to insert JavaScript in ABAP: *&---------------------------------------------------------------------* *& Report ZDANY_JAVASCRIPT_TEST *&---------------------------------------------------------------------* REPORT ZDANY_JAVASCRIPT_TEST. APPEND p_where2 TO lt_where. APPEND p_selfl3 TO lt_sel_list. Using JavaScript in ABAP You can code JavaScript directly in your ABAP code. ENDLOOP. APPEND p_selfl5 TO lt_sel_list. ASSIGN COMPONENT comp_fld-name OF STRUCTURE <ls_outtab> TO <l_fld>. APPEND p_selfl3 TO lt_group. Nowe. . you can code your Java in an ABAP editor. APPEND p_selfl4 TO lt_sel_list. * Creation of a new javaScript l_JS_PROCESSOR = CL_JAVA_SCRIPT=>CREATE( ). l_SOURCE type STRING. APPEND p_selfl1 TO lt_group. * THE dynamic select SELECT (lt_sel_list) FROM (p_tabnam) INTO CORRESPONDING FIELDS OF TABLE <lt_outtab> WHERE (lt_where) GROUP BY (lt_group) HAVING (l_having) ORDER BY (lt_group). * creation of the "where" clause APPEND p_where1 TO lt_where. APPEND p_selfl4 TO lt_group.

Start SE39 Choose Compare different systems Enter both program names and the RFC destination of the remote program Choose Display . write / 'JavaScript was executed'. Saving an internal table in Microsoft Excel format You can compare the source code of a program / method / function from different systems with transaction SE39.JS' SCRIPT = L_SOURCE ). else.JS' ). exit. 3. 1. ' into l_SOURCE separated by CL_ABAP_CHAR_UTILITIES=>CR_LF. * Any problem during execution ? if l_JS_PROCESSOR->LAST_CONDITION_CODE <> 0. l_JS_PROCESSOR->LAST_ERROR_MESSAGE. exit.' ). else. write : / l_RETURN_VALUE. 4.". 2.* this is the Javascript code concatenate 'var l_source = "Hello World. * Let's go and run the script l_JS_PROCESSOR->EXECUTE( SCRIPT_NAME = 'DANYTEST. * we read the output variable l_RETURN_VALUE = l_JS_PROCESSOR->EVALUATE( JAVA_SCRIPT = 'l_source. write: / 'Error in EXECUTE'. write: / 'Error in COMPILE'. This is very useful if you want to be sure that your transport was successful or to see whether the same version runs on both machines. ' 'l_source += " JavaScript!". write / 'JavaScript was compiled'. endif. ' 'l_source += " I''m".l_JS_PROCESSOR->LAST_ERROR_MESSAGE. * Any syntax error ? if l_JS_PROCESSOR->LAST_CONDITION_CODE <> 0. endif. * we compile the JavaScript code l_JS_PROCESSOR->COMPILE( SCRIPT_NAME = 'DANYTEST. ' 'l_source.

note that the system show difference in blue .Here is an example of the result.

You can also compare table content :     Start transaction OY19 Choose Manual selection Enter the name of the table that you want to compare Choose Execute .

For results such as these: Saving an internal table in Microsoft Excel format You can use standard program RPR_ABAP_SOURCE_SCAN to search ABAP program code/screen logic for specific texts (strings. The benefits of using this program are as follows: .) This program offers many more options than programs RSRSCAN1 or RKCTSEAR.

You no longer need to write SQL code as objects are transparently loaded from the database when needed. you just have to map which fields you need in your persistent class . Only the texts are applied in the search. The object services layer now provides a persistence framework that closes the object-relational gap.+). etc.e. In the class builder. i. You must create a persistent class. Managing persistent objects with object services There is a way to avoid building a fully object-oriented program while still working with non-object-oriented relational it : in the next screen. Found location +/. selection option conditions such as greater than.x lines: Here we can specify how many program lines before and after the found location of the search string should be included in the output. equal to. are ignored You can restrict the search to either the program code or the flow logic of the selected screens or both the program code and the flow logic of the screens. The search text should be entered without formatting characters(*. a new button is added in the main toolbar .. You can set the option to ignore the comments for search. We can also specify the option to search in all the includes used in the specified programs."Persistence" .     Several texts can be entered for which the system searches. this class must be protected. Choose transaction SE24 and create a persistent class.

Activate the whole class. . you will notice that the system creates a set/get method for each field that you selected. Now that we have a persistent object to access the database table SFLIGHT. we must access it in a program. Here is a small example to read/write data into SFLIGHT using persistent objects.After having saved the previous screen.

COMMIT WORK. *We read a specific field l_seatsfree = l_flight->get_seatsmax( ) . *We read a record from SFLIGHT using a unique key l_flight = l_flight_agent->get_persistent( i_carrid = 'LH' i_connid = '0400' i_fldate = '20031030' ). go to the menu Utilities -> Settings / choose tab "ABAP editor " / choose tab "Debugging" check the chek . Contact Dany Charbonneau for more info. TRY. i. * Reference to the class agent." in the User field enter the user used in the Java logon (not the alias of the user!! e.g.REPORT zdany_sflight_persistent. There are lots of other methods and techniques that you can use in persistent classes. Auth. ENDIF. for BRUNO enter "3B1968D7DD1") 4. DATA : l_flight l_flight_agent l_seatsfree l_seatsocc TYPE TYPE TYPE TYPE REF TO zcl_dany_sflight. ROLES o Double click the different roles -> o new session will open o Choose Authorizations -> Display Authorization Data 2. * We write back a specific field into the DB l_flight->set_seatsocc( l_seatsocc ). go to the ABAP coding 3. REF TO "Actv. ALWAYS required for any operation l_flight_agent = zca_dany_sflight=>agent.l_flight->get_seatsocc( ). object S_DEVELOP has to contain 'DEBUG' o Use su01. Press enter or choose OK to get back to your source code 5. Check whether your user has debugging authority. IF l_seatsfree > 0. ENDTRY. Debugging ABAP programs from JAVA applications You can do ABAP debugging from java applications here is how : 1. l_seatsocc = l_flight->get_seatsocc( ) + 1. If you set your next break-point a pop-up will occur to ask you if you want to set an external break-point or a session break-point --> click external break-point (= former HTTP break-point) --> if you run you Java application now and the coding with the break-point is called a new R/3 (CRM) window will open and you will see you code in debug mode (may take some seconds) Defining a default variant . i.

here is a short example of this: * The code must be in the INITIALIZATION section INITIALIZATION. Here is how to create a the variant "SAPDEFAULT" always using as a default date today minus 30 days: Goto -> variant -> save as variant Here is the standard variant save screen. the default variant will be ignored. CALL FUNCTION 'RS_SUPPORT_SELECTIONS' EXPORTING report = sy-cprog "actual program name variant = 'SAPDEFAULT' "default variant name EXCEPTIONS variant_not_existent = 0 variant_obsolete = 0 OTHERS = 0.There are 2 different ways to define a default variant. ENDIF. * We must check if a default variant was already entered by the user in a batch job or in the transaction code * we do not want to overwrite it ! the current variant is store in the syslset field IF sy-slset IS INITIAL.By assigning a variant directly on the transaction code. * After the initialization we start the real code of our program in the section START-OF-SELECTION START-OF-SELECTION.By assigning a variant in the code. Method 2 . Very few know how to handle the weird looking bottom part of this screen: . This is the easiest way but if the program was called from another program or directly from SE38. Enter a name and a description and press "execute". Method 1 .

Check the variables for which you want to maintain default values 2. Choose selection variables button and see the next one .1.

we double click on the traffic lights of the column "D" for Dynamic date calculation. when the traffic light turn green. this is not really good screens but nevertheless. You can release these breakpoints in production and a customer will have the opportunity to activate and debug your code more easily. This will bring a popup with all possibilities you can imagine for defaulting a date. Because we want to create a date.The first part is a legend of the column headers (T D B Z). this tool is very powerful. The following is an activable break-point : BREAK-POINT ID dany. you can press on the down arrow in the "T" column. From a usability point of view. Creating Activable Breakpoints and Assertions You can now create (de)activable breakpoints in your programs. The checkpoint group is defined by double clicking on the checkpoint group in the editor OR directly via transaction SAAB. .

the_sorting_algorithm. All breakpoint groups will be shipped inactive by default. you can find cause of error in shorter time. 3. In the breakpoints part of the screen. ignore the assert Log the assertion in a log Terminate the program with runtime error ASSERTION_FAILED The assertions are defined in SAAB (exactly like the breakpoints. Start the debugger from this assert Do nothing. l_f2 TYPE c LENGTH 10 VALUE 'test'. The reaction when violating an assertion depend on a customizing and could be : 1. 2. DATA: l_f1 TYPE i VALUE 2. ASSERT ID SUBKEY FIELDS dany 'danysub1' l_f1 l_f2 l_t1 . Assert : An assertion is a condition which must be true during program execution. l_t1 TYPE TABLE OF sflight.Here is an example of a use for an assertion : METHOD sort_by_name.Below is the SAAB screen. 4. you can set it to "inactive" or "break". see screen above). By using asserts in your program.

This generated two copies for basically nothing. Could be client dependant 6. Copy-free: very fast access 2.CONDITION itab->is_sorted_by_name( ) <> ' '. Preloading: you can now request a specific variable no matter if the "sending" program already created them 4. Easy monitoring . Versioning management: you can handle many version of the variables at the same time 3. Below is the result of the log for this assert Using Shared Objects Shared objecta are SAP's answer to an age-old request by programmers. and the "receiving" program had to copy these variables from the shared memory into its own program memory. Automatic propagation from a database or to different application servers 5. This method was very slow because the "sending" program had to copy variables from its memory to the shared memory. the only way to share variables between programs was to use EXPORT/IMPORT TO/FROM MEMORY. Up until now. ENDMETHOD. Here are the benefits of shared objects: 1. This will ensure that the table is sorted.

It is important to put the class you created in step 1 in the field "root class". In this class you will defined all variables you want to share in the attributes tab. This class must be "Shared memory enabled" : Step 2 : You have to define your shared memory object using the transaction SHMA. Step 1 : You have to define a Root class using SE24. .Here is a very simple example but you can do very powerful shared object. see documentation for more information.

*Access root object component to write the variable . Step 4 : You have to create a program to read from the shared memory DATA : hdl TYPE REF TO zcl_sm_area. * when we attach for write. * Create the link between the root object and the shared memory object hdl->set_root( root ). * commit hdl->detach_commit( ). root TYPE REF TO zcl_root_area.Step 3 : You have to write a program to write to the shared memory. * Open default instance for read hdl = zcl_sm_area=>attach_for_read( ). * put data in the shared memory variable root->big_var = 'hello world!'. * Create the default instance for write. we must use the new keyword addition AREA HANDLE CREATE OBJECT root AREA HANDLE hdl. DATA : hdl TYPE REF TO zcl_sm_area. *when we create our root object to access variables. an exclusive lock is performed on the shared memory object hdl = zcl_sm_area=>attach_for_write( ).

field3(6). <<==-. 'FIELD4'. TYPES: BEGIN OF ltt_fields.This is impossible in ABAP. Step 5: You can monitor the result in transaction SHMM Defining dynamic orders in an ABAP sort You can easily define dynamic fields in an ABAP sort using ( ) : data : l_fieldname type dd03l-fieldname value 'CARRID'. s_ord1(3) s_ord2(3) s_ord3(3) s_ord4(3) s_ord5(3) DEFAULT DEFAULT DEFAULT DEFAULT DEFAULT 'ASC'. Each time you will run the program. 'FIELD3'. Here is a small example on how to do that: *&---------------------------------------------------------------------* *& Report ZDANY_DYN_SORT *&---------------------------------------------------------------------* REPORT z_dany_dyn_sort. . with the new tree control. The first method is by using a CREATE SUBROUTINE POOL with your sort. Now. DATA: l_field_asc1(6). This is VERY slow and we should avoid using this command whenever it's possible. l_field_asc3(6).WRITE / hdl->root->big_var. 1 copy for ascending and 1 for descending. SORT sflight by (l_fieldname) DESCENDING. field1(6).F5 or space ) * s_ord* .ASC or DES ( ascending or descending) PARAMETERS: s_field1(6) s_field2(6) s_field3(6) s_field4(6) s_field5(6) DEFAULT DEFAULT DEFAULT DEFAULT DEFAULT 'FIELD1'. * s_field* .F4. field5(6). 'DES'. 'ASC'. l_field_asc2(6). when you want to give fully customizable tree.field name for sorting ( F1. You duplicate each fields you want to sort. field4(6). The second method is a simple trick that have no major impact on performance. 'FIELD5'. field2(6). 'ASC'. *Release lock hdl->detach( ). 'DES'.F2.F3. BUT you CANNOT define the order (ascending or descending) dynamically : SORT sflight by (l_fieldname) (l_order). You move the fieldname only in 1 of those fields depending on what order you want. END OF ltt_fields. 'FIELD2'. ou need to dynamically set the order in the sort command. this subroutine will be recompiled.

l_field_des5(6). l_field_des3(6). l_field_des4(6). DO 3 TIMES. ls_fields-field5 = sy-index. 3. ENDDO. * The order must be "ASC" l_flag_not_asc_des = 'X'. ls_fields TYPE ltt_fields. lt_fields TYPE TABLE OF ltt_fields. * the field name must be = "FIELD1. * Just to fill an internal tables for testing DO 3 TIMES. ls_fields-field3 = sy-index. any other value is CS CS CS CS CS s_field1 AND s_field2 AND s_field3 AND s_field4 AND s_field5. 4 or 5". ENDDO.l_field_asc4(6). if the user ask descending order. rejected l_flag_invalid_field = 'X'. INITIALIZATION. DO 3 TIMES. or "DES" or space. APPEND ls_fields TO lt_fields. the name of this field is * moved in l_field_des1 AND it's important that l_field_asc1 remain empty. CHECK 'FIELD1FIELD2FIELD3FIELD4FIELD5' 'FIELD1FIELD2FIELD3FIELD4FIELD5' 'FIELD1FIELD2FIELD3FIELD4FIELD5' 'FIELD1FIELD2FIELD3FIELD4FIELD5' 'FIELD1FIELD2FIELD3FIELD4FIELD5' CLEAR l_flag_invalid_field. any other value is rejected s_ord1 s_ord2 s_ord3 s_ord4 s_ord5 = = = = = 'DES' 'DES' 'DES' 'DES' 'DES' OR OR OR OR OR s_ord1 s_ord2 s_ord3 s_ord4 s_ord5 IS IS IS IS IS INITIAL INITIAL INITIAL INITIAL INITIAL ) AND ) AND ) AND ) AND ). l_flag_not_asc_des. ls_fields-field2 = sy-index. l_flag_invalid_field. CHECK ( s_ord1 = 'ASC' OR ( s_ord2 = 'ASC' OR ( s_ord3 = 'ASC' OR ( s_ord4 = 'ASC' OR ( s_ord5 = 'ASC' OR CLEAR l_flag_not_asc_des. ENDDO. ENDDO. START-OF-SELECTION. IF s_ord1 = 'ASC'. . DO 3 TIMES. * for a certain field. DO 3 TIMES. l_field_des1(6). l_field_des2(6). ls_fields-field4 = sy-index. 2. ENDDO. ls_fields-field1 = sy-index. IF s_field1 IS NOT INITIAL. l_field_asc5(6). FIELD-SYMBOLS <fs> TYPE ANY.

FIELD4 or FIELD5. l_field_asc5 = s_field5. ENDIF. FIELD2.'. ENDIF. ELSE. ENDIF. ENDIF. 1 of the * 2 fields will be empty and the sort will ignore it. l_field_des4 = s_field4. l_field_asc2 = s_field2. IF s_ord2 = 'ASC'. l_field_des2 = s_field2. IF s_ord3 = 'ASC'. IF s_ord4 = 'ASC'. ELSE. IF s_field2 IS NOT INITIAL.l_field_asc1 = s_field1. * if parameters was not entered correctly IF l_flag_not_asc_des = 'X'. ELSE. ENDIF. WRITE: / 'Only ASC for ascending or DES for DESCENDING are allowed for fields S_ORDn'. IF s_field5 IS NOT INITIAL. ENDIF. * Display the results EDITOR-CALL FOR lt_fields. l_field_asc4 = s_field4. SORT lt_fields BY (l_field_asc1) ASCENDING (l_field_des1) DESCENDING (l_field_asc2) ASCENDING (l_field_des2) DESCENDING (l_field_asc3) ASCENDING (l_field_des3) DESCENDING (l_field_asc4) ASCENDING (l_field_des4) DESCENDING (l_field_asc5) ASCENDING (l_field_des5) DESCENDING. ELSE. IF s_ord5 = 'ASC'. ELSE. FIELD3. ENDIF. l_field_des1 = s_field1. IF s_field4 IS NOT INITIAL. ELSEIF l_flag_invalid_field = 'X'. ENDIF. l_field_asc3 = s_field3. ENDIF. * EACH field is used twice in the sort with different name for ascending and descending. END-OF-SELECTION. IF s_field3 IS NOT INITIAL. l_field_des3 = s_field3. WRITE: / 'S_FIELDn must be = FIELD1. l_field_des5 = s_field5. ENDIF. ENDIF. .

Creating graphical charts (bar.Inserting charts It's a known fact that customers are very sensitive to the appeal of charts. The following are two short examples of the huge potential of function module GFW_PRES_SHOW : * Contain the constants for the graph type TYPE-POOLS: GFW. VALUES-ROWTXT = 'Life cost'. VALUES-VAL2 = 51000. Use transaction GRAL to explore all possibilities provided by this class and this FM. pie char. APPEND VALUES. APPEND VALUES. DATA: VALUES TYPE TABLE OF GPRVAL WITH HEADER LINE. this function could be used for many * different graphic types depending on the presentation_type field : * gfw_prestype_lines * gfw_prestype_area * gfw_prestype_horizontal_bars * gfw_prestype_pie_chart * gfw_prestype_vertical_bars * gfw_prestype_time_axis CALL FUNCTION 'GFW_PRES_SHOW' EXPORTING CONTAINER = 'CONTAINER' "A screen with an empty container must be defined PRESENTATION_TYPE = GFW_PRESTYPE_LINES TABLES VALUES = VALUES COLUMN_TEXTS = COLUMN_TEXTS . REFRESH VALUES. * Call a chart into a standard container. There are two main methods for creating charts in ABAP   Using the class CL_GFW Using the function module GFW_PRES_SHOW There are also other classes and function modules derived from these ones. lines graphs) in ABAP is simple. APPEND COLUMN_TEXTS. COLUMN_TEXTS-COLTXT = '2004'. VALUES-ROWTXT = 'Salary'. COLUMN_TEXTS TYPE TABLE OF GPRTXT WITH HEADER LINE. COLUMN_TEXTS-COLTXT = '2003'. VALUES-VAL1 = 50000. VALUES-VAL2 = 51200. APPEND COLUMN_TEXTS. VALUES-VAL1 = 49000. REFRESH COLUMN_TEXTS.


VALUES COLUMN_TEXTS EXCEPTIONS ERROR_OCCURRED OTHERS = VALUES = COLUMN_TEXTS = 1 = 2 Knowing when to use SELECT SINGLE or SELECT . Why is this ?? The answer is simple.. not much apart from the extra ENDSELECT statement.. UP TO 1 ROWS' statement is subtly different. ordering or grouping functions to them and then returns the first record of the result set. The database selects all of the relevant records that are defined by the WHERE clause. ... UP TO 1 ROWS A lot of people use the SELECT SINGLE statement to check for the existence of a value in a database. UP TO 1 ROWS' statement ? If you're considering the statements SELECT SINGLE field INTO w_field FROM table.. then looking at the result. So what's the difference between using 'SELECT SINGLE' statement as against a 'SELECT .. applies any aggregate. The 'SELECT .. The 'SELECT SINGLE' statement selects the first row in the database that it finds that fulfils the 'WHERE' clause If this results in multiple records then only the first one will be returned and therefore may not be unique. ENDSELECT. Other people prefer to use the 'UP TO 1 ROWS' variant of the SELECT statement.. Look at the run time and memory usage and they may be worlds apart. and SELECT field INTO w_field FROM table UP TO 1 ROWS.

MANDT of type MANDT and POSNR of type POSNR. * * Creation Date: 21/04/2004 * * Requested By: * * Reference Doc: * * Author: R Harper * * Modification History: * * Date Reason Transport Who * ****************************************************************** Report Z_Difference Message-id 38 Line-Size 80 Line-Count 0 No Standard Page Heading. a friend of mine on sapfans. * Start-Of-Selection. credit for this example goes to Richard Harper. Make sure both of these are keys. Also create a table maintenance dialog for it (SE11->Utilities->Table Maintenance Generator). * Select Posnr into table t_Rows from zDifference . Data: w_Single type Posnr. * Select single Posnr from zDifference into w_Single. Then run the program shown below: Code: ****************************************************************** * * Program: Z_Difference * * Purpose: A program that demonstrates the difference * between SELECT SINGLE and SELECT UP TO n ROWS.Get the difference ?? If not. t_Rows type standard table of Posnr initial size 0 with header line. Fill the table with ten rows 000001000010. * * This program requires the data table Z_DIFFERENCE * to have been created according to the structure * outlined in the text above and populated with * at least 10 : Create a Ztable called ZDifference with 2 fields in it. here is a good example.

This is false and groundless. rumour has it that it's somewhere between 1000 and 2000 records.. lt_range-sign = 'I'. Skip 1. Write :/ 'Up to 1 rows :'. This is a good example of a warning that we should ignore.IN When you use a range table in a select (SELECT * FROM sflight WHERE carrid IN lt_carrid). In fact.. EndLoop. Write t_Rows. you sometimes get a short dump with the error DBIF_RSQL_INVALID_RSQL. This is what a 'SELECT SINGLE' does. considering you are sure of what you are doing !! Working around the limitations of a range in SELECT. Here is a small example of a program to create a short dump : DATA : lt_range TYPE RANGE OF sflight-carrid WITH HEADER LINE.. * Write :/ 'Select single:'. In order to be able to do this the database has read the entire table. ENDDO. You should see the output: Select single: 000001 Up to 1 rows : 000010 The first 'SELECT' statement selected the first record in the database according to any selection criterion in the 'WHERE' clause. Replacing the 'SELECT SINGLE' by an "UP TO 1 ROWS" will give the same exact results without any warning but the program will run slower and consume more memory.WHERE. The second 'SELECT' has asked the database to reverse the order of the records before returning the first row of the result. There is a limitation on the length of the generated SQL string.up to 1 rows order by Posnr descending.. sort it and then return the first record. the problem is that the "IN" keyword is not native SQL and the compiler converts it into native SQL. If there was no ORDER BY clause then the results would have been identical (ie both '000001') but the second select if given a big enough table to look at would be far slower. w_Single. lt_sflight TYPE TABLE OF sflight. APPEND lt_range. lt_range-low = 'AA'. A lot of people think that a maximum number of records was reached. Loop at t_Rows. Note that this causes a problem in the Extended Program Check if the full key is not specified in a 'SELECT SINGLE'... . lt_range-option = 'EQ'. DO 5000 TIMES.

* Exception table to handle the exception that can occur during the * execution of the function data EXCP_TAB type ABAP_FUNC_EXCPBIND_TAB.. data NAME type STRING value `READ_SPFLI_INTO_TABLE`. data PARA_LINE like line of PARA_TAB. could be between 2k and 32k (usually 4k or 8k) depending on the DB system. . instead. exporting * and changing data PARA_TAB type ABAP_FUNC_PARMBIND_TAB. There are two ways to avoid this problem : 1. DB2.) by IT.. * Parameter table... *The constants and structures required to use the dynamic function call *is stored in the type pool ABAP. The compiler convert the SELECT in native SQL like that : . FOR ALL ENTRIES IN. The threshold is stored in dbs/io_buf_size and could NOT be change by programmers because this is maintained on DB level (oracle. WHERE carrid = lt_range[1]-low OR lt_range[2]-low OR lt_range[3]-low OR . data EXCP_LINE like line of EXCP_TAB. etc. Usually the best way to do it is using a SELECT. Create some small packages (500 records) and call the SELECT within a loop with APPENDING TABLE keyword 2. This threshold is variable. you have to call your function dynamically.. importing..SELECT * FROM sflight INTO TABLE lt_sflight WHERE carrid IN lt_range. Calling function modules dynamically When you only know the function name to call at run-time. *This is the name of the function you want to call.... The short dump occur when the generated SQL caracter string is over a certain threshold.. type-pools abap.. where you store all parameters. Here is an example of how to call a function dynamically (note: comments were added to an existing example from the standard help) REPORT ZDANY_DYN_FM_CALL. lt_range[5000]-low.

EXCP_LINE-VALUE = 4. EXCP_LINE-VALUE = CARRIER type SPFLI-CARRID. * abap_func_tables value 30. CARRIER = 'XYZ'. *Same thing for parameter 2 PARA_LINE-NAME = 'ITAB'. EXCP_LINE-NAME = 'OTHERS'. * abap_func_changing value 40. *We need the datatype of the parameter to pass get reference of CARRIER into PARA_LINE-VALUE. insert EXCP_LINE into table EXCP_TAB. * abap_func_importing value 20. append PARA_LINE to PARA_TAB. get reference of JTAB into PARA_LINE-VALUE. *Now we create the possible exceptions EXCP_LINE-NAME = 'NOT_FOUND'. PARA_LINE-KIND = ABAP_FUNC_EXPORTING. could be : * abap_func_exporting value 10. PARA_LINE-KIND = ABAP_FUNC_IMPORTING. . append PARA_LINE to PARA_TAB. data JTAB type SPFLI_TAB. * type of the first parameter. * Name of the first parameter PARA_LINE-NAME = 'ID'.

when 1. message id SY-MSGID type SY-MSGTY number SY-MSGNO. when an environment is about to get shut down.. select your programs one by one. programs. You have to launch se38/37/24/80.. or structures. *. choose utilities -> versions -> generate version . Unzip Cut and paste in an ABAP program Compile and run All your projects (including multiple classes. This is a lengthy procedure that does not even enable you to save screens. or use function module WS_DOWNLOAD. function groups. tables. An ABAP program available for free download at http://www. Downloading ABAP code to your local PC Creating Z* test programs is a popular method for conducting tests.ZIP file. when 2. message E888(SABAPDOCU) with 'Error in function module'.dalestech. endcase. keeping your test programs becomes tricky. it might be preferable use a tool that is already embedded in the Workbench: in se38/37/24/ can help you save your test programs. If you want to backup your work in order to keep a certain stable version while you are programming. 5. 4. Choose home -> R/3 entreprise -> direct download entreprise 1. 2. and we dynamically call the function with the parameter-table and * exception-table addition call function NAME parameter-table PARA_TAB exception-table EXCP_TAB. 1. and choose system -> list -> save > local file. 3. * We check the result code case SY-SUBRC. screens and tables) can be saved in less than one minute.insert EXCP_LINE into table EXCP_TAB. However.2 download the .