1 6 7 8 9 10 63 Previous Next

ABAP Development

940 Posts

I have preferred to post this blog here in ABAP space, because I believe I can easily find here, SAP dinosaurs like me



1. Google is not used in an R/3 project:

Because Google was not established yet .  We need to wait 6 years that Larry Page and Sergey Brin to establish Google in 4th of September in 1998. We often use our notes on papers, pals, debug  or self trials to explore any information.



2. 3,5” floppy disks or commonly diskettes are used in R/3 projects:

There were no SD cards, cloud spaces or memory sticks. We have only 720 kb or1,44 MB of floopies to store any piece of data. To be honest we did not have any fancy data at all



3. Lotus 1-2-3 or Quattro Pro is used in an R/3 Project:

Excel was not so popular before year 1995, so Lotus 1-2-3 and quattro pro were the key spreadsheet solutions those days.



4. Remote connection or job is not acceptable in R/3 project:

Since there were no public remote connection facility in early 1990’s. So we need to work long long days in offices during go-live preparation and cut-over phases.



5. Help.sap.com is not used in an R/3 projects:

Because it was not established yet. We have Help documentation CD’s provided by SAP software, which were also come with CDs. This documentation should be installed on network to search for help J


There are many differences, but these are my favorites, please share yours:)





The ABAP Channels infrastructure offers best support for native event-driven interactive and collaborative scenarios in ABAP and is generally available with ABAP 7.40 Support Package 5 (SP05). The ABAP 7.40 Support Package 8 (SP08) contains various enhancements including API refactoring to support WebSocket subprotocols.and message exchange with SAP Push Channel Protocol (PCP).


Take your time to watch these YouTube video tutorials to learn how to implement and use ABAP Channels.


How to implement ABAP Push Channel (APC)

ABAP Push Channel enables bi-directional communication via WebSockets in ABAP. This video gives you step-by-step introduction on how to implement and use ABAP Push Channel.




How to implement ABAP Messaging Channel (AMC)

ABAP Messaging Channel enables event-driven communication based on publish/subscribe mechanism for message exchange between different ABAP sessions which can reside on different ABAP Servers. Any ABAP session can subscribe to channels and any ABAP session can publish messages to channels. This video gives you step-by-step introduction on how to implement and use ABAP Messaging Channel.



How to implement collaboration using ABAP Push Channel (APC) and ABAP Messaging Channel (AMC)


The collaboration scenario provides the possibility on the basis of publish/subscribe mechanism of ABAP Messaging Channels and WebSocket implementation of ABAP Push Channel to exchange messages between different WebSocket Clients. This video gives you step-by-step introduction on how to implement collaboration scenario using ABAP Messaging Channel and ABAP Push Channel.


sameer p

The case for other tools

Posted by sameer p Mar 9, 2015

Although this post is not directly about ABAP development, I think its relevant to most ABAPers. For people in the ABAP world, it’s unusual stray far from SAP's suite of Development tools. However having additional skills can add a lot of value, especially with SAP's pivot towards using more open standards and tools (think UI5, D3.js). The embedded developer tools within a browser are one such set of tools, as we will see below:



After a recent upgrade to SAP CRM, we had issues with the SAP CIC. Attempts at launching the CIC would result in a service not reached error. These are usually an easy fix because the inactive service is displayed on the error page. Once in a while though, someone gets an error which looks like this (fig. 1, click to enlarge), for which even the mighty Google doesn't have a solution.


HTTP://host:port/sap<!DOCTYPE html PUBLIC"-//W3C//DTD HTML 4.01Transitional//EN"><html> <head><title>Logon Error Message</title> ….

Fig 1.png


As many of us have experienced, these never-seen-before issues tend to get discovered during the critical stage of the project, which also happens to be a Friday evening of a long week. It being a critical phase, It was  important to analyze and fix the issue right away so I began the analysis immediately with the usual set of tools: ABAP Debugger, ICM, ICF, Logs etc. After spending considerable time  with these to and not making much progress, it seemed worthwhile to start the analysis afresh and from a different perspective. This time I decided to begin the analysis at the opposite end of the problem i.e. instead of starting the analysis at the server (SAP), starting the analysis at the client (browser) using the embedded developer tools.

For those who have made this far, the obvious question is how does one go about doing this? Firstly, To launch the developer tools , look under the browser tools menu or use the shortcut key Ctrl/Cmd + Shift + I (works under many browsers) . Once launched, they will automatically start collecting and displaying the relevant data. Under the developer tools, there are tabs focussing on a specific function such as network analysis, DOM inspection, Stylesheets, Debugger etc. The names of these tabs can be different on different browsers.The next step would be to launch the CIC (or the relevant webpage). Since the issue I was facing was an unreachable service, it made sense to start with the network analysis tool. It’s a good default tool to start with as it will give an idea to the order of calls and the services called. An example of its output can be seen below (fig 2):


