Difference between revisions of "SAP ABAP DYNAMIC"

From SapWiki
Line 296: Line 296:
  
 
===Saber si un dato es de tipo moneda, EX02===
 
===Saber si un dato es de tipo moneda, EX02===
   <nowiki
+
   <nowiki>
 
TYPES: BEGIN OF ty_pernr,
 
TYPES: BEGIN OF ty_pernr,
 
         pernr  TYPE p0001-pernr,
 
         pernr  TYPE p0001-pernr,

Revision as of 19:18, 6 September 2021

Jerarquía Tipo CLase

CL_ABAP_TYPEDESCR
  CL_ABAP_DATADESCR
    CL_ABAP_ELEMDESCR
    CL_ABAP_REFDESCR
    CL_ABAP_COMPLEXDESCR
      CL_ABAP_TABLEDESCR
      CL_ABAP_STRUCTDESCR
  CL_ABAP_OBJECTDESCR
    CL_ABAP_CLASSDESCR
    CL_ABAP_INTFDESCR

Ejemplo 01: generar archivo CSV independiente del tipo

FORM crear_csv USING p_tabla TYPE ANY TABLE
            CHANGING p_tabla_csv TYPE ppe_cust_table.

  CONSTANTS: c_field_separator TYPE c VALUE ';',
             c_darl_number(12) TYPE c VALUE '1234567890 '.

  DATA: cl_descr_struc_ref TYPE REF TO cl_abap_structdescr,
        it_components      TYPE abap_compdescr_tab,
        wa_components      LIKE LINE OF it_components.

  DATA lt_data TYPE ppe_cust_table.

  DATA: l_struc_index     TYPE syindex,
        l_len_string      TYPE i,
        l_max_field       TYPE char1024,
        l_struc_raw_data  TYPE char1024,
        l_start_string    TYPE i,
        l_len_field_sep   TYPE i,
        l_date_extern(30) TYPE c,
        l_help_id         LIKE tline-tdline,
        l_tabix           TYPE sytabix.

  FIELD-SYMBOLS <fs_field> TYPE ANY.
  FIELD-SYMBOLS <ls_envio> TYPE ANY.

  l_len_field_sep = STRLEN( c_field_separator ).

  LOOP AT p_tabla ASSIGNING <ls_envio>.
    CLEAR: l_struc_index, l_len_string, l_struc_raw_data, l_start_string.

    IF it_components[] IS INITIAL.
      cl_descr_struc_ref ?= cl_abap_typedescr=>describe_by_data( <ls_envio> ).
* obtener campos de estructura
      it_components = cl_descr_struc_ref->components.
    ENDIF.

    DO.
      ADD 1 TO l_struc_index.
      CLEAR l_len_string.
      READ TABLE it_components INTO wa_components INDEX sy-index.
      IF sy-subrc = 0.
        ASSIGN COMPONENT wa_components-name OF STRUCTURE <ls_envio> TO <fs_field>.

        CASE wa_components-type_kind .
          WHEN 'P'.
            WRITE <fs_field> TO l_date_extern.
            CATCH SYSTEM-EXCEPTIONS conversion_errors  = 4.
              IF sy-subrc <> '0'.
*                MESSAGE e899(ux) WITH l_type <f_source> l_help_id
*                                      l_tabix RAISING conversion_failed.
              ENDIF.
            ENDCATCH.
            CONDENSE l_date_extern.
            ASSIGN l_date_extern TO <fs_field>.
          WHEN 'D'.
            MOVE <fs_field> TO l_date_extern.
*20191220 -> 20/12/2019
            REPLACE FIRST OCCURRENCE OF REGEX '(\d{4})(\d{2})(\d{2})' IN l_date_extern
                                           WITH '$3/$2/$1'.
        ENDCASE.

      ELSE.
        EXIT.
      ENDIF.

      IF l_struc_index <> 1.
        l_max_field+l_len_string(l_len_field_sep) = c_field_separator.
        l_len_string = l_len_field_sep.
      ENDIF.

      l_max_field+l_len_string = <fs_field>.
      l_len_string = STRLEN( l_max_field ).
      CHECK l_len_string <> '0'.
      l_struc_raw_data+l_start_string(l_len_string) = l_max_field.
      l_start_string = l_start_string + l_len_string.
    ENDDO.

    APPEND l_struc_raw_data TO lt_data.

  ENDLOOP.

  p_tabla_csv[] = lt_data[].
