Tuesday, March 27, 2018

Field Exit and User Exit

MM42
Key in article and select Logistics, execute then hot enter.
Select Accounting 

Data Element: BKLAS

Program: SAPLMGD2

Screen: 2802

Data Element: VERPR

Run program: RSMODPRF
Execute
FIELD_EXIT_BKLAS
Create Field Exit
----------------------------------
User exit

Program: SAPLMGMW
Screen:  3000

Next to find the package
SE38 pass the program SAPLMGMW then select attribute
The package: MGW

Now find the User exit
SMOD then go to menu utilities/find

fill in MGW then execute

MGW0001
MGW0002



Sunday, March 25, 2018

Event in OO

Instance-Events

EVENT evt [ Exporting parameters].
* Declare Event
  EVENTS employee_added_to_list EXPORTING VALUE(ex_employee_name) TYPE string.

CLASS-Events

CLASS-EVENT evt [ Exporting parameters].

Declaration of Eventhandler-Methods:

METHODS evt-handler
                FOR EVENT evt of CLASS lcl_some_class
                [ IMPORTING p1 p2 ... [sender]]

* Event method
    METHODS on_employee_added_to_list FOR EVENT employee_added_to_list OF zcl_employee
            IMPORTING ex_employee_name sender.

* Event method implimentation
  METHOD on_employee_added_to_list.
    WRITE: / 'Employee added to list ', ex_employee_name.
  ENDMETHOD.

* Raise event

  METHOD display_employee.
    write: / g_empl_id, / g_empl_name, / g_position, / g_salary.
    ULINE.
    RAISE event employee_added_to_list EXPORTING ex_employee_name = g_empl_name.
  ENDMETHOD.


" Register event
if g_employee1 IS NOT INITIAL.
  " Register event
  set HANDLER g_employee1->on_employee_added_to_list FOR g_employee1.
  IF  g_employee1->is_further_educated( ) = abap_true.
      g_employee1->raise_salary( 5 ).
  ENDIF.
* 2 ways to call component method
call METHOD g_employee1->display_employee( ).
ENDIF.

-----------------------------
sample program
REPORT zqc_first_local_class.


CLASS zcl_employee DEFINITION.
  PUBLIC SECTION.
* Declare Event
  EVENTS employee_added_to_list EXPORTING VALUE(ex_employee_name) TYPE string.


    TYPES: BEGIN OF ty_create_empl,
            id                  TYPE i,
            name                TYPE string,
            position            TYPE string,
            further_educated    TYPE boolean,
          END OF ty_create_empl.


    METHODS display_employee.

    METHODS set_name IMPORTING im_name TYPE string.

    METHODS get_name RETURNING VALUE(re_name) TYPE string.

*    METHODS constructor IMPORTING im_empl_id        TYPE i
*                                  im_empl_name      TYPE string
*                                  im_position       TYPE string.
    METHODS constructor IMPORTING im_employee        TYPE ty_create_empl.
    METHODS is_further_educated RETURNING VALUE(re_further_educated) TYPE boolean.
    METHODS raise_salary IMPORTING im_percent TYPE i.

* Event method
    METHODS on_employee_added_to_list FOR EVENT employee_added_to_list OF zcl_employee
            IMPORTING ex_employee_name sender.

    CLASS-METHODS get_no_of_employees RETURNING VALUE(re_no_of_employees) TYPE i.
    CLASS-METHODS display_no_of_employees.
    CLASS-METHODS class_constructor.

  PRIVATE SECTION.
    DATA: g_empl_id             TYPE i,
          g_empl_name           TYPE string,
          g_position            TYPE string,
          g_salary              TYPE p LENGTH 4 DECIMALS 2,
          g_is_further_educated TYPE boolean.


    CLASS-DATA g_no_of_employees TYPE i.
    CLASS-DATA g_max_no_of_empl  TYPE i.

    CONSTANTS co_start_salary TYPE p LENGTH 4 DECIMALS 2 VALUE '2000.00'.
    CLASS-METHODS count_employee.




ENDCLASS.

CLASS zcl_employee IMPLEMENTATION.

  METHOD display_employee.
    write: / g_empl_id, / g_empl_name, / g_position, / g_salary.
    ULINE.
    RAISE event employee_added_to_list EXPORTING ex_employee_name = g_empl_name.
  ENDMETHOD.

  METHOD class_constructor.
    g_max_no_of_empl = 10.
  ENDMETHOD.

  METHOD constructor.
    IF g_no_of_employees < g_max_no_of_empl.
      g_empl_id             = im_employee-id.
      g_empl_name           = im_employee-name.
      g_position            = im_employee-position.
      g_is_further_educated = im_employee-further_educated.
      g_salary              = co_start_salary.
      me->count_employee( ).

*      g_empl_id     = im_empl_id.
*      g_empl_name   = im_empl_name.
*      g_position    = im_position.
*      g_salary      = co_start_salary.
*      me->count_employee( ).
    ENDIF.
  ENDMETHOD.

  METHOD set_name.
    g_empl_name = im_name.
  ENDMETHOD.

  METHOD get_name.
    re_name = g_empl_name.
  ENDMETHOD.

  METHOD count_employee.
    add 1 to g_no_of_employees.
  ENDMETHOD.

  METHOD get_no_of_employees.
    re_no_of_employees = g_no_of_employees.
  ENDMETHOD.

  METHOD display_no_of_employees.
    WRITE: / 'Number of Employees ', g_no_of_employees.
  ENDMETHOD.
  METHOD is_further_educated.
    re_further_educated = g_is_further_educated.
  ENDMETHOD.
  METHOD raise_salary.
    me->g_salary = g_salary + ( g_salary / 100 * im_percent ).
  ENDMETHOD.
* Event method implimentation
  METHOD on_employee_added_to_list.
    WRITE: / 'Employee added to list ', ex_employee_name.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

DATA g_employee1    TYPE REF TO zcl_employee.
DATA g_employee2    TYPE REF TO zcl_employee.
DATA g_empl_data    TYPE zcl_employee=>ty_create_empl.

TRY .
  g_empl_data-id                = 1.
  g_empl_data-name              = 'John Doe'.
  g_empl_data-position          = 'Sales'.
  g_empl_data-further_educated  = abap_true.
  CREATE OBJECT g_employee1
          EXPORTING
            im_employee = g_empl_data.
