Wednesday, July 25, 2012

To find the IP address of application server in SAP

TYPES: BEGIN OF kernel_version,
         key(21) TYPE c,
         data(69) TYPE c,
      END OF kernel_version.
  DATA : gt_kernel_version TYPE STANDARD TABLE OF kernel_version,
         gw_kernel_version TYPE kernel_version.
  DATA ip_address(69) TYPE c.
  CALL 'SAPCORE' ID 'ID' FIELD 'VERSION'
                 ID 'TABLE' FIELD gt_kernel_version[].
  READ TABLE gt_kernel_version INTO gw_kernel_version INDEX 11.
  ip_address = gw_kernel_version-data.
WRITE ip_address.

Shift negative sign from right to left in ABAP

DATA: gv_amount type konp-kbetr.
DATA: gv_amount_text(15)  type c.
gv_amount = 100.
gv_amount = gv_amount * -1.
gv_amount_text = gv_amount.
Now value will be 100 -
CALL FUNCTION 'CLOI_PUT_SIGN_IN_FRONT'
    CHANGING
      value         = gv_amount_text.
Now final value will be -100

Details of messages being displayed on WEB UI in SAP CRM

In order to figure out the details of the messages being displayed on WEB UI in SAP CRM for analysis purpose, the following steps can be performed:
1.      Put a break-point in the method ADD_MESSAGE of the message service class CL_BSP_WD_MESSAGE_SERVICE  and replicate the scenario for which the error message is appearing on the WEB UI. The  import parameters IV_MSG_ID and IV_MSG_NUMBER of this method would have the message details.
2.      The standard database table T100 maintains the standard error messages and their message class and message number.

3.      The method call stack in the debugger (‘Standard’ tab) can then be used to trace where in the logic this message is being added.

Grey out fields on ME21N/ME22N/ME23N

How to grey out fields on ME21N/ME22N/ME23N

For certain Purchase orders, based on some condition, we need to grey out the fields NETPR & KBETR.

In order to do this, we need to find the right BADI or the right user exit to code our functionality. For this debug tool is a must to know where and how these fields are populated on the purchase order screen.

This functionality can be achieved by following the below steps.

For the PO creation/change screen below is the solution to gray out the required fields (NETPR & KBETR)

1. for NETPR:

The field catalog that fills NETPR is TC_1211 Actually in standard program SAPLMEGUI, there is a call to the FM MEGUI_BUILD_PO_ITEMOV_PLUGIN.. Inside that, in line 44, TC_1211 gets populated. This contains all field catalog values. So in BADI, code to disable field NETPR by reading values using field symbols.

In SE19:

Create Implementation — > Classic BADI –> ME_ACTV_CANCEL_PO –> Implementation name ZCL_IM_TEST

In method CHECK_ACTIVITY code the following:

Method IF_EX_ME_ACTV_CANCEL_PO~CHECK_ACTIVITY.
FIELD-SYMBOLS :<fs>        TYPE ANY TABLE,
<ls>        TYPE ANY,
<lr_screen> TYPE screen.

ASSIGN (‘(SAPLMEGUI)TC_1211-COLS’) TO <fs>.
IF sy-subrc IS INITIAL.
LOOP AT <fs> ASSIGNING <ls>.
ASSIGN COMPONENT ’SCREEN’ OF STRUCTURE <ls> TO <lr_screen>.
IF <lr_screen>-name = ’MEPO1211-NETPR’.
<lr_screen>-input = 0.
ENDIF.
ENDLOOP.
ENDIF.

endmethod.

Activate the implementation. NETPR will be disabled in the header when u try to create or change purchase order.

2. for KBETR

In Screen 6201 of program SAPLV69A -> LV69AO03à Module FELDAUSWAHL, there is a User Exit: PERFORM userexit_field_modification.

Inside this EXIT, change the contents of TCTRL_KONDITIONEN-COLS [6]-SCREEN-INPUT to 0. KBETR will get grayed out.

Capture error messages for function modules without exceptions


At times we see function modules without any exceptions but still there is an 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. In this case there is no SY-SUBRC other than 0.

To solve this, in the program where you have written your code for the FM, include the following lines of code.

EXCEPTIONS
    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, and SY-MSGV5.
SAMPLE CODE:
CALL FUNCTION 'RV_CUSTOMER_MATERIAL_UPDATE'
  
TABLES
    xknmt_tab     = lt_xknmt
    yknmt_tab     = lt_ykmt
    tcatalog_tab  = lt_cat
  
EXCEPTIONS
    error_message = 
99.
  IF sy-subrc <> 0.
     
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
         
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  
ENDIF.

Wednesday, May 30, 2012

Embedding Image in mail body instead of sending it as an attachment

Get the path of image residing in MIME repository, fetch the binary content of the image, convert into BASE64 data and attach the base64 data into HTML mail body to embed image.
·         Create a z report program.
·         Get the image path from MIME repository (SE80): '/SAP/PUBLIC/image.jpg' (Path of image in mime repository which need to be embedded)
·         Get the binary content of the image.
  DATA: o_mr_api  type ref to if_mr_api,
                 is_folder  type boole_d,
                 l_current type xstring,
                 l_loio type skwf_io.

 IF o_mr_api is initial.
    o_mr_api = cl_mime_repository_api=>if_mr_api~get_api ( ).
  ENDIF.
      CALL METHOD o_mr_api->get
    EXPORTING
      i_url              = '/SAP/PUBLIC/image.jpg'
    IMPORTING
      e_is_folder        = is_folder
      e_content          = l_current
      e_loio             = l_loio
    EXCEPTIONS
      parameter_missing = 1
      error_occured      = 2
      not_found          = 3
      permission_failure = 4
      OTHERS             = 5.

*l_current will hold the image in a XSTRING 
·         Convert the binary image data into Base64.
  CALL FUNCTION 'SSFC_BASE64_ENCODE'
    EXPORTING
      bindata                        = l_current
   IMPORTING
     b64data                        = b64data.
  IF sy-subrc <> 0.  
  ENDIF.
·         Create mail body using HTML.
     In email body, the image will be displayed using its binary content.
    DATA lv_length TYPE I,
                 lv_len2 TYPE i.

  clear wa_mail_body.
  move '<html>' to wa_mail_body.
  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.
  move '<head>' to wa_mail_body.
  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.
  move '<title>hello</title>' to wa_mail_body.
  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.
  move '<meta http-equiv="content-type" content="text/html;charset=iso-8859-   1">' to wa_mail_body.
  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.
  move '</head>' to wa_mail_body.
  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.
  move '<body>' to wa_mail_body.
  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.
  wa_mail_body  = '<em><font'  .
  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.
  wa_mail_body  = 'color="#0000ff" size="+7" face="arial,'.
  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.
  wa_mail_body  = 'helvetica, sans-serif">test image</font></em>'.
  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.
*add image base64 content
  wa_mail_body = '<img src="data:image/gif;base64,'.

  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.

  lv_length = strlen (b64data).
  lv_len2 = lv_length / 255.

  wa_mail_body = b64data.
  append wa_mail_body to gt_mail_body.
  CLEAR wa_mail_body.


  DATA :lv_len3 TYPE I,
              temp1 TYPE i,
              temp2 TYPE i.
  do lv_len2 times.
    lv_len3 = 255 * sy-index.

    if lv_len3 <= lv_length.
      wa_mail_body = b64data+lv_len3.
      if wa_mail_body is not initial.
        append wa_mail_body to gt_mail_body.
        clear wa_mail_body.
      else.
        exit.
      endif.
    elseif lv_len3 > lv_length.

        exit.
    endif.
  enddo.

  wa_mail_body = '"alt="happy birthday" align="middle" width="304" height="228" />'.
  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.
  move '</body>' to wa_mail_body.
  append wa_mail_body to gt_mail_body.

  clear wa_mail_body.
  move '</html>' to wa_mail_body.
  append wa_mail_body to gt_mail_body.