Fig 2.png


Here you can see the HTTP requests made by the browser to the server and the corresponding responses. From the 'Path' column (first column), it’s easy to determine the resource requested. The 'Initiator' column also holds important information, usually a hyperlink to the source of the request (when available). Double clicking on the request will provide additional details on the request and its response plus other details.



For my issue, it was relatively easy to find the HTTP request that called the non reachable service (in red). Usually the CIC will keep sending polling requests so it may a good idea to stop recording the traffic once the page loads what we need. Just by looking at the error URL (fig. 1 & 2), it was evident that the browser was trying to reach a service that would not exist in SAP. The next step was to figure out how this requested URL was formed.  The bad URL could either be formed using a string delivered by SAP, or it could be the result of JavaScript(js) that did some unexpected manipulation in the browser. For the HTTP request we found above, the initiator was a js function, which was conveniently linked to in the Initiator column. This would serve as the starting point for our next step, by taking us to the Sources(debugger) tab to display the js triggering the HTTP request.


A little more about the Sources tab before we proceed further: all js loaded for a webpage can be seen under the Sources tab. The tab, along with displaying the js, can also be used to debug any js that executes in the browser. The debugger is very similar to the ABAP debugger with the ability to traverse the stack, lookup values of global and local variables, set breakpoints and watchpoints etc. Having found the code that made the HTTP request, it was time to work backwards to the source of the bad URL. Using the same approach used to debug ABAP code, we setup relevant breakpoints in the call stack plus watchpoints as desired to start debugging.


During debugging, I was able to find the function where the bad URL is actually formed (fig. 4, click to expand). The function is mergeManglingURL in the file crmuifServer.js, under the BSP crm_ui_start. The function performs its job perfectly well, serving us a URL that led nowhere because the parameter mangling has a long and incorrect string value. On a side note, the contents of the parameter ‘mangling’ seemed to be a well formed HTML page by itself, so I saved the contents of mangling to a separate file for examination later. At this stage, the cause was the incorrect value in the mangling parameter. I followed the trail down the rabbit hole further to determine what put the incorrect value in the parameter but reached a dead end.

Fig 4.png

At this stage, instead of debugging further, I wanted to examine the contents of mangling that I had saved separately. It had looked like valid HTML and I believed/hoped that it might hold clues to the root cause of this issue. After verifying the consistency of the HTML, I was able to open it up in a browser. The HTML was successfully rendered as shown below, finally displaying the service name that was actually inactive(fig. 5):


Fig 5.png


Upon activating the service uif_callback, I had the CIC up and running immediately. This is where I stopped the investigation which may seem a little anticlimactic, but the job was done and Friday evening was close to turning into Saturday morning .


A little more analysis on Monday revealed we had missed steps from note 1115493, which is in addition to note 1295006. (LINK).


To conclude, I hope I convinced you to play around with the developer tools inside your browser if you haven't already and also demonstrated an unconventional approach to solving the issue of an inactive service, where the service name in the error page looks like HTML markup.

Over the last 6 months I've been working on a set of custom checks for code inspector, the project is available on github.


Currently it contains the following general purpose checks, some complex and some simple.


CHECK_01 - IF in IF

CHECK_02 - EXIT outside of loop

CHECK_03 - TRY without CATCH

CHECK_04 - Line length

CHECK_05 - 7 bit ASCII

CHECK_06 - Check for use of pretty printer

CHECK_07 - Functional writing style for CALL METHOD

CHECK_08 - Obsolete statement

CHECK_09 - Tab instead of spaces

CHECK_10 - Use icon_ constants

CHECK_11 - Max one statement per line

CHECK_12 - Specify SORT order

CHECK_13 - Sequential blank lines

CHECK_14 - Commented code

CHECK_17 - Definitions in top of routine

CHECK_18 - Empty branch


CHECK_20 - Bad indentation

CHECK_21 - Unused FORM parameter

CHECK_22 - Conditions contain identical code

CHECK_23 - CHECK outside of loop

CHECK_24 - Identical code blocks

CHECK_25 - Selection screen data not referenced statically

CHECK_26 - No direct changes to standard tables


You can configure code inspector or ATC to use these checks in your default variant.



The checks are provided "AS IS", some might not fit your development requirement, and some might be slow or not even work.

This is a box of chocolates; take the ones you like . Some of the checks contains settings so it is possible to change to fit your requirements.


Feel free to submit pull requests or open issues. More checks will be added over time.



The author has collected the most important recurring solutions for ABAP development in this book. Therefore he could restrict the book to a manageable size. Nevertheless the solutions are explained by using practical examples. Furthermore the book contains many screenshots with detailed explanations that make it easier to understand.

The first part of the compendium explains an example from real life – the examples are showing that he was working at public utilities. It shows how specific development and enhancement of SAP standard can solve the requirements.

