Programación dinámica <fs_wa>-matrnr

Hola a Todos…
Estaba probando sobre este tema que esta en el libro TAW12-01 Leción 6.
En esta se muestra un programa de Ejemplo de SAP SAPBC402_DYND_DATADECL.

*&---------------------------------------------------------------------*
*& Report  SAPBC402_DYND_DATADECL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT  sapbc402_dynd_datadecl.

*----------------------------------------------------------------------*
DATA:
    gr_itab TYPE REF TO data,
    gr_wa   TYPE REF TO data.

*----------------------------------------------------------------------*
FIELD-SYMBOLS:
    <fs_itab> TYPE ANY TABLE,
    <fs_wa>   TYPE ANY,
    <fs_comp> TYPE ANY.

*----------------------------------------------------------------------*
PARAMETERS
    pa_tab TYPE dd02l-tabname DEFAULT 'SPFLI'.


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

  CREATE DATA gr_itab TYPE STANDARD TABLE OF (pa_tab)
                       WITH NON-UNIQUE DEFAULT KEY.

  ASSIGN gr_itab->* TO <fs_itab>.

  SELECT * FROM (pa_tab)
      INTO TABLE <fs_itab>
      UP TO 100 ROWS.

  CREATE DATA gr_wa LIKE LINE OF <fs_itab>.         "or: TYPE (pa_tab).

  ASSIGN gr_wa->* TO <fs_wa>.

  LOOP AT <fs_itab> ASSIGNING <fs_wa>.
    DO.
      ASSIGN COMPONENT sy-index OF STRUCTURE <fs_wa> TO <fs_comp>.
      IF sy-subrc NE 0.
        NEW-LINE.
        EXIT.
      ENDIF.

      WRITE <fs_comp>.
    ENDDO.
  ENDLOOP.

Durante la explicación de este código menciona lo siguiente:
Si conoce los nombres de los componentes, podría visualizar los campos
directamente mediante WRITE <fs_wa>-…

Entonces intente codificarlo para comprobar, por ejemplo si lo llamo con la tabla MARA.


Pero el compilador no me permite pasar
Si estoy en tiempo de ejecución y busco la variable si se puede.

La pregunta es: a que se refiere el libro con… conocer los campos ?
alguna ayuda…
Saludos…

1 me gusta

No será que tienes que ponerle los nombres técnicos de los campos?

PD: @Abapers, una mano aquí :slight_smile:

Gracias…
Me refiero es a que yo si se el nombre el campo, pero poniendo el nombre en el programa me da error…
Entonces quiero entender como se codifica correctamente.

Para poder referenciar a un campo en concreto de una tabla, o lo haces como dice del assing-component (para hacerlo totalmente dinámico) o entonces la tabla tiene que tener la estructura deseada:

FIELD-SYMBOLS: <tab> type mara.
<tab>-matnr = '33'.

Para hacerlo para cualquier tabla (un ejemplo):

DATA:
      descr_ref TYPE REF TO cl_abap_typedescr,
      lv_subrc TYPE sysubrc.

FIELD-SYMBOLS: 
               <campo> TYPE ANY,
               <c_estructura> type any.

  WHILE lv_subrc = 0.
    ASSIGN COMPONENT sy-index OF STRUCTURE <c_estructura> TO <campo>.
    lv_subrc = sy-subrc.
    descr_ref = cl_abap_typedescr=>describe_by_data( <campo> ).

    IF ( descr_ref->type_kind = 'C'  OR " char
         descr_ref->type_kind = 'D' ). "STRING
      CONDENSE <campo>.
    ENDIF.
  ENDWHILE.
1 me gusta

Gracias Salco…
No logro usarlo correctamente…

REPORT ZPRUEBA.
*----------------------------------------------------------------------*
DATA:
      gr_itab TYPE REF TO data,
      gr_wa   TYPE REF TO data,
      descr_ref TYPE REF TO cl_abap_typedescr,
      lv_subrc TYPE sysubrc.

FIELD-SYMBOLS:
               <fs_itab> TYPE TABLE,
               <campo> TYPE ANY,
               <c_estructura> type TABLE.

*----------------------------------------------------------------------*
PARAMETERS:
    pa_tab    TYPE dd02l-tabname  DEFAULT 'SPFLI'.

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