*            im_empl_data-id        =  1
*            im_empl_data-name      = 'John Doe'
*            im_employee-position  = 'Sales'.
CATCH cx_sy_create_object_error.

ENDTRY.
if g_employee1 IS NOT INITIAL.
  " Register event
  set HANDLER g_employee1->on_employee_added_to_list FOR g_employee1.
  IF  g_employee1->is_further_educated( ) = abap_true.
      g_employee1->raise_salary( 5 ).
  ENDIF.
* 2 ways to call component method
call METHOD g_employee1->display_employee( ).
ENDIF.
TRY .
  clear g_empl_data.
  g_empl_data-id                = 2.
  g_empl_data-name              = 'Quang Cao'.
  g_empl_data-position          = 'IT'.
  g_empl_data-further_educated  = abap_false.
  CREATE OBJECT g_employee2
          EXPORTING
            im_employee = g_empl_data.
*            im_empl_id    =  2
*            im_empl_name  = 'Quang Cao'
*            im_position   = 'IT'.
CATCH cx_sy_create_object_error.

ENDTRY.
if g_employee2 IS NOT INITIAL.
    " Register event
  set HANDLER g_employee2->on_employee_added_to_list FOR g_employee2.
  IF g_employee2->is_further_educated( ) = abap_true.
    g_employee2->raise_salary( 5 ).
  ENDIF.
  g_employee2->display_employee( ).
ENDIF.


* Class method
zcl_employee=>display_no_of_employees( ).


Class

REPORT zqc_first_local_class.


CLASS zcl_employee DEFINITION.
  PUBLIC SECTION.
    TYPES: BEGIN OF ty_create_empl,
            id                  TYPE i,
            name                TYPE string,
            position            TYPE string,
            further_educated    TYPE boolean,
          END OF ty_create_empl.


    METHODS display_employee.

    METHODS set_name IMPORTING im_name TYPE string.

    METHODS get_name RETURNING VALUE(re_name) TYPE string.

*    METHODS constructor IMPORTING im_empl_id        TYPE i
*                                  im_empl_name      TYPE string
*                                  im_position       TYPE string.
    METHODS constructor IMPORTING im_employee        TYPE ty_create_empl.
    METHODS is_further_educated RETURNING VALUE(re_further_educated) TYPE boolean.
    METHODS raise_salary IMPORTING im_percent TYPE i.


    CLASS-METHODS get_no_of_employees RETURNING VALUE(re_no_of_employees) TYPE i.
    CLASS-METHODS display_no_of_employees.
    CLASS-METHODS class_constructor.

  PRIVATE SECTION.
    DATA: g_empl_id             TYPE i,
          g_empl_name           TYPE string,
          g_position            TYPE string,
          g_salary              TYPE p LENGTH 4 DECIMALS 2,
          g_is_further_educated TYPE boolean.


    CLASS-DATA g_no_of_employees TYPE i.
    CLASS-DATA g_max_no_of_empl  TYPE i.

    CONSTANTS co_start_salary TYPE p LENGTH 4 DECIMALS 2 VALUE '2000.00'.
    CLASS-METHODS count_employee.




ENDCLASS.

CLASS zcl_employee IMPLEMENTATION.

  METHOD display_employee.
    write: / g_empl_id, / g_empl_name, / g_position, / g_salary.
    ULINE.
  ENDMETHOD.

  METHOD class_constructor.
    g_max_no_of_empl = 10.
  ENDMETHOD.

  METHOD constructor.
    IF g_no_of_employees < g_max_no_of_empl.
      g_empl_id             = im_employee-id.
      g_empl_name           = im_employee-name.
      g_position            = im_employee-position.
      g_is_further_educated = im_employee-further_educated.
      g_salary              = co_start_salary.
      me->count_employee( ).

*      g_empl_id     = im_empl_id.
*      g_empl_name   = im_empl_name.
*      g_position    = im_position.
*      g_salary      = co_start_salary.
*      me->count_employee( ).
    ENDIF.
  ENDMETHOD.

  METHOD set_name.
    g_empl_name = im_name.
  ENDMETHOD.

  METHOD get_name.
    re_name = g_empl_name.
  ENDMETHOD.

  METHOD count_employee.
    add 1 to g_no_of_employees.
  ENDMETHOD.

  METHOD get_no_of_employees.
    re_no_of_employees = g_no_of_employees.
  ENDMETHOD.

  METHOD display_no_of_employees.
    WRITE: / 'Number of Employees ', g_no_of_employees.
  ENDMETHOD.
  METHOD is_further_educated.
    re_further_educated = g_is_further_educated.
  ENDMETHOD.
  METHOD raise_salary.
    me->g_salary = g_salary + ( g_salary / 100 * im_percent ).
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

DATA g_employee1    TYPE REF TO zcl_employee.
DATA g_employee2    TYPE REF TO zcl_employee.
DATA g_empl_data    TYPE zcl_employee=>ty_create_empl.

*TRY .
*  g_empl_data-id                = 1.
*  g_empl_data-name              = 'John Doe'.
*  g_empl_data-position          = 'Sales'.
*  g_empl_data-further_educated  = abap_true.
*  CREATE OBJECT g_employee1
*          EXPORTING
*            im_employee = g_empl_data.
**            im_empl_data-id        =  1
**            im_empl_data-name      = 'John Doe'
**            im_employee-position  = 'Sales'.
*CATCH cx_sy_create_object_error.
*
*ENDTRY.
if g_employee1 IS NOT INITIAL.
  IF  g_employee1->is_further_educated( ) = abap_true.
      g_employee1->raise_salary( 5 ).
  ENDIF.
* 2 ways to call component method
call METHOD g_employee1->display_employee( ).
ENDIF.
TRY .
  clear g_empl_data.
  g_empl_data-id                = 2.
  g_empl_data-name              = 'Quang Cao'.
  g_empl_data-position          = 'IT'.
  g_empl_data-further_educated  = abap_false.
  CREATE OBJECT g_employee2
          EXPORTING
            im_employee = g_empl_data.
