Tuesday, March 31, 2009

Off Topic: Google Indic API plug-in for Firefox

Most of us who from time to time like to type in our native language find Google Indic Transliteration the best. But then you would have to keep that page open then do copy and paste into where you want to actually write. Sridhar has written a beautiful plug-in to use Google’s API in almost any web page. Well done! शबाश.

Download from here.

Here is an example on Google search page.

image

Off Topic: Indic Support in Firefox

A lot sites use proprietary Indic fonts on their websites e.g. Hindustan Dainik. It was a pain to view these if you were using Firefox browser, having to launch the site in IE. Now there is a plug-in that will allow conversion of proprietary fonts to public formats.

From their website

Padma is a technology for transforming Indic text between public and proprietary formats. The technology currently supports Telugu, Malayalam, Tamil, Devanagari (including Marathi), Gujarati, Bengali, and Gurmukhi.

Install from here.

Thursday, March 26, 2009

Get the components of an internal table dynamically

Sometimes you would want to go through the structure of an internal table in the program without know what the table is based on. Using RTTS (Run Time Type Services) one can find out the definition of any data. The following code will get the components of internal table ITAB. The object of referring class CL_ABAP_STRUCTDESCR will have internal table attribute COMPONENTS that contains all the fields.

DATA:
  l_o_tabledescr TYPE REF TO cl_abap_tabledescr,
  l_o_structdescr TYPE REF TO cl_abap_structdescr,
  l_s_abap_compdescr_tab TYPE abap_compdescr.
FIELD-SYMBOLS:
  <l_fs_field1> TYPE ANY.
l_o_tabledescr ?= cl_abap_tabledescr=>describe_by_data( p_data = itab ).
l_o_structdescr ?= l_o_tabledescr->get_table_line_type( ).
WHILE sy-subrc IS INITIAL.
  ASSIGN COMPONENT sy-index OF STRUCTURE itab TO <l_fs_field1>.
* Get field name
  READ TABLE l_o_structdescr->components INDEX sy-index INTO l_s_abap_compdescr_tab.
ENDWHILE.

Friday, March 20, 2009

Reuters data feed in CFM

In configuration Go to Accounting->CFM->Basic Functions->Market Data Management->Datafeed->Current Datafeed Settings

Monday, March 16, 2009

Consolas Font for ABAP editor

We end up spending a lot of time on the ABAP editor looking at code and the default SAP font is not that great to look at. Microsoft has introduced a new font for their visual studio environment called Consolas. This can be used in the SAP ABAP editor as well. Download and install from here.

Got to customising section of the editor

image

and choose font Consolas from the list of available fonts.

image

There, you should have a beatified look in the code.

Wednesday, March 11, 2009

होली है!

सबको होली की बोहुत बोहुत बधाई

Friday, March 06, 2009

Two ALV list in one with download option

The requirement was to create two fixed width files to be sent to a third party. The selection of data is pretty straight forward. I wanted to display the data sent in an ALV and wanted to do all this in one report.

For each output format and file structure I created one dictionary structure. For the fields I didn’t bother with data elements as the file output was to be of different lengths then the existing domains lengths. So I just went for the predefined ones.

Structure 1 = File 1

Structure 2 = File 2

The logic I was going to follow was:

  1. Select Data
  2. Download data
  3. Create Split Container
  4. Display ALV in each container

For doing all this I created a local class as I want to as much coding as possible in OO. The definition of class looks as like this:

