Thursday, August 25, 2011

Restricting Call Transactions - SE97

Problem: We are in one transaction and we click on an ICON and it goes into different transaction, even when the user does not have access to that transaction.

Cause: In the coding there is a statement called CALL TRANSACTION. Normally when user executes a transaction the system is forced to check for S_TCODE and Field TCD. But in this case the Check is missed unless the Transaction mapping is in TCDCOUPLES table. The program checks the TCDCOUPLES  table and see if the called transaction need to be checked. If there is not entry then the check is not performed and user is able to get to the transaction even when the user does not have access to this t-code.

Solution:  Go to transaction SE97 which updates TCDCOUPLES table and add the t-code. So now you will have entry in TCDCOUPLES.
Examples: KSB5 form MB51, MD04 from ME2O, MMBE from MB51 and ME2O, KSB5 from MMBE

PS: This may not work for all transaction so testing is always required

Tuesday, August 16, 2011

How to change development class of a SAPscript

At times developers develop SAPScript as local object. Unlike reports where we can change the development class using the attributes option , nothing such is available for SAPScripts.

However we can use the program RSWBO052 to change the development class.

Following are the step by step screenshots to change the development class

Tuesday, August 9, 2011

How many types of reports are there in ABAP?

In ABAP, there are a total of 7 types of reports. They are:  
  1. Classical
  2. Interactive
  3. Logical Database
  4. ABAP query
  5. ALV Reports
  6. Report Writer/Report Painter

What “Custom SAP Application development” means to me?

I had read this interesting article somewhere.

Here is my list of what makes someone qualified to claim “SAP Custom application development experience”.
  1. I can play 20 questions with non-technical users to learn their current process, the exceptions, the variations, and the vision for future business needs.
  2. I can design data dictionary objects from the ground up to support those needs including domains with value tables, text tables, table maintenance views, database views, and structures for screens and reports.
  3. I can write functional and technical specifications that speak to both business persons and ABAP developers. My documents incorporate flowcharts using Visio or Powerpoint diagrams.
  4. I can generate function modules and includes for change documents to provide standard change history analysis for my applications.
  5. I can create a custom IMG structure to organize all configuration tables, setup programs, and link documentation together.
  6. I can use the SAP documentation transaction SE61 and know how to use hyperlinks and includes so that any user will have access to online help from any screen or report I’ve developed.
  7. I can build applications that utilize parallel processing when performance is critical.
  8. I know the reason for the Update Task and table locking. Nobody will ever lose their changes in one of my applications.
  9. I can capture background messages in the Application log if it is not feasible to transmit them back to the user.
  10. I can incorporate email functionality into my screens and background jobs to eliminate hard copy printouts or the need for users to remember to “go online and check”.
  11. I know the difference between a perform, a function module, and a class method and when to use each in my design.
  12. I know how to incorporate hooks and user exits into my application so that future developers can easily make changes without touching the core modules.
  13. All screens have search helps, F1 documentation, memory IDs, and double-clicking on stuff naturally takes you to the most meaningful screen for that particular element. I even include documentation for future programmers to give them some hints on how to extend or enhance the application.
  14. I know what makes a BAPI different than just any old RFC. I also know when I should use a real-time ALE interface instead of a BAPI and vice-versa.
  15. I know how to work with Grid controls, Tree controls, Text editor controls, and splitter controls to provide the most robust user tools possible.
  16. I know how to code in order to handle Unicode files and text. My applications are fully multi-lingual, requiring only someone bilingual to help with the translations.

    And lastly, most encompassing:
  17. When people use my applications, they would swear it was just another SAP transaction.
I hope this highlights some of the value that a skilled ABAP developer can bring to a project. Custom SAP application development can cost companies hundreds of thousands of dollars per year. A well designed application with attention paid to the details will surely save as much over the course of its lifetime.

Monday, August 8, 2011

Safeguard your ABAP code

An article from SDN

I have learned this lesson in a hard way, but would like to share the grief with everybody. While working with one of our clients, I developed a COBRA interface that sends out an automatic email to employees when their dependents turn 19 or 21 of age to inquire about COBRA forms.  We tested the COBRA interface and pushed it to production and guess what? The SAP Basis resource forgot to run the job with variants, so the interface run for everybody with end date ‘12/31/9999,’ which sent out 30,000 emails. Yes, 30,000 emails that morning. 

Instead of pointing out to the SAP Basis resource that he forgot to give the variant name in production, I held myself responsible as well for not creating a safeguard in the code.