*            im_empl_id    =  2
*            im_empl_name  = 'Quang Cao'
*            im_position   = 'IT'.
CATCH cx_sy_create_object_error.

ENDTRY.
if g_employee2 IS NOT INITIAL.
  IF g_employee2->is_further_educated( ) = abap_true.
    g_employee2->raise_salary( 5 ).
  ENDIF.
  g_employee2->display_employee( ).
ENDIF.


* Class method
zcl_employee=>display_no_of_employees( ).

Object Component Selector

Object Component Selector
A component comp of an object is accessed using the following name:
ref->comp
In this case, the character -> is the object component selector. A reference variable ref must be specified on the left of the object component selector as follows:
  • Name of a reference variable (can itself be a composite).
The name comp of the component must be on the right of the object component selector. The object component selector dereferences the reference variable ref and makes the components of the referenced object accessible.
  • If ref is an object reference variable, the components comp of the object (attributes and methods) to which the object reference variable points are addressed using the object component selector.
  • If ref is a data reference variable that is typed as a structure, the components comp of the structure to which the data reference variable points are addressed using the object component selector.
If an attempt is made to access a data object (an instance attribute or structure component) using a reference variable that contains the null reference, a non-handleable exception is raised. Dereferencing of a data reference in the statement ASSIGN is an exception to this. If an attempt is made to access an instance method using a reference variable that contains the null reference, a handleable exception of the class CX_SY_REF_IS_INITIAL is raised.
Note
If ref is a data reference variable, the character * can be specified after the object component selector ->. This creates the general dereferencing operator ->*. The expression ref->* names the entire data object to which the data reference variable points. The dereferencing operator is the only way to dereference data references. In the case of untyped data reference variables, this is only possible in the statement ASSIGN. The dereferencing operator cannot be specified after object reference variables. The instance components of classes can only be accessed using the expression ref->comp.
Example
Accesses the public attribute a1 of a class c1 by using the object reference variable oref.
CLASS c1 DEFINITION.
  PUBLIC SECTION.
    DATA a1 TYPE string READ-ONLY.
ENDCLASS.

...

DATA oref TYPE REF TO c1.

... oref->a1 ...
Example
The data reference variable dref is typed as a structure and the component carrid of the referenced structure is accessed using the object component selector. The expression dref->carrid has the same meaning as the chaining dref->*-carrid.
DATA dref TYPE REF TO sflight.

...

... dref->carrid ...




Class component selector

CLASSNAME=>component_name

In this case, no instance of the class needs to be created. The characters => are the class component selector. The name class of a class must be on the left of the class component selector. The name comp of the component must be on the right of the class component selector.
The class component selector can also be used to access the data types and constants of an interface.
intf=>type, intf=>const
The name intf of an interface must be on the left of the class component sector. The name type of a data type defined using TYPES or the name const of a constant defined using CONSTANTS must be on the right of the object component selector.
Note
It is also possible to access the static components of a class using the object component selector if an instance of the class was created.
Example
Declares a class factory and accesses its static attribute oref.
CLASS factory DEFINITION CREATE PRIVATE.
  PUBLIC SECTION.
    CLASS-DATA oref TYPE REF TO factory.
    CLASS-METHODS class_constructor.
    METHODS do_something.
ENDCLASS.

...

factory=>oref->do_something( ).

...

CLASS factory IMPLEMENTATION.
  METHOD class_constructor.
    CREATE OBJECT oref.
  ENDMETHOD.
  METHOD do_something.
    ...
  ENDMETHOD.
ENDCLASS.



Wednesday, March 21, 2018

Program to Create a Class dynamically by passing class name at run time

REPORT z_dyn_classname.
 
CLASS cl_abap_objectdescr DEFINITION LOAD.
DATA: container TYPE REF TO object,
      pic_container TYPE REF TO cl_gui_container,
      exc_ref TYPE REF TO cx_root,
      lo_cast_error TYPE REF TO cx_sy_move_cast_error,
      exc_text TYPE string.
* Picture Control
DATA picture TYPE REF TO cl_gui_picture.
 
DATA: class TYPE string VALUE 'CL_GUI_DIALOGBOX_CONTAINER',
      ptab TYPE abap_parmbind_tab,
      ptab_line TYPE abap_parmbind.
 
CALL SCREEN 100.
 
*----------------------------------------------------------------------*
*  MODULE STATUS_0100 OUTPUT
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
 
  ptab_line-name = 'WIDTH'.
  ptab_line-kind = cl_abap_objectdescr=>exporting.
  GET REFERENCE OF 1000 INTO ptab_line-value.
  INSERT ptab_line INTO TABLE ptab.
 
  ptab_line-name = 'PARENT'.
  ptab_line-kind = cl_abap_objectdescr=>exporting.
  GET REFERENCE OF cl_gui_container=>desktop
                INTO ptab_line-value.
  INSERT ptab_line INTO TABLE ptab.
 
  ptab_line-name = 'HEIGHT'.
  ptab_line-kind = cl_abap_objectdescr=>exporting.
  GET REFERENCE OF 300 INTO ptab_line-value.
  INSERT ptab_line INTO TABLE ptab.
 
  TRY.
      CREATE OBJECT container TYPE (class)
        PARAMETER-TABLE ptab.
    CATCH cx_sy_create_object_error INTO exc_ref.
      exc_text = exc_ref->get_text( ).
      MESSAGE exc_text TYPE 'I'.
  ENDTRY.
  TRY.
* Now, the Widening cast to move the reference from the
* generic object to dialogbox parent container class (more specific class).
      pic_container ?= container.
    CATCH cx_sy_move_cast_error INTO lo_cast_error.
      WRITE: / 'Widening cast failed'.
  ENDTRY.
 
  CREATE OBJECT picture
    EXPORTING
      parent = pic_container.
 
* Request an URL from the data provider by exporting the pic_data.
  DATA url(255).
  CLEAR url.
  PERFORM load_pic_from_db CHANGING url.
 
* load picture
  CALL METHOD picture->load_picture_from_url
    EXPORTING
      url = url.
 
  CALL METHOD cl_gui_cfw=>flush
    EXCEPTIONS
      cntl_system_error = 1
      cntl_error        = 2.
  IF sy-subrc <> 0.
* error handling
  ENDIF.