·         Send Mail.
           DATA : lt_mail_body TYPE soli_tab,
         lwa_mail_body LIKE LINE OF lt_mail_body.

  l_subject = 'Test : Image in mail'.

  lr_email_body = cl_document_bcs=>create_document(
                                   i_type = 'HTM'
                                   i_text = gt_mail_body
                                   i_subject = l_subject ).

  lr_email = cl_bcs=>create_persistent( ).
  lr_email->set_document( lr_email_body ).

  l_mail_address = 'test@test.com'.

  lr_receiver = cl_cam_address_bcs=>create_internet_address( l_mail_address ).
  lr_email->add_recipient( i_recipient = lr_receiver ).

  "Set Sender and send mail
  l_sender = cl_sapuser_bcs=>create( sy-uname ).
  lr_email->set_sender( l_sender ).
  lr_email->set_send_immediately( 'X' ).  "Send email directly
  l_send_result = lr_email->send( i_with_error_screen = 'X' ).

  COMMIT WORK.
Output:
Go to SAP inbox check mail for the image embedded in the mail.

Saturday, May 12, 2012

Distributing material master idoc using changepointers

To create material master idocs without the use change pointers execute transaction BD10
The step to distribute material master idocs to other systems using change pointers are:
• Create logical system for the receiver system: BD54
• Create distribution model: BD64
• Activate change pointers for message type MATMAS: Transaction BD50
• Add MATMAS message type to the Outbound parameters for the partner profile for the receiver system: WE20
• After the a material has been changed - Creater idocs from change pointers: BD21
Program RBDMIDOC which generates idocs from changepointers, can be schedules to run automatically

SAP FI - Parked Documents Transactions and Tables

Transaction codes

FBV0 : Poste parked document
FBV2 : Change
FBV3 : Display
FBV4 : Change Header
FBV5 : Display Changes
FBV6 : Refuse
FV50 : Post / Delete : Single Screen Transaction

Tables

Parked document header data goes to bkpf table but item level data does NOT go to bseg table. Instead the tables below are used:
VBSEGA - Assets parked document detail
VBSEGD - Customers parked document detail
VBSEGK - Suppliers parked document detail
VBSEGS - General Ledger  parked document detail

Thursday, May 3, 2012

ABAP Performance Tuning Tips

Tools that can be used to help with performance tuning.
1. ST05 is the performance trace. It contains the SQL Trace plus RFC, enqueue and buffer trace. Mainly the SQL trace is is used to measure the performance of the select statements of the program.
2. SE30 is the Runtime Analysis transaction and can be used to measure the application performance.
3. SAT transaction is the replacement SE30. It provides same functionality as SE30 plus some additional features.
4. ST12 transaction (part of ST-A/PI software component) is a combination of ST05 and SAT. Very powerful performance analysis tool used primarily by SAP Support.

5. One of the best tools for static performance analyzing is Code Inspector (SCI). There are many options for finding common mistakes and possible performance bottlenecks.
Steps to optimize the ABAP Code
1. Database
a. Use WHERE clause in your SELECT statement to restrict the volume of data retrieved. 
b. Design the Query to use as many index fields as possible from left to right in the WHERE statement
c. Use FOR ALL ENTRIES in your SELECT statement to retrieve the matching records at one shot
d. Avoid using nested SELECT statement and SELECT within LOOPs, better use JOINs or FOR ALL ENTRIES. Use FOR ALL ENTRIES when the internal table is already there. Try JOINs if the SELECT statements are right behind each other.
e. Avoid using ORDER BY in SELECT statements if it differs from used index  (instead, sort the resulting internal table), because this may add additional work to the database system which is unique, while there may be many ABAP servers
f. INDEX: Creation of Index for improving performance should not be taken without thought. Index speeds up the performance
but at the same time adds two overheads namely; memory and insert/append performance. When INDEX is created, memory is used up for storing the index and index sizes can be quite big on large transaction tables! When inserting a new entry in the table, all the indices are updated. More indices, more time. More the amount of data, bigger the indices, larger the time for updating all the indices
g. Avoid Executing an identical Select (same SELECT, same parameter) multiple times in the program
h. Avoid using join statements if adequate standard views exist.

2. Table Buffer
a. Defining a table as buffered (SE11) can help in improving the performance but this has to be used with caution. Buffering of tables leads to data being read from the buffer rather than from table. Buffer sync with table happens periodically, only if something changes. If this table is a transaction table chances are that the data is changing for particular selection criteria, therefore application tables are usually not suited for table buffering. Using table buffering in such cases is not recommended. Use Table Buffering for configuration data and sometimes for Master Data
b.  Avoid using complex Selects on buffered tables, because SAP may not be able to interpret this request, and may transmit the request to the database. The code inspector tells which commands bypass the buffer.


3. Internal Table
a. Use sorted tables when nested loops are required.
b. Use assign (field symbol) instead of into in LOOPs for table types with large work areas
c. Use READ TABLE BINARY SEARCH with large standard tables speed up the search. Be sure to sort the internal table before binary search.
d. Use transaction SE30 to check the code

4. Miscellaneous
a. PERFORM: When writing a subroutine, always provide type for all the parameters. This reduces the overhead which is present when the system determines on its own each type from the formal parameters that are passed.

Which is the better - JOINS or SELECT... FOR ALL ENTRIES?
The effect of FOR ALL ENTRIES needs to be observed first by running a test program and analyzing SQL trace. Certain options set by BASIS can cause FOR ALL ENTRIES to execute as an 'OR' condition. This means if the table being used FOR ALL ENTRIES has 3 records, SQL Trace will show 3 SQLs getting executed. In such a case using FOR ALL ENTRIES is useless. However of the SQL Trace shows 1 SQL statement it's beneficial since in this case FOR ALL ENTRIES is actually getting executed as an IN List.
JOINS are recommended to be used till 5 joins. If the JOIN is being made on fields which are key fields in both the tables, it reduced program overhead and increases performance. So, if the JOIN is between two tables where the JOINING KEYS are key fields JOIN is recommended over FOR ALL ENTRIES.
You can use for all entries to reduce the database hits, and use non-key fields.
Here is a code with join :
SELECT A~VBELN A~KUNNR A~KUNAG B~Name1
into table i_likp
FROM LIKP AS A
  INNER JOIN KNA1 AS B
    ON A~kunnr = B~KUNNR.

* For with limited data using for all entries:
* Minimize entries in I_likp by deleting duplicate kunnr.

LOOP AT i_likp INTO w_likp.
  w_likp2-KUNAG = w_likp-KUNAG.
  APPEND w_likp2 TO i_likp2.
ENDLOOP.

SORT i_likp2 BY kunnr.
DELETE ADJACENT DUPLICATES FROM i_likp2 COMPARING kunnr.
* GET DATA FROM kna1
IF NOT i_likp2[] IS INITIAL.
  SELECT kunnr name1
    INTO TABLE i_kna1
    FROM kna1
    FOR ALL ENTRIES IN i_likp2
    WHERE kunnr = i_likp2-KUNNR.
ENDIF.


Avoid use of nested loops
When a nested loop has to be used, use a condition for the inner loop.  Otherwise in the production environment it may be possible that the loop takes a lot of time and dumps.
loop at itab1.
  loop at itab2 where f1 = itab1-f1.
  ....
  endloop.
end loop.

Another option is to use READ with BINARY SEARCH for the second table.
SORT itab2 BY f1.loop at itab1.
  Read table itab2 with key f1 = itab1-f1 BINARY SEARCH.
  if sy-subrc = 0.
    idx = sy-tabix.
    loop at itab2 from idx.
      if itab2-f1 <> itab1-f1.
        exit.
      endif.
     ....
    endloop.
  endif.
endloop.

SAP ABAP Fine Tuning Developments