I have included the following code below!!

   IF  SY-SLSET IS INITIAL. " Used Selection Screen Variant
     WRITE : 'No Variant Selected check SM36 & SM37' COLOR COL_NEGATIVE.
      MESSAGE  e016(RP) with 'No Variant Selected' space space space.

Wednesday, August 3, 2011

ERROR_MESSAGE -- Capture messages

At times we see function modules without any exceptions but still there is a error message being thrown inside the function module if any piece of code fails. If this situation happens then the program terminates at that point. Ever wondered how do you capture the error message as there is no exception and hence no SY-SUBRC other than 0. Well here is the way.

In the program where you have written your code for the FM, include the following for the FM
    error_message = 99.

By doing this you will ensure that whenever there is any error thrown by the function  module, SY-SUBRC is set as 99 and you can then capture the message in system fields i.e. SY-MSGID, SY-MSGTY, SY-MSGNO, SY-MSGV1, SY-MSGV2, SY-MSGV3, SY-MSGV4, SY-MSGV5.

Tuesday, August 2, 2011

Compare two same database table contents

Sometimes we come up across a requirement to compare the contents of two database tables. For example to check if roles created in development have been successfully transferred to production or not. How do we do this???

SAP has provided a standard transaction code SCMP to compare contents of two database tables.

Monday, August 1, 2011

Table Buffering and Buffering types

Tables that are frequently read during production use, but only rarely modified, such as those containing configuration data, should be buffered on the application server. The access to data in a buffered table is 10-50 times faster than accessing data in a non-buffered table, being read from the database cache.  In the technical settings of a table in transaction SE11, you are able to turn on the table buffering and select the buffer type (fully buffered, generically buffered, or single record buffering).

In the following diagram it is depicted, how delivery class, data class, and buffering should be combined for (most of) the tables in your system.

Examples on how to read this diagram:
  • delivery class C (customizing table) should not be combined with data class APPL1 (transactional data)
  • a table that contains configuration data (APPL2), and which is assigned to delivery class S (system table), should be buffered
  • a master data table (APPL0) with delivery class A (application table) should not be buffered, except if it has only a few entries (size category 0, or single record buffered with size category 0, 1, or 2)

ALV Checkbox, Select All & Filter

Often in editable ALV, we come across a requirement to add a checkbox and have select all & deselect all buttons in ALV toolbar. This blog is not about how to add a check box or buttons to the toolbar. Even the code for select all button is easy i.e. just loop at the internal table, mark the checkbox column as 'X' and then use method refresh_table_display to show it. However there is a small hiccup when one uses the filter option. Lets say we are displaying 10 Purchase Orders(PO) 101...110 and we want to update the PO quantity. And we use the filter option to select the POs 106 till 110. This can be esily done using the standard filter option. But what now if you use the select all option??? All the POs will be selected i.e. 101 till 110 instead of 106 till 110. And when you update the quantity and press the save button, all the 10 POs will get updated. However we want to update only 5 POs. The trick over here to select only the non filtered entries is to use the method get_filtered_entries of class cl_gui_alv_grid to get the filtered entries(i.e. hidden) and then mark 'X' against those records which are not filtered. 

Following code should be written on clicking the select all button.

  DATA: wa_out             TYPE ty_out,                  " Output Table for Display
              i_filter_entries  TYPE lvc_t_fidx,             " Filtered entries
              l_tabix              TYPE sy-tabix,                " Index
              l_valid              TYPE c,                          " Flag     
              ls_stable          TYPE lvc_s_stbl.            " WA for LVC_S_STBL

Note - 1. g_grid is the object reference for CL_GUI_ALV_GRID class.
           2. it_out is the internal table for display.

  CALL METHOD g_grid->check_changed_data
      e_valid = l_valid. 
 IF l_valid EQ 'X'.
    CALL METHOD g_grid->get_filtered_entries
        et_filtered_entries = i_filter_entries.
    LOOP AT it_out INTO wa_out.
      l_tabix = sy-tabix.
      READ TABLE i_filter_entries FROM l_tabix TRANSPORTING NO FIELDS.
      IF sy-subrc IS NOT INITIAL.
        wa_out-chk = 'X'.
        MODIFY it_out INDEX l_tabix FROM wa_out TRANSPORTING chk.
    ls_stable-row = 'X'.
    ls_stable-col  = 'X'.

    CALL METHOD g_grid->refresh_table_display
        is_stable = ls_stable.