ENDMODULE.                    "STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
*&      Form  load_pic_from_db
*&---------------------------------------------------------------------*
FORM load_pic_from_db CHANGING url.
  DATA query_table LIKE w3query OCCURS 1 WITH HEADER LINE.
  DATA html_table LIKE w3html OCCURS 1.
  DATA return_code LIKE w3param-ret_code.
  DATA content_type LIKE  w3param-cont_type.
  DATA content_length LIKE  w3param-cont_len.
  DATA pic_data LIKE w3mime OCCURS 0.
  DATA pic_size TYPE i.
 
  REFRESH query_table.
  query_table-name = '_OBJECT_ID'.
  query_table-value = 'ENJOYSAP_LOGO'.
  APPEND query_table.
 
  CALL FUNCTION 'WWW_GET_MIME_OBJECT'
    TABLES
      query_string        = query_table
      html                = html_table
      mime                = pic_data
    CHANGING
      return_code         = return_code
      content_type        = content_type
      content_length      = content_length
    EXCEPTIONS
      object_not_found    = 1
      parameter_not_found = 2
      OTHERS              = 3.
  IF sy-subrc = 0.
    pic_size = content_length.
  ENDIF.
 
  CALL FUNCTION 'DP_CREATE_URL'
    EXPORTING
      type     = 'image'
      subtype  = cndp_sap_tab_unknown
      size     = pic_size
      lifetime = cndp_lifetime_transaction
    TABLES
      data     = pic_data
    CHANGING
      url      = url
    EXCEPTIONS
      OTHERS   = 1.
 
ENDFORM.                    "load_pic_from_db

ABAP Class to Import CSV Files

class Z_BC_USER_FILEIO definition
 public
 final
 create public .

public section.

 type-pools ABAP .
 methods UPLOAD
  importing
   !I_SHOW_DIALOG type ABAP_BOOL default ' '
   !I_WINDOW_TITLE type STRING default ''
   !I_INITIAL_DIRECTORY type STRING default ''
   !I_DEFAULT_FILE type STRING default '*.*'
   !I_DEFAULT_EXTENSION type STRING default '*.*'
   !I_FILE_FILTER type STRING default '*.*'
   !I_UPLOAD_PATH type STRING default ''
   !I_CSV_PARSE type ABAP_BOOL default ' '
   !I_CSV_DATA_SEP type CHAR1 default ','
   !I_CSV_ESC_CHAR type CHAR1 default '"'
   !I_CSV_NUM_COLS type I default 9999
   !I_CSV_SKIPHEAD type ABAP_BOOL default ' '
  exporting
   !E_FILE_RAWDATA type TEXTLINE_T
  changing
   !E_FILE_CSV_STRUCT type ANY optional
   !E_FILE_CSV_TABLE type STANDARD TABLE optional
  exceptions
   UPLOAD_ERROR
   PARSE_ERROR
   PATH_ERROR
   PROGRAM_ERROR .

private section.

 data P_UPLOAD_PATH type STRING .

 type-pools ABAP .
 class-methods PARSE_CSV
  importing
   !I_CSV_DATA_SEP type CHAR1 default ','
   !I_CSV_ESC_CHAR type CHAR1 default '"'
   !I_CSV_NUM_COLS type I default 9999
   !I_CSV_SKIPHEAD type ABAP_BOOL default ' '
   !I_FILE_RAWDATA type TEXTLINE_T
  exporting
   !E_FILE_CSV_STRUCT type ANY
   !E_FILE_CSV_TABLE type STANDARD TABLE
  exceptions
   PARSE_ERROR
   TABLE_ERROR .


METHOD upload.
 DATA: lf_error TYPE i VALUE 0,
    lf_upload_path TYPE char1024,
    lf_window_title TYPE string.

 p_upload_path = i_upload_path.
 lf_upload_path = p_upload_path.

 " let user select file if needed
 IF i_show_dialog = 'X'.
  IF I_WINDOW_TITLE IS INITIAL.
   lf_window_title = text-002.
  ELSE.
   lf_window_title = I_WINDOW_TITLE.
  ENDIF.

  CALL FUNCTION '/SAPSLL/BROWSE_LOCAL_FILE_SYST'
   EXPORTING
    iv_window_title = lf_window_title
    iv_default_extension = i_default_extension
    iv_default_filename = i_default_file
    iv_file_filter = i_file_filter
    iv_initial_directory = i_initial_directory
    iv_multiselection = ' '
   IMPORTING
    ev_rcode = lf_error
   CHANGING
    iv_path = lf_upload_path
    .
 ELSE.
  " Must have the path if not using the dialog
  IF p_upload_path IS INITIAL.
   lf_error = 1.
  ENDIF.
 ENDIF.

 " upload the file if we have a path
 IF lf_error = 0.
  CALL METHOD cl_gui_frontend_services =>gui_upload
   EXPORTING
    filename = p_upload_path
   CHANGING
    data_tab = e_file_rawdata
   EXCEPTIONS
    file_open_error = 1
    file_read_error = 2
    no_batch = 3
    gui_refuse_filetransfer = 4
    invalid_type = 5
    no_authority = 6
    unknown_error = 7
    bad_data_format = 8
    header_not_allowed = 9
    separator_not_allowed = 10
    header_too_long = 11
    unknown_dp_error = 12
    access_denied = 13
    dp_out_of_memory = 14
    disk_full = 15
    dp_timeout = 16
    not_supported_by_gui = 17
    error_no_gui = 18
    others = 19
      .
  IF sy-subrc = 0.
   IF i_csv_parse = 'X'.
    "IF ( e_file_csv_struct IS NOT INITIAL ) AND ( e_file_csv_table IS NOT INITIAL ).
    CALL METHOD parse_csv
     EXPORTING
      i_csv_data_sep = i_csv_data_sep
      i_csv_esc_char = i_csv_esc_char
      i_file_rawdata = e_file_rawdata
      i_csv_num_cols = i_csv_num_cols
      i_csv_skiphead = i_csv_skiphead
     IMPORTING
      e_file_csv_struct = e_file_csv_struct
      e_file_csv_table = e_file_csv_table
     EXCEPTIONS
      parse_error = 1
      table_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
           RAISING parse_error.
    ENDIF.

    "ELSE. " I_CSV_PARSE set without other CSV parameters
    " MESSAGE s000(Z_gts) DISPLAY LIKE 'E'
    "     WITH text-001 space space space
    "     RAISING program_error.
    "ENDIF.
   ENDIF.

  ELSE. " GUI_UPLOAD error
   MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
         WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
         RAISING upload_error.
  ENDIF.

 ELSE. " Path not set or error with user dialog
  MESSAGE s000(Z_gts) DISPLAY LIKE 'E'
      WITH text-000 p_upload_path space space
      RAISING path_error.
 ENDIF.
