Quantcast
Channel: Tweaks
Viewing all 66 articles
Browse latest View live

Create & Change Variants without Fire Fighter

$
0
0

At times, you need to create or modify the program variants directly in Production system. Usually the variants are moved in transports and that is the right way. But certain clients allow you to create variants in production system directly.

The dilemma is, you do not have access to SE38, SA38, SE80 or variant t-code in production system to create/change variants. You need to log in using your Fire Fighter id. For those youngsters who have never worked in any support project, Fire Fighter is a user id which has elevated role. You have privilege to all those transactions which you do not have access with your normal user id. But, keep in mind, the Fire Fighter is monitored id. Every click of yours is tracked and you need to be very careful while using it.

Creating/changing the variant via Fire Fighter id is not that painful, but lately I have been updating/changing the variants without using Fire Fighter role and also not via SE38/SA38/SE80.

[adToAppearHere]

This might be very common practice, but since I learnt it (accidentally) so late in my career, therefore thought of  sharing it. There might be someone like me who is not aware of this method and would appreciate this.

You might also like to check our other popular post ‘Simple SAP Security Breach’.

The assumption here is, you have access to batch job scheduling and display t-code SM37.

Check I do not have access to SE38.

SAP Variant

Go to SM37. Search for a job which is already scheduled or running in your system for the program for which you want to create/change/update the variant.

Fire Fighter

Check we found three jobs for our program.

sapyard

Choose one of the job and hit Step button.

5

Keep the cursor on the program name, click GoTo menu and Maintain Variants.

SAPYard

Check you are in ABAP: Variants Screen.

7

You can change, display and create variants here. But please take extra caution. You need to know what you are doing and you should have the valid requirements and approvals for the change and/or create.

If you want to get such practical issues and resolutions straight to your inbox, please SUBSCRIBE.

Thank you very much for your time!!

 

 

Image courtsey : www.design999.co.uk


Delete Foreign Lock Entries in Debug

$
0
0

We know, we can manually delete ours lock using t-code SM12. In some project, you might not have access to t-code SM12 at all. In some, you might have access to t-code SM12 but only in display mode. And in some clients like I am in now, you can only delete your locks, not the foreign locks i.e. you cannot delete objects locked by other users.

Inspiration of this post.
Your colleague was editing an object (program) in the office at offshore. When he left for the day, he just locked his desktop (window + L) and went. He did not close the windows he was working on and also did not shut down his desktop.

At a distant land, in a different time zone, you are starting your day and you need to correct/modify the same object which your colleague has locked. You try to call him but he is not reachable; may be he is partying somewhere.  🙂

You have 3 options.
1) Park this object to be worked on some other day. Work on some other issue/development now.
2) Wait till SAP Auto Logs out the user with message ‘maximum user idle time exceeded‘ and all sessions of the users are closed.
3) Delete/Release that lock entry and start working on that object immediately.

This page is for option 3.

Disclaimer: This page is not to encourage you to delete others locks. Please use it ethically and responsibly.

[adToAppearHere]

SAP says:
Before you can manually delete lock entries, you must make sure that there are no processes active that need the objects in question to be locked (transaction, update). Otherwise, there is a danger that the objects that are no longer protected can be changed by several processes at once and, as a result, become inconsistent and incorrect.

Before you delete any lock, make sure you know what you are doing and there would not be any inconsistency.

Enough, caution. Let move on!!

Check, user is not able to edit the program as it is locked by another user.

Locked

Go to T-Code SM12. Provide the user id of the person who has locked the program and hit list.

sap abap locks

You will get the list of all locks under his id.

Lock concept in SAP

Identify and select your program which you want to release/unlock. Hit the Delete icon.

Foreign lock

Check you get the message, ‘You are not authorized to delete foreign lock entries‘.

As we know, ABAPer with debug and change role can enter and break even the safest bank lockers. Select the line you want to unlock. Type ‘/h’ at the command entry section. Hit enter. You will get ‘debugging switched on‘ message. Hit the Delete icon.

5

You are in the debugger mode now.

6

Type sy-uname. You would find your user id by default.

Locks in SAP

Now, we just need to fool the system. In the sy-uname variable, replace your user id with the userid of the person who has locked this object.

8

You are done. You will get a pop up confirmation message. Just hit Yes.  The lock entry is gone. Without wasting any time, you can change your object now. 🙂

Earlier too, I use to delete the locks in debug mode by by-passing the validation and authorization section. But, recently, I figured out that just replacing the sy-uname is the simplest way to fool the system if you want to delete foreign locks.

Hope you enjoyed this tweak. You might also like to check our other post about changing variants in production system without Fire Fighter.

If you want to get such practical issues and resolutions straight to your inbox, please SUBSCRIBE.

Thank you very much for your time!!

 

 

Image courtesy : www.123rf.com

Disable User Personalization in Web Dynpro Screen

$
0
0

In the previous post we saw  how someone can personalize the Web Dynpro screen to hide and unhide screen UI elements or fields. After we recovered the hidden field, our business asked us, ‘Can we prevent the users from hiding the screen fields?In simple terms, business wanted to disable Personalization of Web Dynpro screens in portal.

The answer from an ABAPer: “Yes, we can handcuff them”. 🙂

We need to set parameter ‘WDDISABLEUSERPERSONALIZATION‘ to the Web Dynpro application.

Check, before activating the ‘Disable User Personalization’ parameter, user can personalize the screen. User Settings option is available to the users to play around.

Personalization in Web Dynpro

[adToAppearHere]

Let’s add the parameter and save and activate our application.

Disable User Personalization in Web Dynpro

Now, the User Setting option is not available. Your screen is locked for any personalization.

Customization in Web Dynpro

Happy Business Team !! Poor Users.. 🙂

If you want to get such practical issues and resolutions straight to your inbox,  please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share button at the left side of your screen.

Thank you very much for your time!!

Our series on Web Dynpro ABAP

1. Let’s Web Dynpro. Part I : Overview of Web Dynrpo
2. Let’s Web Dynpro. Part II : Create your first Web Dynpro Application
3. Let’s Web Dynpro. Part II : Display a simple tabular output in Web Dynpro
4. Let’s Web Dynpro. Part IV : Show and hide UI elements dynamically in Web Dynpro
5. Let’s Web Dynpro. Part V : ALV display explaining Component Usage in Web Dynpro
6. Let’s Web Dynpro. Part VI : Add custom buttons programmatically to the ALV output tool bar/header
7. Let’s Web Dynpro. Part VII : Personalization and Customization in Web Dynpro
8. Let’s Web Dynpro. Part ZZ : Export an EXCEL file with data in cell formatted excel sheet with colors, borders, filters in Web Dynpro
9. Is data element WDY_BOOLEAN and Flag (Char1) same for Web Dynpro ALV? : Trick to create checkbox in ALV
10. Taking one step back after EhP7.4, does it make sense for Web Dynpro UI? : Getting back the old look and feel after EhP740 upgrade
11. Can we avoid Table Type declaration for Attributes section in Web Dynpro?
12. Disable User Personalization in Web Dynpro Screen.

to be updated..

 

Image source : www.123rf.com

Maths in ABAP

$
0
0

Being an Engineering student, I am bit inclined towards Mathematics. A few months ago when I wanted to write a program to find out prime numbers, I felt the need of ABAP command which can give me remainder (something like % in C). Finally I found it out and here are some compilations of such ABAP commands.

Finding the absolute value of a number: |a| -> ABS( a ).
Finding the lowest integer greater than a: CEIL( a ).
Finding the greatest integer less than a: FLOOR( a ).
For trigonometric operands, try ACOS, COS, etc
Finding the square root of a, a > 0: SQRT( a )
Finding the length of characters in the string: STRLEN( a )
Finding remainder a/b: a MOD b.

[adToAppearHere]

If you want to remove characters from any string which has both characters and numbers then there is an easy trick.

Suppose, you have an string like 12wer34op. Take a variable which is type NUMC and assign string to this variable and you will have only integers.

DATA: v_string TYPE char10,
      v_num    TYPE num10.

v_string = '12wer34op'.
v_num = v_string.

WRITE: v_num.

Food for thought:
With the hint above, what do you think would be the output v_num. Please write it at the comment section before you write the code in your system and execute the program. It would be fun. We are sure, you would be amazed with the output.

If you like Maths, you would also like to read our other post, Do all ABAPers know Fixed Point Arithmetic?

We all know ABAP is very simple language and help is present just with one click. Still I face problems now and then with all the help present on the net, I feel a quick tip from a friend/colleague is more helpful. We can help you with our experience. We can help and together we can learn.

If you want to get such practical issues and resolutions straight to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share button at the left side of your screen.

Thank you very much for your time!!

 

SAP ABAP Tips

$
0
0

Please find some uncommon SAP Technical requirements and tips. One would face these issue only in some very rare Project scenarios. Hope you will have fun below.

A) Changing description of SAP standard Data Element

Did you know that we can change the description of standard fields? I am sure many of us did not know this fact. If you want to change the label/field description for any SAP table field, then you can use the following method.

Let us check how the description of standard data element ‘FSH_MG_ATTRIBUTE3′ of table MARA is changed.

SAP ABAP

1. Go to transaction code: CMOD.

2. Goto-Text Enhancement->Key words->Change

SAP Data Dictionary
3. Enter the Data Element

SAP Tricks4. Change the Description text.

SAP Tips5. Save in the transport (or local for test).
6. Goto SE11, check the changed description.

SAP ABAP

Did you know this trick? 🙂

Also Read: ‘How to enable table entries maintenance in SE16N ‘.

B) RF Gun ‘BEEP’ Sound

If requirement comes to you that business needs a beep sound in RF console when it scans a bar code this is what you should do.

Step 1: Stop laughing .. 🙂
Step 2: Follow SAP note 371838

For freshers, RF = Radio Frequency. Usually a small hand held device enabled with RFID is common in warehouse and plants. You can compare it with a scanning/bar code reading machine.

C) Daylight Saving Setting in SAP

Often we need to convert the system time to local time of the plant and if the local time of the plant observes daylight then sometimes the result is X hour off. X may be 1, 2, 3 etc depending upon the location. This problem occurs due to time difference of daylight saving. If you are facing this problem (like me) then please check your DST system using transaction STZBC.

First check whether Daylight rule is active or not.

Day light saving in SAP

Check the rule (Variable summer time rule).

dl12

Check the rule (Fixed summer time rule),

DL13For freshers, wiki says, Daylight saving time (DST) or summer time is the practice of advancing clocks during summer months by one hour so that in the evening daylight is experienced an hour longer, while sacrificing normal sunrise times.

[adToAppearHere]

D) Find the Type of Transaction in exit (whether it is Create, Change, Display etc)

For Purchasing transaction exits, you may use table entries like T160 or T180 to find the nature of transaction.
Field – TRTYP (Transaction type)

E) Checking log for table changes

SCU3 – Use this transaction if log is activated for that table. If you are unable to see the log, try debugging and by passing the authority check.

Include – RSVTPF01, FORM CHECK_AUTHORITY

SELECT SINGLE * FROM tddat INTO w_tddat

By-pass this error or maintain your entry in TDDAT or View V_DDAT_54
Please check SAP note 323636 for more info.

F) Issue while creating EH spot

If you are facing problem while creating implicit enhancements; getting error like: UNCAUGHT_EXCEPTION CX_SY_MESSAGE_ILLEGAL_TEXT then you may need to apply the following SAP notes: 1034360, 1098603, 1087299

For Authorization of SE20 transaction you may need SAP note 987152.

G) Mechanism of FOR ALL ENTRIES SELECT

SAP first fetches all the record for the selected fields and then it SORT the records found and then it does a DELETE ADJACENT DUPLICATES COMPARING ALL FIELDS. So, if you want to retrieve all the records, you MUST select all the KEY fields or else you will lose some records.

Also Read: Curious case of FAE (For All Entries)

H) Issue with Pop up display

SAP is full of surprises. The other day, when I was trying to test a program, I saw the messages were not coming properly. Instead of showing the full message, it truncated with a cross icon.

Pop up issue

Finally, I was able to trace the source of the problem. The problem lies in the SAP FM POPUP_WITH_TABLE_DISPLAY_OK. I have used this function module numerous times in past and but this time, I realized there is a “IF” condition in the source code of this FM at MODULE LISTPROCESSING OUTPUT .

LOOP AT LISTTAB.
IF LISTTAB+15(1) = 'S' OR LISTTAB+15(1) = 'F'.
IF LISTTAB+15(1) = 'S'.
WRITE: / LISTTAB+0(15), ICON_OKAY AS ICON.
ELSEIF LISTTAB+15(1) = 'F'.
WRITE: / LISTTAB+0(15), ICON_CANCEL AS ICON.
ENDIF.
ELSE.
WRITE: / LISTTAB.
ENDIF.
ENDLOOP.

So, if the 16th character of your message is either S or F, then your message will be truncated. If you are facing this problem now you the reason. You can solve this issue in your own way.

[My solution – simply convert the 16th character to lower case if it F or S.]

If you want to get such practical tweaks and tricks straight to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons at the left side of your screen. Please like us at facebook and encourage us.

Thank you very much for your time!!

 

Image source: www.efficientlifeskills.com

SAP HANA Tips

$
0
0

In our other post ‘ SAP ABAP Tips‘, we shared some uncommon but very useful tips on ABAP. In this post, I would like to share similar useful tips in regards to SAP HANA.

i) Parameter to limit the CPU usage for a thread in SAP HANA

There is a parameter that can be used to limit the amount of CPU, a thread can take in SAP HANA.

indexserver.ini -> parallel = numes_cores

ii) How to find the size of the HANA DB?
We have two aspects here:
a. Column store
b. Row store

a. To find column store utilization:

SELECT round (sum(MEMORY_SIZE_IN_TOTAL)/1024/1024) AS "Column Tables MB" FROM M_CS_TABLES;

b. To find row store utilization:

SELECT round (sum(USED_FIXED_PART_SIZE + USED_VARIABLE_PART_SIZE)/1024/1024) 
AS "Row Tables MB" FROM M_RS_TABLES

iii) Migrating tables to specified nodes in SAP HANA multi-node system

If you want to migrate a particular table from one node of HANA to another for performance or space issue:

a. To view current location of table

Open SQL editor on HANA studio and run the sql query:

select * from "SYS"."M_TABLE_LOCATIONS" order by LOCATION, table_name

b. To view current location decide the node where you want to move it and run the below query on SQL editor of HANA studio:

ALTER TABLE MOVE TO ‘node:port number’

Also Read: ‘Smart Data Integrator & Data Load In SAP HANA’

iv) Delivery Classes for tables (Not specific to HANA)

While doing some migrations (BW on HANA ) I felt that we as technical consultant need to have a better understanding of delivery classes. I felt that we need to recap the concept. I am intending to have a small listing of the same. For each database table, a delivery class has to be specified. The delivery class determines the handling of the entries for a specific table during
Transports
Client Copies
– Installation & Upgrades

SE11 Delivery Classes for tables:

Delivery Class in SAP TABLE2 Delivery Classes

Delivery Classes for tables:

SE11

[adToAppearHere]

Examples:

CCommon Address Data (Country: T005)
EMessages (T100)
GCommunication: country dialling code (T005K)
LLock Arguments (E070USE)
SLanguage Key (T002)
APersonal Address Data, Username (USR01)
WTransport (E070), Tables (DD02L)

Delivery Classes – Client Copy & Client Transport:

Is Delivery Class copied?

Delivery Classes – Transport SAP -> Customer

Delivery Class

Delivery Classes – Transport Customer -> Customer

Client dependent tables

For more details, please refer SAP Note: 2857

If you want to get such practical tweaks and tricks straight to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the Share buttons. Please like us at facebook and encourage us.

Thank you very much for your time!!

Series on SAP HANA

1. SAP HANA from Space Level

2. SAP HANA at Ground Zero

3. View the HANA Views from different angles

4. ‘ABAP for SAP HANA’ Points to remember

5. SAP HANA ; S/4 HANA and S/4 HANA Finance in Nutshell

6. Smart Data Integrator & Data Load In SAP HANA

to be updated..

 

Image source: rahulurs.com(modified)

Creating Dynamic Internal Table

$
0
0

In one of our post, we showed the usage of Dynamic Where Condition . In this article, we would show one out of the many ways to generate Dynamic Internal Table and display it in ALV output.

Say you have a requirement where you want to show a report to indicate one Material is present in how many Plants. Say your input material ‘M1’ is present in two plants say ‘P1’ and ‘P2’. So the output ALV report should show only two three columns, M1, P1 and P2. Say you have another material ‘M2’ which is present in 5 plants ‘P1’, ‘P2’, ‘P3’, ‘P4’ and ‘P5’. Then the output table would have six columns. M1, P1, P2, P3, P4 and P5.

Make a note, the number of columns are changing based on the input. Let us see a real example.

Check the MARC table.

CREATE_DYNAMIC_TABLE

Above screenshot shows that Material ‘100522’ is present in two plants. Our ALV would show as below.

CL_ALV_TABLE_CREATE

Dynamic Internal Table

Check the MARC screenshot, Material ‘100567’ is present in four plants. Our ALV would show as below.

4

5

Did you notice, the number of columns are changing dynamically as per the data? This can be done in many ways, but the most convenient way is to create  dynamic structure/internal table and display it.

[adToAppearHere]

Function Module ‘DDIF_FIELDINFO_GET‘ would help us to fetch table field information. Check the code below, we are replacing ‘MARC-WERKS’ field label, with the actual Plant number. This was just a specific project requirement. You might have some other requirement.

Dynamic Internal Table

Material is a fixed column but Plants are dynamic based on data from MARC. Check we are looping through the internal table and using FM ‘DDIF_FIELDINFO_GET‘ to determine and populate field catalog information.

Once we have the field catalog (i_fcat), we need to build the dynamic internal table with the required columns determined by i_fcat. For this example, we are using method ‘CREATE_DYNAMIC_TABLE‘ of class CL_ALV_TABLE_CREATE.

CREATE_DYNAMIC_TABLE

The below two steps are the most important ones. Here we are assigning the dynamic structure to the <field-symbol> table and <field-symbol> work area which would be used later to display the ALV.