The foundation for any development, the SAP Data Dictionary, is explained in great depth. It covers the most important features of the Data Dictionary for developers: table properties, indexes, foreign keys, append structures, expansion categories, conversion routines in domains, table maintenance generator and modification adjustments, lock objects, database utility, search helps.

The next chapter on debugging is the chapter that I like most because for good development you must discover your program errors fast. This chapter explains the new debugger in more detail than the old debugger, because it has a cleaner Look & Feel and has an increased functionality. The author shows the core functionality so that almost all debugging cases during programming are covered. Additionally he gives hints in which cases a debugging instruction should be used. Furthermore some special debug mechanisms are explained, such as debugging pop-up-screens and background programs.

The chapter on professional ABAP development shows how you can use a basic structure for your ABAP programs. He starts with the mostly underrated topic documentation because ABAP programs are not scripts for a short-term event. So if you must maintain an old program it would be nice to have a good documentation inside the program. Also a kind of documentation is the user-friendly error handling that comes next. Here you can see that the author limits himself to the essential error-handling. After some lines about version management he turns to the SAP Control Framework. The book is covering only the ALV Grid Control, but this very extensively. The author is right that this control is the most used among all the controls of this framework but some lines on the Tree Control would have been nice. Nevertheless the author explains the ALV Grid lists for reporting and interactive programming in great detail. Furthermore data transfer and sending mail are explained with simple examples. Some minor topics like the use of “dirty assign” complete the book.

The book is suitable for developers with at least some previous knowledge and also as a reference book for advanced developers. In the moment it is only available  in German, but I hope that an English translation will be available soon. If you want to know more Google Play provides the most comprehensive free sample I have seen.

Hi guys, recently I got into trouble with some SAP 4.7 developments, I have SAP 4.7 release 620 at level 0063. I don't really know what the basis team upgraded but some reports begun to generate wrong PDF files. In SAP preview there was no problem but when you downloaded or sent them by email and then opened with Adobe Reader a message was shown: "Insufficient Data for an Image" / "Datos insuficientes para una imagen" (I have Adobe in Spanish version).


Basically the problem happened with the FMs 'CONVERT_OTFSPOOLJOB_2_PDF' and 'CONVERT_ABAPSPOOLJOB_2_PDF' when trying to flat compress images and font types to attach PDF binaries to an email. To solve it you need to check if one of these options meets your case:


A. Using report  RSTXPDF3:


This report is used to maintain the OTF-PDF conversion parameters in SAP. The parameter FLATE_COMPR_OFF (Do not use flat compression) must be set to ON, this way you disable flat compression and the PDF are generated correctly. To do it follow the next sequence:



1. Go to SE38 and run report RSTXPDF3.


2. Select 'List settings' check box and execute it.


3. Check if the value of parameter FLATE_COMPR_OFF is set to ON.


4. Go back and select 'Change Settings' check box, in the field Name enter the parameter you want to change and execute it.


5. Click on 'ON' button.


6. The parameter's value is changed, now you can test your PDF generation again.




B. Implementing SAP Notes:


0000924752PDF converter: Logging OTF data
0001029572Prerequisite for Note 1499987
0001112170Error in SAPconnect OTF documents with format=TXT
0001125846CONVERT_OTF: Adobe Reader does not display any creation date 
0001151257Converting document content    
0001278061CONVERT_OTF: Overriding "Author" field in the PDF
0001320163Incorrect PDF data after Unicode conversion   
0001324547Sending a spool request as PDF via e-mail


Go to transaction SNOTE to implement the notes.



Hope these help you if you experience this problem.

This article has its original at my blog http://oprsteny.com


If you need to extend your Material Master view tabs then this article will show how you can do it in few simple steps.

Let's have an example where we'd like to add some Plant-specific fields to the Material Master and we'd also like these fields to be visible and editable in MM transactions MM01 / MM02 / MM03.

In the example we will add new field Process Code (ZZ_PROCCODE) to the MM View named General Plant Data / Storage 1

Extending the master table

  1. Go to TCode SE11 and display table for plant-specific fields (MARC)
  2. Extend an existing or create new custom Append for MARC table- it will be a normal structure (will be editable in SE11) which will be appended at the end of the table

    New MARC Append structure
  3. Add your fields to the Append-structure - In our example we will add field for storing a process code called ZZ_PROCCODE of type ZZ_DTEL_PROCCODE built on domain ZZ_DOM_PROCCODE.

    New data element for MARC Append structure

    Data element Domain definition
  4. Activate the append structure -> this will trigger the MARC table
    (and all depending tables/structures) adjustments - this can be quite
    time consuming so take care when doing such change in production

    Updated MARC table with new Append structure