Factors influencing Performance Tuning
§          Database Operation
§          Application Code
§          Memory Handling
§          Tools for Tuning
-          SQL Trace
-          Runtime Analysis
Database Operation
§          Database Access
§          Data volume and Network Load
§          Bulk retrieval or update
§          Frequency of Communication between Application Program & Database System (Array operation over Single Row)
§          Usage of Index
§          Table buffering
Design Stage Considerations
§          Restrict Data Selection
§          Make more mandatory fields..
§          If initial data selection itself is huge.
-          warn user about performance before proceeding further
-          Terminate further processing with suggestion to run with more restriction
-          Suggest Background operation
§          Designing the selection screen :
-          Correctly group the fields which are used for filtering the data during selection.
-          group the fields which would be used for only restricting the output.
User then would know, which can improve response and which cannot.
§          If the report is used for on-line purpose only, drill down report would be better alternative.
§          Get more information only when you need it!
§          Check current data size and the expected growth rate.
Effective Select Statement
§          Specify by Key fields while selection
§          Avoid select within loops / select.. Endselect
§          Inner join / views better than nested selects / multiple selects
§          Take care 'For All Entries in Table'
-          Initial or Not
-          Large number of records
§          Keep Select Clause simple
§          Into Corresponding Fields Vs Into Table
Data Selection from database
§          INTO TABLE with the SELECT statement provides faster access to the database than using an APPEND statement with SELECT
§          The INTO TABLES statement groups the records which accounts for reduction in network traffic whereas  APPEND statements access the DATABASE for individual records
§          For data which is used once the SELECT  ENDSELECT loop is effective since  the INTO TABLE statement collects  all the data of a table in the memory
§          Use package size option, Data is put in table in packets of size n
§          Use "where" clause with index rather than select all and check
Aggregate Clauses
§          Use ORDER BY Clauses only if indexes are taken
§          Do not use ORDER BY if data selected is more ( more than 20% of total )
§          Statements like COUNT, SUM, MIN,  MAX, AVG are done at the database level
§          Usage of these statements avoid  transferring large amounts of data to an application for calculating its aggregate
§          These aggregate functions can also be combined well with the GROUP BY statement
INDEXES   
•          An index can be considered a sorted  copy of a database table of certain fields.
•           Sorting provides faster access to the data records of the table, ( binary search ).
•           Indexes are of two types:- Primary and Secondary
•          .The primary index contains the key fields of the table and a pointer to the non-key fields
•           The primary index is created automatically when the table is created in the database.
•           Other indexes created are called secondary indexes.
•           Table is accessed frequently with fields other than fields of primary index
Programming using Indexes
§          Data being selected
§          Volume of data
§          Order of fields in Index


What to Keep in Mind for Secondary Indexes                               
§          When table contents change, indexes are readjusted
§          Slows down database insertion
§          Frequently accessed tables should not have too many indexes
§          Create indexes only when that index is likely to be used frequently
§          Indexes created may not be used to one's liking.
§          Determined by database optimizer by an algorithm
§          Indexes should have few common fields. Too many common fields would
   create problems for the optimizer
§          Use SQL Trace for determining indexes
Type of Index Scans
§          Unique Index Scan :- The entry specified by that index is unique
§          Range Scan:-              Most frequent, a range of values scanned
§          Full Table Scan:-          No index used, full table scanned for data
Buffering - Important Points to consider
§          The database interface of SAP provides buffers on each application server which allows local storage of database tables
§          Access to data in tables which are buffered can take place from application server instead of accessing the database directly
§          Table buffers enhance the performance of a system by reducing the number of times the database is accessed through the network for data
§          The performance improvement due to table buffers on a systems with several application servers is considerably more compared to a central system with only one application server
§          But on a central system with one application server a noticeable effect on the performance comes due the reduction in the number of processes when a buffer is accessed instead the database
§          The buffer values remain unchanged when a read access is  made. If the application changes the data the changes are made on the database and then the buffer on the corresponding application server
§          When data is changed on the database it is logged in the DDLOG table on the database
§          Buffers on other application servers  are updated at  intervals of one to two minutes
§          This is done with the help of the log maintained in the DDLOG table. When the synchronizing mechanism is run, the log invalidates the buffers on all other application servers
§          This causes all the other application servers to access the database directly for data and update their buffers the next time when data is needed
Operations on Internal Tables
§          Copying of Internal Tables - Copy whole table rather than line by line
§          Do not delete records of the same internal table within loop
§          Delete records using where clause
Memory Management
§          Avoid unnecessary variables
§          Use local variables in modularization units
§          Transfer key information to the Calls
§          Free Internal table no longer in use
§          Optimize usage of bulk data, memory and processing overhead
SQL Trace (ST05)
§          Overview
§          Understanding What is Measured
§          Creating an SQL Trace Data File
§          Calling an SQL Trace Data File
§          Analyzing an SQL Trace Data File
SQL Trace: Overview
§          The SQL statements that the application uses.
§          Shows what the ABAP processor is requesting from the database
§          Lists actual duration of each database request
§          What database accesses or changes occur in the update section of the application
§          How the system translates ABAP OPEN SQL commands (such as SELECT) into standard SQL commands
§          Gives index usage and available indexes
§          Presents types of table scans used on fields
§          Red flags questionable SQL statements
§          Where the application makes unnecessary database accesses or repeated accesses
§          Gives index usage and available indexes
§          Presents types of table scans used on fields
§          Red flags questionable SQL statements
§          Where the application makes unnecessary database accesses or repeated accesses
From the time the trace function is turned on to the time it is turned off again, all database activity occurring either for a specific user or for an entire system is recorded. The SQL Trace tool measures the following database requests:
Buffering of Database Requests
-          To keep the number of runtime-consuming PREPARE calls small, each an application's work processes hold a certain number of already translated SQL statements in a special buffer. By default, a process holds up to 250 statements.
-          If the system must execute a specific OPEN SQL, the system first checks whether this statement is stored in the "statement cache". If the statement is in the cache, the system executes it immediately using a REOPEN (SELECT) or a REEXEC (INSERT, UPDATE, DELETE).

Buffering of Database Requests (cont'd)
-          If the statement is not buffered, a PREPARE operation prepares it for the subsequent OPEN/EXEC. The system administers the buffer according to the LRU algorithm ("least recently used"). When space is needed for new statements, the statements that are rarely used are deleted. As a result of the LRU algorithm, the statement must prepare frequently used statements usually only once.
-          An application server buffers the DECLARE, PREPARE, OPEN, and EXEC requests within the cursor cache of one work process. As a result, once the system opens a cursor for a DECLARE operation, it can use this cursor over and over again within the same work process.
Understanding What is Measured
§          Logical Sequence of Database Requests
-          Database requests are interconnected and always occur in the same logical sequence. The DECLARE function defines and numbers the cursor. DECLARE precedes the PREPARE function. Use PREPARE to prepare a specific database statement, such as:
-          select * from sflight where carrid eq 'LH'.
-          and define the access method before the system can transfer the request to the database. During this preparation, the system is concerned only with the structure of the SQL statement and not with the values it contains.
-          The OPEN function takes the prepared SELECT statement and completes it with the correct values. In the above example, OPEN would issue the field carrid the value LH.
Creating an SQL Trace Data File
§          Go to the program to be SQL traced
§          If the program has a selection screen, execute the program and bring it to the selection screen
§          From the menu, choose System > Create Session, and type /nst05 in the transaction entry field of the new session.  Select the Trace on button.
§          Go back to the program session, and execute the program (F8).  Once the program is through executing, return to the SQL Trace session and select Trace off.  Now select List Trace.   A detailed list of all database requests will appear, as shown on the next slide.
Retrieving Trace Data File
1) Call up the initial screen of the SQL Trace tool.
2) Choose List trace.
           The system asks to specify a trace file. The last trace that was run is suggested as the default value.
3) Ensure that the information is correct.
           If a trace is run using an * (asterisk) for the user name, enter * (asterisk) in the DB trace for user to retrieve the trace.