* Assign the structure of dynamic table to field symbol
ASSIGN i_dynamic_table->* TO <i_dyn_table>.

* Create the dynamic work area
CREATE DATA wa_dyn_line LIKE LINE OF <i_dyn_table>.
ASSIGN wa_dyn_line->* TO <wa_dyn>.

Also Read: ‘SAP  HANA from space level’.

There is some mathematic done to mark ‘X’ for the column where the material is present. So do not be confused. In debugging, it shows that although MATNR has 18 characters, the dynamic table show 36 (just the double). Same with Plant, it shows 8 instead of 4. So, this is something you want to check before you put your data.

Once you have populated the data in the dynamic internal table, displaying data in ALV is a cake walk. Just use the FM ‘REUSE_ALV_GRID_DISPLAY‘.

Check the code behaviour in Debugging mode”

Dynamic Internal Table

Check I_FCAT table, it has 4 rows of fields. This means, the dynamic internal table would have 4 columns. One fixed for Material and 3 dynamic for plants.

CL_ALV_TABLE_CREATE

This is the class and method which actually creates the dynamic internal table.

Dynamic Internal Table

Check I_DYNAMIC_TABLE, it has now 3 columns for plants. This is the structure you need. Now just create the internal table and work area and populate your final data and display it.

CL_ALV_TABLE_CREATE

Let us see, how the output would look like when we input 3 materials which are available in multiple plants.

6

Check, the number of plant columns are the union of all the three materials. Isn’t it dynamic? 

7

Please find the working program for the above requirement here.

REPORT zsapyard.
*----------------------------------------------------------------------*
* Created by   : SAPYard  (http://www.sapyard.com/)                    *
* Purpose      : Program to show Dynamic Internal table                *
* Visit http://www.sapyard.com/ for SAP Technical Tips & Solutions     *
*----------------------------------------------------------------------*
*---------------------------------------------------------------------*
* POOLS                                                              *
*---------------------------------------------------------------------*
TYPE-POOLS: slis.
*---------------------------------------------------------------------*
* TABLES                                                              *
*---------------------------------------------------------------------*
TABLES: mara.
*---------------------------------------------------------------------*
* TYPES
*---------------------------------------------------------------------*
TYPES: BEGIN OF x_data,
         matnr TYPE matnr,
         werks TYPE werks_d,
       END OF x_data.
*---------------------------------------------------------------------*
*  DATA                                                               *
*---------------------------------------------------------------------*
DATA:
* Internal tables
  i_data          TYPE STANDARD TABLE OF x_data,
  i_data_temp     TYPE STANDARD TABLE OF x_data,
  i_fcat          TYPE lvc_t_fcat,
  i_dynamic_table TYPE REF TO data,
  i_plant         TYPE STANDARD TABLE OF x_plant,
  i_fieldcat      TYPE slis_t_fieldcat_alv,

* Work ara
  wa_fcat         TYPE lvc_s_fcat,
  wa_dyn_line     TYPE REF TO data,
  wa_plant        TYPE x_plant,
  wa_data         TYPE x_data,

* Variable
  v_field_name    TYPE fieldname,
  v_tabix         TYPE sytabix,
  v_fieldname     TYPE fieldname,
  v_seltext       TYPE scrtext_l.
*---------------------------------------------------------------------*
*  Field Symbols                                                      *
*---------------------------------------------------------------------*
FIELD-SYMBOLS:
  <i_dyn_table>   TYPE STANDARD TABLE,
  <i_final_table> TYPE STANDARD TABLE,
  <wa_dyn>        TYPE any,
  <wa_final>      TYPE any.
*---------------------------------------------------------------------*
* SELECTION SCREEN                                                    *
*---------------------------------------------------------------------*
SELECT-OPTIONS: s_matnr FOR mara-matnr.
*---------------------------------------------------------------------*
* INITIALIZATION                                                      *
*---------------------------------------------------------------------*
INITIALIZATION.
* Select data
*---------------------------------------------------------------------*
* START-OF-SELECTION.                                                 *
*---------------------------------------------------------------------*
START-OF-SELECTION.
  PERFORM sub_slect_data.

*---------------------------------------------------------------------*
* END-OF-SELECTION.                                                   *
*---------------------------------------------------------------------*
END-OF-SELECTION.
* Populate the dynamic columns needed for each run
  PERFORM sub_populate_catlog.

* Build the dynamic internal table
  PERFORM sub_build_int_table.

* Build ALF Field Catalog information
  PERFORM sub_alv_field_cat.

* Display data
  PERFORM sub_display_data.

*---------------------------------------------------------------------*
* SUB ROUTINES                                                        *
*---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&      Form  SUB_SLECT_DATA
*&---------------------------------------------------------------------*
FORM sub_slect_data .

  SELECT matnr werks
    INTO TABLE i_data
    FROM marc
    WHERE matnr IN s_matnr.
  IF sy-subrc EQ 0.
    SORT i_data BY matnr.

    i_data_temp[] = i_data[].
    SORT i_data_temp BY werks.
    DELETE ADJACENT DUPLICATES FROM i_data_temp
    COMPARING werks.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SUB_POPULATE_CATLOG
*&---------------------------------------------------------------------*
FORM sub_populate_catlog .
  v_field_name = 'MATNR'.
* There is one Material column
  PERFORM sub_pop_field_catlog USING v_field_name.

  v_field_name = 'WERKS'.
* There would be 'N' number of dynamic Plant columns
* depending on the material and plants combination
  LOOP AT i_data_temp INTO wa_data.
    PERFORM sub_pop_field_catlog USING v_field_name.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SUB_POP_FIELD_CATLOG
*&---------------------------------------------------------------------*
FORM sub_pop_field_catlog  USING    p_l_field_name TYPE fieldname.

  DATA: l_i_dfies  TYPE STANDARD TABLE OF dfies,
        l_wa_dfies TYPE dfies.

* Call FM
  CALL FUNCTION 'DDIF_FIELDINFO_GET'
    EXPORTING
      tabname        = 'MARC'
      fieldname      = p_l_field_name
    TABLES
      dfies_tab      = l_i_dfies
    EXCEPTIONS
      not_found      = 1
      internal_error = 2
      OTHERS         = 3.
  IF sy-subrc EQ 0.

    CLEAR l_wa_dfies.
    READ TABLE l_i_dfies INTO l_wa_dfies INDEX 1.
    CLEAR wa_fcat.
* Since we want the Plant number to be the header text
* Replacing the field name with actual plant value
    IF v_field_name = 'WERKS'.
      l_wa_dfies-fieldname = wa_data-werks.
    ENDIF.

    MOVE-CORRESPONDING l_wa_dfies TO wa_fcat.
    APPEND wa_fcat TO i_fcat.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SUB_BUILD_INT_TABLE
*&---------------------------------------------------------------------*
FORM sub_build_int_table .

* Prepare the dynamic internal table with required columns of each run
  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog           = i_fcat
    IMPORTING
      ep_table                  = i_dynamic_table
    EXCEPTIONS
      generate_subpool_dir_full = 1
      OTHERS                    = 2.
* Assign the structure of dynamic table to field symbol
  ASSIGN i_dynamic_table->* TO <i_dyn_table>.

* Create the dynamic work area
  CREATE DATA wa_dyn_line LIKE LINE OF <i_dyn_table>.
  ASSIGN wa_dyn_line->* TO <wa_dyn>.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SUB_ALV_FIELD_CAT
*&---------------------------------------------------------------------*
FORM sub_alv_field_cat .

* Build field catalog for Material
  PERFORM sub_fill_alv_field_cat USING
        'MATNR' '<I_DYN_TABLE>' 'L' 'Material Number' 36.

* Number of Plant columns would be dynamic for Plants
  LOOP AT i_data_temp INTO wa_data.

    v_fieldname = wa_data-werks.
    v_seltext =   wa_data-werks.

    PERFORM sub_fill_alv_field_cat USING
              v_fieldname '<I_DYN_TABLE>' 'L' v_seltext 8.

  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SUB_FILL_ALV_FIELD_CAT
*&---------------------------------------------------------------------*
FORM sub_fill_alv_field_cat  USING
                             p_fldnam    TYPE fieldname
                             p_tabnam    TYPE tabname
                             p_justif    TYPE char1
                             p_seltext   TYPE dd03p-scrtext_l
                             p_outlen    TYPE i.

  DATA l_lfl_fcat TYPE slis_fieldcat_alv.

  l_lfl_fcat-fieldname  = p_fldnam.
  l_lfl_fcat-tabname    = p_tabnam.
  l_lfl_fcat-just       = p_justif.
  l_lfl_fcat-seltext_l  = p_seltext.
  l_lfl_fcat-outputlen  = p_outlen.

  APPEND l_lfl_fcat TO i_fieldcat.

  CLEAR l_lfl_fcat.

ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  SUB_DISPLAY_DATA
*&---------------------------------------------------------------------*
FORM sub_display_data .

  DATA: l_count     TYPE i,
        l_factor    TYPE i,
        l_wa_layout TYPE slis_layout_alv.

  LOOP AT i_data INTO wa_data.

    CLEAR: l_factor, l_count.

    READ TABLE i_data_temp WITH KEY werks = wa_data-werks
    TRANSPORTING NO FIELDS
    BINARY SEARCH.
    IF sy-subrc EQ 0.

      <wa_dyn>+0(18) = wa_data-matnr.
      l_factor = sy-tabix - 1.
      l_count = 36 + ( 8 * l_factor ).

      <wa_dyn>+l_count(8) = 'X'.

      AT END OF matnr.
        APPEND <wa_dyn> TO <i_dyn_table>.
        CLEAR <wa_dyn>.
      ENDAT.
    ENDIF.

  ENDLOOP.

  l_wa_layout-colwidth_optimize = 'X'.
  l_wa_layout-zebra = 'X'.

* Funtion module for displaying the ALV report
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
    EXPORTING
      i_callback_program = sy-repid
      is_layout          = l_wa_layout
      it_fieldcat        = i_fieldcat
    TABLES
      t_outtab           = <i_dyn_table>
    EXCEPTIONS
      program_error      = 1
      OTHERS             = 2.


ENDFORM.

If you want to get such practical tweaks and tricks straight to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons. Please like us at facebook and encourage us. If you have any suggestions, criticism, comments or questions, please comment or reach out to us.

Thank you very much for your time!!

 

Image source: www.mobygames.com (modified)

Mastering SAP Debugging

$
0
0

Code debugging is something all programmers need to know and the same is true for SAP developers. It is needed to find bugs on custom developments and it is also needed to understand how standard SAP programs work in detail. This last part is quite important, being able to go into the code of a program is what makes us capable of finding the answer to some question. I’m sure most experts will agree with me that debugging is one of the important skills on SAP.

But learning how to debug is not trivial. It is something that takes many hours to learn and it is also something that is hard to learn in abstract, it is much easier to understand with practical examples. I think this topic is one that fits well in the new online courses concept (called moocs) that have a lot of focus on exercises and assignments and use very short videos. I tried to develop the SAP debugging course (http://academy.onsap.com) that way, combining short tutorial examples and exercises to practice the skills.

[adToAppearHere]

The video below is an example video from one of the course units. If you want to learn or improve your debugging skill, try the course, it is completely FREE. Hope you enjoy it.

https://www.youtube.com/watch?v=zJod4vrMYa4

PS: This is a guest post by our friend Pedro.

Pedro Lima has more than 15 years of industry experience in SAP software development and consulting, having previously worked for SAP and currently being managing partner at Cognitiva“.

Also Read: ‘Simple Security Breach in SAP’.

If you want to get practical issues and resolutions straight to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you like our page, please hit the share button.

Thank you very much for your time!!

 

 

Image source: community.dynamics.com(modified)


Is data element BOOLE_D and CHAR1 same in SAP Selection Screen?

$
0
0

In one of our post in Web Dynpro we showed that WDY_BOOLEAN and FLAG data elements, which are both of type CHAR 1 behave differently. Similarly, very recently, I came to know that all CHAR1 data elements are not same.

Let us look this example.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
PARAMETERS: p_init TYPE char1.
SELECTION-SCREEN END OF BLOCK b1.

You expect a selection screen parameter with one character length. You are right.

check box in sap

Now, instead of TYPE CHAR1, let us take BOOLE_D which is also of TYPE CHAR1.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
PARAMETERS: p_delt TYPE boole_d.
SELECTION-SCREEN END OF BLOCK b1.

What do you expect the output to be?
Honestly, I expected the same as above. One character placeholder. But to my surprise, when I execute this piece of code, it gave me a CHECKBOX.

AS CHECK BOX

[adToAppearHere]

All these years, I have been using the explicit CHECKBOX statement to generate a checkbox in the selection screen. And every time, I needed to declare a checkbox in my selection screen, I needed to refer to previous code snippet, google or do an F1 to get the syntax. Even after 10 years of ABAP programming, I do not remember the syntax (actually, I do not want to).

But not anymore. Now, I can declare a CHECKBOX in my selection screen without referring anything.. 🙂

This is the explicit CHECKBOX syntax.

* Explicit CHECKBOX syntax
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
PARAMETERS: p_init AS CHECKBOX.
SELECTION-SCREEN END OF BLOCK b1.

This is WITHOUT AS CHECKBOX keyword

* CHECKBOX through data element
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
PARAMETERS: p_delt TYPE boole_d.
SELECTION-SCREEN END OF BLOCK b1.

The output of both these PARAMETERS is the same.

check box declaration

So next time you need a CHECKBOX for your program, you have another alternative. 🙂

Also Read: Six Selection Screen Development in every other Project

Please note: All one character data elements of TYPE CHAR1 which has a domain with Value Range X and blank can be used for CHECKBOX declaration.

check box in sap 4

Data elements like WDY_BOOLEAN, BOOLE_D, FLAG, LVOMA etc can be used for CHECKBOX.

I am sure, all of us knew about the Value Range domains. But did you really use them in such practical cases?

Food for thought:
Data element FLAG can be used for CHECK BOX declaration. Can we NOT use data element FLAG1 for CHECK BOX declaration? FLAG1 is also CHAR1 type. 🙂

If you want to get such practical issues and resolutions straight to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons.

Thank you very much for your time!!

How to update custom field of PRPS table

$
0
0

Or How to update custom fields of CJ20N t-code?

At the outset, you might feel why is the need of this topic. It is such a common requirement where we need to update custom field of a screen (or table). There should be plenty of FMs and BAPis available to do this work.

In this post, we are talking about custom field in WBS screen (transaction CJ02 or CJ20N).

Recently, when I received this enhancement requirement to add two custom fields in CJ20N screen and then another conversion requirement to populate these custom fields using a batch program. I thought it would be a cake walk. Adding the custom field was easy. I enhanced structure CI_PRPS and SAP Project (t-code SMOD) CNEX0007 ‘PS customer specific fields WBS element’.

Enhance PRPS table

The enhanced project’s detail from t-code CMOD is below:

Bapi function module to update PRPS table

After implement this exit, you see a new tab Cust Enhancement in CJ20N with the custom fields.

User-defined fields are not displayed

In case, you do not see user defined fields in the screen, then you might be missing this step.

Use transaction SE51 to create the user-defined screen SAPLXCN1 0700 and develop the layout. In particular, you can get fields from the ABAP Dictionary (from the table PRPS):
Choose “Goto -> Dict./program fields”.
Maintain the table/field name PRPS and select the fields that are to be displayed on the screen.

Activate and you would see the custom fields.

For more details to implement project CNEX0007, refer SAP Note 522581 – User-defined fields are not displayed.

But my intention to write this post was not to show how to enhance WBS screen. This is well documented and easily available in internet. I wanted to show how to update these custom fields from custom program (batch conversion jobs). You can do the BDC and achieve the functionality, but we did not want to take the BDC route. We wanted to achieve it using standard FM or BAPI (preferably). I found the BAPI ‘BAPI_BUS2054_CHANGE_MULTI‘ which would do the job. But passing the correct parameters to the BAPI was tricky.

Also the internet is flooded with queries regarding how to make BAPI ‘BAPI_BUS2054_CHANGE_MULTI’ update the custom fields using EXTENSIONIN. But all are not answered clearly. Some even suggest to implement a BADI to make this BAPI work. Friends, if you want to just update the custom fields, you do not need to implement the BADI ‘BAPIEXT_BUS2054′ (Enhancement for BAPIs for BO WBSPI). You need the BADI for some other requirements.

Check some of the questions and answers from SCN and other sites.

Bapi function module to update PRPS table.
How to Update Multiple WBS elements. 
How can I pass extensionin for BAPI_BUS2054_CHANGE_MULTI to enhance. 
Bapi function module for updating data into PRPS table.

There is no clear answer/solution and working code provided in the communities (at least I did not find one).

Actual solution:
The tricky part was to pass the Key Field (WBS_ELEMENT) to the EXTENSIONIN structure which would make the custom field entries unique. Please read the BAPI documentation properly. 🙂

*&---------------------------------------------------------------------*
* Very Very Important
ls_te_wbs_element-wbs_element = wa_prps-posid. " Key to identify the custom fields
*&---------------------------------------------------------------------*

Now it looks so obvious. Is n’t it? Trust me, I wasted an evening to figure this out. Our goal at SAPYard is to help our readers know about such small tricks and not to reinvent the wheel.

Please find the working code below to update the custom fields in t-code CJ20N (CJ02) or PRPS table.

*&---------------------------------------------------------------------*
*& Form UPDATE_CUSTOM_WBS_FIELDS
*&---------------------------------------------------------------------*
* Update the Custom WBS Fields
*----------------------------------------------------------------------*
FORM update_custom_wbs_fields.
DATA:
lv_project_def TYPE ps_pspid,
ls_wbs_element_up TYPE bapi_bus2054_upd,
ls_wbs_element TYPE bapi_bus2054_chg,
lt_wbs_element TYPE STANDARD TABLE OF bapi_bus2054_chg,
lt_wbs_element_up TYPE STANDARD TABLE OF bapi_bus2054_upd,
lt_te_wbs_element TYPE STANDARD TABLE OF bapi_te_wbs_element,
ls_te_wbs_element TYPE bapi_te_wbs_element,
lt_pre_return TYPE STANDARD TABLE OF bapiret2,
ls_return TYPE bapiret2,
lt_return TYPE STANDARD TABLE OF bapiret2,
ls_extensionin TYPE bapiparex,
lt_extensionin TYPE STANDARD TABLE OF bapiparex,
lwa_report TYPE ty_report.

* Project
CALL FUNCTION 'CONVERSION_EXIT_KONPD_OUTPUT'
EXPORTING
input = wa_prps-psphi
IMPORTING
output = lv_project_def.
*--------------------------------------------------------------------*
ls_wbs_element-wbs_element = wa_prps-posid.
APPEND ls_wbs_element TO lt_wbs_element.

*--------------------------------------------------------------------*
ls_wbs_element_up-wbs_element = wa_prps-posid.
APPEND ls_wbs_element_up TO lt_wbs_element_up.

*--------------------------------------------------------------------*
CLEAR ls_extensionin.
ls_extensionin-structure = 'BAPI_TE_WBS_ELEMENT'. " Extension Structure

* Pass the Key.. Important
ls_te_wbs_element-wbs_element = wa_prps-posid. " Key to identify the custom fields

* These are the custom fields. You will have your own logic to get the data
* to be populated
ls_te_wbs_element-zswbsref = wa_prps-poski.
ls_te_wbs_element-zaufnr = wa_cobrb-aufnr.

ls_extensionin-valuepart1 = ls_te_wbs_element.

APPEND ls_extensionin TO lt_extensionin.
*--------------------------------------------------------------------*
* Initialization of the Current Processing Unit
CALL FUNCTION 'BAPI_PS_INITIALIZATION'.

* BAPI to update Custom WBS Elements
CALL FUNCTION 'BAPI_BUS2054_CHANGE_MULTI'
EXPORTING
i_project_definition = lv_project_def
TABLES
it_wbs_element = lt_wbs_element
it_update_wbs_element = lt_wbs_element_up
et_return = lt_return
extensionin = lt_extensionin. " Here we have custom field

* Pre Commit Check
CALL FUNCTION 'BAPI_PS_PRECOMMIT'
TABLES
et_return = lt_pre_return.

* Looking for error
READ TABLE lt_pre_return INTO ls_return WITH KEY type = 'E'.
IF sy-subrc EQ 0.

* Add your ERROR message as per requirement

* Rollback
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.

ELSE.
* Add your SUCCESS message as per requirement

* Do the commit
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = 'X'.

ENDIF.

ENDFORM.

If you want to get such practical issues and resolutions straight to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons.

Thank you very much for your time!!

GPS like tool in SAP using Google Map API

$
0
0

In the earlier article, we saw how we can get the latitude and longitude of any address using Google Map API. Adding to that learning, in this post, we would learn how to get the distance between two addresses. We would also see how we can derive turn by turn directions between two given addresses. To add more to the fun, we would also open a browser from SAP and display the route between two points on the map.

Do you think, this is interesting? 🙂

In short, this tool would act like a GPS in SAP, which would help you get the Coordinates (Latitudes/Longitudes), Route and Map with complete direction.

Before we check, how it can be done, let us first see, what we are talking about.

I.  First radio button: Coordinates & Distance

Latitude and Longitude

We get the Coordinates of two addresses and also the distance between them.

Latitudes and Longitudes in ABAP

II.  Second Radio button: Turn by turn route

GPS Route in SAP

The tool would provide you the complete break-up of the route from the source to the destination address. It would also provide you with multiple routes if available.

Turn by turn direction and route

II.  Let’s check the third radio button which says ‘Display Map‘.

Display Map

As requested, this GPS Tool would display the map along with the routes in a Web Browser. Check this out.

Google Map

 

Also Read: SAP ABAP on HANA. Part I : Create your first program in HANA Studio.

Did you like it?

You can use the  code snippet provided at the end of this article and try it yourself. The code provided here would work as it is. The concept was already explained in our earlier post ‘Get Latitude and Longitude of any place using Google Map API in SAP’.

For the three output options, we need to call three APIs. As explained in the earlier article, we concatenate the strings with source and destination address, Latitudes and Longitudes etc to complete the API URL and get the XML data. Reading through the XML data and pinpointing the needed information is the trick which we have already learned.

a) GeoCode API String for Coordinates:

* Prepare the url of the GeoCode API
  CONCATENATE
    'http://maps.google.com/maps/api/geocode/xml?address='
    lv_address
    INTO lv_http_url .

b) Distance Matrix API String for retrieving the distance between Coordinates:

* Prepare the url for the DistanceMatrix API using From Address Coordinates and To Address Coordinates
  CONCATENATE
    'http://maps.googleapis.com/maps/api/distancematrix/xml?origins='
    <fs_dest>-place_f '|' <fs_dest>-lat_f ',' <fs_dest>-lng_f ','
    '&destinations=' <fs_dest>-place_t '|' <fs_dest>-lat_t ',' <fs_dest>-lng_t
    '&alternatives=' 'true'
    INTO lv_http_url .

c) Directions API String to trace the route on the Map:

* Prepare the url for Directions API for the From Address Coordinates and To Address Coordinates
  CONCATENATE
    'http://maps.googleapis.com/maps/api/directions/xml?origin='
    <fs_dest>-place_f '|' <fs_dest>-lat_f ',' <fs_dest>-lng_f
    '&destination=' <fs_dest>-place_t '|' <fs_dest>-lat_t ',' <fs_dest>-lng_t
    '&alternatives=' 'true'
    INTO lv_http_url .

where:
lv_address               = From/To address
<fs_dest>-place_f = From address
<fs_dest>-lat_f      = From address latitude
<fs_dest>-lng_f     = From address longitude
<fs_dest>-place_t = To address
<fs_dest>-lat_t      = To address latitude
<fs_dest>-lng_t      = To address longitude

Once you have the correct API URL, use this cl_http_client class and create_by_url method to get the detailed information.

* Get client from url
  CALL METHOD cl_http_client=>create_by_url
    EXPORTING
      url                = lv_http_url
    IMPORTING
      client             = p_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.

Please go through the detailed code to check how it works. There might be better ways to read these APIs and XML data but we just wanted to show the possibilities. You can explore more and figure out the best way for you.

If you find any difficulty in understanding the code or concept, please do write to us or leave your question in the comment section. We would surely respond.

If you have doubt whether this tool would work for Non-India address. Be rest assured, it works for any address. Check the output for the address in the USA. 🙂

7

 

Also Check: SAP HANA from Space Level.

If you want to get such practical issues and resolutions straight to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons.

Thank you very much for your time!!

SAPYard would like to thank Kuldeep Joshi for the inputs, concept and code snippet for this article. Kuldeep is an Electronics Engineer graduate. He has more than 7 years of experience in SAP with specialization in ABAP. He is an ex-IBMer who also has good working experience in SAP BI BPC.

*-----------------------------------------------------------------------
* Date   :    05/27/2016
* Author :   Kuldeep Joshi (For www.sapyard.com)
* Title  :     Get Latitude and Longitude of a place from Google API
*               Get distance between two addresses
*               Show the turn by turn route of two addresses
*               Show route in map in a browser
*-----------------------------------------------------------------------
* Change History :
* Author         DATE       REQUEST#     DESCRIPTION
*--------------- ---------- ----------- -------------------------------
* Kuldeep Joshi  05/27/2016              Intial Development
*-----------------------------------------------------------------------
REPORT  zsapyard_gps_google_api NO STANDARD PAGE HEADING
                                   LINE-COUNT 132.
*&---------------------------------------------------------------------*
*& TYPE-POOLS
*&---------------------------------------------------------------------*
TYPE-POOLS: truxs, slis.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-t01.
PARAMETERS : p_add_f TYPE c LENGTH 50,
             p_add_t TYPE c LENGTH 50.
SELECTION-SCREEN END OF BLOCK b1.

SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE text-t02.
PARAMETERS:
  p_alv   RADIOBUTTON GROUP yard,
  p_route RADIOBUTTON GROUP yard,
  p_map   RADIOBUTTON GROUP yard.
SELECTION-SCREEN END OF BLOCK b2.

*&---------------------------------------------------------------------*
*& Types and Data
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_dest,
         place_f TYPE c LENGTH 50,    " From Place
         place_t TYPE c LENGTH 50,    " To Place
         lat_f   TYPE c LENGTH 20,    " From Latitude
         lng_f   TYPE c LENGTH 20,    " From Longitude
         lat_t   TYPE c LENGTH 20,    " To Latitude
         lng_t   TYPE c LENGTH 20,    " To Longitude
         dis     TYPE c LENGTH 30,    " Distance
       END OF ty_dest,

       BEGIN OF ty_route,
         route_n TYPE c LENGTH 255,   " Start of New Route
         summary TYPE c LENGTH 120,   " Route Summary
         step    TYPE syst_tabix,     " Turn step
         ins     TYPE c LENGTH 255,   " Instruction
         dis     TYPE c LENGTH 20,    " Distance
       END OF ty_route.

TYPES: t_ty_route TYPE TABLE OF ty_route.

DATA:
  gt_dest  TYPE STANDARD TABLE OF ty_dest,
  gt_route TYPE STANDARD TABLE OF ty_route.

FIELD-SYMBOLS:
  <fs_dest> TYPE ty_dest.


*&---------------------------------------------------------------------*
*& Start of Selection
*&---------------------------------------------------------------------*
START-OF-SELECTION .

* Get longitude and latitude of From Address
  PERFORM get_long_lat USING p_add_f.

* Get longitude and latitude of To Address
  PERFORM get_long_lat USING p_add_t.

*&---------------------------------------------------------------------*
*& End of Selection
*&---------------------------------------------------------------------*
END-OF-SELECTION .

* Get distance between two address
  PERFORM measure_distance.

* Get detailed turn by turn address
  PERFORM turn_by_turn_route.

* Show the output
  PERFORM show_output.


************************************************************************
*&---------------------------------------------------------------------*
*& Sub Routines
*&---------------------------------------------------------------------*
************************************************************************
FORM get_long_lat USING lv_address TYPE char50.

  DATA:
    lv_http_client TYPE REF TO if_http_client,
    lv_content     TYPE string.

* Creation of new IF_HTTP_Client object
  PERFORM create_http_client USING lv_address
                             CHANGING lv_http_client .

* Request and Get
  PERFORM http_client_request_get_method USING lv_http_client.

* Send the request
  PERFORM http_client_send USING lv_http_client.

* Retrieve the result
  PERFORM http_client_receive USING lv_http_client CHANGING lv_content.

* Get the actual coordinate using the content string
  PERFORM get_coordinates USING lv_content lv_address.


ENDFORM. " get_long_lat
*&---------------------------------------------------------------------*
*&      Form  CREATE_HTTP_CLIENT
*&---------------------------------------------------------------------*
*       Create HTTP Client
*----------------------------------------------------------------------*
FORM create_http_client USING    lv_address TYPE char50
                        CHANGING p_http_client TYPE REF TO if_http_client.

  DATA: lv_http_url TYPE string.

* Prepare the url of the GeoCode API
  CONCATENATE
    'http://maps.google.com/maps/api/geocode/xml?address='
    lv_address
    INTO lv_http_url .

* Get client from url
  CALL METHOD cl_http_client=>create_by_url
    EXPORTING
      url                = lv_http_url
    IMPORTING
      client             = p_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  HTTP_CLIENT_REQUEST_GET_METHOD
*&---------------------------------------------------------------------*
*       Request and Get Method
*----------------------------------------------------------------------*
FORM http_client_request_get_method USING p_http_client TYPE REF TO if_http_client..
* Request and Get
  p_http_client->request->set_header_field( name = '~request_method' value = 'GET' ).
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  HTTP_CLIENT_SEND
*&---------------------------------------------------------------------*
*       Send request
*----------------------------------------------------------------------*
FORM http_client_send USING p_http_client TYPE REF TO if_http_client.
* Send the request
  p_http_client->send( ).
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  HTTP_CLIENT_RECEIVE
*&---------------------------------------------------------------------*
*       Get the string content
*----------------------------------------------------------------------*
FORM http_client_receive  USING    p_http_client TYPE REF TO if_http_client
                          CHANGING p_p_content   TYPE string.
* Reterive the result
  CALL METHOD p_http_client->receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3
      OTHERS                     = 4.

*  CALL METHOD p_http_client->response->get_cdata(
*    RECEIVING
*      data   = p_p_content " Character data
*    EXCEPTIONS
*      OTHERS = 1 ).

  p_p_content = p_http_client->response->get_cdata( ).

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_COORDINATES
*&---------------------------------------------------------------------*
*       Get Latitute Longitude Coordinate
*----------------------------------------------------------------------*
FORM get_coordinates  USING    p_p_content TYPE string
                               lv_address  TYPE char50.

* Local data declaration
  DATA: lv_url  TYPE c LENGTH 255,
        ls_dest TYPE ty_dest,
        moff    TYPE syst-tabix,
        moff1   TYPE syst-tabix,
        lv_len  TYPE syst-tabix,
        lv_lat  TYPE c LENGTH 20,
        lv_lng  TYPE c LENGTH 20.

* Field symbol
  FIELD-SYMBOLS:
        <lfs_dest> TYPE ty_dest.
*&---------------------------------------------------------------------*
*& Processing string
*&---------------------------------------------------------------------*
  DO .
* Find <location> text in the content string
    FIND '<location>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .

    IF sy-subrc = 0 .
* <location> is a 10 character string, hence adding 10
      moff = moff + 10 .

* Find closing tag </location> text in the content string
      FIND '</location>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .

* Find the length of string between tag <location> and </location>
      lv_len = moff1 - moff .

* We have seen the API string contet, so we know <lat> </lat> <lng> </lng> are there between
* <location> and </location>
*--------------------------------------------------------------------*
* ---------------Find latitude
*--------------------------------------------------------------------*
* Find string <lat>
      FIND '<lat>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
      IF sy-subrc = 0 .
* <lat> is a 5 character string, hence adding 5
        moff = moff + 5 .

* Find closing tag </lat> text in the content string
        FIND '</lat>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .

* Find the length of string between tag <lat> and </lat>
        lv_len = moff1 - moff .

* Characters between <lat> </lat> will have the latitude coorniate
        lv_lat = p_p_content+moff(lv_len) .

* From place address
        ls_dest-place_f = lv_address .

* Keep latitude in structure
        ls_dest-lat_f = lv_lat.

      ENDIF.

*--------------------------------------------------------------------*
* ---------------Find longitude
*--------------------------------------------------------------------*
* Find string <lng>
      FIND '<lng>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
      IF sy-subrc = 0 .

* <lng> is a 5 character string, hence adding 5
        moff = moff + 5 .

* Find closing tag </lng> text in the content string
        FIND '</lng>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .

* Find the length of string between tag <lng> and </lng>
        lv_len = moff1 - moff .

* Characters between <lng> </lng> will have the latitude coorniate
        lv_lng = p_p_content+moff(lv_len) .

* Keep longitude in structure
        ls_dest-lng_f = lv_lng.

      ENDIF.
    ELSE.

      EXIT.

    ENDIF.

  ENDDO .

  IF gt_dest[] IS INITIAL.
* This part would trigger for From Latitude and Longitude
* Put in internal table to display later
    APPEND ls_dest TO gt_dest.
    CLEAR:ls_dest .

  ELSE.

* This part would trigger for To Latitude and Longitude
    READ TABLE gt_dest ASSIGNING <lfs_dest> INDEX 1.
    IF sy-subrc EQ 0.
      <lfs_dest>-place_t = lv_address.
      <lfs_dest>-lat_t = ls_dest-lat_f.
      <lfs_dest>-lng_t = ls_dest-lng_f.
    ENDIF.

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY_LAT_LONGITUDE
*&---------------------------------------------------------------------*
*       Display Latitude and Longitude
*----------------------------------------------------------------------*
FORM display_lat_longitude .

  DATA:
    lr_alv       TYPE REF TO cl_salv_table,
    lr_columns   TYPE REF TO cl_salv_columns_table,
    lr_column    TYPE REF TO cl_salv_column,
    lr_functions TYPE REF TO cl_salv_functions_list,
    lr_display   TYPE REF TO cl_salv_display_settings,
    lr_layout    TYPE REF TO cl_salv_layout,
    ls_key       TYPE salv_s_layout_key,
    lr_sorts     TYPE REF TO cl_salv_sorts.

  " Check to make sure the internal table has data.
  IF lines( gt_dest ) > 0.

    TRY.
*       Create ALV instance
*       Use CALL METHOD since this is a static method
        CALL METHOD cl_salv_table=>factory
          IMPORTING
            r_salv_table = lr_alv
          CHANGING
            t_table      = gt_dest.

*       Get functions object and then set all the functions to be allowed
        lr_functions = lr_alv->get_functions( ).
        lr_functions->set_all( ).

        lr_columns = lr_alv->get_columns( ).

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'PLACE_F'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'From Place Name'.

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'LAT_F'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'From Latitude'.

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'LNG_F'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'From Longitude'.

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'PLACE_T'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'To Place Name'.

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'LAT_T'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'To Latitude'.

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'LNG_T'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'To Longitude'.

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'DIS'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Distance between From & To Address'.



        lr_columns->set_optimize( ).

*       Set sort column
        lr_sorts = lr_alv->get_sorts( ).
        lr_sorts->clear( ).

*       This code is to get the layout, save the layout and display the layout
        lr_layout = lr_alv->get_layout( ).
        ls_key-report = sy-repid.
        lr_layout->set_key( ls_key ).
        lr_layout->set_default( ' ' ).
        lr_layout->set_save_restriction( cl_salv_layout=>restrict_none ).


        lr_display = lr_alv->get_display_settings( ).
        lr_display->set_striped_pattern( cl_salv_display_settings=>true ).

*       Now display the report as an ALV grid
        lr_alv->display( ).

      CATCH cx_salv_msg.
        WRITE: 'Error displaying grid CX_SALV_MSG!'(001).

      CATCH cx_salv_not_found.
        WRITE: 'Error displaying grid CX_SALV_NOT_FOUND!'(002).

      CATCH cx_salv_data_error.
        WRITE: 'Error displaying grid CX_SALV_DATA_ERROR!'(003).

      CATCH cx_salv_existing.
        WRITE: 'Error displaying grid CX_SALV_EXISTING!'(004).

    ENDTRY.

  ELSE.
    MESSAGE 'No data to display' TYPE 'I'.
    LEAVE LIST-PROCESSING.

  ENDIF.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  MEASURE_DISTANCE