Create/Extend own sub-screen

  1. Create new function group (you can skip this step if you already
    have a FUGR created for this purpose) where you define new sub-screens
    which will contain your custom fields.

    !!! STOP !!!

    Do not create the FUGR manually but go through customizing for the MM views in
    SPRO IMG -> Logistics General -> Material Master ->
    Configuring the Material Master -> Create Programs for Customized

    SAP IMG for Material Master Customizing

    Let's call our new FUGR ZSALES_MASTER.
  2. In SE80 display FUGR MGD1 and select the screen (MM View
    sub-screen) you want to enhance with your own fields - in our case it
    will be screen 2701 (Storage data: general data)
  3. Copy the selected screen from MGD1 to your FUGR (keep its current number)

    Copy standard screen to your FUGR
  4. Using Screen Painter edit the new screen in your FUGR (in our case
    screen 2701) and rename the group to some custom text describing the
    group of fields you're going to put inside. Then delete all fields from
    the screen and put there only your custom fields.

    ...the original layout will be changed from this

    Original screen layout

    ... to the following

    New screen layout
  5. Save and activate your new screen
  6. In SE80 open the screen (in our case 2701) and go to tab Flow logic
  7. In the code displayed remove (or comment out) all lines manipulating
    with fields that no longer exist in the screen and replace them with
    commands that will manipulate with your own custom fields. Be careful -
    don't remove (comment out) module calls MODULE GET_DATEN_SUB and MODULE SET_DATEN_SUB - these are responsible for reading data from database and putting them back once you change them in the MM views.

    Changed Flow logic of your new screen
  8. Activate all changes in the custom FUGR (added screen, its layout and flow logic)

Add the new subscreen to the standard MM Views

  1. Go to customizing for the MM views in SPRO IMG -> Logistics
    General -> Material Master -> Configuring the Material Master
    -> Define Structure of Data Screens for Each Screen Sequence
    (Tcode OMT3)

  2. Now you can either create your own screen sequence (by copying some
    of the existing ones) or just modify one of the already prepared ones -
    we will go to update already existing one (21 - Standard Industry: Tab

    SAP IMG - MM Screens Sequence Customizing
  3. select the line and double-click on Data Screens

    SAP IMP Screens Sequence Customizing - Data Screens
  4. Now select the line with Screen Desription General Plant Data / Storage 1 and double-click on Subscreens

    SAP IMG Screens Sequence Customizing - Sub Screens
  5. Here you can preview the whole screen with its all sub-screens by pushing the button View Data Screen
  6. You can see your custom sub-screen is not visible ... yet :-)
  7. Go back and select the first line where  PROGRAM = SAPLMGD1 and SCREEN=0001 (screen 0001 is a dummy/empty screen), click on the Add new Entries button and replace the program name with SAPLZSALES_MASTER (main program of your FUGR) and put your own screen number (2701)
  8. Press SAVE button (you will be asked for a transport number) and voila ...YOU ARE DONE 8-)

To test your new screen go to MM01 or MM02

New material creation

Check in the General Plant Data / Storage 1 tab, that your new field (ZZ_PROCCODE) in your new sub-screen (2161) is visible. Change its value, enter all other required fields and save changes.

New material details

Check in SE16 that data has been saved correctly in the MARC table

New material details in MARC table

Modification of new fields data in PAI

In case you need to process or modify data of your new fields (or

also data of standard fields) during PAI in MM01/MM02/MM03) you have to

implement Customer-Exit EXIT_SAPLMGMU_001.

This user exit is called every time PAI is triggered.

If you need to do some error-checking during the SAVE action only, then you can surround your code with something like

  1. IF sy-ucomm = 'BU'. "this code executed only during SAVE
  2. * your code
  3. ENDIF.


I research about it and i want to share my solution.


This post is just to share knowledge and to receive your opinions.


First i went to dictionary ABAP and selected the BKPF table, then clicked in append structure.



after that this pop up dynpro is showed and you need to select the "Create Append" button



put the name in the box and then create, here you need to create the structure as any other, finally active.


Note: the field name must start with ZZ or YY. more information in Methods for Modifying Dictionary Tables - Contributor Corner - SCN Wiki


Until here we just have the fields to use, the next step is creating an BTE (bussines Transaction Event), if you don't know what is BTE or how it works see the doc FI Enhancement Technique - How-To-Guide on the Usage of Business Transaction Events (BTE)


Just to abstract.

"Business Transaction Events (BTE) allows attaching additional components, in the form of a function module to the R/3 system. Business transaction events function in the same manner as customer exits"- Jelena Perfiljeva in doc Business Transaction events(BTE) - Code Gallery - SCN Wiki

I used the BTE process Interface '00001120' - DOCUMENT POSTING:  Field substitution header/items, the sample function module is "SAMPLE_PROCESS_00001120", in FIBF transaction you can see more documentation.


Sample function.

 *"*"Lokale Schnittstelle:

The main purpose of this process is update head or line fields using the tables T_BKPFSUB and T_BSEGSUB, we going to use the T_BKPFSUB because the change was in the head of FI document, by logic the custom fields isn't in the Substitutable fields table, so, we need to appending it too with our fields.


Note: you need to copy the SAMPLE functions, never do changes in these, then you copy that go to the FIBF transaction to update the tables control.


Finally i didn't want to change the screen of every FI posting screens, for allow to the user to write in that fields, i just use the function  POPUP_GET_VALUES_USER_HELP


         FIELDS = FIELDS
        ERROR_IN_FIELDS                 = 1
        OTHERS                          = 2
        t_bkpf-ZZFIELD1 = FIELDS-VALUE.

And that's all, if you want to make a validation after posting the document about this fields you can try with the BTE P/S Interface '00001030 - POST DOCUMENT:Posting of standard data.' for FI transactions and '00001050 - POST DOCUMENT: Accounting interface' to interface like MIRO, PCP0, etc.


Finally remember in BTE's do a SY-TCODE or SY-REPID or document class types validation because it affect to many transactions.


Hope you find it helpful.


Thank you to take the time to read.


Francisco Romero.

This is a follow-up to the Test Driving the ABAP Test Double Framework

That blog contains screen shots of ABAP Unit tools in SAPGUI.

I've since re-installed my Eclipse. Below are the equivalent ABAP Unit Tools in Eclipse.


The ABAP Unit Runner ( CTRL+SHIFT+F10 ) displays the test methods and shows which tests have failed.


ABAP Unit Runner.GIF



The ABAP Coverage View ( CTRL+SHIFT+F11 ) displays the statistics on how much of the code have been covered by the tests.


ABAP Coverage.GIF


Navigating to the code from the ABAP Coverage View displays which piece of code has not been tested.



Code Coverage.GIF

The accounting tab of MM03 transaction displays all the valuation data of the material. All this data is fetched from MBEW table. For some materials there will be difference in the values displayed in MM03 and MBEW depending on sales area. Moving Average Price (VERPR), Standard Price (STPRS), Moving Average price of previous year (VJVER), Moving Average Price of previous period (VMVER ), Standard price of Previous period (VMSTP) and previous year (VJSTP ) are the fields for which we could find the difference in database values and MM03.


Any currency field in MBEW have the potential to generate the issue. Their values in database will be different from the values in MM03. This is because of the currency conversion which takes place before the values are displayed to the user. The currency conversion will takes place based on the values in MM03. The possible decimals places for each currency will be configured in TCRUX table.


TCURX is a standard SAP table that is used to support translation of currency values from/to internal (e.g. stored in a table) to/from external (e.g. displayed in user screen) values.  Standard SAP stores all values with two digits to the right of the decimal (looking like cents) so the table helps SAP to interpret the values when moving between internal and external processing.


The valuation data is converted from internal to external based on the configuration maintained in TCRUX table. SAP data associated with the referenced material is retrieved from SAP tables and displayed. This data is update to the database while creating an new material and below function modules are triggered in this process.



          This funciton module is triggered to save the material data to the database. Function module CURRENCY_AMOUNT_BAPI_TO_SAP is called in the           subroutine Save_MBEW_DATA for currency conversions.



          This function module is called to convert valuation fields data from the screen to SAP tables. For example the table value is 12.34 CLP, have a value of           1234 CLP or 12.34 CLP in the screen.


          This function module can be called to convert the screen values to table values, i.e., with this the screen values and the SAP table values will be same.           However this can cause some inconsistency if the same material is part of multiple sales areas, which may use different currencies.

After reading  Gungor Ozcelebi's blog, Top 10 ABAP crimes, I though I would share some Wisdom from "The Zen of Python" written by Tim Peters. This is valid for any programming language or developer, especially ABAP . Also check out  Python's PEP - 8 guideline which lays out strict coding formats and standards but the language does not enforce these. This would be a good idea for the ABAP elders to create some general consensuses or rules for programming guidelines.


Copied from https://www.python.org/dev/peps/pep-0020/


The Zen of Python by Tim Peters


    Beautiful is better than ugly.

    Explicit is better than implicit.

    Simple is better than complex.

    Complex is better than complicated.

    Flat is better than nested.

    Sparse is better than dense.

    Readability counts.

    Special cases aren't special enough to break the rules.

    Although practicality beats purity.

    Errors should never pass silently.

    Unless explicitly silenced.

    In the face of ambiguity, refuse the temptation to guess.

    There should be one-- and preferably only one --obvious way to do it.

    Although that way may not be obvious at first unless you're Dutch.

    Now is better than never.

    Although never is often better than *right* now.

    If the implementation is hard to explain, it's a bad idea.

    If the implementation is easy to explain, it may be a good idea.

    Namespaces are one honking great idea -- let's do more of those!