4) Choose OK.
General Tips
§          Visualize table growth and build suitable restrictions while on drawing board itself like limiting document selection by date / status / material etc.
§          SELECT less with right where clause than selecting all and then filtering.
§          Use effective table joins or use correct views.
§          Reduce database hits by selecting all info. in one shot rather than repeated access.
§          Use of secondary sales table may reduce time instead using main table and using custom indices.
§          Check whether right index is picked
§          Apply all performance related techniques while processing internal tables, especially when they are expected to be big.
§          Perform run time analysis and SQL trace to identify bottle necks
 

Monday, April 30, 2012

Logic to get next business day in SAP


PARAMETER:  W_DATE like sy-datum.
 DATA:
        W_BUSDAY   TYPE D.
  DATA: DAY_ATTRIBUTES TYPE STANDARD TABLE OF CASDAYATTR INITIAL SIZE 1
  WITH HEADER LINE.

    DO.
      W_DATE  =  W_DATE + 1.
*Initial clean up of Day attributes
      CLEAR DAY_ATTRIBUTES .
      REFRESH DAY_ATTRIBUTES .

      CALL FUNCTION 'DAY_ATTRIBUTES_GET'
        EXPORTING
          HOLIDAY_CALENDAR = 'US'
          DATE_FROM        = W_DATE
          DATE_TO          = W_DATE
          LANGUAGE         = SY-LANGU
        TABLES
          DAY_ATTRIBUTES   = DAY_ATTRIBUTES.
      IF SY-SUBRC <> 0.
      ENDIF.

      READ TABLE DAY_ATTRIBUTES INDEX 1.
      IF DAY_ATTRIBUTES-HOLIDAY NE 'X' AND DAY_ATTRIBUTES-WEEKDAY NE
      '7' AND DAY_ATTRIBUTES-WEEKDAY NE '6'.
        EXIT.
      ENDIF.
    ENDDO.

   write: W_DATE .

Sunday, April 29, 2012

Program to find Userexits, BADI's and Enhancement spots in SAP standard transaction codes and programs


report  zenhtest message-id z25m_x_tool.

tables: tstc,    " SAP Transaction Codes
        tadir,   " Directory of Repository Objects
        modsapt, " SAP Enhancements - Short Texts
        sxs_attrt,"Exit: Definition side: Attributes, Text table
        trdir,   " System table TRDIR
        tfdir,   " Function Module
        enlfdir, " Additional Attributes for Function Modules
        tstct.   " Transaction Code Texts

data : g_oname type sobj_name,                  "Variable to hold Program Name Entered
       g_tcode type tcode.                      "Variable to hold Transaction Code Entered
data : jtab like tadir occurs 0 with header line.             "Internal Tabele declaration.. Withe header line

data : v_devclass like tadir-devclass.                    "Variable to hold Package of Tcode/prog entered
data : v_smod type i ,
       v_badi type i ,
       v_object type trobjtype.
data:    l_es_erw        type enh_hook_def,                 

         l_es_erw_s      type enh_hook_def_spot,          
         l_erw           type enhincinx,                   
         l_imp           type enh_hook_source,              
         l_full_name     type string,                       
         l_full_name_ret type string.                      
data : itab_inc type standard table of d010inc,       " Internal Table to handle include programs
       wa_inc type d010inc.                           "Work area Declarations

***************************Structure Declasrations********************************************
data:  begin of wa_result,                        " Result structure
         obj_type       type enhobj-obj_type,
         obj_name       type enhobj-obj_name,
         enhspot        type enhspotobj-enhspot,
         enhname        type enhobj-enhname,
         switch_id type sfw_switch_id,
         state     type  sfw_switchpos,
       end of wa_result.

data:  begin of wa_enhnames,                      " Enhancement name details structure
          enhname      type sobj_name,
          main_name    type enhobj-main_name,
       end of wa_enhnames.
**--
data:  begin of wa_enhnames_enho,                " Enhancement deatils structure
          enhname      type enhname,
          obj_name     type trobj_name,
          main_type    type trobjtype,
       end of wa_enhnames_enho.

data:  begin of wa_es_head_it,                    "Enhnacement Spot name
          enhspot       type enhobj-main_name,
       end of wa_es_head_it.

* Batch Input Table
data: begin of i_bdcdata occurs 0.                 "BDC data structure
        include structure bdcdata.
data: end of i_bdcdata.

data:   i_eso_it        type standard table of enhspotobj,                    "enhancements details
        i_eso_it_1      type standard table of enhspotobj,                    "enhancements details
        i_result        like wa_result occurs 0 with header line,             "result table with details
        i_final         like wa_result occurs 0 with header line,             "display table
        i_enhnames      like wa_enhnames occurs 0 with header line,
        i_enhnames_enho like wa_enhnames_enho occurs 0 with header line,
        i_es_head_it    like wa_es_head_it occurs 0 with header line,
        i_jtab          like tadir occurs 0 with header line,                 "table to capture enhancements
        i_jtab_enho     like tadir occurs 0 with header line,
        i_messtab       like bdcmsgcoll occurs 0 with header line.                      "#EC *  "BDC message tab

data : wa_eso_it        like line of i_eso_it,
       lv_enhname       like enhobj-enhname,
       lv_fld           type enhname.

*"A: show all dynpros "E: show dynpro on error only N: do not display dynpro
data: ctumode like ctu_params-dismode value 'E',
*"S: synchronously *"A: asynchronously *"L: local
      cupdate like ctu_params-updmode value 'L'.

**-- Include program names
types: begin of t_includes,
         prog type trobj_name,
       end of t_includes.

**-- Program content for text download
data: begin of content occurs 0,           "#EC *
        line(255),                         "#EC *
      end of content.

**--  Types for enhancement spots
types: begin of type_enhspotobj,
         enhspot   type enhspotname,
         version   type r3state,
         obj_type  type trobjtype,
         obj_name  type trobj_name,
         main_type type trobjtype,
         main_name type eu_aname,
       end of type_enhspotobj.

**--
types: begin of type_enho_obj,
         obj_name type trobjtype,
         devclass type devclass,
       end of type_enho_obj.

**--
types: begin of type_switch,
         switch_id type sfw_switch_id,
         devclass  type packname,
       end of type_switch.
**--
types: begin of type_switch_state,
         switch_id type sfw_switch_id,
         state     type  sfw_switchpos,
       end of type_switch_state.

**-- Names of function modules used within programmes
data: i_prog_includes type standard table of  t_includes with header line.

**-- Internal table for enhancement spots
data: i_enhspotobj type standard table of  type_enhspotobj with header line,
      wa_enhspotobj    type type_enhspotobj,
**-- Development classes for implimentation
      i_enho_obj type standard table of  type_enho_obj with header line,
**--  Switch
      i_switch   type standard table of type_switch with header line,
**-- Switch state
      i_switch_state type standard table of type_switch_state with header line.

field-symbols : <l_imp>  type enh_hook_source,            
                <l_eso> type enhspotobj,
                <l_enhspotobj> type type_enhspotobj.

selection-screen begin of block b1 with frame title text-001.
parameters : r_exit  radiobutton group g1 user-command ucom default 'X',            "To find user exits/badis
             r_espot radiobutton group g1.                                          "To find Enhancement spots

selection-screen end of block b1.
selection-screen begin of block b2 with frame title text-002.
parameters : r_tcode radiobutton group g2   user-command ucom2 modif id a default 'X',                 "Search Based on Transaction Code
             p_tcode type tstc-tcode modif id b,                                    "Transaction code name
             r_name radiobutton group g2 modif id c,                                "Search Based on Program
             p_name type tadir-obj_name modif id d.                                 "Program name


selection-screen end of block b2.
** Four MODIF ID's are used, because for 2nd block in selection screen, if transaction code has to be entered,
** then Program Name is suppose to be input inactive and vice-versa.