*&---------------------------------------------------------------------*
*       Get distance between the from and to address
*----------------------------------------------------------------------*
FORM measure_distance .

  DATA:
    lv_http_client TYPE REF TO if_http_client,
    lv_content     TYPE string.

  LOOP AT gt_dest ASSIGNING <fs_dest>.

* Creation of new IF_HTTP_Client object
    PERFORM create_http_client_dist CHANGING lv_http_client .

* Request and Get
    PERFORM http_client_request_get_method USING lv_http_client.

* Send the request
    PERFORM http_client_send USING lv_http_client.

* Retrieve the result
    PERFORM http_client_receive USING lv_http_client CHANGING lv_content.

* Get the actual coordinate using the content string
    PERFORM get_coordinates_dist USING lv_content.

  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CREATE_HTTP_CLIENT_DIST
*&---------------------------------------------------------------------*
*       *       Create HTTP Client
*----------------------------------------------------------------------*
FORM create_http_client_dist  CHANGING p_http_client TYPE REF TO if_http_client.

  DATA: lv_http_url TYPE string.

* Prepare the url for the DistanceMatrix API From Address Coordinates and To Address Coordinates
  CONCATENATE
    'http://maps.googleapis.com/maps/api/distancematrix/xml?origins='
    <fs_dest>-place_f '|' <fs_dest>-lat_f ',' <fs_dest>-lng_f ','
    '&destinations=' <fs_dest>-place_t '|' <fs_dest>-lat_t ',' <fs_dest>-lng_t
  '&alternatives=' 'true'
    INTO lv_http_url .

* Get client from url
  CALL METHOD cl_http_client=>create_by_url
    EXPORTING
      url                = lv_http_url
    IMPORTING
      client             = p_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_COORDINATES_DIST
*&---------------------------------------------------------------------*
*       Get Latitute Longitude Coordinate
*----------------------------------------------------------------------*
FORM get_coordinates_dist  USING    p_p_content TYPE string.

* Local data declaration
  DATA: lv_url  TYPE c LENGTH 255,
        ls_dest TYPE ty_dest,
        moff    TYPE syst-tabix,
        moff1   TYPE syst-tabix,
        lv_len  TYPE syst-tabix,
        lv_lat  TYPE c LENGTH 20,
        lv_lng  TYPE c LENGTH 20.

* Field symbol
  FIELD-SYMBOLS:
        <lfs_dest> TYPE ty_dest.
*&---------------------------------------------------------------------*
*& Processing string
*&---------------------------------------------------------------------*
  DO .
* Find <distance> text in the content string
    FIND '<distance>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
    IF sy-subrc = 0 .

* <distance> is a 10 character string, hence adding 10
      moff = moff + 10 .

* Find closing tag </distance> text in the content string
      FIND '</distance>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .

** Find the length of string between tag <distance> and </distance>
*      lv_len = moff1 - moff .

* We have seen the API string contet, so we know <text> </text> are there between
* <distance> and </distance>
      FIND '<text>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
      IF sy-subrc = 0 .
* <text> is a 6 character string, hence adding 6
        moff = moff + 6 .

* Find closing tag </text> text in the content string
        FIND '</text>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .

* Find the length of string between tag <text> and </text>
        lv_len = moff1 - moff .

* Characters between <text> </text> will have the distance
        <fs_dest>-dis = p_p_content+moff(lv_len).

* Get one distance and exit
        EXIT.

      ENDIF.

    ELSE.
      EXIT.
    ENDIF.
  ENDDO .
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SHOW_OUTPUT
*&---------------------------------------------------------------------*
*       Show output
*----------------------------------------------------------------------*
FORM show_output .

  IF p_alv IS NOT INITIAL.

* Show Latitute, Longitude and Distance
    PERFORM display_lat_longitude.

  ELSEIF p_route IS NOT INITIAL.

* Show the complete break down of driving route
    PERFORM display_turn_by_turn_route.

  ELSEIF p_map IS NOT INITIAL.

* Show direction in map
    PERFORM show_map.

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  TURN_BY_TURN_ROUTE
*&---------------------------------------------------------------------*
*       Get turn by turn ROUTE
*----------------------------------------------------------------------*
FORM turn_by_turn_route .

  DATA:
    lv_http_client TYPE REF TO if_http_client,
    lv_content     TYPE string,
    lv_xstring     TYPE xstring,
    li_xml_table   TYPE TABLE OF smum_xmltb.

  IF p_route IS NOT INITIAL.

    LOOP AT gt_dest ASSIGNING <fs_dest>.

* Creation of new IF_HTTP_Client object
      PERFORM create_http_client_direction CHANGING lv_http_client .

* Request and Get
      PERFORM http_client_request_get_method USING lv_http_client.

* Send the request
      PERFORM http_client_send USING lv_http_client.

* Retrieve the result
      PERFORM http_client_receive USING lv_http_client CHANGING lv_content.

** Get the actual coordinate using the content string
*      PERFORM get_coordinates_dist USING lv_content.

* Convert String to XString
      PERFORM convert_string_to_xstring USING lv_content CHANGING lv_xstring.

* Parse XML document into a table structure
      PERFORM parse_xml_to_table USING lv_xstring CHANGING li_xml_table.

* Clean XML file
      PERFORM clean_xml_data USING li_xml_table.



    ENDLOOP.

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CONVERT_STRING_TO_XSTRING
*&---------------------------------------------------------------------*
*       Convert sting to xstring
*----------------------------------------------------------------------*
FORM convert_string_to_xstring USING p_p_content TYPE string
                               CHANGING p_p_xstring TYPE xstring.

  CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
    EXPORTING
      text   = p_p_content
    IMPORTING
      buffer = p_p_xstring
    EXCEPTIONS
      failed = 1
      OTHERS = 2.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  PARSE_XML_TO_TABLE
*&---------------------------------------------------------------------*
*       Parse XML docment into a table structure
*----------------------------------------------------------------------*
FORM parse_xml_to_table  USING    p_p_xstring    TYPE xstring
                         CHANGING p_li_xml_table TYPE hrpayfr_t_smum_xmltb.

  DATA:
      li_return    TYPE TABLE OF bapiret2.

  CALL FUNCTION 'SMUM_XML_PARSE'
    EXPORTING
      xml_input = p_p_xstring
    TABLES
      xml_table = p_li_xml_table
      return    = li_return.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CREATE_HTTP_CLIENT_DIRECTION
*&---------------------------------------------------------------------*
*       Get Direction API
*----------------------------------------------------------------------*
FORM create_http_client_direction  CHANGING p_http_client TYPE REF TO if_http_client.

  DATA: lv_http_url TYPE string.

* Prepare the url for Directions API for the From Address Coordinates and To Address Coordinates
  CONCATENATE
    'http://maps.googleapis.com/maps/api/directions/xml?origin='
    <fs_dest>-place_f '|' <fs_dest>-lat_f ',' <fs_dest>-lng_f
    '&destination=' <fs_dest>-place_t '|' <fs_dest>-lat_t ',' <fs_dest>-lng_t
    '&alternatives=' 'true'
    INTO lv_http_url .

  CONDENSE lv_http_url.

* Get client from url
  CALL METHOD cl_http_client=>create_by_url
    EXPORTING
      url                = lv_http_url
    IMPORTING
      client             = p_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CLEAN_XML_DATA
*&---------------------------------------------------------------------*
*       Clean XML data to cleaner format
*----------------------------------------------------------------------*
FORM clean_xml_data  USING    p_li_xml_table TYPE hrpayfr_t_smum_xmltb.
  DATA:
    ls_xml  TYPE smum_xmltb,
    ls_path TYPE ty_route.

* Deleting time mentioned in the XML. If you want time, you need to
* keep this and manipulate later
  DELETE p_li_xml_table WHERE cvalue CS 'min'.

* Remove sub total for partial route. If you want time, you need to
* keep this and manipulate later
  DELETE p_li_xml_table WHERE
  hier = '5' AND
  type = 'V' AND
  cname = 'text'.

* Reading the XML data
  LOOP AT p_li_xml_table INTO ls_xml.

    AT FIRST.
* First step is new route by default
      ls_path-route_n = abap_true.
    ENDAT.

* Remove the XML format tag codes
    REPLACE ALL OCCURRENCES OF '<b>' IN ls_xml-cvalue WITH space.
    REPLACE ALL OCCURRENCES OF '</b>' IN ls_xml-cvalue WITH space.

* Remove the XML format tag codes
    REPLACE ALL OCCURRENCES OF '<div style="font-size:0.9em">' IN ls_xml-cvalue WITH '.'.
    REPLACE ALL OCCURRENCES OF '</div>' IN ls_xml-cvalue WITH space.

* Check the name
    CASE ls_xml-cname.

* Get the summary of the route
      WHEN 'summary'.
        ls_path-summary = ls_xml-cvalue.

* Driving instruction
      WHEN 'html_instructions'.
        ls_path-ins = ls_xml-cvalue.

* Text would have the distance and unit
      WHEN 'text'.
        ls_path-dis = ls_xml-cvalue.

* Copyrights means, start of new path
      WHEN 'copyrights'.

        ls_path-route_n = 'X'.
        CLEAR ls_path-step.

      WHEN OTHERS.
* do nothing

    ENDCASE.

* If there is some data, populate the route table
    IF    ls_path-ins     IS NOT INITIAL
      AND ls_path-dis     IS NOT INITIAL.

      ls_path-step = ls_path-step + 1.

* This will have the route details
      APPEND ls_path TO gt_route.

      CLEAR: ls_path-ins, ls_path-dis, ls_path-route_n, ls_path-summary.

    ENDIF.

    CLEAR: ls_xml.

  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY_TURN_BY_TURN_ROUTE
*&---------------------------------------------------------------------*
*       Display Turn by Turn route
*----------------------------------------------------------------------*
FORM display_turn_by_turn_route .

  DATA:
    lr_alv       TYPE REF TO cl_salv_table,
    lr_columns   TYPE REF TO cl_salv_columns_table,
    lr_column    TYPE REF TO cl_salv_column,
    lr_functions TYPE REF TO cl_salv_functions_list,
    lr_display   TYPE REF TO cl_salv_display_settings,
    lr_layout    TYPE REF TO cl_salv_layout,
    ls_key       TYPE salv_s_layout_key,
    lr_sorts     TYPE REF TO cl_salv_sorts.

  " Check to make sure the internal table has data.
  IF lines( gt_route ) > 0.

    TRY.
*       Create ALV instance
*       Use CALL METHOD since this is a static method
        CALL METHOD cl_salv_table=>factory
          IMPORTING
            r_salv_table = lr_alv
          CHANGING
            t_table      = gt_route.

*       Get functions object and then set all the functions to be allowed
        lr_functions = lr_alv->get_functions( ).
        lr_functions->set_all( ).

        lr_columns = lr_alv->get_columns( ).

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'ROUTE_N'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'New Route Indicator'.

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'SUMMARY'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Via'.

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'STEP'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Important Turns'.

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'INS'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Instructions'.

        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'DIS'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Distance'.

        lr_columns->set_optimize( ).

*       Set sort column
        lr_sorts = lr_alv->get_sorts( ).
        lr_sorts->clear( ).

*       This code is to get the layout, save the layout and display the layout
        lr_layout = lr_alv->get_layout( ).
        ls_key-report = sy-repid.
        lr_layout->set_key( ls_key ).
        lr_layout->set_default( ' ' ).
        lr_layout->set_save_restriction( cl_salv_layout=>restrict_none ).


        lr_display = lr_alv->get_display_settings( ).
        lr_display->set_striped_pattern( cl_salv_display_settings=>true ).

*       Now display the report as an ALV grid
        lr_alv->display( ).

      CATCH cx_salv_msg.
        WRITE: 'Error displaying grid CX_SALV_MSG!'(001).

      CATCH cx_salv_not_found.
        WRITE: 'Error displaying grid CX_SALV_NOT_FOUND!'(002).

      CATCH cx_salv_data_error.
        WRITE: 'Error displaying grid CX_SALV_DATA_ERROR!'(003).

      CATCH cx_salv_existing.
        WRITE: 'Error displaying grid CX_SALV_EXISTING!'(004).

    ENDTRY.

  ELSE.
    MESSAGE 'No route data to display' TYPE 'I'.
    LEAVE LIST-PROCESSING.

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SHOW_MAP
*&---------------------------------------------------------------------*
*       Show direction on the map
*----------------------------------------------------------------------*
FORM show_map .

  DATA:
    lv_http_client TYPE REF TO if_http_client,
    lv_content     TYPE string.

  LOOP AT gt_dest ASSIGNING <fs_dest>.

* Call Browser
    PERFORM call_browser.

    EXIT.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CALL_BROWSER
*&---------------------------------------------------------------------*
*       Route map
*----------------------------------------------------------------------*
FORM call_browser.

  DATA: lv_url TYPE c LENGTH 255.

* Prepare the url for Directions API for the From Address Coordinates and To Address Coordinates
  CONCATENATE
    'https://www.google.co.in/maps/dir/'
    <fs_dest>-lat_f ',' <fs_dest>-lng_f '/'
    <fs_dest>-lat_t ',' <fs_dest>-lng_t
    INTO lv_url .

* Condense the text
  CONDENSE lv_url.

* Open the route in browser
  CALL FUNCTION 'CALL_BROWSER'
    EXPORTING
      url                    = lv_url
    EXCEPTIONS
      frontend_not_supported = 1
      frontend_error         = 2
      prog_not_found         = 3
      no_batch               = 4
      unspecified_error      = 5
      OTHERS                 = 6.


ENDFORM.

 

ABAP Objects Tips

$
0
0

Hello Friends

Long before (or maybe not so long before), ABAP was written with subroutines and function calls. But in recent times, due to various reasons, developers are forced to use the Object Oriented Programming. Hands down, Object Oriented programming is the better way to write programs but I have a problem with the forced approach. This has led to a time, where many developers are writing ABAP objects without even understanding them. Many developers really find it easy but initially I found OOPs pretty intimidating as I have never written (from scratch) code in JAVA or C++ during my college days. My friends, who are like me, fear not. We all can learn and more importantly understand and master ABAP Objects. As usual, several sources are available on the internet, so I am just concentrating on the tips:

The difference between STATIC and INSTANCE methods: STATIC method looks easier to call but it comes with a price. It cannot be REDEFINED. This should be enough to stop you from creating STATIC methods. But what if, you are creating local classes and you know that you do not need redefinition. STATIC Method has 1 more problem. It is static and uses only static variables. So the values of the variables will remain same throughout the program. In order to feel the difference, declare a static variable in a subroutine and call the subroutine multiple times in your program. You will see that all the DATA variables have instantiated but the STATIC variable remembers the old value. This makes STATIC variable tricky and you need to be extra careful with them. Let me draw the parallel with Internet Browsing. Open Chrome in normal mode and no matter how many new windows you open, it will remember the content of the other windows. Now, open Chrome in Incognito mode. Every time you open a new window, you will get the same refreshed state. So the first case is STATIC Method call and the incognito mode is the Instance Method call. It is like keeping the history of your internet browsing. It is great and helpful but you need to be careful. Just avoid it, and write few extra lines of code. Use STATIC Method only when it is necessary and it is necessary in generally 2 cases. You need to use the method before creating in the implementation and objects or you need to keep the values of the variables same throughout the call of the program.

Constructors: You have read the definition that it is called with CREATE Object Statement. But it is a special class. It can be executed only once for each instance and obviously, it is getting triggered before any other instance method. So, if there is something which you want to ensure before any of your instantiated methods triggers, you need to put that in the CONSTRUCTOR. Best Analogy, I can find is the Matrix movie. When Morpheus was explaining Neo, about his first training program. Before loading the actual program, the Construct is loaded. Because Construct has provided the base for the other program to load. Or in SAP terms, can default the values. It can also be used if you need to ensure it is triggered only (automatically) once for an instance.  Maybe Matrix was designed following OOPs approach.

As I said, there is no end to learning. So, please post your suggestions, tips and questions. If you find this blog helpful, please pass it to your friends and follow us on the facebook.

Lazy and Smart ABAPers

$
0
0

One of my very good friends once wrote a four line article titled “What Laziness leads to?” in LinkedIn.

What is the Outcome of Laziness?
Automation.

What is the after effect of Automation?
More Laziness, More Profit.

If there were to be a competition of short articles, my friend’s article would have definitely featured in the top list. Being an ABAPer, we often do the repetitive work every day. For example, in every program we need to create flower boxes, we need to declare the events of the programs, we need to create selection screen etc. Copy and Paste is the best tool invented by the Computer scientists. The majority of computer users use the Ctrl + C and Ctrl + V feature irrespective of the software platform.

ABAP editor has also evolved all these years. From the boring blue screen to any screen colour/background we like. From GUI to eclipse editor, ABAP and ABAPer have made huge jumps. These days ABAPer are also working in javascript, SQL and UI programming. But old ABAPers (like me) and those who did not get the opportunity to work in new areas, still do 90 percent of their work in the ABAP workbench/editor.

Let us see what are the common shortcuts and helpers which smart ABAPers of this age (not lazy) have in the same old ABAP editor.

1. Copy the same line below the existing line i.e duplicate the statement.

Use Ctrl + D to copy duplicate lines just below it.

Copy duplicate line2. Copying multiple rows of one column and paste them. Remember only one column not all columns (copying all the columns is easy).
You can copy multiple rows of one column using Alt + drag your cursor.

Can you copy just one column in ABAP editor? Yes, we can.

Check the image below. Only constant lc_tab is selected and the other columns of the other rows are not.

Press Alt + drag your cursor to left till the column end and then drag down.

ABAP Technical
Then press Ctrl+C and then go to the rows where you want to paste it.

You need to apply the same trick where you want to paste it. Check this image. You need to hold Alt and drag the cursor vertically down and right side to create space for the copied rows of one column.

SAP ABAP for beginners