CLASS lcl_report DEFINITION.
  PUBLIC SECTION.
    METHODS:
      extract,
      build_file_names,
      download,
      display.
    CLASS-METHODS:
      get_directory RETURNING value(r_dir) TYPE localfile.
  PRIVATE SECTION.
    CONSTANTS:
      c_container(15) VALUE 'C_CONTROL'.
    METHODS:
      create_split_control CHANGING ch_split_container TYPE REF TO cl_gui_easy_splitter_container,
      display_alv IMPORTING im_o_container TYPE REF TO cl_gui_container
                            im_heading     TYPE string
                  CHANGING  ch_t_out_tab   TYPE table,
      set_column_text IMPORTING im_alv       TYPE REF TO cl_salv_table
                                im_t_out_tab TYPE table.
    DATA:
      t_candidate TYPE TABLE OF zst_cand_out,
      t_centre TYPE TABLE OF zst_centre_out,
      centre_file TYPE string,
      cand_file TYPE string.
ENDCLASS.                    "lcl_report DEFINITION


In the selection option I provided a parameter to enter the directory to which the files will be downloaded. The F4 to display the directories on the local PC was implemented by the following code.



F4 event for the parameter



AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_dir.
  p_dir = lcl_report=>get_directory( ).

 



Static method that does the directory display dialog



  METHOD get_directory.
    DATA:
        l_t_file_table TYPE TABLE OF file_table,
        l_s_file_table TYPE file_table,
        l_subrc TYPE i,
        l_directory TYPE string.
*    CALL METHOD cl_gui_frontend_services=>file_open_dialog
*      CHANGING
*        file_table              = l_t_file_table
*        rc                      = l_subrc
*      EXCEPTIONS
*        file_open_dialog_failed = 1
*        cntl_error              = 2
*        error_no_gui            = 3
*        not_supported_by_gui    = 4
*        OTHERS                  = 5.
*    IF sy-subrc <> 0.
*      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
*                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
*    ENDIF.
    CALL METHOD cl_gui_frontend_services=>directory_browse
      CHANGING
        selected_folder      = l_directory
      EXCEPTIONS
        cntl_error           = 1
        error_no_gui         = 2
        not_supported_by_gui = 3
        OTHERS               = 4.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
*    READ TABLE l_t_file_table INTO l_s_file_table INDEX 1.
*    r_dir = l_s_file_table-filename.
    r_dir = l_directory.
  ENDMETHOD.                    "get_directory


So the report once executed will do the extract, download and display



START-OF-SELECTION.
  CREATE OBJECT o_report.
  o_report->build_file_names( ).
  o_report->extract( ).
END-OF-SELECTION.
  o_report->download( ).
  CALL SCREEN 0100.


The ALV is display in the screen 0100. Call to the method display( ) will display the output in PBO



MODULE status_0100 OUTPUT.
  SET PF-STATUS 'STATUS'.
  SET TITLEBAR 'TITLE'.
  o_report->display( ).
  CALL METHOD cl_gui_cfw=>flush.
ENDMODULE.                 " status_0100  OUTPUT


Within the display method we create the split screen and display the two alv’s



  METHOD display.
    DATA:
      l_o_split_container TYPE REF TO cl_gui_easy_splitter_container.
    create_split_control( CHANGING ch_split_container = l_o_split_container ).
* Display candidates
    display_alv( EXPORTING im_o_container = l_o_split_container->top_left_container
                           im_heading     = 'Candidates'
                 CHANGING  ch_t_out_tab   = t_candidate ).
* Display centre
    display_alv( EXPORTING im_o_container = l_o_split_container->bottom_right_container
                           im_heading     = 'Centres'
                 CHANGING  ch_t_out_tab   = t_centre ).
  ENDMETHOD.                    "display


The split ALV posed one problem for me which was giving the title to each of the containers. I posted this question on SDN and got response from Naimesh Patel. The class CL_SALV_DISPLAY_SETTINGS takes care of that. The code for displaying each ALV is modularised in the method display_alv( ). Since the structure I had created did not refer to any data elements the output was coming without any column heading. For this I created another method set_cloumn_text( ) that would read the DDIC structure and get the values from there and the set the column text. I got to use the ABAP runtime classes that give data type description in that method. This works both the structures I had



  METHOD display_alv.
    DATA:
      l_o_table   TYPE REF TO cl_salv_table.