ENDMETHOD.


METHOD parse_csv.
 DATA: lt_csv_table_struct TYPE REF TO data,
    lt_csv_table_desc TYPE REF TO cl_abap_tabledescr,
    ls_csv_table_desc TYPE REF TO cl_abap_structdescr,
    lt_csv_table_flds TYPE abap_compdescr_tab,
    ls_csv_table_flds TYPE abap_compdescr,
    ls_file_rawline TYPE LINE OF textline_t,
    lt_file_columns TYPE table_of_strings,
    ls_file_columns TYPE LINE OF table_of_strings,
    lf_skip_line  TYPE abap_bool VALUE ' ',
    ls_fieldcatalog TYPE lvc_s_fcat,
    lt_fieldcatalog TYPE lvc_t_fcat,
    lt_dynamictable TYPE REF TO data,
    ls_dynamicline TYPE REF TO data,
    lf_loop_count  TYPE i,
    lf_line_count  TYPE i,
    lf_fieldname  TYPE char30.

 FIELD-SYMBOLS: <fs_csv_table_struct> TYPE STANDARD TABLE,
         <fs_dynamic_table> TYPE STANDARD TABLE,
         <fs_dynamic_lines> TYPE ANY,
         <fs_dynamic_field> TYPE ANY.

 " determine the structure of the destination table
 GET REFERENCE OF e_file_csv_table INTO lt_csv_table_struct.
 ASSIGN lt_csv_table_struct->* TO <fs_csv_table_struct>.
 lt_csv_table_desc ? =
  cl_abap_structdescr =>describe_by_data_ref( lt_csv_table_struct ).
 ls_csv_table_desc ? = lt_csv_table_desc->get_table_line_type( ).
 lt_csv_table_flds = ls_csv_table_desc->components.

 " use destination table structure for results table
 LOOP AT lt_csv_table_flds INTO ls_csv_table_flds.
  ls_fieldcatalog-fieldname = ls_csv_table_flds-name.
  ls_fieldcatalog-inttype = ls_csv_table_flds-type_kind.
  ls_fieldcatalog-intlen = ls_csv_table_flds-length.
  ls_fieldcatalog-decimals = ls_csv_table_flds-decimals.
  APPEND ls_fieldcatalog TO lt_fieldcatalog.
 ENDLOOP.

 " build a dynamic table to put the CSV contents into
 CALL METHOD cl_alv_table_create =>create_dynamic_table
  EXPORTING
   it_fieldcatalog = lt_fieldcatalog
  IMPORTING
   ep_table = lt_dynamictable
  EXCEPTIONS
   generate_subpool_dir_full = 1
   OTHERS = 2.
 IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
        RAISING table_error.
 ENDIF.

 " finish dynamic table, create dynamic table lines
 ASSIGN lt_dynamictable->* TO <fs_dynamic_table>.
 CREATE DATA ls_dynamicline LIKE LINE OF <fs_dynamic_table>.
 ASSIGN ls_dynamicline->* TO <fs_dynamic_lines>.

 " delete header line if needed
 IF i_csv_skiphead = 'X'.
  lf_skip_line = 'X'.
 ENDIF.

 " process the CSV file raw data
 LOOP AT i_file_rawdata INTO ls_file_rawline.
  CALL FUNCTION 'RSDS_CONVERT_CSV'
   EXPORTING
    i_data_sep = i_csv_data_sep
    i_esc_char = i_csv_esc_char
    i_record = ls_file_rawline
    i_field_count = i_csv_num_cols
   IMPORTING
    e_t_data = lt_file_columns
   EXCEPTIONS
    escape_no_close = 1
    escape_improper = 2
    conversion_error = 3
    OTHERS = 4.
  IF sy-subrc <> 0. " RSDS_CONVERT_CSV error
   MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
         WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
         RAISING parse_error.
  ENDIF.

  " store CSV fields into dynamic table
  lf_loop_count = 1.
  DESCRIBE TABLE lt_file_columns LINES lf_line_count.
  LOOP AT lt_csv_table_flds INTO ls_csv_table_flds.
   MOVE ls_csv_table_flds-name TO lf_fieldname.
   ASSIGN COMPONENT lf_fieldname
    OF STRUCTURE <fs_dynamic_lines>
TO <fs_dynamic_field>.
   READ TABLE lt_file_columns INDEX lf_loop_count INTO ls_file_columns.

   IF lf_loop_count < = lf_line_count.
    <fs_dynamic_field> = ls_file_columns.
   ELSE.
    <fs_dynamic_field> = ''.
   ENDIF.

   lf_loop_count = lf_loop_count + 1.
  ENDLOOP.

  " move dynamic table line to resultant table, unless we are skipping
  IF lf_skip_line = ' '.
   MOVE-CORRESPONDING <fs_dynamic_lines> TO e_file_csv_struct.
   APPEND e_file_csv_struct TO e_file_csv_table.
  ELSE.
   lf_skip_line = ' '.
  ENDIF.
 ENDLOOP.
ENDMETHOD.

Tuesday, March 20, 2018