CREATE DATA gr_itab TYPE STANDARD TABLE OF (pa_tab)
                       WITH NON-UNIQUE DEFAULT KEY.
  ASSIGN gr_itab->* TO <c_estructura>.

  SELECT * FROM (pa_tab)
      INTO TABLE <c_estructura>
      UP TO 30 ROWS.


   WHILE lv_subrc = 0.
    ASSIGN COMPONENT sy-index OF STRUCTURE <c_estructura> TO <campo>.
    lv_subrc = sy-subrc.
    descr_ref = cl_abap_typedescr=>describe_by_data( <campo> ).

    IF ( descr_ref->type_kind = 'C'  OR " char
         descr_ref->type_kind = 'D' ). "STRING
      CONDENSE <campo>.
    ENDIF.
    WRITE: <campo>.
  ENDWHILE

<img src="/uploads/db7262/original/2X/f/f7b6341af968b10cc1028a68cffac2f67a2c87e0.png" width="483" height="500">
<img src="/uploads/db7262/original/2X/c/c3930f2c5aebe19634f1dfb8c2c119ba3082637f.png" width="497" height="500">
<img src="/uploads/db7262/original/2X/d/dbb1f9eee7dc3820e95f68ac3db9f8139c94f0fa.png" width="690" height="162">

Ahí lo que sucede es que debes de condicionar esa linea que solo se ejecute cuando sy-subrc sea 0, bueno mas bien todo ese cogido que esta después de la asignación de sy-subrc debe ejecutarse si es igual a 0.

1 me gusta

Prueba así:

DATA:
      gr_itab TYPE REF TO data,
      gr_wa   TYPE REF TO data,
      descr_ref TYPE REF TO cl_abap_typedescr,
      lv_subrc TYPE sysubrc.

FIELD-SYMBOLS:
              <campo> TYPE ANY,
              <gt_tab> type TABLE,
              <gs_line> type any.

*----------------------------------------------------------------------*
PARAMETERS:
    pa_tab    TYPE dd02l-tabname  DEFAULT 'BNKA'.

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

CREATE DATA gr_itab TYPE STANDARD TABLE OF (pa_tab)
                       WITH NON-UNIQUE DEFAULT KEY.

  ASSIGN gr_itab->* TO <gt_tab>.

  SELECT * FROM (pa_tab)
      INTO TABLE <gt_tab>
      UP TO 30 ROWS.

LOOP AT <gt_Tab> ASSIGNING <gs_line>.
   WHILE lv_subrc = 0.
    ASSIGN COMPONENT sy-index OF STRUCTURE <gs_line> TO <campo>.
    lv_subrc = sy-subrc.
    descr_ref = cl_abap_typedescr=>describe_by_data( <campo> ).

    IF ( descr_ref->type_kind = 'C'  OR " char
         descr_ref->type_kind = 'D' ). "STRING
      CONDENSE <campo>.
    ENDIF.
    WRITE: <campo>.
  ENDWHILE.

ENDLOOP.

Lo que ocurría es que <c_estructura> no era una estructura sino una tabla.

1 me gusta

Gracias si imprime en pantalla los campos…
Lo que yo busco es: poder acceder a algunos elementos de la tabla que paso por referencia, de la forma como explica el Libro

<fs_wa>-matnr

Yo lo que me imagino es poder tener una tabla interna, PROPIETARIA, NO TABLA ESTÁNDAR, formada con Objetos de datos estándar.
Por ejemplo:

TYPES: BEGIN OF  TY_DATA_TO_PRINT,
        GESME TYPE LQUA-GESME,  "Cantidad
        MEINS TYPE T006A-MSEH3,  "Unidad de medida
        WDATU TYPE LQUA-WDATU,  "Fecha de entrada
        MATNR TYPE LQUA-MATNR,  "Clave de material
        LENUM TYPE LQUA-LENUM,  "Número de unidad de almacén
        LGPLA TYPE LQUA-LGPLA,  "Ubicación
        MAKTX TYPE MAKT-MAKTX,  "Descripción del material
END OF TY_DATA_TO_PRINT.

DATA it_toprint TYPE STANDARD TABLE OF ty_data_to_print.