I would also like to point out that we should not be so quick to blame the fellow developers in ABAP but the rather the language. ABAP may be open source but it is proprietary. Many people in ABAP may have never worked with another language and often learn from outdated materials, bad examples, or over priced books. Another consequence of ABAP's proprietary status is the lack of appreciation for the work, especially for contract developers. How many people do you know who develop in ABAP as a hobby or learned it just to make something cool? This may or may not even be some of the reasons SAP is offering an alternative JAVA instance (as if JAVA is a better alternative to anything). I think it is a good idea for any developer in any language to learn other technical skills/languages to get a broader appreciation for development. In any case, ABAP certainly has it's advantages as well.

I just realized how to use CURR type with more than 2 decimals.


I created a DOMAIN with Data Type CURR and 8 decimal places. Look at what happens at SE16N Details:


Value on right (Value Unconverted) is the real values on table with 8 decimals, and values on LEFT are showing on any ALV Output (SE16, SE16N or any ALV report). There is NO Conversion Routine at the Domain, only standard CURR type.



I could set DECIMALS on SALV using CL_SALV_COLUMN->SET_DECIMALS( '8' ), but it will only add ZEROS


Ex for first line in table, TOTFRDOC will show 11,006,361.60000000 instead of 11.00636160.




Yes, you may use CURR type with more than 2 decimals, knowing that this output conversion will happens.

So when use it?? If you want your CURR value converted to percentage (as a rate) usually using 4 decimals. Example:

Value unconverted: 0.6160

Output will show as percentage 61.60

Out of curiosity...

there are 57 standard domains type CURR with more than 2 decimals in my SAP system, 109 standard tables using that without any conversion...but most of them are rates with 4 decimals, so when converting to 2 decimals it shows value multiplied by 100, as in the example above.

I could fix my domain using DataType DEC instead. My ALV outputs are now showing right values with 8 decimals.

The events in the smartforms are helpful in the requirements, where we need the following scenarios to be done:

  1. Page break based on the document(sales order number, delivery number, ship-to number)
  2. To print the subtotal of the smartform.
  3. Page number Reset.


For printing the sub total of the smartforms, the links are already available.

This blog contains the detailed description about how to set the page break, based on the document number and page number reset.


1.1 Steps to be followed in Page Break


The below steps are followed and code is applied for the page break:


  • Sort the table, in which our loopis present on the basis of the field where the page break is to be applied; in this case, it would be “Ship-to” (KUNNR).


  • An automatic event would be created named KUNNR.


  • Right click on the event and create a command. This command would be to print the new ship-to party and its corresponding data in the new page.


The output of the form would be as below:



This would be the first page and the next page would have a different ship to number



2.    How to Reset Page Number


Generally, in smartforms, we would use the system fields for printing the page number. There could be a requirement, wherein the page numbers are to be reset according to the document number. Taking the above given example, in case the page break is in the occurrence of new ship-to number, the page number should reset, rather than the continuous increment of the page number.


Say, for instance, there are 2 ship-to numbers; the first ship-to number has 2 pages of data, so, the page number here should be printed as:

      • Page 1 of 2
      • Page 2 of 2


The second ship-to number has 1 page, so here the page number would be Page 1 of 1. To achieve the above requirement, events in the smartforms would be used. The flow here for page break logic would always go as below:


      • Initialization
      • Header
      • Sort Beginning
      • Sort End
      • Sort Beginning (would go here again for the next new document number)
      • Footer


Sort beginning and end areas are created automatically at the time when the sort is applied at the table. We just need to click on sort begin and sort end. Below is the screenshot for the same:


Following is the code to be executed:


In the initialization, we need to count the total number of pages for each new ship-to, the same variable is saved in the final table (used as in loop).


DATA: lw_count TYPE i,
      lw_tabix TYPE i,
      lst_lips_kna1 TYPE gty_lips_kna1.

gw_page = 1.
LOOP AT gt_lips_kna1 INTO gst_lips_kna1.
  ADD 1 TO lw_tabix.
  AT NEW kunnr.

    lw_tabix = 1.
  IF gw_page IS INITIAL.
    lw_count = 31.   "  It is set 31 here for the number of line items, the value would differ according to the line items one needs to print in a page

   lw_count = ( gw_page * 30 ) + 1."All the line items would be in the multiple of 30 + 1. For eg : 60 + 1, 90 + 1 etc.
  IF lw_tabix >= lw_count.
    ADD 1 TO gw_page.
  CLEAR gw_page_total.
  AT END OF kunnr.