ENDFORM.                    "crear_csv

Ejemplo 02: leer archivo desde servidor separado por tabs, independiente del tipo

types: ty_t001 type t001.
  DATA lt_t001 TYPE STANDARD TABLE OF ty_t001.

  PERFORM open_un USING '/tmp/t001_dat2.txt' CHANGING lt_t001.

FORM open_un USING p_file
          CHANGING p_table TYPE ANY TABLE.
  DATA: lr_structdescr TYPE REF TO cl_abap_structdescr,
        lr_datadescr   TYPE REF TO cl_abap_datadescr,
        lr_tabledescr  TYPE REF TO cl_abap_tabledescr,
        line_descr TYPE REF TO cl_abap_typedescr.
  DATA: l_string  TYPE string,
        l_string2 TYPE string,
        l_campo   TYPE string,
        ld_name TYPE string.
  FIELD-SYMBOLS: <fs> TYPE any,
                 <wa> TYPE any.
  DATA: wa_ref TYPE REF TO data.

  lr_tabledescr ?= cl_abap_tabledescr=>describe_by_data( p_table ).
  line_descr = lr_tabledescr->get_table_line_type( ).
  ld_name = line_descr->get_relative_name( ).
*     get the field list of the table linetype
  DATA(lt_components) = CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_name( ld_name ) )->components.

  CREATE DATA wa_ref TYPE (ld_name).   "Suitable work area
  ASSIGN wa_ref->* TO <wa>.

  OPEN DATASET p_file FOR INPUT IN TEXT MODE
                            ENCODING DEFAULT
                            WITH SMART LINEFEED.
  IF sy-subrc <> 0.
    RETURN.
  ENDIF.

  WHILE sy-subrc = 0.
    READ DATASET p_file INTO l_string.
    CHECK l_string IS NOT INITIAL.
    DATA(l_index) = 1.
    WHILE l_string IS NOT INITIAL.
      SPLIT l_string AT cl_abap_char_utilities=>horizontal_tab INTO l_string2 l_string.
      READ TABLE lt_components INTO data(ls_comp) INDEX l_index.
      IF sy-subrc = 0.
        ADD 1 TO l_index.
        CONCATENATE '<WA>' ls_comp-name INTO l_campo SEPARATED BY '-'.
        ASSIGN (l_campo) TO <fs>.
        MOVE l_string2 TO <fs> .
      ELSE.
        EXIT.
      ENDIF.
    ENDWHILE.
    INSERT <wa> INTO TABLE p_table.
  ENDWHILE.

ENDFORM.

Crear archivo CSV

Llamar a una Función dinamicamente

DATA: fm_name   TYPE string,
      filename  TYPE string,
      filetype  TYPE c LENGTH 10,
      text_tab  LIKE STANDARD TABLE OF line,
      fleng     TYPE i,
      ptab      TYPE abap_func_parmbind_tab,
      ptab_line LIKE LINE OF ptab,
      etab      TYPE abap_func_excpbind_tab,
      etab_line LIKE LINE OF etab.

fm_name = 'GUI_DOWNLOAD'.
filename = 'C:\temp\pepetrueno.txt'.
filetype = 'ASC'.

ptab_line-name = 'FILENAME'.
ptab_line-kind = abap_func_exporting.
GET REFERENCE OF filename INTO ptab_line-value.
INSERT ptab_line INTO TABLE ptab.

ptab_line-name = 'FILETYPE'.
ptab_line-kind = abap_func_exporting.
GET REFERENCE OF filetype INTO ptab_line-value.
INSERT ptab_line INTO TABLE ptab.

data lt_t001 type TABLE OF t001.
select * into table lt_t001 from t001.

ptab_line-name = 'DATA_TAB'.
ptab_line-kind = abap_func_tables.
GET REFERENCE OF lt_t001 INTO ptab_line-value.
INSERT ptab_line INTO TABLE ptab.

ptab_line-name = 'FILELENGTH'.
ptab_line-kind = abap_func_importing.
GET REFERENCE OF fleng INTO ptab_line-value.
INSERT ptab_line INTO TABLE ptab.

* prepare exception-table
 data: lt_except           type abap_func_excpbind_tab,
       wa_except          like line of lt_except.

  wa_except-name = 'OTHERS'.
  wa_except-value = 22.
  insert wa_except into table lt_except.

   try.
    call function fm_name
         parameter-table ptab[]
         exception-table lt_except[].
  catch cx_sy_dyn_call_error.
    exit.
  endtry.