Una vez teniendo esta tabla O CUALQUIER OTRA Des esto se trata.
Pasarle esta tabla como parte de un atributo a un método.
Y este método pueda hacer cosas con esta tabla:
Cosas como:
Agregar los textos de los materiales.
Enviarla a una impresión de un SapScript que imprime etiquetas
etc…
Lo que busco es escribir un código que se pueda usar Muchas veces, el mismo código, NO COPIAR Y PEGAR el mismo código en muchos programas.

Continuando.
Entonces no se le puede pasar la tabla al método porque tendría que poner la estructura en su firma y esto no permitirá que el método funcione cuando cambio la tabla.

Resulta que los las referencias pueden ser pasadas como parámetro. Pero los FIELD-SYMBOLS No.
Y no se puede acceder a la tabla tabla como, tal desde una referencia. Entonces dentro de la función se asigna la referencia a un Field-symbols.

Adjunto este ejemplo en donde lo intento:
La Clase:

* INLCUDE zlcl_dinamic

CLASS lcl_dinamic DEFINITION create PRIVATE.
    PUBLIC SECTION.

        CLASS-METHODS   write_tabla      IMPORTING  p_ref_itable TYPE REF TO data.
        ClASS-METHODS   mat_desc_text IMPORTING matnr type matnr
                        RETURNING VALUE(MAKTX)  type MAKTX.
ENDCLASS."-----------------------------------------------------------"


CLASS lcl_dinamic IMPLEMENTATION.

* <SIGNATURE>---------------------------------------------------------+
* | Instance Public Method lcl_dinamic=>write_tabla(p_ref_itable )
* +-------------------------------------------------------------------+
* | [--->] INPUT      ref_itable TYPE REF TO data
* +--------------------------------------------------------</SIGNATURE>
    METHOD  write_tabla."*********************
        DATA  ref_wa_itable   TYPE REF TO data.
        FIELD-SYMBOLS:
            <fs_itable>     TYPE ANY TABLE,
            <fs_wa_itable>  TYPE ANY,
            <fs_comp>       TYPE ANY.

       ASSIGN p_ref_itable->* TO <fs_itable>.
       CREATE DATA ref_wa_itable LIKE LINE OF <fs_itable>.
       ASSIGN ref_wa_itable->* TO <fs_wa_itable>.

        LOOP AT <fs_itable> ASSIGNING <fs_wa_itable>.
            <fs_wa_itable>-MAKT = mat_desc_text( <fs_wa_itable>-matnr ). "<=================
            MODIFY <fs_itable> FROM <fs_wa_itable>.
        ENDLOOP.

    ENDMETHOD."--------------------------------------


* <SIGNATURE>---------------------------------------------------------+
* | Instance Public Method LCL_dinamic=>mat_desc_text(matnr)
* +-------------------------------------------------------------------+
* | [--->] INPUT      matnr      TYPE  matnr
* | [<-()] RETURNING  MAKTX      TYPE  MAKTX
* +--------------------------------------------------------</SIGNATURE>
 METHOD mat_desc_text.

    DATA:  MAKT TYPE MAKT.  "TABLA TIPO MAKT

  CALL FUNCTION 'MAKT_SINGLE_READ'
    EXPORTING
        MATNR = matnr
        SPRAS = SY-LANGU
    IMPORTING
        WMAKT = MAKT
    EXCEPTIONS
      WRONG_CALL = 1
      NOT_FOUND = 2
      OTHERS = 3.
    CASE SY-SUBRC.
        WHEN 0.
            MAKTX = MAKT-MAKTX.
        WHEN OTHERS.
          CONCATENATE 'TEXTO NO ENCONTRADO PARA: ' matnr INTO MAKTX.
        ENDCASE.


 ENDMETHOD. "---------unit_text-----------------------------------------


ENDCLASS.

El Problema:

El programa que lo llama:

REPORT zdinamic.
    INCLUDE zlcl_dinamic.
**********************************************************************
* DECLARACION DE  VARIABLES                                          *
**********************************************************************
TYPES: BEGIN OF  TY_DATA_TABLE,
        GESME TYPE LQUA-GESME,  "Cantidad
        MEINS TYPE T006A-MSEH3,  "Unidad de medida
        WDATU TYPE LQUA-WDATU,  "Fecha de entrada
        MATNR TYPE LQUA-MATNR,  "Clave de material
        LENUM TYPE LQUA-LENUM,  "Número de unidad de almacén
        LGPLA TYPE LQUA-LGPLA,  "Ubicación
        MAKTX TYPE MAKT-MAKTX,  "Descripción del material