* Get the ALV object refering to the output table
    TRY.
        cl_salv_table=>factory(
          EXPORTING
            r_container = im_o_container
          IMPORTING
            r_salv_table = l_o_table
          CHANGING
            t_table      = ch_t_out_tab ).
      CATCH cx_salv_msg.                                "#EC NO_HANDLER
    ENDTRY.
** Add basic default functionality in the ALV report
** Functions
*    DATA:
*      l_o_functions TYPE REF TO cl_salv_functions_list.
*
*    l_o_functions = l_o_table->get_functions( ).
*    l_o_functions->set_all( abap_true ).
* Column text
    set_column_text( im_alv = l_o_table im_t_out_tab = ch_t_out_tab ).
* Heading
    DATA:
      l_o_display TYPE REF TO cl_salv_display_settings,
      l_title TYPE lvc_title.
    l_title = im_heading.
    l_o_display = l_o_table->get_display_settings( ).
*   Title to ALV
    l_o_display->set_list_header( l_title ).
* Display the list
    l_o_table->display( ).
  ENDMETHOD.                    "display_alv


  METHOD set_column_text.
* Columns
    DATA:
      l_o_columns TYPE REF TO cl_salv_columns_table,
      l_o_column TYPE REF TO cl_salv_column.
    l_o_columns = im_alv->get_columns( ).
    l_o_columns->set_optimize( abap_true ).
    DATA:
      l_o_tabledescr TYPE REF TO cl_abap_tabledescr,
      l_o_structdescr TYPE REF TO cl_abap_structdescr,
      l_t_fields TYPE ddfields.
    FIELD-SYMBOLS:
      <l_field> TYPE LINE OF ddfields.
    l_o_tabledescr ?= cl_abap_typedescr=>describe_by_data( im_t_out_tab ).
    l_o_structdescr ?= l_o_tabledescr->get_table_line_type( ).
    CALL METHOD l_o_structdescr->get_ddic_field_list
*  EXPORTING
*    P_LANGU                  = SY-LANGU
*    P_INCLUDING_SUBSTRUCTRES = ABAP_FALSE
      RECEIVING
        p_field_list             = l_t_fields
    EXCEPTIONS
      not_found                = 1
      no_ddic_type             = 2
      OTHERS                   = 3
            .
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
    LOOP AT l_t_fields ASSIGNING <l_field>.
      TRY.
          CALL METHOD l_o_columns->get_column
            EXPORTING
              columnname = <l_field>-fieldname
            RECEIVING
              value      = l_o_column.
        CATCH cx_salv_not_found .
      ENDTRY.
      CALL METHOD l_o_column->set_short_text
        EXPORTING
          value = <l_field>-fieldtext(10).
      CALL METHOD l_o_column->set_medium_text
        EXPORTING
          value = <l_field>-fieldtext(20).
    ENDLOOP.
  ENDMETHOD.                    "set_column_text


The split is created using the class CL_GUI_EASY_SPLITTER_CONTAINER this is done in:



  METHOD create_split_control.
    DATA:
      l_o_container TYPE REF TO cl_gui_custom_container.
*      o_split_container TYPE REF TO cl_gui_easy_splitter_container.
    CREATE OBJECT l_o_container
      EXPORTING
*    PARENT                      =
        container_name              = c_container
*    STYLE                       =
*    LIFETIME                    = lifetime_default
*    REPID                       =
*    DYNNR                       =
*    NO_AUTODEF_PROGID_DYNNR     =
      EXCEPTIONS
        cntl_error                  = 1
        cntl_system_error           = 2
        create_error                = 3
        lifetime_error              = 4
        lifetime_dynpro_dynpro_link = 5
        OTHERS                      = 6
        .
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
    CREATE OBJECT ch_split_container
      EXPORTING
*    LINK_DYNNR        =
*    LINK_REPID        =
*    METRIC            = cntl_metric_dynpro
    parent            = l_o_container