***********************************************************************************************************
*                    TOGGLING FACILITY OF SELECTION SCREEN                                                *
***********************************************************************************************************
at selection-screen output.

  loop at screen.
    if r_exit = 'X'.
      if screen-group1 = 'C' or screen-group1 = 'D'.

        screen-active = 0.                          "if user exit radio button is selected, grey out Prog name parameter
        modify screen.
      endif.
    elseif r_espot = 'X'.
      "if Enhancement Spots radio button is selected
      if screen-group1 = 'A' or screen-group1 = 'B' or screen-group1 = 'C' or screen-group1 = 'D'.
        screen-active = '1'.
        if r_tcode = 'X'.
          "if Tcode radio button is selected, grey out Prog name parameter
          if screen-group1 = 'D'.
            screen-input = 0.
          endif.
        elseif r_name = 'X'.
          "if Prog name radio button is selected, grey out Tcode parameter
          if screen-group1 = 'B'.
            screen-input = 0.
          endif.
        endif.
        modify screen.
      endif.
    endif.
  endloop.

***********************************************************************************************************
*                    SELECTION SCREEN VALIDATIONS                                                         *
***********************************************************************************************************

at selection-screen on p_tcode.
  case sy-ucomm.
    when 'ONLI'.
      if  r_tcode = 'X'.                  "if user selects Transaction code and does not fill in a tcode
        if p_tcode is initial.            " display an Error message.
          message e000.
        endif.
      endif.
  endcase.

at selection-screen on p_name.
  case sy-ucomm.
    when 'ONLI'.
      if r_espot = 'X' and r_name = 'X'.                "if user selects Program and does not fill in a prog name
        if p_name is initial.                           " display an Error message.
          message e001.
        endif.
      endif.
  endcase.

***********************************************************************************************************
*                    AT SELCTION SCREEN EVENT                                                             *
***********************************************************************************************************
at selection-screen.

  if r_exit eq 'X'.
    clear r_name.
  endif.

  if r_espot = 'X'.
    if r_tcode = 'X'.
      clear p_name.
    endif.
    if r_name = 'X'.
      clear p_tcode.
    endif.
  endif.

  if r_tcode = 'X' and p_tcode is not initial.                  "If user enters a transaction code
    select  single tcode                                        "Check if tcode exists in standard table TSTC
         from tstc
         into g_tcode
        where tcode = p_tcode.

    if sy-subrc ne 0.
      message e003.
    endif.
  endif.

  if r_name = 'X' and p_name is not initial.                    "If user enters program name
    select  single obj_name "#EC *  " Check if prog name exists in standard table TADIR.
         from tadir
         into g_oname
        where obj_name = p_name.

    if sy-subrc ne 0.
      message  e002.
    endif.
  endif.
***********************************************************************************************************
*                             START OF SELECTION EVENT                                                    *
***********************************************************************************************************

start-of-selection.
  if r_exit = 'X'.                            "if user wants to find user exits.
    perform f_badis_exits.                    "Subroutine to find User Exits/Badis

  elseif r_espot = 'X'.                        " if user want to find ENHANCEMENT SPOT.
    if r_tcode = 'X'.
      perform f_tcode_spots.                  "Subroutine to find Enhancment Spots For a given Tcdoe
    else.
      perform f_pname_spots.                  "Subroutine to find Enhancment Spots For a given Program
    endif.


  endif.
***********************************************************************************************************
*                             AT LINE SELECTION EVENT                                                     *
***********************************************************************************************************

at line-selection.                              "Navigation on clicking on a list item
**--
  clear: lv_fld,
         lv_enhname.
**--
  get cursor field lv_fld value lv_enhname.

  "If user clicks on Enhancment Name in list display, it transits to 2nd screen of SE19.
  if lv_fld = 'I_FINAL-ENHNAME'.
    if lv_enhname is not initial.
      perform fbdc_dynpro      using 'SAPLSEXO' '0120'.
      perform fbdc_field       using 'BDC_OKCODE' '=IMP_SHOW'.
      perform fbdc_field       using 'BDC_CURSOR' 'G_ENHNAME'.
      perform fbdc_field       using 'G_IS_NEW_1' 'X'.
      perform fbdc_field       using 'G_ENHNAME'  lv_enhname.
      perform fbdc_field       using 'G_IS_NEW_2' 'X'.

      perform fbdc_dynpro      using 'SAPLSEXO' '0120'.
      perform fbdc_field       using 'BDC_OKCODE' '=WB_BACK'.
      perform fbdc_field       using 'BDC_CURSOR' 'G_ENHNAME'.
      perform fbdc_field       using 'G_IS_NEW_1' 'X'.
      perform fbdc_field       using 'G_ENHNAME'  lv_enhname.
      perform fbdc_field       using 'G_IS_NEW_2' 'X'.

      perform fbdc_transaction using 'SE19'.         " Call transaction se19
    endif.

    "If user clicks on Enhancment Spot in list display, navigate to 2nd screen of SE18.
  elseif lv_fld = 'I_FINAL-ENHSPOT'.
    perform fbdc_dynpro      using 'SAPLSEXO' '0100'.
    perform fbdc_field       using 'BDC_OKCODE' '=SHOW'.
    perform fbdc_field       using 'BDC_CURSOR' 'G_ENHSPOTNAME'.
    perform fbdc_field       using 'G_IS_SPOT' 'X'.
    perform fbdc_field       using 'G_ENHSPOTNAME'  sy-lisel+1(29).

    perform fbdc_dynpro      using 'SAPLSEXO' '100'.
    perform fbdc_field       using 'BDC_OKCODE' '=WB_BACK'.
    perform fbdc_field       using 'BDC_CURSOR' 'G_BADINAME'.
    perform fbdc_field       using 'G_IS_BADI' 'X'.

    perform fbdc_transaction using 'SE18'.            " Call transaction se18
  elseif lv_fld(4) eq 'JTAB'.
    read table jtab with key obj_name = sy-lisel+1(20).
    move jtab-object to v_object.

    case v_object.
        "if user clicks on a User-Exit in list display, navigate to 2nd screen of SMOD.
      when 'SMOD'.
        set parameter id 'MON' field sy-lisel+1(10).

        perform fbdc_dynpro      using 'SAPMSMOD' '2010'.
        perform fbdc_field       using 'BDC_CURSOR' 'MOD0-NAME'.
        perform fbdc_field       using 'BDC_OKCODE' '=SHOW'.
        perform fbdc_field       using 'MOD0-NAME' sy-lisel+1(10).
        perform fbdc_field       using 'MODF-CHAM' 'X'.

        perform fbdc_dynpro      using 'SAPMSMOD' '2010'.
        perform fbdc_field       using 'BDC_CURSOR' 'MOD0-NAME'.
        perform fbdc_field       using 'BDC_OKCODE' '=BACK'.
        perform fbdc_field       using 'MODF-HEAS' 'X'.

        perform fbdc_transaction using 'SMOD'.              "CALL TRANSACTION smod
        "if user clicks on a BADI in list display
      when 'SXSD'.

        perform fbdc_dynpro      using 'SAPLSEXO' '0100'.
        perform fbdc_field       using 'BDC_OKCODE' '=ISSPOT'.
        perform fbdc_field       using 'BDC_CURSOR' 'G_IS_BADI'.
        perform fbdc_field       using 'G_IS_BADI' 'X'.

        perform fbdc_dynpro      using 'SAPLSEXO' '0100'.
        perform fbdc_field       using 'BDC_OKCODE' '=SHOW'.
        perform fbdc_field       using 'G_BADINAME'  sy-lisel+1(29).

        perform fbdc_dynpro      using 'SAPLSEXO' '100'.
        perform fbdc_field       using 'BDC_OKCODE' '=WB_BACK'.
        perform fbdc_field       using 'BDC_CURSOR' 'G_BADINAME'.
        perform fbdc_field       using 'G_IS_BADI' 'X'.


        perform fbdc_transaction using 'SE18'.              "CALL TRANSACTION se18
    endcase.
  endif.
***********************************************************************************************************
*                             END OF SELECTION EVENT                                                      *
***********************************************************************************************************
end-of-selection.
  refresh: i_result,      i_final,          i_enhnames,
           i_es_head_it,  i_jtab,             i_bdcdata,
           i_messtab.

  free: i_result,         i_final,          i_enhnames,
        i_es_head_it,     i_jtab,             i_bdcdata,
        i_messtab.

