SAP

22 Feb

Crear una tabla dinámica en tiempo de ejecución

En este primer post de la sección SAP voy a desgranar los pasos necesarios para crear y posteriormente acceder a una tabla interna de la que no conocemos su estructura hasta tiempo de ejecución. Esto es muy útil sobre todo para subrutinas que deberán devolver una tabla u otra dependiendo de uno o más parámetros que le lleguen en la llamada.

Los pasos a seguir son los siguientes:

  • Crear las variables que nos permitan la declaración y el manejo de la tabla
  • Crear la tabla en tiempo de ejecución y asignar las variables de manejo
  • Cargar datos en la tabla (si es necesario)
  • Acceder a datos de la tabla (si es necesario)

Paso 1: Crear las variables que nos permitan la declaración y el manejo de la tabla

Las variables que hemos de crear son las siguientes:

  • Variable que contiene el nombre de la tabla
  • Variable de tabla genérica
  • Variable de línea (registro) genérica

La declaración en código ABAP es:


DATA: lv_tabla TYPE dd02l-tabname,
generic_table TYPE REF TO data,
generic_line TYPE REF TO data.

Los “manejadores”, o punteros a los datos contenidos en las variables anteriores, a crear son los siguientes:

  • Puntero a la tabla completa
  • Puntero a una fila / registro de la tabla
  • Puntero a un campo de la tabla

La declaración en código ABAP es:


FIELD-SYMBOLS: < table > TYPE ANY TABLE,
< wa > TYPE ANY,
< field > TYPE ANY.

Es importante remarcar que los FIELD-SYMBOLS SIEMPRE se declaran entre < y > SIN ESPACIOS entre ellos y el nombre (lo he tenido que poner así para que salga bien el código fuente)

Paso 2: Crear la tabla en tiempo de ejecución

Para crear la tabla en tiempo de ejecución partimos desde el supuesto de que en la variable lv_tabla se encuentra el nombre de la tabla de diccionario ABAP a partir de la cual queremos crear la tabla interna.

El código fuente ABAP para crear una tabla y una fila / registro / área de trabajo de manera dinámica es el siguiente


lv_tabla = "Insertar nombre de la tabla de diccionario ABAP aquí
CREATE DATA generic_table TYPE STANDARD TABLE OF (lv_tabla).
ASSIGN generic_table->* TO < table >.


CREATE DATA generic_line TYPE (lv_tabla).
ASSIGN generic_line->* TO < wa >.

Paso 3: Cargar datos en la tabla dinámica

A la hora de cargar datos en la tabla dinámica normalmente se accederá a la base de datos con una SELECT que recupere todos los campos ya que se desconocen estos en tiempo de compilación y por lo tanto a pesar de que nombrándolos explícitamente no da ningún fallo de compilación, es posible que el resultado sea un DUMP si el campo especificado no existe en la tabla de diccionario ABAP que se defina en tiempo de ejecución como tabla base para la tabla interna.

Así pues el código fuente estándar para cargar una tabla interna con datos provenientes de la base de datos sería el siguiente:


SELECT *
INTO CORRESPONDING FIELDS OF TABLE < table >
FROM (lv_tabla).

Paso 4: Recuperar los datos de una tabla dinámica

Como la mayoría de las veces las tablas internas se recuperan para acceder a ellas registro por registro de manera secuencial, la recuperación de datos consistiría en una repetitiva LOOP y una asignación del campo que queremos recuperar.

Valga como ejemplo el siguiente código ABAP:


CONSTANTS: lv_nombre_campo(255) TYPE C VALUE 'nombre del campo'.


DATA: lv_valor_campo. "Tipo del campo a recuperar


LOOP AT < table > INTO < wa >.
ASSIGN COMPONENT lv_nombre_campo OF STRUCTURE < wa > TO < field >.
MOVE < field > TO lv_valor_campo.
ENDLOOP.

Este código es solamente válido si estamos TOTALMENTE SEGUROS de que la tabla creada va a tener SIEMPRE un campo cuyo nombre sea: lv_nombre_campo. Si no se sabe que campos tiene lo mejor es asignar el campo con un indice. Esto puede realizarse de la siguiente manera:

DATA: lv_indice_campo TYPE I,
lv_valor_campo. "Tipo del campo a recuperar


lv_indice_campo = "Número de posición en la tabla del campo
LOOP AT < table > INTO < wa >.
ASSIGN COMPONENT lv_indice_campo OF STRUCTURE < wa > TO < field >.
MOVE < field > TO lv_valor_campo.
ENDLOOP.

Hasta aquí el tutorial para la creación, carga y acceso a los datos de una tabla dinámica cuyo tipo se conoce solamente en tiempo de ejecución.