END OF TY_DATA_TABLE.

DATA it_table TYPE STANDARD TABLE OF ty_data_table.
DATA wa_it_table TYPE ty_data_table.

DATA  ref_itable TYPE ref to data.          " Referencia para pasar tablas como parametros

START-OF-SELECTION.

    SELECT         GESME MEINS
                   WDATU MATNR
                   LENUM LGPLA
    FROM           LQUA
    INTO CORRESPONDING FIELDS OF TABLE    it_table
    UP TO 10 ROWS.

 Loop at it_table into wa_it_table.
    WRITE: / wa_it_table-maktx.

 ENDLOOP.


GET REFERENCE OF it_table INTO ref_itable.
  lcl_dinamic=>write_tabla( ref_itable ).

Loop at it_table into wa_it_table.
    WRITE: / wa_it_table-maktx.

 ENDLOOP.

END-OF-SELECTION.

@ivanchodelat, yo tenía una estructura cualquiera y lo que me interesaba es que para los campos de esa estructura que fueran de tipo C o string quitara los blancos de los campos.
Lo que hice fue, crear una clase con la SE24 y un método que fuera quitar blancos. Yo le pasé una estructura pero para tu caso le puedes pasar una tabla.
La llamada es así:

CALL METHOD zutilidades=>quita_blancos
  CHANGING
    c_estructura = ls_recibos. 

A ese método le puedo pasar cualquier estructura, porque en la clase defino el parámetro con type any:

METHOD QUITA_BLANCOS.

  FIELD-SYMBOLS: <campo> TYPE ANY.
  DATA:
      descr_ref TYPE REF TO cl_abap_typedescr,
      lv_subrc TYPE sysubrc.

  lv_subrc = 0.

  WHILE lv_subrc = 0.
    ASSIGN COMPONENT sy-index OF STRUCTURE c_estructura TO <campo>.
    lv_subrc = sy-subrc.
    descr_ref = cl_abap_typedescr=>describe_by_data( <campo> ).

    IF ( descr_ref->type_kind = gc_c  OR " char
         descr_ref->type_kind = gc_g ). "STRING
      CONDENSE <campo>.
    ENDIF.
  ENDWHILE.

ENDMETHOD.

Lo que debes hacer es usar DESCRIBE_BY_NAME así ya sabes que el nombre del componente es MATNR para detectar las variables origen y destino.

2 Me gusta

Gracias realmente me ayudaste con tu ejemplo.
Lo hice un poco distinto pero con tu ejemplo entendí el concepto que me permitido escribirlo.

* <SIGNATURE>---------------------------------------------------------+
* | Instance Public Method GET REFERENCE OF it_table INTO ref_itable.
* |                    CALL METHOD lcl_dinamic=>write_tabla
* |                         CHANGING  p_ref_itable = ref_itable .
* +-------------------------------------------------------------------+
* | [--->] CHANGIN      ref_itable TYPE REF TO data
* +--------------------------------------------------------</SIGNATURE>
    METHOD  write_tabla."*********************
        FIELD-SYMBOLS: <campo> TYPE ANY.
            DATA  ref_wa_itable   TYPE REF TO data.
        FIELD-SYMBOLS:
            <fs_itable>         TYPE ANY TABLE,
            <fs_wa_itable>      TYPE ANY,
            <fs_comp1>          TYPE ANY,
            <fs_comp2>          TYPE ANY.
       ASSIGN p_ref_itable->* TO <fs_itable>.
       CREATE DATA ref_wa_itable LIKE LINE OF <fs_itable>.
       ASSIGN ref_wa_itable->* TO <fs_wa_itable>.

        LOOP AT <fs_itable> ASSIGNING <fs_wa_itable>.
             ASSIGN COMPONENT 'MATNR' OF STRUCTURE <fs_wa_itable> TO <fs_comp1>.
             ASSIGN COMPONENT 'MAKTX' OF STRUCTURE <fs_wa_itable> TO <fs_comp2>.
            <fs_comp2> = mat_desc_text( <fs_comp1> ) .

        ENDLOOP.


    ENDMETHOD."--------------------------------------

1 me gusta

Este tema se cerró automáticamente 7 días después del último post. No se permiten nuevas respuestas.