domingo, 16 de diciembre de 2012

Crear tabla interna dinámicamente

Hace poco me surgió un desarrollo en el que tenía que cargar un fichero. Hasta aquí no hay nada raro, el problema en este caso es que la estructura del fichero a cargar era variable y además dependía de los datos introducidos en una tabla Z que también podía variar en el tiempo. Es decir, hoy podía tener 10 campos, mañana 20 o tener 10 pero que se llamasen diferente, así que no podía guardar los datos mediante estructuras del diccionario ni crear una estructura fija en mi programa Abap.

La única opción que se me ocurrió para solucionar esto fué crear una tabla interna dinámicamente. Para esto encontre que algún método de los ALV orientados a objetos me podía ayudar.

Vamos con la parte interesante ahora. Lo primero que necesito es definir mis variables. Obviamente no todo puede ser estático y en este caso sé la tabla que contiene mis campos y necesito definir una tabla "fieldcat" que contendrá la estructura:

DATA: gs_estructura LIKE zTabla,
      gt_tabla LIKE STANDAR TABLE OF gs_estructura,
      gs_fielcat TYPE lvc_t_fcat,
      gt_fieldcat TYPE lvc_s_fcat.

A continuación leemos la tabla del diccionario que tiene la estructura de nuestra tabla interna a crear.

SELECT * INTO TABLE gt_tabla
  FROM zTabla
  WHERE condiciones.

Y ahora debemos recorrer nuestra tabla y asignar el campo a la estructura del fieldcat.

LOOP AT gt_tabla INTO gs_estructura.
  gs_fieldcat-col_pos = sy-tabix.

  gs_fieldcat-fieldname = gs_estructura-field.
  APPEND gs_fieldcat TO gt_fieldcat.

  CLEAR GS_FIELDCAT.
ENDLOOP.


A continuación llamamos al método que crea la tabla interna a partir del fieldcat.

CALL METHOD cl_alv_table_create=>create_dynamic_table
  EXPORTING
   it_fieldcatalog = gt_fieldcat
  IMPORTING
   ep_table = gt_tabla
  EXCEPTIONS
   generate_subpool_dir_full = 1
  OTHERS = 2.

Y por último utilizamos field symbols (no podría ser de otra forma) para asignar los datos de la tabla y las posiciones.

ASSIGN gt_tabla->* TO <fs_table>.
CREATE DATA ep_line LIKE LINE OF <fs_table>.
ASSIGN ep_line->* TO <fs_line>.
 
Con esto hemos creado una tabla en tiempo de ejecucíón con los datos definidos por una tabla interna.