Check the copied rows of one column are pasted (Ctrl + V) in your selected area.

SAP Techies
This is quite handy when you have repetitive words to be written in multiple rows. In the above example, it is Tab separator constant. In another case, it might be key work TYPE to be written while BEGIN OF TYPE declaration. Also, you can copy field name and data element from SE11 structure/table and paste it into your editor and then use Alt + drag to add TYPE.3 4

Initially, you might find some difficulty selecting columns using the trick. Keep trying and using and in no time you would start appreciating it more and more. 🙂

Also Read: Back to Basics

3. Line Separators or Code Separators
If you need a dashed line in your code, it might be for separation of code or modularization or just for making your code pretty. Do you type ‘*’ or ‘”‘ and then press ‘-‘ till the end of the line? Sometimes you might want to use ***** asterisks to do the same. Do you press ‘*’ till the end?

You should be taking advantage of the code completion feature of SAP. Just type ‘*–‘ and you get suggestions. Similarly type ‘***’ and you get suggestions. Hit ‘TAB’ key and it writes the full code for you.

Auto Code Completion

You might be using IF-ELSE, DO-ENDO, LOOP ENDLOOP, CASE ENDCASE auto completion. But have you ever used IF ELSE ENDIF? Just type ife, and you get the suggestion. In fact, you can make SAP auto suggest you for anything and everything you code. It is completely in your control.

SAP Technical

Where can we find the list of all Code Completion short codes?

Vanilla ABAPClick the small Options icon on the right-hand side bottom corner in your editor. You can control the timing and properties of Code Completion. Code Template would actually have the code which would be written when you hit TAB when code completion suggestion creeps in.

You can create your own custom Code Completion list and add them to the repository.

You might like this: Are you an ABAP Coder or a Programmer?

4. Program Templates
Whenever an ABAPer creates a new program, they have some codes which are needed in each and every program they created. Flower box, revision log, Selection Screen, Program Events etc. Usually, we refer to another program and copy the template.

Patterns in SAP

Check, I am creating a fresh new program and start typing ZZ_TEMPLATE. As I complete the word the auto-completion is visible and when I hit ‘TAB‘ key, the whole program skeleton is written for me.

Program Events

The idea is to have the template for all the needed areas. Flower box, revision log, selection screen, events. Now, once I have the template, I just give the correct program name, description, logs and change the selection screen fields. If I do not need checkbox or radio buttons declaration, I delete them.

I remember in some projects we had the custom Pattern saved and used for the same purpose.

But later I realised, SAP has provided a smart way to avoid creation of that custom Pattern (since Pattern is also a development which we need to save in transport or local). Click the same small Options icon again on the right-hand side bottom corner in your editor. Hit Code Templates ->Add -> Give the name & description -> OK.5

6

Paste your template code and Save it. Now everyone using this development box can use your template to get the job done faster. 🙂

9

Note : You can create one template for any work which you need very often, for example, selection screen snippet or file validation code or F4 Help code or MODIF id code etc. If you do not remember some syntax, just save a template for it and you do not need to remember it for life. 🙂

If you like the template and want to use it, you can copy from this file.  Template File.

But most projects will have their own flower box and templates, so use your project specific ones and save in the template.

Also Read: Do all ABAPers know Fixed Point Arithmetic?

5. Save the code in PDF format
Sometimes you want to take a backup of your code. Usually, we copy and paste it to a notepad or we go through Utilities -> More Utilities -> Download. But keeping your code back up in PDF format has its own beauty.

Just click the same icon at the bottom right of your editor, go to Keyboard option and look for File.ExportPDF short cut. For my case it is Shift + P. You can change this keys and assign your favourite keys to save as PDF. I have kept Shift + P unchanged.

Save code in PDF file

Go to the desired program which you want to save in PDF. Hit Shit + P or any other keys if you have changed it. Save at the desired path you want.

Save Program in PDF format 13

The code in PDF file always looks better. Isn’t it? 🙂

6. Have charm in the editor where you spend maximum time at work.
There should always be spice in your life. If you are bored of looking at the blue screen of your editors or just want to customize the fonts and colours for better readability or want different colours for fun or want something which soothes your eyes, check the below image.

Change background color of editor

This the current configuration of my workplace.

You can configure it for yourself using the same small icon on the right bottom corner of your editor. Choose Fonts and Colors. Below is the setting for my editor. Try and have fun!!

Fonts setting

We have tried to reveal that small Options icon on your screen in this article. Hope after going through this post, that icon can no longer hide from your sharp eyes.

If you have some more short codes/cuts or tricks or any other interesting stuff, please do share it with us. If you have something which can help us be more smart/lazy, that would be more welcomed. 🙂

If you want to get such useful articles directly to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons and like us on facebook.

Thank you very much for your time!!

 

Also, check our Tutorials:

Web Dynpro ABAP
SAP ABAP for HANA

Logical Lock Vs Physical Lock in SAP

$
0
0

This morning I had a chat with an ABAPer who has few months of experience after training. While discussing he said if a table is ENQUEUED (locked for change) in one session, no one else can modify/update that table. I tried to explain that the statement is not completely true. This post is an extension of that conversation.

There are quite a few good articles and blogs on Locking Concept. We are not going to sing the same song here. Today we would focus our discussion on just two words, Logical and Physical.

The literal meaning of the two words are:

Logical : Logical describes something that comes from clear reasoning.

Physical :When something is physical it’s really there.

If you ask anyone, what is the difference between Database Lock and SAP Lock, the knee-jerk answer is Database Lock is a Physical Lock and SAP Lock in a Logical Lock. For seasoned and experienced consultants, it is not difficult to assimilate and understand these two words. But freshers and newbies might have some questions which they are reluctant to ask their seniors.

Without wasting any time, let us start our mission.

Can two ABAPers open the same program in SE38 in change mode in the same client and system? Or can two functional consultants open the same sales order in VA02 (change mode)?

A picture is worth a thousand words. Let me demonstrate it in some images.

Check, I have opened program ZSAPYard in one session.
Lock Concept in SAP ABAP

Check the lock in the T-code SM12 shows I am inside the program in change mode.

Lock Concept

Now check this image.
SAP Lock in ABAP

Q: How can I be in editable/change mode for the same program in the same system and client?
A: Super-ABAPers have the power of ‘/h’. 🙂 Debugger. Yes

The SAP Lock would try to throw the error message that a lock is already set for the program, but you can always bypass the error message and force the system to pretend that everything is normal and do not spit any venom.

You just need to hit ‘/h’ and hit enter in the same program in the second screen in SE38 in change mode a second time. Then put a dynamic breakpoint at statement ‘MESSAGE’.

13

14 15

When the system would identify that a Lock is already there for the program and it would try to throw the error message, just use your debugging skill to get past the error (put the cursor on the next executable line and jump to that line without allowing the error message line to be executed).

Menu: Debugger -> Goto statement  (Shift + F12) (This helps to jump statements)

Get past the error message at a couple of places as shown above.

Boom.. You are now editing the same program in two screens in the same client in the same system.

Whether you would be able to change and activate in both the editable screen, you need to try it yourself to find it out. Let us know whether you were able to activate the changes in both screen. We would be happy to reveal, what we found.

Also Read: Everyday SAP Security Breach.

What are we trying to prove here?
SAP Lock is Logical. Even though the program was logically locked for editing, still we forced it to be open for editing in another session. How illogical!! Isn’t it?

Logical means the developer has to use his discretion and handle the locks logically. If someone has already locked something, if you want, you CAN make change simultaneously. But whether you should be changing something when someone else is trying to change at the same time? That is the logical question. SAP Locks are not physical.

Let us look another example. This would make the picture clearer.

I am locking the custom table in change mode in SM30.

2_2

Check the logical SAP lock in T-code SM12.

1

Now, I wrote a program to check if the table is locked. Then illogically I decide, even if it is locked, I do not care. Let the system be inconsistent. I want to update the table.

See, I am updating the table when SY-SUBRC <> 0.
Foreign Lock

Will I be able to update the table?

Untitled2Yes. Even if someone else is simultaneously editing the table, I can update the table at the same time. SAP Locks are only Logical and it needs the programmers discretion to use it properly. Check the Process flag, modified by, date and time are updated successfully for the PO item 10 which is in the WHERE clause of the UPDATE statement.

Hope now, you understand what does Logical Lock means.. 🙂

Also Read: Are you a Lazy ABAPer?

Change our focus to Physical now.

For our freshers: Database locks are set by data changing SQL statements such as INSERT, UPDATE, MODIFY etc. These are physical locks and are held until the SQL statement COMMIT is reached. Once the COMMIT statement is executed the DB lock is released.

Let us see in pictures what it means.

0

I have written a program to update a custom table. I set a breakpoint at COMMIT statement.

Execute the program in one session and the execution stops at COMMIT statement. Since the database executed the UPDATE statement, a database lock is set by the database. We can check the database lock using T-code DBACOCKPIT (follow the path highlighted in the below image). If you do not have access to this t-code, go to your Basis team and ask them to show you this lock.

How to check Physical Lock

Now let us run the same program in another session and set our breakpoint at the UPDATE statement.

Remember, the first debugger in the other session is still there at COMMIT statement i.e. the Physical database logic is still active as COMMIT statement has not been executed.

Database Lock

You would find that even if you hit F5, F6 or F8, you cannot get past the UPDATE statement for the second run. This is Physical. No matter how hard you try, you cannot UPDATE the same table if the first lock is not released.

I walked to the washroom, went to the cafeteria and fetched a glass of water and returned to my desk (6 to 8 minutes). The second session was still trying to get past the UPDATE statement. I came back and executed the COMMIT statement in the first debugger and boom, the UPDATE statement is executed on the second screen and waiting on COMMIT statement.

As soon as COMMIT WORK statement is executed in the first debugger, the Lock is released and the second session Locks it again as the UPDATE statement is finally executed.

DB Lock

Hope you understand the essence of Physical Lock now. It is like the real Physical lock which can be opened and closed with the key one at a time. If one key is entered in the lock hole, no other key can lock or open it.

In straight words. if there is a Physical Lock (Database Lock) on a table, it cannot be updated/changed in any other session. Period.. 🙂

For your reading pleasure, you can refer to this external link for the R/3 Lock Concept.

If you want to get such useful articles directly to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons and like us on facebook.

Thank you very much for your time!!

Know Who is doing What in your SAP System

$
0
0

These days micro-management has become very common. Clients want  the breakdown of all the work you do every day, sometimes as ridiculous as at t-code level. 🙂 . I know clients who monitor when the contractor last logged into the system and from which terminal.

If you are that manager who is in that unavoidable circumstance where you have to keep track of the activities of some users (who are trying to fool you), this tool would be handy for you. Or else, if you are just a developer but still would like to see who performs what activity at any point of time, you can also make use of this tool.

This is more for academic fun rather than having real project usage. No HANA, SAP UI5, OData or Fiori in this post. Just plain Vanilla ABAP. So, relax and try the code for this tool in your system and check what your team members and users do. 😛 . You can also check if your Team Lead/Project Lead ever log into their respective SAP system or are they happy preparing spreadsheet and presentations. 😀

We have provided only 4 radio buttons. You can improvise upon it and create multiple permutations and combinations.

The heart and mind of this application tool is FM ‘TH_LONG_USR_INFO‘. The information is returned in structure UINFO2 (Full information on a user).

Buckle up, we are moving!!!

a) Let us see who all are logged into the system. Just for attendance. 🙂

Monitor User in SAP

See the output below. It provides the unique list of UserId along with the name. Terminal (laptop/desktop) name is also provided. Is it good information?

TH_LONG_USR_INFO

Also Read: Everyday Simple Security Breach in SAP.

b) Let us see in details what t-code each logged user is using. Have they just logged in or are they really working?

micromanagement in SAP

Check Ali has 6 sessions opened and Shrestha has 3 sessions. You also get the information about the transaction they are using and the time they last logged into that t-code. If someone is in the t-code for long, it means he is idle or not using that SAP session.

User Log

Also Read: Do you have Lazy ABAPers in your Team?

c) Let us check what my best friend is doing in his SAP system.

dynamic selection screen elements

The moment you click the third radio button, the SAP User Id element of the screen would be visible. The simple hide and display code is written at initialization (for freshers only).

Check Shrestha is logged into two different clients and opened six different sessions. Looks like he is working a lot. 😛

6

d) Finally, let us see who all are messing around with the same t-code at one point of time.

7
Seems three different users (ali, man and med) in three different clients (110, 120, 140) are playing with t-code HRFORMS. HR is always popular. 😛

8

This post is just a breather from all the heat and noise from HANA, SAPUI5 and Fiori. After all, the normal ABAP has been the bread and butter of all ABAPers till date. It is like the old habit which cannot be forgotten or left so easily. 🙂

Please find below the working code for the tool. You might need to populate the text elements manually in your program. Create the program in your development/test box and be the secret agent. 😛

*---------------------------------------------------------------------*
* TABLES *
*---------------------------------------------------------------------*
TABLES: tstc, usr21.

*---------------------------------------------------------------------*
* TYPES *
*---------------------------------------------------------------------*
TYPES:
BEGIN OF ty_report,
session TYPE numc4, "usession,
client TYPE mandt,
user TYPE ubname,
name TYPE ad_namtext,
terminal TYPE uterm,
tcode TYPE utcode,
ltime TYPE syst_uzeit,
END OF ty_report.
*---------------------------------------------------------------------*
* DATA *
*---------------------------------------------------------------------*
DATA:
it_output TYPE STANDARD TABLE OF uinfo2,
it_report TYPE STANDARD TABLE OF ty_report.


*---------------------------------------------------------------------*
* SELECTION SCREEN *
*---------------------------------------------------------------------*

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-s01.

SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(75) text-c01.
PARAMETERS:
r_onl RADIOBUTTON GROUP opt1 DEFAULT 'X' USER-COMMAND aa.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(75) text-c02.
PARAMETERS:
r_det RADIOBUTTON GROUP opt1.

SELECTION-SCREEN END OF LINE.

SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(75) text-c03.
PARAMETERS:
r_usr RADIOBUTTON GROUP opt1.

SELECTION-SCREEN END OF LINE.

SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(75) text-c04.
PARAMETERS:
r_tcd RADIOBUTTON GROUP opt1.

SELECTION-SCREEN END OF LINE.

SELECTION-SCREEN END OF BLOCK b1.

SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE text-s02.
SELECT-OPTIONS: s_tcode FOR tstc-tcode NO INTERVALS.
SELECTION-SCREEN END OF BLOCK b2.

SELECTION-SCREEN BEGIN OF BLOCK b3 WITH FRAME TITLE text-s03.
SELECT-OPTIONS: s_user FOR usr21-bname NO INTERVALS.
SELECTION-SCREEN END OF BLOCK b3.

*---------------------------------------------------------------------*
* INITIALIZATION *
*---------------------------------------------------------------------*
INITIALIZATION.
* Restrict user to enter range in t-code and user id
PERFORM restrict_range.

*---------------------------------------------------------------------*
* AT SELECTION-SCREEN OUTPUT. *
*---------------------------------------------------------------------*
AT SELECTION-SCREEN OUTPUT.
PERFORM hide_unrelevent_select_options.

*---------------------------------------------------------------------*
* AT SELECTION-SCREEN. *
*---------------------------------------------------------------------*
AT SELECTION-SCREEN.

*---------------------------------------------------------------------*
* START-OF-SELECTION. *
*---------------------------------------------------------------------*
START-OF-SELECTION.

* Get the user/system info
PERFORM get_user_system_info.

*---------------------------------------------------------------------*
* END-OF-SELECTION. *
*---------------------------------------------------------------------*
END-OF-SELECTION.
* Show ALV Report
PERFORM display_report.

*---------------------------------------------------------------------*
* SUB-ROUTINES *
*---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form RESTRICT_RANGE
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* Restrict range
*----------------------------------------------------------------------*
FORM restrict_range .
CONSTANTS: lc_opt_list TYPE rsrest_opl VALUE 'OPT_LIST',
lc_s TYPE rsscr_kind VALUE 'S',
lc_tcode TYPE blockname VALUE 'S_TCODE',
lc_user TYPE blockname VALUE 'S_USER',
lc_inc TYPE c VALUE 'I'.

DATA: lw_opt_list TYPE sscr_opt_list,
lw_restrict TYPE sscr_restrict,
lw_ass TYPE sscr_ass.

lw_opt_list-name = lc_opt_list.
lw_opt_list-options-bt = space.
lw_opt_list-options-eq = 'X'.
APPEND lw_opt_list TO lw_restrict-opt_list_tab.

lw_ass-kind = lc_s.
lw_ass-name = lc_tcode.
lw_ass-sg_main = lc_inc.
lw_ass-op_main = lc_opt_list.
APPEND lw_ass TO lw_restrict-ass_tab.

lw_ass-kind = lc_s.
lw_ass-name = lc_user.
lw_ass-sg_main = lc_inc.
lw_ass-op_main = lc_opt_list.
APPEND lw_ass TO lw_restrict-ass_tab.

CALL FUNCTION 'SELECT_OPTIONS_RESTRICT'
EXPORTING
restriction = lw_restrict
EXCEPTIONS
too_late = 1
repeated = 2
selopt_without_options = 3
selopt_without_signs = 4
invalid_sign = 5
empty_option_list = 6
invalid_kind = 7
repeated_kind_a = 8
OTHERS = 9.


ENDFORM.
*&---------------------------------------------------------------------*
*& Form HIDE_UNRELEVENT_SELECT_OPTIONS
*&---------------------------------------------------------------------*
* Hide the select options when not needed
*----------------------------------------------------------------------*
FORM hide_unrelevent_select_options .

LOOP AT SCREEN.

* If user radio button is not chosen, hide the user block
IF r_usr IS INITIAL.
CASE screen-name.

WHEN '%B003006_BLOCK_1000'.
screen-active = 0.

WHEN '%_S_USER_%_APP_%-TEXT'.
screen-active = 0.

WHEN '%_S_USER_%_APP_%-OPTI_PUSH'.
screen-active = 0.

WHEN 'S_USER-LOW'.
screen-active = 0.

WHEN '%_S_USER_%_APP_%-VALU_PUSH'.
screen-active = 0.