CX_STATC_CHECK
CX_DYNAMC_CHECK
CX_SY_ARTHMETC_ERROR
CX_SY_ZERODVDE
CX_SY_ARTHMETC_OVERFLOW
CX_SY_ARG_OUT_OF_DOMAN
CX_SY_PRECSON_LOSS
CX_SY_ASSGN_ERROR
CX_SY_ASSGN_CAST_ERROR
CX_SY_ASSGN_CAST_LLEGAL_CAST
CX_SY_ASSGN_CAST_UNKNOWN_TYPE
CX_SY_ASSGN_OUT_OF_RANGE
CX_SY_CODEPAGE_CONVERTER_NT
CX_SY_CONVERSON_ERROR
CX_SY_CONVERSON_CODEPAGE
CX_SY_CONVERSON_DATA_LOSS
CX_SY_CONVERSON_NO_BOOLEAN
CX_SY_CONVERSON_NO_DATE_TME
CX_SY_CONVERSON_NO_NUMBER
CX_SY_CONVERSON_NO_RAW
CX_SY_CONVERSON_NO_UUD
CX_SY_CONVERSON_OVERFLOW
CX_SY_CONVERSON_ROUNDNG
CX_SY_CONVERSON_UNKNOWN_LANGU
CX_SY_CREATE_ERROR
CX_SY_CREATE_OBJECT_ERROR
CX_SY_CREATE_DATA_ERROR
CX_SY_DATA_ACCESS_ERROR
CX_SY_RANGE_OUT_OF_BOUNDS
CX_SY_TAB_RANGE_OUT_OF_BOUNDS
CX_SY_OFFSET_NOT_ALLOWED
CX_SY_DYN_CALL_ERROR
CX_SY_DYN_CALL_LLEGAL_CLASS
CX_SY_DYN_CALL_LLEGAL_FORM
CX_SY_DYN_CALL_LLEGAL_FUNC
CX_SY_DYN_CALL_LLEGAL_METHOD
CX_SY_DYN_CALL_PARAMETER_ERROR
CX_SY_DYN_CALL_EXCP_NOT_FOUND
CX_SY_DYN_CALL_LLEGAL_TYPE
CX_SY_DYN_CALL_PARAM_MSSNG
CX_SY_DYN_CALL_PARAM_NOT_FOUND
CX_SY_EXPORT_NO_SHARED_MEMORY
CX_SY_FLE_ACCESS_ERROR
CX_SY_FLE_AUTHORTY
CX_SY_FLE_CLOSE
CX_SY_FLE_O
CX_SY_FLE_OPEN
CX_SY_FLE_OPEN_MODE
CX_SY_FLE_POSTON
CX_SY_FLE_TRUNCATE
CX_SY_FND_NFNTE_LOOP
CX_SY_GEN_SOURCE_TOO_WDE
CX_SY_MPORT_MSMATCH_ERROR
CX_SY_MPORT_FORMAT_ERROR
CX_SY_TAB_ERROR
CX_SY_TAB_DUPLCATE_KEY
CX_SY_MATCHER
CX_SY_REGEX_TOO_COMPLEX
CX_SY_NVALD_REGEX_FORMAT
CX_SY_MOVE_CAST_ERROR
CX_SY_PROGRAM_NOT_FOUND
CX_SY_PROVDE_EXCEPTON
CX_SY_PROVDE_NTERVAL_OVERLAP
CX_SY_PROVDE_TABLE_NOT_SORTED
CX_SY_READ_SRC_LNE_TOO_LONG
CX_SY_REF_S_NTAL 
CX_SY_REGEX
CX_SY_NVALD_REGEX
CX_SY_REPLACE_NFNTE_LOOP
CX_SY_SCAN_SOURCE_TOO_WDE
CX_SY_SQL_ERROR
CX_SY_OPEN_SQL_ERROR
CX_SY_OPEN_SQL_DB
CX_SY_DYNAMC_OSQL_ERROR
CX_SY_DYNAMC_OSQL_SEMANTCS
CX_SY_DYNAMC_OSQL_SYNTAX
CX_SY_NATVE_SQL_ERROR
CX_SY_UNKNOWN_CURRENCY
CX_SY_WRTE_NVALD_STYLE
CX_SY_WRTE_SRC_LNE_TOO_LONG
CX_TRANSFORMATON_ERROR
CX_ST_ERROR
CX_ST_CALL_ERROR
CX_ST_CALL_METHOD_ERROR
CX_ST_CONSTRANT_ERROR
CX_ST_CONDTON
CX_ST_DESERALZATON_ERROR
CX_ST_FORMAT_ERROR
CX_ST_NVALD_XML
CX_ST_MATCH
CX_ST_REF_ACCESS
CX_ST_RUNTME_ERROR
CX_ST_SERALZATON_ERROR
CX_XSLT_EXCEPTON
CX_XSLT_SYSTEM_ERROR
CX_XSLT_ABAP_CALL_ERROR
CX_XSLT_DESERALZATON_ERROR
CX_XSLT_FORMAT_ERROR
CX_XSLT_RUNTME_ERROR
CX_XSLT_SERALZATON_ERROR
CX_NO_CHECK
CX_BAD
CX_BAD_CONTEXT_ERROR
CX_BAD_FLTER_ERROR
CX_BAD_NTAL_CONTEXT
CX_BAD_NTAL_REFERENCE
CX_BAD_NOT_SNGLE_USE
CX_BAD_MULTPLY_MPLEMENTED
CX_BAD_NOT_MPLEMENTED
CX_BAD_UNKNOWN_ERROR
CX_SY_EXPORT_BUFFER_NO_MEMORY
CX_SY_GENERATE_SUBPOOL_FULL
CX_SY_LLEGAL_HANDLER
CX_SY_LOCALZATON_ERROR
CX_SY_NESTED_PRNT_ON
CX_SY_NO_HANDLER
CX_SY_PPES_NOT_SUPPORTED
CX_SY_PPE_REOPEN
CX_SY_REMOTE_CALL_ERROR
CX_SY_RMC_COMM_FALURE
CX_SY_RMC_NVALD_STATUS
CX_SY_RMC_SYSTEM_FALURE
CX_SY_TOO_MANY_FLES