* extract return parameters out of table ptab
  read table ptab with key name = 'FILELENGTH'
                         kind = abap_func_importing
                    into ptab_line.

* get content as field symbol
  field-symbols: <filelength> type i.
  assign ptab_line-value->* to <filelength>.

  write:/ <filelength>.

Llamar a un Método dinamicamente

DATA: line     TYPE c LENGTH 80,
      text_tab LIKE STANDARD TABLE OF line,
      filename TYPE string,
      filetype TYPE c LENGTH 10,
      fleng    TYPE i.

DATA: meth  TYPE string,
      class TYPE string,
      ptab TYPE abap_parmbind_tab,
      etab TYPE abap_excpbind_tab.

DATA: exc_ref TYPE REF TO cx_sy_dyn_call_error.

class    = 'CL_GUI_FRONTEND_SERVICES'.
meth     = 'GUI_DOWNLOAD'.
filename = 'c:\temp\text.txt'.
filetype = 'ASC'.

ptab = VALUE #( ( name  = 'FILENAME'
                  kind  = cl_abap_objectdescr=>exporting
                  value = REF #( filename ) )
                ( name  = 'FILETYPE'
                  kind  = cl_abap_objectdescr=>exporting
                  value = REF #( filetype ) )
                ( name  = 'DATA_TAB'
                  kind  = cl_abap_objectdescr=>changing
                  value = REF #( text_tab ) )
                ( name  = 'FILELENGTH'
                  kind  = cl_abap_objectdescr=>importing
                  value = REF #( fleng ) ) ).

etab = VALUE #( ( name = 'OTHERS' value = 4 ) ).

TRY.
    CALL METHOD (class)=>(meth)
      PARAMETER-TABLE
        ptab
      EXCEPTION-TABLE
        etab.
    CASE sy-subrc.
      WHEN 4.

    ENDCASE.
  CATCH cx_sy_dyn_call_error INTO exc_ref.
    MESSAGE exc_ref->get_text( ) TYPE 'I'.
ENDTRY.

Ejemplos Varios

Saber si un dato es de tipo moneda

TYPES: BEGIN OF ty_pernr,
         pernr  TYPE p0001-pernr,
         begda  TYPE begda,
         dias   TYPE i,
         sueldo TYPE pad_amt7s,
       END OF ty_pernr.

DATA: ls_pernr     TYPE ty_pernr.

  FIELD-SYMBOLS: <lv_data>      TYPE data.
  DATA: lr_descr        TYPE REF TO cl_abap_elemdescr,
        lt_ddic_info    TYPE dd_x031l_table,
        lrs_ddic_info   TYPE REF TO x031l.
*--------------------------------------------------------------------*
  ASSIGN ls_pernr-sueldo to <lv_data>.
  lr_descr ?= cl_abap_elemdescr=>describe_by_data( <lv_data> ).
  lt_ddic_info = lr_descr->get_ddic_object( ).

  READ TABLE lt_ddic_info INDEX 1 REFERENCE INTO lrs_ddic_info.
  IF sy-subrc = 0.
    if lrs_ddic_info->dtyp = 'CURR'.
    endif.
  ENDIF.

Saber si un dato es de tipo moneda, EX02

 
TYPES: BEGIN OF ty_pernr,
         pernr  TYPE p0001-pernr,
         begda  TYPE begda,
         dias   TYPE i,
         sueldo TYPE pad_amt7s,
         waers  TYPE waers,
       END OF ty_pernr.

DATA: lt_pernr     TYPE TABLE OF ty_pernr,
      ls_pernr     TYPE ty_pernr.

DATA: lr_tab        TYPE REF TO data,
      lr_typedesc   TYPE REF TO cl_abap_typedescr,
      lr_tabdesc    TYPE REF TO cl_abap_tabledescr,
      lr_datadesc   TYPE REF TO cl_abap_datadescr,
      lr_structdesc TYPE REF TO cl_abap_structdescr.
DATA: lt_campo TYPE cl_abap_structdescr=>component_table,
      ls_campo TYPE abap_componentdescr.

DATA: lr_descr      TYPE REF TO cl_abap_elemdescr,
      lt_ddic_info  TYPE dd_x031l_table,
      lrs_ddic_info TYPE REF TO x031l.
*--------------------------------------------------------------------*
DATA l_struc_index TYPE i.
DATA l_date_extern(30) TYPE c.

FIELD-SYMBOLS: <ls_structcomp> TYPE abap_compdescr.
FIELD-SYMBOLS: <lv_data>      TYPE data.
FIELD-SYMBOLS <fs_field> TYPE any.
FIELD-SYMBOLS <fs_field2> TYPE any.

ls_pernr-pernr = '00000001'.
ls_pernr-begda = sy-datum.
ls_pernr-sueldo = 6200.
ls_pernr-dias = 30.
ls_pernr-waers = 'CLP'.

ASSIGN ls_pernr TO <lv_data>.
lr_structdesc ?= cl_abap_typedescr=>describe_by_data( <lv_data> ).

lt_campo = lr_structdesc->get_components( ).

DO.
  ADD 1 TO l_struc_index.
  READ TABLE lt_campo INTO ls_campo INDEX sy-index.
  IF sy-subrc = 0.
    ASSIGN COMPONENT ls_campo-name OF STRUCTURE <lv_data> TO <fs_field>.
    CASE ls_campo-type->type_kind. .
      WHEN 'P'.
        lr_descr ?= cl_abap_elemdescr=>describe_by_data( <fs_field> ).
        lt_ddic_info = lr_descr->get_ddic_object( ).
        READ TABLE lt_ddic_info INDEX 1 REFERENCE INTO lrs_ddic_info.
        IF sy-subrc = 0.
          IF lrs_ddic_info->dtyp = 'CURR'.
            ASSIGN COMPONENT 'WAERS' OF STRUCTURE <lv_data> TO <fs_field2>.
            WRITE <fs_field> TO l_date_extern CURRENCY <fs_field2> NO-GROUPING.
            CONDENSE l_date_extern.
          else.
             WRITE <fs_field> TO l_date_extern NO-GROUPING.
             CONDENSE l_date_extern.
          ENDIF.
        ENDIF.
        when OTHERS.
* do something
    ENDCASE.
  ELSE.
    EXIT.
  ENDIF.
ENDDO.</nowiki

===Ejemplos===
 <nowiki>DATA l_matnr type matnr VALUE '100'.
DATA dref TYPE REF TO data.
FIELD-SYMBOLS <fs> TYPE any.
GET REFERENCE OF l_matnr into dref.
ASSIGN dref->* TO <fs>.
WRITE <fs>.
***********************************************************************
FIELD-SYMBOLS <fs> TYPE DATA.
DATA dref TYPE REF TO DATA.
CREATE DATA dref TYPE i.
ASSIGN dref->* TO <fs>.
<fs> = 5.
***********************************************************************
TYPES: ty_type TYPE p DECIMALS 2.
DATA: v_data TYPE ty_type,
r_typedescr TYPE REF TO cl_abap_typedescr.

START-OF-SELECTION.

r_typedescr = cl_abap_typedescr=>describe_by_data( v_data ).
WRITE: / 'Kind:', r_typedescr->type_kind.
WRITE: / 'Length:', r_typedescr->length.
WRITE: / 'Decimals:', r_typedescr->decimals.
***********************************************************************
DATA l_text(8) TYPE c VALUE '20111201'.
FIELD-SYMBOLS <fs> TYPE sy-datum.
ASSIGN l_text TO <fs> CASTING.
WRITE <fs>.
***********************************************************************
DATA: r_typedescr TYPE REF TO cl_abap_typedescr,
      r_structdescr TYPE REF TO cl_abap_structdescr,
      r_tabledescr TYPE REF TO cl_abap_tabledescr,
      r_table TYPE REF TO data,
      components TYPE cl_abap_structdescr=>component_table,
      component LIKE LINE OF components,
      ro_alv TYPE REF TO cl_salv_table.
FIELD-SYMBOLS : <table> TYPE ANY TABLE.

FORM get_table .
  r_typedescr = cl_abap_typedescr=>describe_by_name( p_table ).
  TRY.
    r_structdescr ?= r_typedescr.
    CATCH cx_sy_move_cast_error.
  ENDTRY.
  components = r_structdescr->get_components( ).
  TRY.
    r_structdescr = cl_abap_structdescr=>get( components ).
    r_tabledescr = cl_abap_tabledescr=>get( r_structdescr ).
    CATCH cx_sy_struct_creation.
    CATCH cx_sy_table_creation .
  ENDTRY.
  TRY.
    CREATE DATA r_table TYPE HANDLE r_tabledescr.
    ASSIGN r_table->* TO <table>.
    CATCH cx_sy_create_data_error.
  ENDTRY.
  TRY.
    SELECT *
    FROM (p_table)
    INTO CORRESPONDING FIELDS OF TABLE <table> WHERE (p_where).
    CATCH cx_sy_sql_error.
  ENDTRY.
ENDFORM.

Crear tabla

FORM form01 USING p_tabla TYPE STANDARD TABLE.
  FIELD-SYMBOLS <work_tab> TYPE ANY TABLE.
  DATA work_tab_ref TYPE REF TO data.

  CREATE DATA work_tab_ref LIKE p_tabla[].

  ASSIGN work_tab_ref->* TO <work_tab>.

ENDFORM.

FORM form02.
  FIELD-SYMBOLS <pannnn_wa> TYPE any.
  FIELD-SYMBOLS <pacccc_wa> TYPE c.
  FIELD-SYMBOLS <pannnn>    TYPE STANDARD TABLE.

  DATA dbtab         TYPE t777d-dbtab.
  DATA pannnn_ref    TYPE REF TO data.
  DATA pannnn_wa_ref TYPE REF TO data.

  dbtab = 'PA0008'.
  CREATE DATA pannnn_ref TYPE STANDARD TABLE OF (dbtab).
  ASSIGN pannnn_ref->* TO <pannnn>.
  CREATE DATA pannnn_wa_ref TYPE (dbtab).
  ASSIGN pannnn_wa_ref->* TO <pannnn_wa>.
  ASSIGN <pannnn_wa> TO <pacccc_wa> CASTING.

  SELECT * FROM (dbtab) INTO TABLE <pannnn> UP TO 100 ROWS.

  LOOP AT <pannnn> INTO <pannnn_wa>.
  ENDLOOP.

ENDFORM.

Crear tabla basado en campos

Tomar componentes de tabla T001, menos columna MANDT, y asignarlos dinamicamente a tabla interna.

FORM crear.
  DATA: struct_type TYPE REF TO cl_abap_structdescr,
        itab_type   TYPE REF TO cl_abap_tabledescr,
        comp_tab    TYPE cl_abap_structdescr=>component_table.

  DATA: lr_tabdata TYPE REF TO data.
  FIELD-SYMBOLS: <lt_table> TYPE STANDARD TABLE.

  struct_type ?= cl_abap_typedescr=>describe_by_name( 'T001' ).

  CALL METHOD struct_type->get_components
    RECEIVING
      p_result = comp_tab.

  DELETE TABLE comp_tab WITH TABLE KEY name = 'MANDT'.
  TRY.
      CALL METHOD cl_abap_structdescr=>create
        EXPORTING
          p_components = comp_tab
*         p_strict     = TRUE
        RECEIVING
          p_result     = struct_type.
    CATCH cx_sy_struct_creation .
  ENDTRY.

  itab_type = cl_abap_tabledescr=>create( struct_type ).

* combine
  CREATE DATA lr_tabdata TYPE HANDLE itab_type.
  ASSIGN lr_tabdata->* TO <lt_table>.

ENDFORM.

Combine

form combine_recs_by_key using
                           it_keys type abap_keydescr_tab
                         changing
                           ct_data type standard table
                         .

  data:
      lr_tabdata type ref to data
    , lo_line_type  type ref to cl_abap_structdescr
    , lo_tab_type   type ref to cl_abap_tabledescr
      .
  field-symbols:
      <lt_combined> type sorted table
    , <ls_line>     type any
    .

* create new table with key
  lo_tab_type ?= cl_abap_tabledescr=>describe_by_data( ct_data ).
  lo_line_type ?= lo_tab_type->get_table_line_type( ).
  call method cl_abap_tabledescr=>create
    exporting
      p_line_type  = lo_line_type
      p_table_kind = cl_abap_tabledescr=>tablekind_sorted
      p_unique     = abap_true
      p_key        = it_keys
      p_key_kind   = cl_abap_tabledescr=>keydefkind_user
    receiving
      p_result     = lo_tab_type.

* combine
  create data lr_tabdata type handle lo_tab_type.
  assign lr_tabdata->* to <lt_combined>.

  loop at ct_data assigning <ls_line>.
    collect <ls_line> into <lt_combined>.
  endloop.

  clear ct_data.
  loop at <lt_combined> assigning <ls_line>.
    append <ls_line> to ct_data.
  endloop.
  sort ct_data.

endform.                    " combine_recs_by_key