WHEN OTHERS.

ENDCASE.

ENDIF.
MODIFY SCREEN.

* If t-code radio button is not chosen, hide the t-code block
IF r_tcd IS INITIAL.
CASE screen-name.

WHEN '%B003006_BLOCK_1000'.
screen-active = 0.

WHEN '%_S_TCODE_%_APP_%-TEXT'.
screen-active = 0.

WHEN '%_S_TCODE_%_APP_%-OPTI_PUSH'.
screen-active = 0.

WHEN 'S_TCODE-LOW'.
screen-active = 0.

WHEN '%_S_TCODE_%_APP_%-VALU_PUSH'.
screen-active = 0.

WHEN OTHERS.

ENDCASE.

ENDIF.
MODIFY SCREEN.

ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_USER_SYSTEM_INFO
*&---------------------------------------------------------------------*
* Get the user and system information
*----------------------------------------------------------------------*
FORM get_user_system_info .

CALL FUNCTION 'TH_LONG_USR_INFO'
EXPORTING
user = '*'
TABLES
user_info = it_output[].
IF it_output[] IS INITIAL.
MESSAGE 'No one has logged into the system' TYPE 'I'.
LEAVE LIST-PROCESSING.

ELSE.
IF r_onl IS NOT INITIAL.

SORT it_output BY user.
DELETE ADJACENT DUPLICATES FROM it_output[] COMPARING user.

ELSEIF r_usr IS NOT INITIAL.

IF s_user IS NOT INITIAL.
DELETE it_output[] WHERE user NOT IN s_user.
ENDIF.

IF it_output[] IS INITIAL.
MESSAGE 'User(s) are not logged into the system' TYPE 'I'.
LEAVE LIST-PROCESSING.
ENDIF.

ELSEIF r_tcd IS NOT INITIAL.
IF s_tcode IS NOT INITIAL.
DELETE it_output[] WHERE tcode NOT IN s_tcode.
ENDIF.

IF it_output[] IS INITIAL.
MESSAGE 'No one is using the input T-Code(s)' TYPE 'I'.
LEAVE LIST-PROCESSING.
ENDIF.

ENDIF.

ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form DISPLAY_REPORT
*&---------------------------------------------------------------------*
* Display the output
*----------------------------------------------------------------------*
FORM display_report .

DATA:
lr_alv TYPE REF TO cl_salv_table,
lr_columns TYPE REF TO cl_salv_columns_table,
lr_column TYPE REF TO cl_salv_column,
lr_functions TYPE REF TO cl_salv_functions_list,
lr_display TYPE REF TO cl_salv_display_settings,
lr_layout TYPE REF TO cl_salv_layout,
ls_key TYPE salv_s_layout_key,
lr_sorts TYPE REF TO cl_salv_sorts.

" Check to make sure the internal table has data.
IF lines( it_output ) > 0.

* Get username
PERFORM get_user_name.

TRY.
* Create ALV instance
* Use CALL METHOD since this is a static method
CALL METHOD cl_salv_table=>factory
IMPORTING
r_salv_table = lr_alv
CHANGING
t_table = it_report.

* Get functions object and then set all the functions to be
* allowed
lr_functions = lr_alv->get_functions( ).
lr_functions->set_all( ).

lr_columns = lr_alv->get_columns( ).

CALL METHOD lr_columns->get_column
EXPORTING
columnname = 'LTIME'
RECEIVING
value = lr_column.

CALL METHOD lr_column->set_short_text
EXPORTING
value = ' '.

CALL METHOD lr_column->set_medium_text
EXPORTING
value = ' '.

CALL METHOD lr_column->set_long_text
EXPORTING
value = 'Start Time'.

CALL METHOD lr_columns->get_column
EXPORTING
columnname = 'SESSION'
RECEIVING
value = lr_column.

CALL METHOD lr_column->set_short_text
EXPORTING
value = 'Session'.

lr_columns->set_optimize( ).

* Set sort column
lr_sorts = lr_alv->get_sorts( ).
lr_sorts->clear( ).

* This code is to get the layout, save the layout
* and display the layout
lr_layout = lr_alv->get_layout( ).
ls_key-report = sy-repid.
lr_layout->set_key( ls_key ).
lr_layout->set_default( ' ' ).
lr_layout->set_save_restriction( cl_salv_layout=>restrict_none ).


lr_display = lr_alv->get_display_settings( ).
lr_display->set_striped_pattern( cl_salv_display_settings=>true ).

* Now display the report as an ALV grid
lr_alv->display( ).

CATCH cx_salv_msg.
WRITE: 'Error displaying grid CX_SALV_MSG!'.

CATCH cx_salv_not_found.
WRITE: 'Error displaying grid CX_SALV_NOT_FOUND!'.

CATCH cx_salv_data_error.
WRITE: 'Error displaying grid CX_SALV_DATA_ERROR!'.

CATCH cx_salv_existing.
WRITE: 'Error displaying grid CX_SALV_EXISTING!'.

ENDTRY.

ELSE.
MESSAGE 'No data to display' TYPE 'I'.
LEAVE LIST-PROCESSING.

ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_USER_NAME
*&---------------------------------------------------------------------*
* Get user name and format
*----------------------------------------------------------------------*
FORM get_user_name .

*--------------------------------------------------------------------*
* Prior to ABAP 7.4
* DATA:
* lwa_report type ty_report,
* lit_output TYPE STANDARD TABLE OF uinfo2,
* lit_username TYPE STANDARD TABLE OF v_username.
*
* lit_output[] = it_output[].
*
* SORT lit_output[] BY user.
* DELETE ADJACENT DUPLICATES FROM lit_output[] COMPARING user.
*
* SELECT * FROM v_username INTO TABLE lit_username[]
* FOR ALL ENTRIES IN lit_output
* WHERE bname = lit_output-user.
*
* IF lit_username[] IS NOT INITIAL.
*
* ENDIF.
*--------------------------------------------------------------------*
DATA: lwa_report TYPE ty_report.

* Making use of inline declaration and host variables ABAP 7.4
DATA(lit_output) = it_output[].

SORT lit_output[] BY user.
DELETE ADJACENT DUPLICATES FROM lit_output[] COMPARING user.

* Escape @
SELECT * FROM v_username INTO TABLE @DATA(lit_username)
FOR ALL ENTRIES IN @lit_output
WHERE bname = @lit_output-user.
* Sy-subrc check not needed
SORT lit_username[] BY bname.

LOOP AT it_output INTO DATA(lwa_output).
READ TABLE lit_username INTO DATA(lwa_username)
WITH KEY bname = lwa_output-user
BINARY SEARCH.
IF sy-subrc EQ 0.
lwa_report-name = lwa_username-name_text. " Full name
ENDIF.

MOVE-CORRESPONDING lwa_output TO lwa_report.
WRITE lwa_output-time TO lwa_report-ltime.
APPEND lwa_report TO it_report[].

CLEAR lwa_report.

ENDLOOP.

* Just sort
SORT it_report[] BY session.
ENDFORM.

Update on 09/11/2016

One of our reader ‘Bikas‘ shared that t-code “AL08” does exact the same thing what we tried with our code snippet. Thanks to Bikas for letting us know. For the reference of our readers, please find the screen print of t-code AL08.

sap abap interview questions

This is a perfect example of learning by sharing. No one can know everything in this world. But we can definitely share our knowledge and educate each other.

If you want to get such useful and practical articles directly to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons and like us on facebook.

If you have anything to say and share. Please write below at the comments section. Please, please share your thoughts. Please do not hold back.

Thank you very much for your time!!


Just 4 Versions of the same program to understand OOPs ABAP

$
0
0

We will modify an ABAP program 4 times today and make it an OOPs ABAP program at the 4th Version. Please stay until the end and I promise, you will learn how to program using Object Oriented Approach in ABAP.

I have been programming in ABAP for more than 10 years now but hardly have I designed an end to end development in OOPs ABAP. I have used classes (local/global), methods (static/instance), attributes etc but I cannot claim I am an OOPs ABAP developer. I am still the same old developer who is used to the procedural language. I have worked extensively in Web Dynpro ABAP, which has MVC as the core Architecture and I have followed the principle to the core. But 90 percent of the time I have used the wizard to generate my code in Web Dynpro. Experts suggest we should write those code ourselves. But Lazy ABAPers always use the wizard, after all, why is that magical wand(wizard) provided in the first place.

I understand the concept of OOPs and I do not want to re-iterate the Vehicle examples here. But even though I have not used OOPs extensively, down at the bottom of my heart I know that OOPs if written correctly is better and maintenance is simpler as opposed to the theory of procedural enthusiasts like me who believe OOPs is difficult to maintain. 🙂

We always give the excuse that the existing program is not in OOPs so we do not want to introduce OOPs while supporting existing object. The other famous excuse is, the deadline is so aggressive. So let me not venture into OOPs and do the way I know better. 🙂 . With this mind set, I was never able to learn OOPs. But, now I am trying to amend myself. I am trying to write the new developments in OOPs even though it might have flaws. It is never too late to learn. If I look back to the tons of codes which I have written in my initial days using procedural approach, I can point out numerous issues in those so called simple approach. So today, if there is a problem with my OOPs approach, it would just be a learning curve. Tomorrow if I look back to these OOPs programming and I can point out the mistakes, then I should consider I have learned some OOPs then. For some reason, if I am not able to find fault in my OOPs then probably, I never ever programmed in OOPs.

Let me pull a real object from one of my project. We had a report to display all the Roles assigned to any Transaction code which Security Team and Business Team could execute to plan the authorization for different users. Check the program which displays classical report output and internal tables with header line were still the practice then when it was written.

Program Version 1.0

*----------------------------------------------------------------------*
* Author: www.sapyard.com
* Title: Security report - Roles assigned to
* Transaction Codes or vice versa.
*----------------------------------------------------------------------*
* Desc : Generates a report of relationships between Transaction
* Codes and Security Roles. It has options of switching the
* dimensions of the report - i.e. TCODE to ROLE or ROLE to
* TCODE
*----------------------------------------------------------------------*
* Old ABAPer's way of programming
*----------------------------------------------------------------------*

SELECTION-SCREEN BEGIN OF BLOCK repopt WITH FRAME TITLE text-001.
PARAMETERS: p_tcode TYPE tcode.
SELECTION-SCREEN END OF BLOCK repopt.

* Internal table with Header line
DATA: BEGIN OF t_tcode OCCURS 0,
tcode LIKE agr_1251-low,
ttext LIKE tstct-ttext,
role LIKE agr_1251-agr_name,
rtext LIKE agr_texts-text,
END OF t_tcode.

TOP-OF-PAGE.
FORMAT COLOR COL_HEADING.

WRITE: / 'Old ABAPer', 60 'Transaction Code to Role Matrix',
136 'Date:', sy-datum.
WRITE: /136 'Page:', (10) sy-pagno NO-SIGN.
ULINE.
WRITE: /(20) 'Txn Code', (36) 'Txn Desc',
60(30)'Role Name', (61) 'Role Desc'.
ULINE.

FORMAT COLOR OFF.
START-OF-SELECTION.

PERFORM report_by_tcode.

*&---------------------------------------------------------------------*
*& Form report_by_tcode
*&---------------------------------------------------------------------*
* Generate report of Roles assigned to TCODEs
*----------------------------------------------------------------------*
FORM report_by_tcode.
SELECT a~low b~ttext a~agr_name c~text INTO TABLE t_tcode
FROM agr_1251 AS a
INNER JOIN tstct AS b ON a~low = b~tcode
INNER JOIN agr_texts AS c ON a~agr_name = c~agr_name
WHERE a~low = p_tcode
AND a~object = 'S_TCODE'
AND b~sprsl = sy-langu
AND c~spras = sy-langu
AND c~line = '00000'
ORDER BY a~low a~agr_name.

LOOP AT t_tcode.
* Table name and Header line name is same
WRITE: /(20) t_tcode-tcode, t_tcode-ttext, 60 t_tcode-role, (61) t_tcode-rtext.
ENDLOOP.
ENDFORM. " report_by_tcode

Highlights of the above program which is no more used.

ABAP Technical

Let us test this program.

ABAP Objects

Classical Output Report

OOPs ABAP

If you have some time, please go through this beautiful (a little long) and eye opener article on SCN. Crossing the Great Divide – Procedural vs OO ABAP Programming

Now let us check the same program which was written by a programmer who is acquainted with REUSE_ALV_GRID_DISPLAY and who does not declare the internal table with HEADER LINE.

Program Version 2.0

*----------------------------------------------------------------------*
* Relatively New ABAPer's way of programming
*----------------------------------------------------------------------*

*----------------------------------------------------------------------*
* TYPE Declaration
*----------------------------------------------------------------------*
TYPES: BEGIN OF ty_tcode,
tcode TYPE agval, " Transaction
ttext TYPE ttext_stct, " Transaction Text
role TYPE agr_name, " Role Name
rtext TYPE agr_title, " Short Description
END OF ty_tcode.
*----------------------------------------------------------------------*
* DATA Declaration
*----------------------------------------------------------------------*
DATA:
gt_tcode TYPE STANDARD TABLE OF ty_tcode,
gs_layout TYPE slis_layout_alv, " Declaration of field
gt_fcat TYPE slis_t_fieldcat_alv, " Declaration of Field
gs_fcat TYPE slis_fieldcat_alv. " Declaration of field
*----------------------------------------------------------------------*
* SELECTION SCREEN
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK repopt WITH FRAME TITLE text-001.
PARAMETERS: p_tcode TYPE tcode.
SELECTION-SCREEN END OF BLOCK repopt.

*----------------------------------------------------------------------*
* AT SELECTION-SCREEN.
*----------------------------------------------------------------------*
AT SELECTION-SCREEN.
PERFORM validate_input.

*----------------------------------------------------------------------*
* START-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.

PERFORM report_by_tcode.

*----------------------------------------------------------------------*
* END-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.

PERFORM display_report.

*----------------------------------------------------------------------*
* SUB ROUTINES
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form VALIDATE_INPUT
*&---------------------------------------------------------------------*
* Validate Selection Input
*----------------------------------------------------------------------*
FORM validate_input.
SELECT COUNT(*) UP TO 1 ROWS
FROM tstc
WHERE tcode = p_tcode.
IF sy-subrc NE 0.
MESSAGE 'Please enter a Valid T-Code' TYPE 'I'.
LEAVE LIST-PROCESSING.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form report_by_tcode
*&---------------------------------------------------------------------*
* Generate report of Roles assigned to TCODEs
*----------------------------------------------------------------------*
FORM report_by_tcode.
SELECT a~low b~ttext a~agr_name c~text INTO TABLE gt_tcode
FROM agr_1251 AS a
INNER JOIN tstct AS b ON a~low = b~tcode
INNER JOIN agr_texts AS c ON a~agr_name = c~agr_name
WHERE a~low = p_tcode
AND a~object = 'S_TCODE'
AND b~sprsl = sy-langu
AND c~spras = sy-langu
AND c~line = '00000'
ORDER BY a~low a~agr_name.

ENDFORM. " report_by_tcode

*&---------------------------------------------------------------------*
*& Form DISPLAY_REPORT
*&---------------------------------------------------------------------*
* Display Report
*----------------------------------------------------------------------*
FORM display_report .
* Filling field catalog.
PERFORM prepare_fields_description.
* Setting the ALV layout
PERFORM build_layout.
* Display ALV Report
PERFORM display_alv_report.
ENDFORM.

*&---------------------------------------------------------------------*
*& Form PREPARE_FIELDS_DESCRIPTION
*&---------------------------------------------------------------------*
FORM prepare_fields_description .
CLEAR gs_fcat.
gs_fcat-fieldname = 'TCODE'.
gs_fcat-seltext_m = 'Txn Code'.
gs_fcat-col_pos = 1.
APPEND gs_fcat TO gt_fcat.

CLEAR gs_fcat.
gs_fcat-fieldname = 'TTEXT'.
gs_fcat-seltext_m = 'Txn Desc'.
gs_fcat-col_pos = 2.
APPEND gs_fcat TO gt_fcat.

CLEAR gs_fcat.
gs_fcat-fieldname = 'ROLE'.
gs_fcat-seltext_m = 'Role Name'.
gs_fcat-col_pos = 3.
APPEND gs_fcat TO gt_fcat.

CLEAR gs_fcat.
gs_fcat-fieldname = 'RTEXT'.
gs_fcat-seltext_m = 'Role Desc'.
gs_fcat-col_pos = 4.
APPEND gs_fcat TO gt_fcat.

ENDFORM. " PREPARE_FIELDS_DESCRIPTION

*&---------------------------------------------------------------------*
*& Form build_layout
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM build_layout .
gs_layout-no_input = 'X'.
gs_layout-colwidth_optimize = 'X'.
gs_layout-zebra = 'X'.
ENDFORM. " BUILD_LAYOUT

*&---------------------------------------------------------------------*
*& Form DISPLAY_ALV_REPORT
*&---------------------------------------------------------------------*
* Display report using ALV grid
*----------------------------------------------------------------------*
FORM display_alv_report.

IF gt_tcode[] IS NOT INITIAL.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_buffer_active = space
i_callback_program = sy-repid
is_layout = gs_layout
it_fieldcat = gt_fcat[]
TABLES
t_outtab = gt_tcode
EXCEPTIONS
program_error = 1
OTHERS = 2.

ENDIF.

ENDFORM. " DISPLAY_ALV_REPORT

Check the output has changed from classical to ALV.

Object Oriented Programming in SAP ABAP

Now, let us check how most of the old-schooled ABAPers try their OOPs programming when they are forced to adopt OOPs. I know some projects where OOPs is the only standard of programming. In such projects, the not so OOPs enthusiast replace PERFORMs by METHODs without really taking the advantage of Object Oriented Architecture. Check how we can really kill the beauty of OOPs below. And I am one of them. 🙂

Also Read: Web Dynpro ABAP Tutorials

Program Version 3.0

*----------------------------------------------------------------------*
* ABAPer who is trying to write his/her first OOPs development
*----------------------------------------------------------------------*

*----------------------------------------------------------------------*
* CLASS-DEFINITIONs and IMPLEMENTATIONs
*----------------------------------------------------------------------*
CLASS lcl_validate_input DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: validate_input.
ENDCLASS.