Exception Handling in ABAP
What are exceptions?
An exception is an event or in simple terms, an error during the execution of a program that interrupts the normal flow of control.
An exception-handling mechanism makes it possible to deal with these run time errors.
The runtime errors can be of two types:
Catchable Runtime Errors which can be caught using the necessary exception handling.
Non-Catchable Runtime Errors which can not be caught by exceptional handling and always result in termination of program
Classical way of handling Exceptions
In the existing concept, exceptions can be raised via the RAISE statement, and function modules or methods then declare them via the EXCEPTI
ONS clause.
Exception handling is done by mapping each exception name to a number, while calling the function module or method. Then check the sy-subrc
for one of these values once the function module or method returns.
After function call there are two ways of handling:
Handle all of them immediately after a function or method call
Select only certain exceptions for handling and pass on the rest to the caller.
But it's a rather tedious process since you have to do the mapping manually, for all exceptions. Not even it takes lot of effort, it makes the
code unreadable.
New Concept of Exception Handling
Exceptions after release 6.10 use the object oriented concept. They are represented by objects that are instances of classes. Each such class is
called an exception e.g., a division by zero, data conversion etc.
There is a class called cx_root which is the root of all the exception classes i.e. all other classes are inherited from this class. This class can be
used to define handlers for all types of exceptions.
Attributes can be used to store the additional information about the cause of exception so that the exception handlers do not need to know the
exception context.
With the help of Inheritance existing exceptions can be more specifically used by adding new attributes to it.
Exception Categories
The cx_root class is the super class and the classes that are directly inherited from cx_root are as follows:
A cx_static_check is checked by both the compiler and the runtime system such that if any exception of this category occurs and is not
handled locally inside of the procedure, has been declared in the RAISING clause of the procedure's interface (described in later
sections).
A cx_dynamic_check is checked only by the runtime system when exception tries to leave a procedure that it has been declared in the
RAISING clause of the procedure's interface.
A cx_no_check exception can always leave the interface of a procedure. Neither the compiler nor the runtime system performs any
interface checks.
Raising and handling Exceptions
Exceptions are raised to indicate that some exceptional situation has occurred. Generally, an exception handler tries to repair the error, find an
alternative solution or, where this is impossible, bring the system to a consistent state and then pass on the error. If the system cannot find a
handler for an exception throughout the entire call hierarchy, the program terminates with a short dump.
Raising Exceptions
Exceptions can be raised at any point in a method, a function module, a subroutine, and so on. There are two ways a class-based exception can
be raised:
Exceptions raised by ABAP runtime system e.g.
x = 1 / 0.
This will result in a run time error of type cx_sy_zerodivide.
Exceptions raised by programmer.This can be done in two ways:
1. Raise and create an exception object simultaneously.
2. Raise an exception with an exception object that already exists In the first scenario, use the syntax:
RAISE EXCEPTION TYPE <EX_CLASS>
[EXPORTING a1 = ... b1 = ... ]
Values to the exception class constructor can be passed using exporting parameters.
In the second, scenario when an exception object already exists. Use the following syntax
RAISE EXCEPTION exep.
Note that exep must be an object variable bound to an exception object instance.
Catching and Handling Exceptions
Handlers are used to "catch" class-based exceptions. Handlers can be defined in following way:
Handlers are defined for statements in a TRY block.
The TRY block, together with the handlers, is defined by the construct- TRY... ENDTRY
Within the TRY ENDTRY construct, each handler is specified by a CATCH statement followed by the exception class.
The TRY block comprises all statements between TRY and the first CATCH.
The statements following the CATCH clause are executed only if the handler catches an exception.
Each exception is caught only once, by the first suitable handler i.e. if the catch clause lists either the class of the exception or a super
class of it.
A handler consists of all statements between its CATCH clause and the CATCH clause of the next handler (or ENDTRY, if there are no
more handlers).
Each handler can catch more than one type of exceptions i.e. the exceptions of particular class and its subclasses.
The sequence of handlers is important.
If a procedure is called within a TRY block, the appropriate handlers in the corresponding TRY ... ENDTRY construct will also catch all
exceptions that are raised but not caught within that procedure.
If the system cannot find an appropriate handler in a TRY ... ENDTRY construct, it searches for handlers in the next outer TRY ...
ENDTRY construct. if it cannot find an appropriate handler there either, it continues the search. If it eventually finds a handler which may
be several steps upward in the call hierarchy
Syntax:
TRY. "Begin of try block
"Write code here which raises an exception
CATCH <EX_CLASS1> <SUBCLASS1><SUBCLASS2>.
"For catching exceptions of class <EX_CLASS1>
"Including the subclasses. <SUBCLASS1> & <SUBCLASS2>.
"Any no of statements
CATCH<EX_CLASS2>. "For catching exceptions of class <EX_CLASS2>
"Including all the subclasses.
"Any no of statements
CATCH cx_root. "For catching catchable exceptions of all kinds
" Any number of statements
ENDTRY.
Why is the sequence of handlers important?
Suppose there are two handlers with one of the handlers with class cx_root. If the order of the two handlers were swapped, the system would use
the handler for all exceptions of the class cx_root and the other handler would never be used. To avoid this, the compiler always checks that
handlers are listed in the program in ascending order, with respect to inheritance.
The CLEANUP clause.
When a handler catches an exception, the normal flow of control is changed. In many cases, ending procedures prematurely in this way causes
objects to be left in an inconsistent state or prevents resources from being released. In particular, if the system jumps several levels up the
hierarchy, the handler might not be able to take the appropriate corrective measures. For this reason, there is another clause for the TRY
construct: the CLEANUP clause, it consists of the keyword CLEANUP and a number of statements that form the CLEANUP block.
The statements of the CLEANUP block are executed whenever an exception occurs in a TRY block that is not caught by the handler of the same
TRY ... ENDTRY construct, but rather in a surrounding TRY construct. Within the CLEANUP clause, the system can, for example, restore an
object to a consistent state or release external resources.
Each TRY ... ENDTRY construct contains a maximum of one CLEANUP clause. You must include it after the last CATCH and before the ENDTR
Y, if at all
Syntax:
TRY. "Begin of try block
"Write code here which may raise an exception
CATCH <EX_CLASS1> <SUBCLASS1><SUBCLASS2>.
"For catching exceptions of class <EX_CLASS1>
"Including the subclasses. <SUBCLASS1> & <SUBCLASS2>.
. "Any no of statements
CATCH<EX_CLASS2>. "For catching exceptions of class <EX_CLASS2>
"Including all the subclasses.
"Any no of statements
*CATCH *cx_root. "For catching catchable exceptions of all kinds
"Any number of statements
CLEANUP.
"Cleanup block
"Statements to restore consistent state
ENDTRY.
Defining Exceptions
Exception classes can be global or local classes. When creating a global exception class, the Class Builder ensures that its name follows the CX
_ prefix naming convention. Exceptions have some specific properties e.g., each exception has an explanatory text assigned to it that describes
the exception.
Constructors for Exceptions
Exceptions are usually created and raised immediately. After calling the constructor of an exception, you usually do not invoke a sequence of set
methods or attribute assignments. That means that all attributes are usually set via the constructor. Following this observation, the exception
constructor is automatically created as soon as you save the exception class; it has one optional parameter for each non-private attribute.
Texts for Exceptions
Each exception has an explanatory text assigned to it that describes the exception. The text is used for error analysis in error logs or short dumps
and therefore describes the exception from a technical point of view. A good user interface therefore usually catches exceptions and describes
the error from a user point of view, instead of simply forwarding the technical message from the exception object.
For texts to adequately describe an exception, you have to be able to set parameters for them.
Attributes can be included in the text by using the name of the attribute surrounded by "&, "as in "&nameofattribute&.If you want the "&"symbol to
appear in the actual text, you have to enter it twice.
Consider the following example:
'I am with &obj1& && &obj2&'
With the following attributes:
obj1 = 'Ankit'
obj2 = 'Bhuvesh'
1.
2.
Produces the following text:
'I am with Ankit & Bhuvesh'
Attributes and Methods of Exceptions
Exception classes inherit the following attributes from cx_root:
Textid - Used to define different texts for exceptions of a particular class, as explained above. Affects the result of the method get_text
(see below).
Previous - If one exception is mapped to another, this attribute can store the original exception, which allows you to build a chain of
exceptions. if a runtime error occurs, the short dump contains the texts belonging to all the exceptions in the chain. Mapping one
exception to another may be advisable if, for example, the context in which the first exception occurred is important for characterizing the
error situation represented by the second exception (see the upcoming section "Mixed Use of Class-Based and Non-Class-Based
Exceptions"). Exception classes inherit the following methods from cx_root:
get_text - Returns the textual representation as a string, according to the system language of the exception, as explained earlier in the
section "Texts for Exceptions"
get_longtext (available only since 6.20) - Returns the long variant of the textual representation of the exception as a string, in the Class
Builder, you can also specify a long text for each exception ID.
get_source_position - Returns the program name, include name, and line number reached where the exception was raised.
Examples of exception handling
Example1:
Simple usage of the Try-Catch Block.
Description
In this example I have taken two parameters of character type. I am dividing the first parameter by second parameter to get the result in a float
type variable.
There can be two types of exceptions that can be generated in this code.
Number conversion error.
Divide by zero exception.First handler catches cx_sy_conversion_no_number exceptions class and the second handler catches
Cx_sy_zerodivide exceptions
Get_text ( ) method of the exception classes is used to get the description of exception
DATA: result TYPE p LENGTH 10 DECIMALS 3,
ex_ref TYPE REF TO cx_root,
msg_text TYPE string.
PARAMETERS: value1 TYPE char40,
value2 TYPE char40.
TRY .
* divide v1 by v2
result = value1 / value2.
CATCH cx_sy_zerodivide INTO ex_ref.
msg_text = ex_ref->get_text( ).
CATCH cx_sy_conversion_no_number INTO ex_ref.
msg_text = ex_ref->get_text( ).
CATCH cx_root INTO ex_ref.
msg_text = ex_ref->get_text( ).
ENDTRY.
IF NOT msg_text IS INITIAL.
WRITE / msg_text.
ELSE.
WRITE: / 'Result :', result.
1.
2.
3.
4.
5.
6.
7.
8.
ENDIF.
Program flow is as follows:
At selection screen user enters the two parameters' values.
Program divides the value1 by value2.
If division is successful the result is stored in variable 'result'.
If the value2 is 0, an exception of type cx_sy_zerodivide exception is raised by the system. The exception is caught in the
corresponding exception block and msg_text is set with the appropriate error message with the help of method get_text of exception
class.
If characters are given as value1 or value2, an exception of type cx_sy_conversion_no_number, exception class is raised by the
system. The exception is caught in the corresponding exception block and msg_text is set with the appropriate error message with the
help of method get_text of exception class.
If there is any other unknown exception that will be caught in catch for cx_root exception class.
At the end if there is any exception them msg_text will not be initial. So msg_text is printed with the help of write statement.
Else the result variable is printed with the help of write statement.
Example2.
Use of Raising Exception keyword and Cleanup block.
This example is a slight modification to the previous example. In this example If any of the numbers input by user exceeds 1000 an
The calculation is done in a perform which propagates the exceptions of type cx_sy_arithmetic_error to the main program whereas the
exceptions of type cx_sy_zerodivide are handled by perform itself.
Cleanup block is utilized to clear the value of result in case of error.
DATA: result TYPE p LENGTH 10 DECIMALS 3,
ex_ref TYPE REF TO cx_root,
msg_text TYPE string.
PARAMETERS: value1 TYPE I,
value2 TYPE I.
TRY.
IF ABS( value1 ) > 1000 OR
ABS( value2 ) > 1000.
RAISE EXCEPTION TYPE cx_demo_abs_too_large.
ENDIF.
PERFORM calculation USING value1
value2
CHANGING result
msg_text.
CATCH cx_sy_arithmetic_error INTO ex_ref.
msg_text = ex_ref->get_text( ).
CATCH cx_root INTO ex_ref.
msg_text = ex_ref->get_text( ).
ENDTRY.
IF NOT msg_text IS INITIAL.
WRITE / msg_text.
ENDIF.
WRITE: / 'Final result:' result.
*&----------------------------------------------------------------------------------
*& Form calculation
*&----------------------------------------------------------------------------------
FORM calculation USING p_value1 LIKE value1
p_value2 LIKE value2
CHANGING p_result LIKE result
p_text LIKE msg_text
RAISING cx_sy_arithmetic_error.
DATA l_ex_ref TYPE REF TO cx_root.
TRY.
p_result = p_value1 / p_value2.
WRITE: / 'Result of division:', p_result.
CATCH cx_sy_zerodivide INTO l_ex_ref.
p_text = l_ex_ref->get_text( ).
CLEANUP.
CLEAR p_result.
ENDTRY.
ENDFORM. "calculation