** All the internal table the feilds are refreshed and free, according to the requirement.

form f_badis_exits .
  if not p_tcode is initial.
*-- Validate Transaction Code using the Standard Table TSTC.
    select single * from tstc
     where tcode eq p_tcode.
*-- Find Repository Objects for transaction code, which has Object Type PROG.
    if sy-subrc eq 0.
      select single * from tadir
       where pgmid = 'R3TR'
         and object = 'PROG'
         and obj_name = tstc-pgmna.
**--Find Repository Objects for transaction code, which has Object Type TRAN.

      if sy-subrc ne 0.
        select single * from tadir
         where pgmid  = 'R3TR'
           and object = 'TRAN'
           and obj_name = p_tcode.
      endif.

      move : tadir-devclass to v_devclass.                  " Capture Package
      if sy-subrc ne 0.                                     "in case object type is function group
        select single * from trdir
         where name = tstc-pgmna.
        if trdir-subc eq 'F'.
          select single * from tfdir                        "#EC *
           where pname = tstc-pgmna.

          select single * from enlfdir
           where funcname = tfdir-funcname.

          select single * from tadir
           where pgmid = 'R3TR'
             and object = 'FUGR'
             and obj_name = enlfdir-area.

          move : tadir-devclass to v_devclass.       "Capture Package
        endif.
      endif.
    else.
      format color col_negative intensified on.
      message e004.
    endif.

  endif.
**--
* Find SAP Modifactions
  select * from tadir                                 "Select user exits/BADIS
    into table jtab
   where pgmid = 'R3TR'
     and object in ('SMOD','SXSD')
     and devclass = v_devclass.
  "To display Tcode Short Descriptions
  select single * from tstct
   where sprsl eq sy-langu
     and tcode eq p_tcode.

  format color col_positive intensified off.
  if not p_tcode is initial.
    write:/(19) text-007,
          20(20) p_tcode,
          45(50) tstct-ttext.
  endif.


  if not jtab[] is initial.
    write:/(105) sy-uline.
    format color col_heading intensified on.
    write:/1 sy-vline,
           2 text-008,
           41 sy-vline,
           42 text-009,
           105 sy-vline.
    write:/(105) sy-uline.
    loop at jtab.
      "For listing out User Exits
      at new object.
        if jtab-object = 'SMOD'.
          format color col_group intensified on.
          write:/1 sy-vline,
              2 'User Exits'(300),
             105 sy-vline.
          "For listing out BADI's
        elseif jtab-object = 'SXSD'.
          format color col_group intensified on.
          write:/1 sy-vline,
              2 ' Business Add-in'(301),
             105 sy-vline.
        endif.
      endat.

      case jtab-object.
        when 'SMOD'. "for user exits
          v_smod = v_smod + 1.                        "counter for user exits, to give the total number of user exits.

          select single * from modsapt
           where sprsl = sy-langu
             and name = jtab-obj_name.
          format color col_normal intensified on.

          write:/1 sy-vline,
                 2 jtab-obj_name hotspot on,
                41 sy-vline ,
                42 modsapt-modtext,
                105 sy-vline.

        when 'SXSD'.
*       For BADI's
          v_badi = v_badi + 1 .                       "counter for BADIS
          select single * from sxs_attrt
                            where sprsl     = sy-langu
                              and exit_name = jtab-obj_name.
          format color col_normal intensified on.

          write:/1 sy-vline,
                 2 jtab-obj_name hotspot on,
                41 sy-vline ,
                42 sxs_attrt-text,
                105 sy-vline.


      endcase.
      at end of object.
        write : /(105) sy-uline.
      endat.


    endloop.
    write:/(105) sy-uline.
    describe table jtab.
    skip.

    format color col_total intensified on.
    write:/ 'No of exits:'(302),  v_smod.
    write:/  'No of BADI''s:'(303), v_badi.
  else.
    "Incase BADI's/ User Exits do not Exist
    call function 'POPUP_TO_INFORM'                                   "EC NOTEXT
      exporting
        titel         = 'Information Message'(500)
        txt1          = 'Sorry!!!'(501)
        txt2          = 'No BADI''s/User exits available for the above Transaction'(502).


    leave program.
  endif.
endform.                    " F_BADIS_EXITS
*&---------------------------------------------------------------------*
*&      Form  F_TCODE_SPOTS
*&---------------------------------------------------------------------*
*  Finds the enhancement spots.
*----------------------------------------------------------------------*
form f_tcode_spots .
  if not p_tcode is initial.
**--select tcode from tadir
    select single * from tstc
     where tcode eq p_tcode.
    if sy-subrc eq 0.
      "Select Prog behind the btransaction
      select single * from tadir
       where pgmid = 'R3TR'
         and object = 'PROG'
         and obj_name = tstc-pgmna.
      "Capture Program pav\ckage
      move : tadir-devclass to v_devclass.
      "Else look in trdir
      if sy-subrc ne 0.
        select single * from trdir
         where name = tstc-pgmna.

        if trdir-subc eq 'F'.
          select single * from tfdir                        "#EC *
           where pname = tstc-pgmna.

          select single * from enlfdir
           where funcname = tfdir-funcname.

          select single * from tadir
           where pgmid = 'R3TR'
             and object = 'FUGR'
             and obj_name eq enlfdir-area.

          move : tadir-devclass to v_devclass.
        endif.    "IF trdir-subc EQ 'F'
      endif.    "IF sy-subrc NE 0
    else.
      format color col_negative intensified on.
      message e004.
    endif.
**--
    perform get_from_tadir.



  endif.    "IF sy-subrc EQ 0
*-Fill i_result
  loop at i_eso_it assigning <l_eso>.
    i_result-enhspot = <l_eso>-enhspot.
    append i_result.
  endloop.

  if not i_result[] is initial.
    delete adjacent duplicates from i_result.

    sort i_jtab by obj_name.
    loop at i_result.
      read table i_jtab with key obj_name  =  i_result-enhspot
                                   binary search.
      if sy-subrc = 0.
        i_result-obj_name  =  i_jtab-obj_name.
        read table i_eso_it into wa_eso_it with key enhspot = i_jtab-obj_name+0(30)
                                     binary search.
        if sy-subrc = 0.
          i_result-obj_type = wa_eso_it-obj_type.
        endif.
        modify i_result.
        clear i_result.
      endif.
    endloop.
    "select Name/ID's of Enhancement Spots
    select enhspot
      into table i_es_head_it
      from enhspotheader
       for all entries in i_result
     where enhspot = i_result-enhspot
       and   version = 'A'.
    "Select Enhancement names and main prog names
    if sy-subrc = 0.
      select enhname
             main_name
        appending table i_enhnames
        from enhobj
         for all entries in i_es_head_it
       where main_type = 'ENHS'
         and main_name = i_es_head_it-enhspot.
      if sy-subrc = 0.
        sort i_enhnames by main_name.
        delete adjacent duplicates from i_enhnames comparing enhname main_name.
**-- Get the development calss for the enhacement spots & implimentation
        select obj_name
               devclass
          into table i_enho_obj
          from tadir
          for all entries in i_enhnames
          where obj_name = i_enhnames-enhname and
                object   = 'ENHO'.
        if sy-subrc = 0.
**-- Get the switch details
          select switch_id
                 devclass
            into table  i_switch
            from sfw_package
            for all entries in i_enho_obj
            where devclass = i_enho_obj-devclass.
          if sy-subrc = 0.
**-- Get the switch status
            select switch_id
                   state
              into table  i_switch_state
              from sfw_switch_state
              for all entries in i_switch
              where  switch_id = i_switch-switch_id.
          endif.
        endif.
**--
        loop at i_result.
          i_final-obj_type  = i_result-obj_type.
          i_final-obj_name  = i_result-obj_name.
          i_final-enhspot   = i_result-enhspot.
          loop at i_enhnames where main_name = i_result-enhspot.