gw_page_total = gw_page.
    gw_page = 1.
  IF gw_page_total IS NOT INITIAL.
    gst_lips_kna1-page_total = gw_page_total.
    MODIFY gt_lips_kna1 FROM gst_lips_kna1
    INDEX sy-tabix TRANSPORTING page_total.
    READ TABLE gt_lips_kna1 INTO lst_lips_kna1
    WITH KEY kunnr = gst_lips_kna1-kunnr.
    IF sy-subrc EQ 0.
      lst_lips_kna1-page_total = gw_page_total.
      MODIFY gt_lips_kna1 FROM lst_lips_kna1
      INDEX sy-tabix TRANSPORTING page_total.

CLEAR gw_page.


lw_count is taken as the counter for the number of line items that would fit in one page.

gw_page_total is the variable to print the total number of pages in one ship-to.

gw_page will store the value for the current page to be printed.


The header portion will have the following code:


      IF gw_new_sort EQ 'X'.
        CLEAR gw_new_sort.
        ADD 1 TO gw_page.


This code sets in the flag, which is used later in the footer part.


Sort begin would have this code to set the current page of the ship-to:


CLEAR gw_count1.
IF gw_count <= 1." This is done to avoid setting the flag as ‘X’ at the first run of the loop

  gw_new_sort = 'X'. " This flag is set to identify the beginning of a new page

READ TABLE gt_lips_kna1 INTO lst_lips_kna1
      WITH KEY kunnr = gst_lips_kna1-kunnr.
IF sy-subrc EQ 0.
  IF sy-tabix = 1 .
  lw_tabix = sy-tabix - 1. “ This marks begin of next document so to fetch the total pages for current ship-to number, subtracted 1 to get last record of current.
    READ TABLE gt_lips_kna1 INTO lst_lips_kna1 INDEX lw_tabix.
  gw_page_total = lst_lips_kna1-page_total.


Sort End:


To fetch the total number of pages of the current document, as per the logic coded in initialization. 





READ TABLE gt_lips_kna1 INTO lst_lips_kna1
      WITH KEY kunnr = gst_lips_kna1-kunnr.
IF sy-subrc EQ 0.
  gw_page_total = lst_lips_kna1-page_total.



The footer would be the area where the page number needs to be printed. After placing the text with the fields of the current page and page total, the code is to be placed in order to reset the page values.



IF gw_new_sort EQ 'X'.
  gw_page = 1.
  READ TABLE gt_lips_kna1 INTO lst_lips_kna1_n
      WITH KEY kunnr = gst_lips_kna1-kunnr.
  IF sy-subrc EQ 0.
    gw_page_total = lst_lips_kna1_n-page_total.

Issue: Create a Report with 2 ALV tables. These should open in full screen and take the maximum amount of space available on the screen. This one is for ABAP beginners.


There is a Report by Ruchi Tiwari which do nearly the same, but use a fixed sized custom control.


  • Create an empty Dynpro with screen number 2000. Create the PBO (status_2000) and PAI (user_command_2000) within forward navigation. I didn’t change the names. You can use includes but is quiet a god idea for real life use, but in this example I’ll put all code in my program “file”.
  • Add a status, because there will be a point in time, where you wish to leave the program( or not )


  • Add the PAI code for the exit. Your PBO and PAi should now look like this.2.png

          Now you should be able to call the programm and leave it with the exit button.

  • Add the code to the Programm:

"Data for output
DATA: gr_container TYPE REF TO cl_gui_docking_container.   "The carrier for the split container
DATA: lv_splitter TYPE REF TO cl_gui_splitter_container"The splitter itself
DATA: lv_parent1 TYPE REF TO cl_gui_container.           "parent 1 and 2
DATA: lv_parent2 TYPE REF TO cl_gui_container.

DATA ref_grid1 TYPE REF TO cl_gui_alv_grid.
DATA ref_grid2 TYPE REF TO cl_gui_alv_grid.
DATA: gr_table1 TYPE REF TO cl_salv_table.
DATA: gr_table2 TYPE REF TO cl_salv_table.

"Some data used for DB query




*&      Module STATUS_2000  OUTPUT
MODULE status_2000 OUTPUT.

"Now we create a docking container which will use the hole screen. So the Dynpro 2000 can't be seen anymore.
CREATE OBJECT gr_container
*     parent                      = g_grid_main
repid                       = sy-repid                                  "needs report id
dynnr                       = sy-dynnr                                  "need dynpro number
side                        = cl_gui_docking_container=>dock_at_bottom  "we want to add the docking on the bottom of the screen 2000
extension                   = cl_gui_docking_container=>ws_maximizebox "The Dockingcontainer should use the hole screen
*     style                       =
*     lifetime                    = lifetime_default
*     caption                     =
*     metric                      = 0
*     ratio                       = 70
*     no_autodef_progid_dynnr     =
*     name                        =
cntl_error                  = 1
cntl_system_error           = 2
create_error                = 3
lifetime_error              = 4
lifetime_dynpro_dynpro_link = 5
OTHERS                      = 6.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