CLASS lcl_validate_input IMPLEMENTATION.
METHOD validate_input.
PERFORM validate_input.
ENDMETHOD.
ENDCLASS.

CLASS lcl_fetch_data DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: fetch_data.
ENDCLASS.

CLASS lcl_fetch_data IMPLEMENTATION.
METHOD fetch_data.
PERFORM report_by_tcode.
ENDMETHOD.

ENDCLASS.

CLASS lcl_display_report DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: display_data.
ENDCLASS.

CLASS lcl_display_report IMPLEMENTATION.
METHOD display_data.
PERFORM display_report.
ENDMETHOD.

ENDCLASS.

*----------------------------------------------------------------------*
* TYPE Declaration
*----------------------------------------------------------------------*
TYPES: BEGIN OF ty_tcode,
tcode TYPE agval, " Transaction
ttext TYPE ttext_stct, " Transaction Text
role TYPE agr_name, " Role Name
rtext TYPE agr_title, " Short Description
END OF ty_tcode.
*----------------------------------------------------------------------*
* DATA Declaration
*----------------------------------------------------------------------*
DATA:
gt_tcode TYPE STANDARD TABLE OF ty_tcode,
gs_layout TYPE slis_layout_alv, " Declaration of field
gt_fcat TYPE slis_t_fieldcat_alv, " Declaration of Field
gs_fcat TYPE slis_fieldcat_alv. " Declaration of field

* Define the Object Data
DATA:
o_validate TYPE REF TO lcl_validate_input,
o_fetch TYPE REF TO lcl_fetch_data,
o_display TYPE REF TO lcl_display_report.
*----------------------------------------------------------------------*
* SELECTION SCREEN
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK repopt WITH FRAME TITLE text-001.
PARAMETERS: p_tcode TYPE tcode.
SELECTION-SCREEN END OF BLOCK repopt.

*---------------------------------------------------------------------*
* INITIALIZATION *
*---------------------------------------------------------------------*
INITIALIZATION.
CREATE OBJECT: o_validate, o_fetch, o_display.
*----------------------------------------------------------------------*
* AT SELECTION-SCREEN.
*----------------------------------------------------------------------*
AT SELECTION-SCREEN.
o_validate->validate_input( ).

*----------------------------------------------------------------------*
* START-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.
o_fetch->fetch_data( ).

*----------------------------------------------------------------------*
* END-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.
o_display->display_data( ).

*----------------------------------------------------------------------*
* SUB ROUTINES
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form VALIDATE_INPUT
*&---------------------------------------------------------------------*
* Validate Selection Input
*----------------------------------------------------------------------*
FORM validate_input.
SELECT COUNT(*) UP TO 1 ROWS
FROM tstc
WHERE tcode = p_tcode.
IF sy-subrc NE 0.
MESSAGE 'Please enter a Valid T-Code' TYPE 'I'.
LEAVE LIST-PROCESSING.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form report_by_tcode
*&---------------------------------------------------------------------*
* Generate report of Roles assigned to TCODEs
*----------------------------------------------------------------------*
FORM report_by_tcode.
SELECT a~low b~ttext a~agr_name c~text INTO TABLE gt_tcode
FROM agr_1251 AS a
INNER JOIN tstct AS b ON a~low = b~tcode
INNER JOIN agr_texts AS c ON a~agr_name = c~agr_name
WHERE a~low = p_tcode
AND a~object = 'S_TCODE'
AND b~sprsl = sy-langu
AND c~spras = sy-langu
AND c~line = '00000'
ORDER BY a~low a~agr_name.

ENDFORM. " report_by_tcode

*&---------------------------------------------------------------------*
*& Form DISPLAY_REPORT
*&---------------------------------------------------------------------*
* Display Report
*----------------------------------------------------------------------*
FORM display_report .
* Filling field catalog.
PERFORM prepare_fields_description.
* Setting the ALV layout
PERFORM build_layout.
* Display ALV Report
PERFORM display_alv_report.
ENDFORM.

*&---------------------------------------------------------------------*
*& Form PREPARE_FIELDS_DESCRIPTION
*&---------------------------------------------------------------------*
FORM prepare_fields_description .
CLEAR gs_fcat.
gs_fcat-fieldname = 'TCODE'.
gs_fcat-seltext_m = 'Txn Code'.
gs_fcat-col_pos = 1.
APPEND gs_fcat TO gt_fcat.

CLEAR gs_fcat.
gs_fcat-fieldname = 'TTEXT'.
gs_fcat-seltext_m = 'Txn Desc'.
gs_fcat-col_pos = 2.
APPEND gs_fcat TO gt_fcat.

CLEAR gs_fcat.
gs_fcat-fieldname = 'ROLE'.
gs_fcat-seltext_m = 'Role Name'.
gs_fcat-col_pos = 3.
APPEND gs_fcat TO gt_fcat.

CLEAR gs_fcat.
gs_fcat-fieldname = 'RTEXT'.
gs_fcat-seltext_m = 'Role Desc'.
gs_fcat-col_pos = 4.
APPEND gs_fcat TO gt_fcat.

ENDFORM. " PREPARE_FIELDS_DESCRIPTION

*&---------------------------------------------------------------------*
*& Form build_layout
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM build_layout .
gs_layout-no_input = 'X'.
gs_layout-colwidth_optimize = 'X'.
gs_layout-zebra = 'X'.
ENDFORM. " BUILD_LAYOUT

*&---------------------------------------------------------------------*
*& Form DISPLAY_ALV_REPORT
*&---------------------------------------------------------------------*
* Display report using ALV grid
*----------------------------------------------------------------------*
FORM display_alv_report.

IF gt_tcode[] IS NOT INITIAL.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_buffer_active = space
i_callback_program = sy-repid
is_layout = gs_layout
it_fieldcat = gt_fcat[]
TABLES
t_outtab = gt_tcode
EXCEPTIONS
program_error = 1
OTHERS = 2.

ENDIF.

ENDFORM. " DISPLAY_ALV_REPORT

Now let us look at the obvious flaws.

Object Oriented Programming in ABAP

Even if you start OOPs programming the above way and you know about the mistakes while writing your second OOPs program, you are on the right path of OOPs. Knowing our own mistake is the first step in learning. The senior mentors and juniors who are expert in OOPs approach should be our guide and pathfinder. Asking for help in understanding the concept should never make us feel ashamed. And no question is too trivial even though you have 10 years of experience. Everyone is learning and it is never too late.

Interested in SAP ABAP for HANA? Browse our ABAP on SAP HANA Tutorials.

Let us check the better way of writing the same program in OOPs. There might be issues in this code as well, so I humbly request the experts to correct me and show the right way.

I have created three classes in SE24 to simulate the MVC. The selection screen parameters and validation are done in one class. The data retrieval is done in the second class. The report is displayed using the third class. Also, the objects from one class are leveraged in the next class and so on. This program might not show the real arsenal of OOPs but it should be sufficient to showcase what we intend. This is a real program in a real project in a real Client’s SAP system. 🙂 . It is not oversimplified for the demo. 😛

Check this OOPs program. Doesn’t it look clean?

Program Version 4.0

*----------------------------------------------------------------------*
* ABAPer who just wrote his first OOPs development nearly correct
*----------------------------------------------------------------------*

* Define the Object Data
DATA:
o_selection TYPE REF TO ycl_report_selection,
o_fetch TYPE REF TO ycl_report_fetch,
o_display TYPE REF TO ycl_report_display.

*----------------------------------------------------------------------*
* SELECTION SCREEN
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK repopt WITH FRAME TITLE text-001.
PARAMETERS: p_tcode TYPE tcode.
SELECTION-SCREEN END OF BLOCK repopt.

*---------------------------------------------------------------------*
* INITIALIZATION *
*---------------------------------------------------------------------*
INITIALIZATION.
CREATE OBJECT o_selection.
CREATE OBJECT o_fetch EXPORTING io_rep_sel = o_selection.
CREATE OBJECT o_display EXPORTING io_rep_fetch = o_fetch.
*----------------------------------------------------------------------*
* AT SELECTION-SCREEN.
*----------------------------------------------------------------------*
AT SELECTION-SCREEN.
* Validation at Selection Screen
o_selection->validate_input( p_tcode ).

*----------------------------------------------------------------------*
* START-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.
o_fetch->fetch_data( ).

*----------------------------------------------------------------------*
* END-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.
o_display->display_alv( ).

Details of the classes used above in the program.

1. Class: YCL_REPORT_SELECTION
ABAP Object Concept

class YCL_REPORT_SELECTION definition
public
final
create public .

public section.

data G_TCODE type TCODE .
data G_LANGU type SPRAS .
data G_OBJECT type AGOBJECT .
data G_LINE type MENU_NUM_5 .

methods VALIDATE_INPUT
importing
!IP_TCODE type TCODE .
protected section.
private section.

types:
*----------------------------------------------------------------------*
* TYPE Declaration
*----------------------------------------------------------------------*
BEGIN OF ty_tcode,
tcode TYPE agval, " Transaction
ttext TYPE ttext_stct, " Transaction Text
role TYPE agr_name, " Role Name
rtext TYPE agr_title, " Short Description
END OF ty_tcode .
types:
tt_tcode TYPE STANDARD TABLE OF ty_tcode .
ENDCLASS.

CLASS YCL_REPORT_SELECTION IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method YCL_REPORT_SELECTION->VALIDATE_INPUT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IP_TCODE TYPE TCODE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD validate_input.
SELECT COUNT(*) UP TO 1 ROWS
FROM tstc
WHERE tcode = ip_tcode.
IF sy-subrc NE 0.
MESSAGE 'Please enter a Valid T-Code' TYPE 'E'.
ELSE.
* Populate the global variable
g_tcode = ip_tcode.
g_langu = sy-langu.
g_object = 'S_TCODE'.
g_line = '00000'.
ENDIF.
ENDMETHOD.
ENDCLASS.

2. Class YCL_REPORT_FETCH

OOPs programming in ABAP

class YCL_REPORT_FETCH definition
public
final
create public .

public section.

types:
*----------------------------------------------------------------------*
* TYPE Declaration
*----------------------------------------------------------------------*
BEGIN OF ty_tcode,
tcode TYPE agval, " Transaction
ttext TYPE ttext_stct, " Transaction Text
role TYPE agr_name, " Role Name
rtext TYPE agr_title, " Short Description
END OF ty_tcode .
types:
tt_tcode TYPE STANDARD TABLE OF ty_tcode .

data O_REP_SEL type ref to YCL_REPORT_SELECTION .
data T_TCODE type TT_TCODE .

methods FETCH_DATA .
methods CONSTRUCTOR
importing
!IO_REP_SEL type ref to YCL_REPORT_SELECTION .
protected section.
private section.
ENDCLASS.

CLASS YCL_REPORT_FETCH IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method YCL_REPORT_FETCH->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_REP_SEL TYPE REF TO YCL_REPORT_SELECTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD constructor.
me->o_rep_sel = io_rep_sel.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method YCL_REPORT_FETCH->FETCH_DATA
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD fetch_data.
SELECT a~low b~ttext a~agr_name c~text INTO TABLE t_tcode
FROM agr_1251 AS a
INNER JOIN tstct AS b ON a~low = b~tcode
INNER JOIN agr_texts AS c ON a~agr_name = c~agr_name
WHERE a~low = me->o_rep_sel->g_tcode
AND a~object = me->o_rep_sel->g_object
AND b~sprsl = me->o_rep_sel->g_langu
AND c~spras = me->o_rep_sel->g_langu
AND c~line = me->o_rep_sel->g_line
ORDER BY a~low a~agr_name.

ENDMETHOD.
ENDCLASS.

3. Class YCL_REPORT_DISPLAY

Introduction to OOPs ABAP

class YCL_REPORT_DISPLAY definition
public
final
create public .

public section.

data O_REP_FET type ref to YCL_REPORT_FETCH .

methods DISPLAY_ALV .
methods CONSTRUCTOR
importing
!IO_REP_FETCH type ref to YCL_REPORT_FETCH .
protected section.
private section.
ENDCLASS.

CLASS YCL_REPORT_DISPLAY IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method YCL_REPORT_DISPLAY->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_REP_FETCH TYPE REF TO YCL_REPORT_FETCH
* +--------------------------------------------------------------------------------------</SIGNATURE>
method CONSTRUCTOR.
me->o_rep_fet = io_rep_fetch.

endmethod.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method YCL_REPORT_DISPLAY->DISPLAY_ALV
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD display_alv.
cl_demo_output=>display_data( EXPORTING
value = me->o_rep_fet->t_tcode
name = 'My First Real OOPs ABAP Development' ).
ENDMETHOD.
ENDCLASS.

The output is the same. 🙂

Constructor in OOPs

Did you check our popular post? Lazy and Smart ABAPers.

Exercise: 

Put breakpoints on the CONSTRUCTOR methods of classes YCL_REPORT_FETCH and YCL_REPORT_DISPLAY and also at the INITIALIZATION of the report. Run your report.

What do you see?

As expected, the CONSTRUCTOR method of the classes would be called at the INITIALIZATION event of the report. Check, how the object data is passed from one class to another in this report and used in other methods (FETCH_DATA and DISPLAY_ALV).

If you want to know the difference between STATIC and INSTANCE method or have fun with CONSTRUCTOR. Read : ABAP Objects Tips

If I start OOPs today, I might be able to grasp the real concept and appreciated its actual power and usage in a couple of years. Till then let me learn from my mistakes.

Hope this post would act as a launching pad to all those ABAPers who were looking for a starting point to begin their OOPs journey. If you are still in a dilemma as of how to start programming in OOPs ABAP, my suggestion is, just pick any existing report from your system and try to convert it to OOPs. Ask your team member or ask SAP mentors or leave your doubts in SCN. Experts would definitely guide you or at least take you to the right link where you can learn further.

If you have any examples of vanilla ABAP program and the new OOPs program for the same, please do share it with us. We would be happy to append it to this post so that it might act as a reference to all those ABAPers who might visit this page by mistake or knowingly. 🙂

Let us try to change our flavor and force ourselves to love the new taste of Object Oriented Programming in ABAP.

If you want to get such useful articles directly to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons and like us on facebook.

Do you have anything to add to this article? Have you faced any issue using OOPs? Do you want to share any real project requirement or solutions? Please do not hold back. Please leave your thoughts in the comment section.

Thank you very much for your time!!

SAP ABAP Tips

$
0
0

Please find some uncommon SAP Technical requirements and tips. One would face these issue only in some very rare Project scenarios. Hope you will have fun below.

A) Changing description of SAP standard Data Element

Did you know that we can change the description of standard fields? I am sure many of us did not know this fact. If you want to change the label/field description for any SAP table field, then you can use the following method.

Let us check how the description of standard data element ‘FSH_MG_ATTRIBUTE3′ of table MARA is changed.

SAP ABAP

1. Go to transaction code: CMOD.

2. Goto-Text Enhancement->Key words->Change

SAP Data Dictionary
3. Enter the Data Element

SAP Tricks4. Change the Description text.

SAP Tips5. Save in the transport (or local for test).
6. Goto SE11, check the changed description.

SAP ABAP

Did you know this trick? 🙂

Also Read: ‘How to enable table entries maintenance in SE16N ‘.

B) RF Gun ‘BEEP’ Sound

If requirement comes to you that business needs a beep sound in RF console when it scans a bar code this is what you should do.

Step 1: Stop laughing .. 🙂
Step 2: Follow SAP note 371838

For freshers, RF = Radio Frequency. Usually a small hand held device enabled with RFID is common in warehouse and plants. You can compare it with a scanning/bar code reading machine.

C) Daylight Saving Setting in SAP

Often we need to convert the system time to local time of the plant and if the local time of the plant observes daylight then sometimes the result is X hour off. X may be 1, 2, 3 etc depending upon the location. This problem occurs due to time difference of daylight saving. If you are facing this problem (like me) then please check your DST system using transaction STZBC.

First check whether Daylight rule is active or not.

Day light saving in SAP

Check the rule (Variable summer time rule).

dl12

Check the rule (Fixed summer time rule),

DL13For freshers, wiki says, Daylight saving time (DST) or summer time is the practice of advancing clocks during summer months by one hour so that in the evening daylight is experienced an hour longer, while sacrificing normal sunrise times.

[adToAppearHere]

D) Find the Type of Transaction in exit (whether it is Create, Change, Display etc)

For Purchasing transaction exits, you may use table entries like T160 or T180 to find the nature of transaction.
Field – TRTYP (Transaction type)

E) Checking log for table changes

SCU3 – Use this transaction if log is activated for that table. If you are unable to see the log, try debugging and by passing the authority check.

Include – RSVTPF01, FORM CHECK_AUTHORITY

SELECT SINGLE * FROM tddat INTO w_tddat

By-pass this error or maintain your entry in TDDAT or View V_DDAT_54
Please check SAP note 323636 for more info.

F) Issue while creating EH spot

If you are facing problem while creating implicit enhancements; getting error like: UNCAUGHT_EXCEPTION CX_SY_MESSAGE_ILLEGAL_TEXT then you may need to apply the following SAP notes: 1034360, 1098603, 1087299

For Authorization of SE20 transaction you may need SAP note 987152.

G) Mechanism of FOR ALL ENTRIES SELECT

SAP first fetches all the record for the selected fields and then it SORT the records found and then it does a DELETE ADJACENT DUPLICATES COMPARING ALL FIELDS. So, if you want to retrieve all the records, you MUST select all the KEY fields or else you will lose some records.

Also Read: Curious case of FAE (For All Entries)

H) Issue with Pop up display

SAP is full of surprises. The other day, when I was trying to test a program, I saw the messages were not coming properly. Instead of showing the full message, it truncated with a cross icon.

Pop up issue

Finally, I was able to trace the source of the problem. The problem lies in the SAP FM POPUP_WITH_TABLE_DISPLAY_OK. I have used this function module numerous times in past and but this time, I realized there is a “IF” condition in the source code of this FM at MODULE LISTPROCESSING OUTPUT .