**-- Populate the switch
            read table i_enho_obj with key obj_name = i_enhnames-enhname. "#EC *
            if sy-subrc = 0.
              read table i_switch with key devclass = i_enho_obj-devclass.
              if sy-subrc = 0.
                read table i_switch_state with key switch_id = i_switch-switch_id.
                if sy-subrc = 0.
                  i_final-switch_id = i_switch_state-switch_id.
                  i_final-state     = i_switch_state-state.
                endif.
              endif.
            endif.
**--
            i_final-enhname  =  i_enhnames-enhname.
            append i_final.
          endloop.
          if sy-subrc <> 0.
            append i_final.
          endif.
          clear i_final.
        endloop.
      endif.
    endif.
**-- Also consider the Enhancement implimentation which are not part of enhancement spot's
    loop at i_jtab where object = 'ENHO'.
      i_jtab_enho = i_jtab.
      append i_jtab_enho.
    endloop.
**--
    if not i_jtab_enho[] is initial.
      select enhname                               "EC#..,bzw.
             obj_name
             main_type
        into table i_enhnames_enho
        from enhobj
        for all entries in i_jtab_enho
         where enhname = i_jtab_enho-obj_name+0(30)
            and obj_type = 'ENHS'.
      if sy-subrc = 0.
**-- Select the enhancement spot object
**--
        select *                                            "#EC
          from enhspotobj
          into corresponding fields of table i_eso_it_1
           for all entries in i_enhnames_enho
         where enhspot = i_enhnames_enho-obj_name+0(30).
        if sy-subrc = 0.
          sort i_eso_it_1 by enhspot.
        endif.

**-- Populate the final table
        delete adjacent duplicates from i_enhnames_enho comparing enhname.
        loop at i_enhnames_enho.
          read table i_final with key enhname  =  i_enhnames_enho-enhname.
          if sy-subrc <> 0.
            clear: i_final.
**--
            clear: wa_eso_it.
            read table i_eso_it_1 into wa_eso_it with key
               enhspot = i_enhnames_enho-obj_name+0(30)  binary search.
            if sy-subrc = 0.
              i_final-obj_type = wa_eso_it-obj_type.
            endif.
            i_final-enhspot  =  i_enhnames_enho-obj_name.
            i_final-enhname  =  i_enhnames_enho-enhname.
            append i_final.
          endif.
        endloop.
      endif.
    endif.
**--
    loop at i_final.

      format color col_normal intensified on.
      at new enhspot.
        write: /1 sy-vline,
                2 i_final-enhspot hotspot on,
                34 sy-vline.
      endat.

      case  i_final-obj_type.
        when 'REPS' or 'PROG'.
          write:  36 'Source Code Enhancement'(304).
        when 'INTF' or 'SXSD'.
          write:  36 'BADI Enhancement'(305).
        when 'FUNC' or 'FUGR'.
          write:  36 'Function group Enhancement'(306).
        when 'CLAS'.
          write:  36 'Class Enhancement'(307).

        when others.
          write:  36 i_final-obj_type.
      endcase.

      write:  64 sy-vline,
              66 i_final-enhname hotspot on,
             100 sy-vline,
             101 i_final-switch_id,
             132 sy-vline.
**--
      case i_final-state.
        when 'T'.
          write 133 'On'(308).
        when 'S'.
          write 133 'Stand-by'(309).
        when 'F'.
          write 133 'Off'(310).
      endcase.

      write: 150 sy-vline.
    endloop.
    write:/(150) sy-uline.

  endif.

endform.                    " F_TCODE_SPOTS
*&---------------------------------------------------------------------*
*&      Form  GET_FROM_TADIR
*&---------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
form get_from_tadir .
  " select records whose object types are enhancment spots/implimentations
  select * from tadir
    into table i_jtab
   where pgmid = 'R3TR'
     and object in ('ENHS','ENHO')
     and devclass = v_devclass.
  "to display short texts for tcode
  select single * from tstct
   where sprsl eq sy-langu
     and tcode eq p_tcode.

  format color col_positive intensified off.
* Transaction Code
  write:/1 text-018.
  if not p_tcode is initial.
    write:         30(20) p_tcode.
  endif.


  write: 55(50) tstct-ttext.
  skip.
  if not i_jtab[] is initial.

**-- Genral information.
    format color col_heading intensified on.
    write:/ 'To see Enhancement spot/Implementation in detail, please click on values under column'(311).

    write:/(150) sy-uline.
    format color col_heading intensified on.
    write:/1 sy-vline,
           2 text-015,
          34 sy-vline,
          36 text-016,
          64 sy-vline,
          66 text-014,
         100 sy-vline,
         101 'Switch'(520),
         132 sy-vline,
         133 'Switch State'(521),
         150 sy-vline.

    write:/(150) sy-uline.
**--Required details from enhspotobj table
    select *                                                "#EC
      from enhspotobj
      into corresponding fields of table i_eso_it
       for all entries in i_jtab
     where enhspot = i_jtab-obj_name+0(30).


    if sy-subrc eq 0.
      sort i_eso_it by enhspot.
    endif.

  else.
    "Information popup

    call function 'POPUP_TO_INFORM'
      exporting
        titel = 'Information Message'(503)
        txt1  = 'Sorry!!!'(504)
        txt2  = 'No Enhancements available for the selected Transaction'(505).


    leave program.

  endif.    "IF NOT I_JTAB[] IS INITIAL

endform.                    " GET_FROM_TADIR
*&---------------------------------------------------------------------*
*&      Form  F_PNAME_SPOTS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form f_pname_spots .


  "select record corresponding to entered tcode
  select single tcode from tstc                             "#EC *
        into p_tcode
        where pgmna = p_name.
  select single * from tstc
   where tcode eq p_tcode.

  if p_tcode is initial.
    select single * from trdir where name = p_name.
    if trdir-subc eq 'I'.
      " in case include programs, select required details from d010inc
      select  * from d010inc
      into table itab_inc
      where include = p_name.

      if itab_inc is not initial.
        loop at itab_inc into wa_inc.
          select single * from tstc                         "#EC *
          where pgmna = wa_inc-master.
          if sy-subrc = 0.
            exit.
          endif.
        endloop.

        tstc-pgmna = p_name.
      endif.
    endif.
  endif.

  if sy-subrc eq 0.

    if not tstc-pgmna is initial.
**-- Select the include program's which are there in the main program
      perform f_find_include_programs using tstc-pgmna.
**-- Append the main program also into internal table I_PROG_INCLUDES
      i_prog_includes-prog = tstc-pgmna.
      append i_prog_includes.
**--
      if not i_prog_includes[] is initial.
**-- Select the enhancement spot's data from ENHSPOTOBJ
**-- All the includes in itab I_PROG_INCLUDES
        select enhspot
               version
               obj_type
               obj_name
               main_type
               main_name
          into table i_enhspotobj
          from enhspotobj
          for all entries in i_prog_includes
          where obj_name = i_prog_includes-prog and
                version  = 'A'.
        if not i_enhspotobj[] is initial.
**--Select Transaction code description in system language
          select single * from tstct
           where sprsl eq sy-langu
             and tcode eq p_tcode.

          format color col_positive intensified off.
**-- Transaction Code
          write:/1 text-013,
                 25(20) p_tcode,
                 48(50) tstct-ttext.
          skip.

**-- Genral information.
          format color col_heading intensified on.
          write:/ 'To see Enhancement spot/Implementation in detail, please click on the enhancements of your choice'(325).

          write:/(150) sy-uline.
          format color col_heading intensified on.
          write:/1 sy-vline,
                 2 text-015,
                34 sy-vline,
                36 text-016,
                64 sy-vline,
                66 text-014,
                100 sy-vline,
               101 'Switch'(522),
               132 sy-vline,
               133 'Switch State'(523),
               150 sy-vline.

          write:/(150) sy-uline.
        endif.    "IF NOT i_enhspotobj[] IS INITIAL
      endif. " IF not I_PROG_INCLUDES[] is initial.
    else.
      "information popup
      call function 'POPUP_TO_INFORM'
        exporting
          titel = 'Information Message'(506)
          txt1  = 'Sorry!!!'(507)
          txt2  = 'No Enhancements available for the selected Transaction'(508).


      leave program.

    endif.
  else.
    "information popup
    call function 'POPUP_TO_INFORM'
      exporting
        titel = 'Information Message'(509)
        txt1  = 'Sorry!!!'(510)
        txt2  = 'No Enhancements available for the selected Transaction'(511).


    leave program.
  endif.    "IF sy-subrc EQ 0