11 comentarios

  1. 1 22/02/2008 at 17:37
    Permalink

    El código fuente queda un poco chapucero (maldito tag code de HTML) pero creo que se entiende bien, lo único recordar que los FIELD SYMBOLS no llevan espacios entre < , > y el nombre del SYMBOL.

    Saludos

  2. 2
    Daniel
    19/03/2008 at 14:50
    Permalink

    Hola, necesito saber como recuperar el nombre fisico de un campo asignado por el:
    begin of StrAny,
    campo1,
    campo2,
    campo3,
    campo4,
    end of StrAny,

    begin of strotra,
    campo4,
    campo3,
    campo1,
    campo2,
    end of strotra,
    ASSIGN COMPONENT sy-index OF STRUCTURE StrAny TO .

    necesito mover ciertos campos de la estructura a la StrAny a la Strotra, No todos los campos por eso necesto el nombre para poder mover dinamicamente

    move (StrAny-campo2) to (strotra-campo2).
    move (StrAny-campo3) to (strotra-campo3).

    help

  3. 3 24/03/2008 at 01:47
    Permalink

    Pues la verdad, no puedo ayudarte, porque no se bien que quieres decir, te recomiendo que busques en Mundo SAP (Te dejo el enlace directamente a los subforos de desarrollo).

    Si ahí no encuentras la respuesta pues podrías poner un post nuevo y ver que te comentan.

    Siento contestar tan tarde pero es que he estado de vacaciones y no he usado nada el ordenador.

    Saludos

  4. 4
    MILTON
    08/04/2009 at 23:37
    Permalink

    Hola!!

    Oye sabes como puedo obtener los atributos de un tabla, ejemplo:
    De la BSEG quiero obtener en una tabla interna todos los campo de la BSEG con sus respectivos atributos..
    Gracias!!

  5. 5 09/04/2009 at 12:25
    Permalink

    @MILTON:

    No se si te valdrá, pero podrías probar a hacer una llamada a REUSE_ALV_FIELDCATALOG_MERGE diciendole que la tabla de la que quieres obtener el catálogo es la BSEG y entonces en la tabla resultante (del tipo slis_t_alv_fieldcat me parece, te lo digo de memoria…) tendrías todos los campos de la BSEG (accediendo al campo i_tabla_f-fieldname)

    Lo malo es que creo que no se recupera el elemento de datos ni ninguna otra característica de los campos…

    Te lo estoy contando todo de memoria, porque ahora mismo no tengo acceso a SAP (estoy de vacaciones :) ) y puede que me esté equivocando :S

    En fin, al menos es un principio, luego ya investigarás más… Puedes acceder a los foros de Mundo SAP (concretamente puedes acceder a los foros de desarrollo desde aquí) y ver si ahí te pueden solucionar el tema con mayor profundidad.

    Un saludo

  6. 6
    RitaMilena
    05/05/2009 at 17:38
    Permalink

    Hola,
    Lo que necesito es crear una tabla interna pero no con base en una tabla del ABAP Dictionary sino dependiendo de una serie de parametros, pero es muy importante para mi, poder crear los nombres de los campos dinamicos.

    Mil gracias

  7. 7
    Angelica
    12/05/2009 at 21:05
    Permalink

    Hola:

    Por fa ayudame con este tema: quiero llenar una tabla interna con datos de un achivo plano.
    Sé que debo utilzar la “GUI_UPLOAD” pero no se que campos debe tener mi tabla interna.
    Me puedes ayudar

  8. 8 14/05/2009 at 16:56
    Permalink

    @Angelica: Normalmente cuando se carga una tabla interna desde fichero se ha de conocer la estructura a la que quieres cargarlo de antemano.

    No se me ocurre ningún caso en el que no se sepa que estructura tiene el fichero plano antes de ejecutar el programa para cargarlo. ¿No tendría mucho sentido hacer esto no?

    Lo único que se me ocurre es que el fichero lleve una cabecera que te indique que campos se van a pasar a continuación, pero en ese caso… el tratamiento se complica yo creo.

    Deberías hacer una tabla interna con un campo tipo CHAR o STRING de al menos 255 caracteres en la que cargues todo a saco y luego identificar la cabecera y de ahí sacar el nombre de los campos… Muy lioso yo creo.

    Estarías en el mismo caso que RitaMilena entonces, o muy parecido…

    Caso que siento deciros no me siento capacitado para resolver al menos así de forma rápida… mirad en Mundo SAP (dejé el enlace en mi respuesta a Milton) que ahí fijo que pueden ayudaros

    Siento la tardanza y el no ser de más ayuda…

    Saludos

  9. 9
    Juan Carlos
    03/10/2009 at 22:31
    Permalink

    Hola:
    Tengo una consulta al respecto de la linea :

    “lv_tabla = “Insertar nombre de la tabla de diccionario ABAP aquí”

    mi problema reside en que tengo una tabla interna con nombres de tablas SAP (Como las EKKO o EKPO) y el contenido del campo de la tabla interna mencionada quiero pasarlo a tu variable “lv_tabla” porque no puedo ponerle directamente ‘EKKO’ o ‘EKPO’.

    dime como podria hacer ese traspaso, eh intentado hacer

    lv_tabla = (it_interna-tabname).

    pero no me funciona, si sabes alguna manera de hacerlo te lo agradeceria bastante.

  10. 10 05/10/2009 at 10:42
    Permalink

    Lo que yo veo es que en ningún momento dices que haces una READ o un LOOP a la tabla it_interna.

    Si necesitas crear N tablas internas en función del contenido de it_interna puedes hacer una tabla it_tablas_dyn que tenga dos campos: uno que sea un identificador (string) con el nombre de la tabla y otro un FIELD-SYMBOL que apunte a la tabla, no se si me explico.

    El código sería algo parecido a esto:

    LOOP AT it_interna.
    it_tablas_dyn-id_tabla = it_interna-tabname.
    PERFORM f_create_dyn_table USING it_interna-tabname
    CHANGING it_tablas_dyn-< tabla >.
    APPEND it_tablas_dyn.
    ENDLOOP.

    El PERFORM debería de llevar la lógica necesaria para convertir it_tablas_dyn-< tabla > en una tabla dinámica que lo tienes explicado arriba.

    No sé si funcionará o no, pero si no tira, te recomiendo, como ya lo he hecho en comentarios anteriores, hacer uso del foro de Mundo SAP.

    Saludos

  11. 11
    penae
    08/10/2009 at 15:34
    Permalink

    Ritamilena, revisa esta pagina, ahi te explican como crea tabla internas dinámicamente

    http://www.sap-img.com/ab030.htm

Comenta

Tu email nunca sera publicado o compartido. Los campos obligatorios estan marcados con *

*
*