LOOP AT LISTTAB.
IF LISTTAB+15(1) = 'S' OR LISTTAB+15(1) = 'F'.
IF LISTTAB+15(1) = 'S'.
WRITE: / LISTTAB+0(15), ICON_OKAY AS ICON.
ELSEIF LISTTAB+15(1) = 'F'.
WRITE: / LISTTAB+0(15), ICON_CANCEL AS ICON.
ENDIF.
ELSE.
WRITE: / LISTTAB.
ENDIF.
ENDLOOP.

So, if the 16th character of your message is either S or F, then your message will be truncated. If you are facing this problem now you the reason. You can solve this issue in your own way.

[My solution – simply convert the 16th character to lower case if it F or S.]

If you want to get such practical tweaks and tricks straight to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons at the left side of your screen. Please like us at facebook and encourage us.

Thank you very much for your time!!

 

Image source: www.efficientlifeskills.com

SAP HANA Tips

$
0
0

In our other post ‘ SAP ABAP Tips‘, we shared some uncommon but very useful tips on ABAP. In this post, I would like to share similar useful tips in regards to SAP HANA.

i) Parameter to limit the CPU usage for a thread in SAP HANA

There is a parameter that can be used to limit the amount of CPU, a thread can take in SAP HANA.

indexserver.ini -> parallel = numes_cores

ii) How to find the size of the HANA DB?
We have two aspects here:
a. Column store
b. Row store

a. To find column store utilization:

SELECT round (sum(MEMORY_SIZE_IN_TOTAL)/1024/1024) AS "Column Tables MB" FROM M_CS_TABLES;

b. To find row store utilization:

SELECT round (sum(USED_FIXED_PART_SIZE + USED_VARIABLE_PART_SIZE)/1024/1024) 
AS "Row Tables MB" FROM M_RS_TABLES

iii) Migrating tables to specified nodes in SAP HANA multi-node system

If you want to migrate a particular table from one node of HANA to another for performance or space issue:

a. To view current location of table

Open SQL editor on HANA studio and run the sql query:

select * from "SYS"."M_TABLE_LOCATIONS" order by LOCATION, table_name

b. To view current location decide the node where you want to move it and run the below query on SQL editor of HANA studio:

ALTER TABLE MOVE TO ‘node:port number’

Also Read: ‘Smart Data Integrator & Data Load In SAP HANA’

iv) Delivery Classes for tables (Not specific to HANA)

While doing some migrations (BW on HANA ) I felt that we as technical consultant need to have a better understanding of delivery classes. I felt that we need to recap the concept. I am intending to have a small listing of the same. For each database table, a delivery class has to be specified. The delivery class determines the handling of the entries for a specific table during
Transports
Client Copies
– Installation & Upgrades

SE11 Delivery Classes for tables:

Delivery Class in SAP TABLE2 Delivery Classes

Delivery Classes for tables:

SE11

Examples:

CCommon Address Data (Country: T005)
EMessages (T100)
GCommunication: country dialling code (T005K)
LLock Arguments (E070USE)
SLanguage Key (T002)
APersonal Address Data, Username (USR01)
WTransport (E070), Tables (DD02L)

Delivery Classes – Client Copy & Client Transport:

Is Delivery Class copied?

Delivery Classes – Transport SAP -> Customer

Delivery Class

Delivery Classes – Transport Customer -> Customer

Client dependent tables

For more details, please refer SAP Note: 2857

If you want to get such practical tweaks and tricks straight to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the Share buttons. Please like us at facebook and encourage us.

Thank you very much for your time!!

Series on SAP HANA

1. SAP HANA from Space Level

2. SAP HANA at Ground Zero

3. View the HANA Views from different angles

4. ‘ABAP for SAP HANA’ Points to remember

5. SAP HANA ; S/4 HANA and S/4 HANA Finance in Nutshell

6. Smart Data Integrator & Data Load In SAP HANA

to be updated..

 

Image source: rahulurs.com(modified)

How to upload the PDF format directly into Adobe form layout

$
0
0

Contributed by: Ram Daruru, Cibersites India Pvt Ltd., Bengaluru, India

This tutorial demonstrates how to upload the PDF format directly into Adobe form layout. This will reduce the effort to draw the lines, boxes, tables etc. In short, it would help the developers design the layout better and faster.

Without much ado, let us jump to the steps.

Go to transaction SFP:  I remember SFP as SmartFormPDF 🙂

Select the Interface Radio button, give the name of the Interface, for example, ZRJ_INTERFACE

SFP

Press on Create, enter the short description.

Import Adobe Layout
Save and Activate. Press Back Button.

Select the Form Radio button, give the Form name, for example, ZRJ_PDFLAYOUT_UPLOAD

SAP Adobe

Press on Create Button. Enter the short description and Interface name which we created earlier.

Interface in SAP Adobe

Adobe in SAP

Select Layout Tab. Tools->Import

SAP ABAP

You might also like to check ‘How I used SAP Adobe Form as my personal PDF editor’

Note: The Original PDF which would be used as template looks like below. Imagine the amount of effort it would take for a developer to design this if the template is not readily available for import.

SAP HANA

Select the PDF file which you wanted to import.

SAPUI5

Hit Ok.

SAP Fiori

The entire PDF layout will get imported into SAP and would look like below. Now you can easily add, remove and change the boxes. The skeleton is ready to start the work.

ABAP on HANA

Summary: The above steps might look self-explanatory. But for someone who is exploring Adobe forms in SAP for the first time, this tutorial might be a ready reference. By following the above steps, they would avoid wasting their time by manually designing the layout and utilize their time better in applying the business logic and providing an error-proof and better solution.

If you want to get such useful articles directly to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons and like us on facebook.

Do you have anything to add to this article? Have you faced any issue using Adobe Forms? Do you want to share any real project requirement or solutions? Please do not hold back. Please leave your thoughts in the comment section.

Thank you very much for your time!!

Useful Tutorials in SAPYard

1. ABAP for SAP HANA Tutorials
2. ABAP Web Dynpro Tutorials
3. GOS Tutorial
4. OOPs ABAP Tutorial
5. HANA Tutorial

 

About the author: Ram Daruru
Ram is a senior SAP Technical Consultant. He has more than 6 years of experience in SAP ABAP. He is also trained in SAP PI. Ram provides training in the area of SAP ABAP in various institutes in Bangalore and also takes Online sessions.

In his leisure, Ram likes to play billiards, play and follow cricket. He is also a vivid reader.

Find more about Ram Daruru at LinkedIn.

 

Real Time Exchange Rate with Real Time Data Using Yahoo Finance API

$
0
0

Contributed by: Kuldeep Joshi, DB Corp Ltd., Jaipur, India

In the earlier posts Google Map API in SAP and GPS like tool in SAP we saw how we can leverage the Google Map APIs and consume them in SAP. In this post, we extend the usage of similar APIs to track the exchange rate real time. By the real time we mean, it would be refreshed automatically at a fixed interval of time which we set and it would show the actual rate at that fraction of the time. Why always Google, this time we would use Yahoo’s API. 🙂

Yahoo Finance API: http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote

This, Yahoo’s Finance API has the below structure.

Yahoo and SAP

We need to consume it in SAP to display the exchange rate real time and also refresh it automatically without the need to hit the REFRESH button on the screen. Won’t it be cool, if you are in a Finance Organization and you project the exchange rate or stock value on a huge wall from SAP and it gets refreshed real time for every passerby to view?

Let us see what our Application can do.

Provide the time interval at which you want the results to be refreshed.

Yahoo API

The output is displayed for a particular time.

ALV Display

Now, it is refreshed automatically. The message shows the time at which the data was refreshed.

refresh_table_display

Please note, there is no refresh button on the screen. Our Application handles the refresh.

There is no rocket science. Class Method CL_GUI_ALV_GRID->REFRESH_TABLE_DISPLAY is doing our job. 🙂

A special mention of the Class/Interface CL_GUI_TIMER and Event FINISHED is also needed.

Check the METHOD TIMER_EVENT in the Class CL_AUTO in the code.

METHODS :display_report,
* Define event handling method for event FINISHED of class CL_GUI_TIMER.
timer_event FOR EVENT finished OF cl_gui_timer.

Conceptually, what is happening?

Event FINISHED of class CL_GUI_TIMER is raised after the Timer has waited for the Interval provided in the selection screen. A listener method for FINISHED event is created and the REFRESH logic is implemented.

Another important step is to call the RUN method of CL_GUI_TIMER after the REFRESH to activate the time again.

METHOD timer_event .

DATA: lv_time TYPE char10.

* Get Data
me->get_data( ) .

IF me->ob_grid IS INITIAL .

CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = ob_grid.
ELSE.

* Refresh the ALV
CALL METHOD ob_grid->refresh_table_display.

ENDIF.

WRITE sy-uzeit TO lv_time USING EDIT MASK '__:__:__'.

CONCATENATE 'Screen refreshed at' lv_time INTO DATA(lv_msg) SEPARATED BY space.

MESSAGE lv_msg TYPE 'S' . " Get the cuuent timE as message

* Call RUN method of CL_GUI_TIMER again to activate timer
me->ob_timer->run( ) .

ENDMETHOD.

This article is an outcome of research done to find a way to track and trace the vehicle of service providers like Ola or Uber etc. The idea was to make use of the interface/program which we created earlier where we consumed Google Map APIs. But unfortunately, we could not figure out any free APIs which would return the exact position of the vehicles real time. But we ended up finding this API which returned real time stock and exchange rate. 😛

The steps to consume the API is exactly the same as our previous articles. Therefore, we have not described them again here. If you have confusion, please refer to our earlier articles or just put breakpoints in the code and start debugging. The logic is straightforward.

If you want to get such useful articles directly to your inbox, please SUBSCRIBE. We respect your privacy and take protecting it seriously.

If you liked this post, please hit the share buttons and like us on facebook.

Do you have anything to add to this article? Have you faced any issue using Adobe Forms? Do you want to share any real project requirement or solutions? Please do not hold back. Please leave your thoughts in the comment section.

Thank you very much for your time!!

About the author: Kuldeep Joshi

Kuldeep is an Electronics Engineer graduate. He has more than 7 years of experience in SAP with specialization in ABAP. He is an ex-IBMer who also has good working experience in SAP BI BPC.

Find more about him on LinkedIn.

We have defined a structure ‘ZAUTO_EXC’ for the below application. You might need this as well.

Exchange Rate in SAP

The complete working code snippet for this topic. Please replicate it in your SAP environment and have fun.

**---------------------------------------------------------------------*
** Date : 12/11/2016 *
** Author : Kuldeep Joshi (SAPYard) *
** Title : Auto Refresh the Screen Output *
**---------------------------------------------------------------------*
REPORT zsapyard MESSAGE-ID zma.

*&---------------------------------------------------------------------*
*& CLASS DEFINATION FOR ADDTING AUTO REFRESH
*&---------------------------------------------------------------------*
CLASS cl_auto DEFINITION .

PUBLIC SECTION .
*&---------------------------------------------------------------------*
*& TYPE-POOLS
*&---------------------------------------------------------------------*
TYPE-POOLS: truxs, slis.

DATA : ob_timer TYPE REF TO cl_gui_timer .

METHODS :display_report,
* Define event handling method for event FINISHED of class CL_GUI_TIMER.
timer_event FOR EVENT finished OF cl_gui_timer.
PRIVATE SECTION .

*&---------------------------------------------------------------------*
*& Types and Data
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_dest,
time_date TYPE zauto_exc-time_date,
ex_type TYPE zauto_exc-ex_type,
rate TYPE zauto_exc-rate,
time_stamp TYPE zauto_exc-time_stamp,
END OF ty_dest.

DATA: gt_dest TYPE STANDARD TABLE OF ty_dest.
DATA : ob_grid TYPE REF TO cl_gui_alv_grid . "DISPLAY DATA
DATA : gt_dest1 TYPE STANDARD TABLE OF ty_dest.

*&---------------------------------------------------------------------*
*& Methods
*&---------------------------------------------------------------------*
METHODS :
get_data,

create_http_client IMPORTING ip_url TYPE string
EXPORTING ex_http_client TYPE REF TO if_http_client,

http_client_request_get_method
IMPORTING ip_http_client TYPE REF TO if_http_client,

http_client_send IMPORTING ip_http_client TYPE REF TO if_http_client,

http_client_receive IMPORTING ip_http_client TYPE REF TO if_http_client
EXPORTING ex_content TYPE string,

get_data_ex IMPORTING ip_content TYPE string.

ENDCLASS.

CLASS cl_auto IMPLEMENTATION.

* Method 1
METHOD create_http_client.

* Get client from url
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = ip_url " 'http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote'.
IMPORTING
client = ex_http_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4.

ENDMETHOD.

* Method 2
METHOD http_client_request_get_method.
* Request and Get
ip_http_client->request->set_header_field( name = '~request_method' value = 'GET' ).
ENDMETHOD.

* Method 3
METHOD http_client_send.
* Send the request
ip_http_client->send( ).
ENDMETHOD.

* Method 4
METHOD http_client_receive.
* Reterive the result
CALL METHOD ip_http_client->receive
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4.
ex_content = ip_http_client->response->get_cdata( ).

ENDMETHOD.

* Method 5
METHOD get_data_ex.

* Local data declaration
DATA: lv_url TYPE c LENGTH 255,
ls_dest TYPE ty_dest,
moff TYPE syst-tabix,
moff1 TYPE syst-tabix,
lv_len TYPE syst-tabix,
lv_ex_type TYPE c LENGTH 20,
lv_rate TYPE c LENGTH 20,
lv_time_date TYPE c LENGTH 40.

*&---------------------------------------------------------------------*
*& Find exchange
*&---------------------------------------------------------------------*
DO .
* Find <location> text in the content string
FIND '<field name="name">' IN SECTION OFFSET moff OF ip_content IGNORING CASE MATCH OFFSET moff .

IF sy-subrc = 0 .

moff = moff + 19 .

FIND '</field>' IN SECTION OFFSET moff OF ip_content IGNORING CASE MATCH OFFSET moff1 .

lv_len = moff1 - moff .

lv_ex_type = ip_content+moff(lv_len) .

ls_dest-ex_type = lv_ex_type.
*--------------------------------------------------------------------*
* ---------------Find rate
*--------------------------------------------------------------------*
FIND '<field name="price">' IN SECTION OFFSET moff OF ip_content IGNORING CASE MATCH OFFSET moff .

IF sy-subrc = 0 .

moff = moff + 20 .

FIND '</field>' IN SECTION OFFSET moff OF ip_content IGNORING CASE MATCH OFFSET moff1 .

lv_len = moff1 - moff .

lv_rate = ip_content+moff(lv_len) .

ls_dest-rate = lv_rate.

ENDIF.

*==============================================================
* Find date and time stamp from api
*==============================================================

FIND '<field name="utctime">' IN SECTION OFFSET moff OF ip_content IGNORING CASE MATCH OFFSET moff .
IF sy-subrc = 0 .

moff = moff + 22 .
FIND '</field>' IN SECTION OFFSET moff OF ip_content IGNORING CASE MATCH OFFSET moff1 .
lv_len = moff1 - moff .
lv_time_date = ip_content+moff(lv_len) .
ls_dest-time_date = lv_time_date.

ENDIF.

* GET TIME form system for verfication .
ls_dest-time_stamp = sy-uzeit.

APPEND ls_dest TO gt_dest.

ELSE.

EXIT.

ENDIF.

ENDDO .

ENDMETHOD.

METHOD get_data .

CLEAR: gt_dest.

DATA: lv_http_client TYPE REF TO if_http_client,
lv_content TYPE string,
lv_url TYPE string.

* Prepare the url of the address
lv_url = 'http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote'.

create_http_client( EXPORTING ip_url = lv_url
IMPORTING ex_http_client = lv_http_client ).

http_client_request_get_method( EXPORTING ip_http_client = lv_http_client ).

http_client_send( EXPORTING ip_http_client = lv_http_client ).

http_client_receive( EXPORTING ip_http_client = lv_http_client
IMPORTING ex_content = lv_content ).

get_data_ex( EXPORTING ip_content = lv_content ).

* Updating data every time
CLEAR:gt_dest1.

me->gt_dest1 = gt_dest.

ENDMETHOD.

METHOD timer_event .

DATA: lv_time TYPE char10.

me->get_data( ) .

IF me->ob_grid IS INITIAL .

CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = ob_grid.
ELSE.

CALL METHOD ob_grid->refresh_table_display.

ENDIF.

WRITE sy-uzeit TO lv_time USING EDIT MASK '__:__:__'.

CONCATENATE 'Screen refreshed at' lv_time INTO DATA(lv_msg) SEPARATED BY space.

MESSAGE lv_msg TYPE 'S' . " Get the cuuent timE as message

* Call RUN method of CL_GUI_TIMER again to activate timer
me->ob_timer->run( ) .

ENDMETHOD.

METHOD display_report . " Only call for first display

me->get_data( ) .

CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
i_structure_name = 'ZAUTO_EXC'
TABLES
t_outtab = me->gt_dest1.
ENDMETHOD.

ENDCLASS.

*--------------------------------------------------------------------*
* Start of Selection
*--------------------------------------------------------------------*
DATA : ob_auto TYPE REF TO cl_auto,
ob_timer TYPE REF TO cl_gui_timer.

*--------------------------------------------------------------------*
* Selection Screen Parameters
*--------------------------------------------------------------------*
PARAMETERS : p_refres TYPE char01 AS CHECKBOX,
p_int TYPE i.

*--------------------------------------------------------------------*
* Start of Selection
*--------------------------------------------------------------------*
START-OF-SELECTION.

* Create main object
CREATE OBJECT ob_auto .

IF p_refres IS NOT INITIAL .

CREATE OBJECT ob_auto->ob_timer .
SET HANDLER ob_auto->timer_event FOR ob_auto->ob_timer .

* Set interval for timer
ob_auto->ob_timer->interval = p_int .

* Call method RUN of CL_GUI_TIMER.
ob_auto->ob_timer->run( ) .

ENDIF.

*--------------------------------------------------------------------*
* End of Selection
*--------------------------------------------------------------------*
END-OF-SELECTION.

* display dat first time
ob_auto->display_report( ) .

 

Viewing all 66 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>