*    ORIENTATION       = 0
*    SASH_POSITION     = 50
*    WITH_BORDER       = 1
*        name              = c_container
      EXCEPTIONS
        cntl_error        = 1
        cntl_system_error = 2
        OTHERS            = 3
        .
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
  ENDMETHOD.                    "create_split_control




The output will look something like this



image

Wednesday, March 04, 2009

Basic template for writing OO Report in ALV format

*&---------------------------------------------------------------------*
*& Report  ZRC_REP6
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT  zrc_rep6.
*----------------------------------------------------------------------*
*       CLASS lcl_report DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_report DEFINITION.
  PUBLIC SECTION.
    METHODS:
      extract,
      display.
  PRIVATE SECTION.
    DATA:
      t_mara TYPE TABLE OF mara.
ENDCLASS.                    "lcl_report DEFINITION
DATA:
  o_report TYPE REF TO lcl_report.
SELECTION-SCREEN BEGIN OF BLOCK file WITH FRAME TITLE text-001.
PARAMETERS:
  p_sub(2),
  p_year(4).
SELECTION-SCREEN end OF BLOCK file.
SELECTION-SCREEN BEGIN OF BLOCK options WITH FRAME TITLE text-002.
SELECT-OPTIONS:
  s_date FOR something.
SELECTION-SCREEN end OF BLOCK options.
START-OF-SELECTION.
  CREATE OBJECT o_report.
  o_report->extract( ).
END-OF-SELECTION.
  o_report->display( ).
*----------------------------------------------------------------------*
*       CLASS lcl_report IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_report IMPLEMENTATION.
  METHOD extract.
    SELECT * INTO TABLE t_mara
      FROM mara UP TO 5 ROWS.
  ENDMETHOD.                    "extract
  METHOD display.
    DATA:
      l_o_table   TYPE REF TO cl_salv_table.
* Get the ALV object refering to the output table
    TRY.
        cl_salv_table=>factory(
          IMPORTING
            r_salv_table = l_o_table
          CHANGING
            t_table      = t_mara ).
      CATCH cx_salv_msg.                                "#EC NO_HANDLER
    ENDTRY.
* Add basic default functionality in the ALV report
* Functions
    DATA:
      l_o_functions TYPE REF TO cl_salv_functions_list.
    l_o_functions = l_o_table->get_functions( ).
    l_o_functions->set_all( abap_true ).
* Display the list
    l_o_table->display( ).
  ENDMETHOD.                    "extract
ENDCLASS.                    "lcl_report IMPLEMENTATION

Tuesday, March 03, 2009

Sending an IDoc to your system via loop back logical system

Why would you need to have a loopback system when you can just post an IDoc using the functional module IDOC_WRITE_AND_START_INBOUND. Because we want to use BAPI to post this IDoc. The transaction BDBG creates a function module for Outbound ALE for sending IDoc against a BAPI structure (it also creates the relevant IDoc messages). If you want to use this function module (naming convention is something like ZZ_ALE*) then you need to have some sort of loopback mechanism. In the parameters of this ALE FM you just give the receivers details. It will automatically fill your own system details as the sender and sets the direction as outbound for the IDoc it creates. Now you want this IDoc to return back to your system to be processed by the BAPI that you have created. The following list the steps to create a logical system that is pointing to itself. There is however a drawback to this approach. You will get two IDocs, one going out and one coming in.

Create loop back RFC destination called INTERNAL via the transaction SM59. It has to be of type Logical Connection (L). It will refer to entry NONE which is an automatically created entry referencing itself.




Create a logical system INTERNAL via transaction BD54

Create a port for this logical system via transaction WE20


Go to transaction BD64 to create model for this loop back scenario using
your required message type



Generate profile for this model via transaction BD82. This will create
outbound message profile


 



Manually add inbound profile for the message type



That’s it.

Reference

Monday, March 02, 2009

Date related function modules

There are function modules related to date functionality in the function groups SCA*