**---
**--
  if not i_enhspotobj[] is initial.
**--
    loop at i_enhspotobj assigning <l_enhspotobj>.
      i_result-enhspot = <l_enhspotobj>-enhspot.
      append i_result.
    endloop.

    if not i_result[] is initial.
**--remove redundant records
      delete adjacent duplicates from i_result.
**--sort table
      sort i_enhspotobj by enhspot.
**--Populate rest of i_result
      loop at i_result.
***--get obj_name and main_type values from ENHSPOTOBJ table
        read table i_enhspotobj into wa_enhspotobj with key enhspot = i_result-enhspot
                                     binary search.
        if sy-subrc = 0.
          i_result-obj_name = wa_enhspotobj-obj_name.
          i_result-obj_type = wa_enhspotobj-main_type. " obj_type.
        endif.
        modify i_result.
        clear i_result.
      endloop.
**--
      select enhspot
        into table i_es_head_it
        from enhspotheader
         for all entries in i_result
       where enhspot = i_result-enhspot
         and   version = 'A'.
      if sy-subrc = 0.
**-- Get the enhancement id data from ENHOBJ
        select enhname
               main_name
          appending table i_enhnames
          from enhobj
           for all entries in i_es_head_it
         where main_type = 'ENHS'
           and main_name = i_es_head_it-enhspot.
        if sy-subrc = 0.
**--sort table
          sort i_enhnames by main_name.
          delete adjacent duplicates from i_enhnames comparing enhname main_name.
**-- Get the development calss for the enhacement spots & implimentation
          select obj_name
                 devclass
            into table i_enho_obj
            from tadir
            for all entries in i_enhnames
            where obj_name = i_enhnames-enhname and
                  object   = 'ENHO'.
          if sy-subrc = 0.
**-- Get the switch details
            select switch_id
                   devclass
              into table  i_switch
              from sfw_package
              for all entries in i_enho_obj
              where devclass = i_enho_obj-devclass.
            if sy-subrc = 0.
**-- Get the switch status
              select switch_id
                     state
                into table  i_switch_state
                from sfw_switch_state
                for all entries in i_switch
                where  switch_id = i_switch-switch_id.
            endif.
          endif.
**--
          loop at i_result.
            i_final-obj_type  = i_result-obj_type.
            i_final-obj_name  = i_result-obj_name.
            i_final-enhspot   = i_result-enhspot.
            loop at i_enhnames where main_name = i_result-enhspot.
**-- Populate the switch
              read table i_enho_obj with key obj_name = i_enhnames-enhname. "#EC *
              if sy-subrc = 0.
                read table i_switch with key devclass = i_enho_obj-devclass.
                if sy-subrc = 0.
                  read table i_switch_state with key switch_id = i_switch-switch_id.
                  if sy-subrc = 0.
                    i_final-switch_id = i_switch_state-switch_id.
                    i_final-state     = i_switch_state-state.
                  endif.
                endif.
              endif.
**--Populate enhancement name
              i_final-enhname  =  i_enhnames-enhname.
              append i_final.
            endloop.
            clear i_final.
          endloop.
        endif.
      endif.
    endif.
**--
**--Fill up the final display table
    loop at i_final.
      format color col_normal intensified on.
      write: /1 sy-vline,
              2 i_final-enhspot hotspot on,
              34 sy-vline.
**--Description of object types
      case  i_final-obj_type.
        when 'REPS' or 'PROG'.
          write:  36 'Source Code Enhancement'(315).
        when 'INTF' or 'SXSD'.
          write:  36 'BADI Enhancement'(316).
        when 'FUNC' or 'FUGR' .
          write:  36 'Function group Enhancement'(317).
        when 'CLAS'.
          write:  36 'Class Enhancement'(318).
        when others.
          write:  36 i_final-obj_type.
      endcase.
**--Enhancement names and switch id
      write:  64 sy-vline,
              66 i_final-enhname hotspot on,
             100 sy-vline,
             101 i_final-switch_id,
             132 sy-vline.
**--Switxh state
      case i_final-state.
        when 'T'.
          write 133 'On'(319).
        when 'S'.
          write 133 'Stand-by'(320).
        when 'F'.
          write 133 'Off'(321).
      endcase.

      write: 150 sy-vline.
    endloop.
    write:/(150) sy-uline.
  elseif  i_enhspotobj[] is initial.
      "information popup
    call function 'POPUP_TO_INFORM'
      exporting
        titel = 'Information Message'(509)
        txt1  = 'Sorry!!!'(510)
        txt2  = 'No Enhancements available for the selected Transaction'(511).


  endif.

endform.                    " F_PNAME_SPOTS
*&---------------------------------------------------------------------*
*&      Form  fbdc_dynpro
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PROGRAM    text
*      -->DYNPRO     text
*----------------------------------------------------------------------*
form fbdc_dynpro using program type any dynpro type any.
  clear i_bdcdata.
  i_bdcdata-program  = program.
  i_bdcdata-dynpro   = dynpro.
  i_bdcdata-dynbegin = 'X'.
  append i_bdcdata.
endform.                    "FBDC_DYNPRO

*----------------------------------------------------------------------*
*        Insert field                                                  *
*----------------------------------------------------------------------*
form fbdc_field using fnam type any fval type any.
  clear i_bdcdata.
  i_bdcdata-fnam = fnam.
  i_bdcdata-fval = fval.
  append i_bdcdata.
endform.                    "FBDC_FIELD

*----------------------------------------------------------------------*
*        Start new transaction according to parameters                 *
*----------------------------------------------------------------------*
form fbdc_transaction using value(l_tcode) like tstc-tcode.
  refresh i_messtab.
  call transaction l_tcode using i_bdcdata
                               mode   ctumode
                               update cupdate
                               messages into i_messtab.

  refresh i_bdcdata.
  clear i_bdcdata.

endform.                    "fbdc_transaction
*&---------------------------------------------------------------------*
*&      Form  F_FIND_INCLUDE_PROGRAMS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_TSTC_PGMNA  text
*----------------------------------------------------------------------*
form f_find_include_programs  using p_tstc_pgmna type any.

  data: lv_fip_prog(255),
        lv_tail(255).                                       "#EC *

*--- Lines for include
  data: i_inc_lines like content occurs 0 with header line.

**-- Read ABAP
  read report p_tstc_pgmna into i_inc_lines.

**-- Examine each line of ABAP
  loop at i_inc_lines.
**-- find include programs.
    if i_inc_lines(1) = '*' or i_inc_lines is initial.
      continue.
    endif.

    translate i_inc_lines-line to upper case.
    shift i_inc_lines-line up to 'INCLUDE'.

    if ( i_inc_lines-line(7) eq 'INCLUDE' ) or
       ( i_inc_lines-line(7) eq 'INCLUDE' )
    and i_inc_lines-line+8(9) ne space
    and sy-tabix <> 1.
      lv_fip_prog = i_inc_lines-line+8(64).
      split lv_fip_prog at '.' into lv_fip_prog lv_tail.
**-       Append program name to list of include programs
      select single * from trdir where name eq lv_fip_prog.
      check sy-subrc eq 0.
      i_prog_includes-prog = lv_fip_prog.
      append i_prog_includes.
*--- Recursively look for other includes.
      perform f_find_include_programs using lv_fip_prog.
    endif.
  endloop.

endform.                    " F_FIND_INCLUDE_PROGRAMS