**   create splitter container in which we'll place the alv table
CREATE OBJECT lv_splitter
parent  = gr_container
rows    = 2
columns = 1
align   = 15. " (splitter fills the hole custom container)
**   get part of splitter container for 1st table
CALL METHOD lv_splitter->get_container
row       = 1
column    = 1
container = lv_parent1.
**   get part of splitter container for 2nd table
CALL METHOD lv_splitter->get_container
row       = 2
column    = 1
container = lv_parent2.

***  Display first ALV
PERFORM set_display.
***  Display second ALV
PERFORM set_display1.

ENDMODULE.                 " STATUS_2000  OUTPUT
*&      Module USER_COMMAND_2000  INPUT
MODULE user_command_2000 INPUT.
IF sy-ucomm = 'EXIT'.
ENDMODULE.                 " USER_COMMAND_2000  INPUT
*&      Form SET_DISPLAY
FORM set_display .
*... Create Instance
CALL METHOD cl_salv_table=>factory
r_container  = lv_parent1
r_salv_table = gr_table1
t_table      = gt_mara.

*... Display table
gr_table1->display( ).

FORM set_display1 .
*... Create Instance
CALL METHOD cl_salv_table=>factory
r_container  = lv_parent2
r_salv_table = gr_table2
t_table      = gt_mard.

*... Display table
gr_table2->display( ).

Gungor Ozcelebi

Top 10 ABAP crimes

Posted by Gungor Ozcelebi Feb 24, 2015

Unfortunately It is not very rare to see sloppy codes in ABAP especially if you are working as a consultant. In this blog  you can see my  selection of worst ten examples. Some might be debatable but some are definitely not. It would  also be nice to discuss examples, cases you experienced in  comments section.


1. Complete program with no modularization blocks

Hundreds sometimes, thousands lines of code with no modularization blocks, no includes. Conditions with hundreds lines of codes. No readability, definitely,  It is my worst nightmare to be asked to correct or change this kind of code. It is not really different having only 2-3 modularization blocks with hundreds line of code.


2. Modification/repairs

Not all of them, but if any modification is done without enough investigation might cause big issues in time and I guess everyone would be agree it is not a good approach to modify standard programs without searching  any alternative solution. So I would suggest to think again if you are often doing modifications. And check first if it is possible to make enhancement instead of modifications.


3- Not considering performance

Codes with nested loops, one big loop with 30 select single, inside, select *, uncontrolled “read”s. They will decrease the performance more than you can imagine and should be avoided all the time. You can avoid some of them using proper design and  many alternative options are in place only if you search them.


4- Development in productive and quality assurance systems

Not very often, but it is not impossible to see such cases, no need to say it may cause big headaches and you are taking big risk if for any reason you are doing this.


5- No success and failure checks

I have seen few of these kind of program, probably it is thought that every single statement in the code will run smoothly but it is  not always the case. and If you  can not see any sy-subrc checks in a program this is not a good sign at all.


6- Not using exceptions

Very similar to point five, it is nice to consider all possibilities and implementing exceptions as described.


7- Copying big templates to every program

Especially for ALV, it is easy to prepare a template with all functionality and copying this template any time where ALV is used.Even it helps to save time, if any function is not needed for the copied programs they should be cleaned, if they are not they will cause issues.


8- Too many global definitions

Global definitions should only be used if they are needed by design, and in a good design they should not be needed too much. 


9- Lack of comments

Readability is very important, and where a complex logic is coded it is very helpful to put some comments to explain what is exactly done.


10-  Too many errors and warnings after SLIN and SCI checks in a recently developed program.

Things might change in time quickly in programming  and easiest way to see if we are on a good track in terms of development quality is  using automated tools like SLIN and SCI. It  is very easy to use, very explanatory and will save us from lots of mistakes. If you are not using this tools you might never know, if something that you have coded is right or wrong. Using these check tools will easily cure most of the mistakes mentioned above. 

It seems ten is not enough I am also adding other points should also have been in this list which are mentioned in comments section

11- Copying standard programs ( From Matthew Billingham)

If you copy standard programs, in every upgrade there will be difference between  copy program and new version of the copied standard which is not a good thing. And it will require big efforts to adapt new functionality into copy program.


12- Writing code like 1999 ( From Patrick Weber )

Using obsolete statements all the time it is very annoying.

13-  Badly formatted source code. ( From Peter Inotai )

It effects readability negatively.

14- Avoid 'Hard codings' (From Tuhin das )

while displaying any text in the program. We should try and use standard text and text elements as much as possible.

15- Using exit and commit work statements in enhancements  (From Johnson Ittyerah ).

The EXIT ensures that any new functionality that you add below doesnt even run because the EXIT is encountered. And the COMMIT WORK leads you on a wild goose chase when you encounter an Update error sometime later.



To keep all the troubles away ABAP programming guidelines  ( from  Horst Keller )


Filter Blog

By author:
By date:
By tag: