Mostrando entradas con la etiqueta MS_EXCEL_OLE_STANDARD_DAT. Mostrar todas las entradas
Mostrando entradas con la etiqueta MS_EXCEL_OLE_STANDARD_DAT. Mostrar todas las entradas

jueves, 2 de mayo de 2013

Clasicos ABAP: Descargar tabla interna a una hoja Excel

Esto es un clásico de la programación ABAP que no puede faltar en todo desarrollo , proyecto , listado , etc... siempre habrá un usuario que te pedirá que el listado 'A', 'B' o 'C' tenga la opción de descargarse  a una hoja Excel.

Para descargar una tabla interna a una hoja de excel:  bapi MS_EXCEL_OLE_STANDARD_DAT

IMPORTANTE: Para que esta bapi os funcione, es necesario que la aplicación Microsoft EXCEL este instala en el equipo local.  Esta bapi envía los datos al SapGUI y después al EXCEL, por tanto tampoco funcionara si ejecutáis el programa como un job en fondo o si queréis que el fichero se cree en el servidor o en una unidad de red.

Si  la tabla interna tiene campos numéricos, por ejemplo integer, float... al ejecutar la bapi MS_EXCEL_OLE_STANDARD_DAT saltara un precioso dump. Esto esta relacionado con lo que anteriormente os he comentado, la Bapi no realiza ningún ajuste, transformación o cast con los datos, lo que puede derivar en problemas con campo numérico, decimales o fechas.

Hay que crear otra tabla interna,  idéntica a la que queremos descargar a excel, pero con todos sus campos de tipo carácter. Traspasaremos los registros a la nueva tabla y descargaremos el contenido de la tabla a una hoja excel con la bapi MS_EXCEL_OLE_STANDARD_DAT.

Un ejemplo vale mas que  mil palabras....

Listado ALV que muestra los vuelos para las compañías y fechas seleccionadas:

Nota: solo voy a pegar las partes importantes del código, si queréis el código completo del ejemplo lo tenéis aquí.


Añadir un pulsador para descargar el ALV a una hoja excel y el siguiente código para controlar el evento.

*---------------------------------------------------------------------*
*       FORM USER_COMMAND_01  Process Call Back Events (Begin)         *
*---------------------------------------------------------------------*
FORM user_command_01 USING ucomm    LIKE sy-ucomm
                        selfield TYPE slis_selfield.

  DATA: wl_file TYPE string.

  CASE ucomm.
    WHEN '&EXC'.
      PERFORM get_filename  CHANGING wl_file.
      PERFORM download_to_exc  USING wl_file ti_spfli.
  ENDCASE.
ENDFORM.                    "user_command_01

*---------------------------------------------------------------------*
*      Form  GET_FILENAME
*---------------------------------------------------------------------*
*     Abrir navegador para seleccionar fichero
*----------------------------------------------------------------------*
FORM get_filename  CHANGING p_file TYPE string.

  DATA w_file LIKE rlgrap-filename.

  CALL FUNCTION 'KD_GET_FILENAME_ON_F4'
    CHANGING
      file_name     = w_file
    EXCEPTIONS
      mask_too_long = 1
      OTHERS        = 2.

  p_file = w_file.

ENDFORM.                      "GET_FILENAME

*---------------------------------------------------------------------*
*      Form  DOWNLOAD_TO_EXC
*---------------------------------------------------------------------*
FORM download_to_exc  USING Pi_file  TYPE STRING
                            ti_spfli TYPE type_t_spfli.

  TYPES: BEGIN OF tl_name,
    fldname(11) TYPE c,
   END OF tl_name.

  DATA: tl_name  TYPE STANDARD TABLE OF tl_name.

  DATA: wl_file TYPE  rlgrap-filename.

  FIELD-SYMBOLS:  <FL> TYPE tl_name.

  wl_file = Pi_file.

  LOOP AT gt_fieldcat .
    APPEND INITIAL LINE TO tl_name ASSIGNING <FL>.
    <FL>-fldname =  gt_fieldcat-fieldname.
  ENDLOOP.

  CALL FUNCTION 'MS_EXCEL_OLE_STANDARD_DAT'
    EXPORTING
      file_name                 = wl_file
      data_sheet_name           = 'SPFLI'
      password_option           = 0
    TABLES
      data_tab                  = ti_spfli
      fieldnames                = tl_name
    EXCEPTIONS
      file_not_exist            = 1
      filename_expected         = 2
      communication_error       = 3
      ole_object_method_error   = 4
      ole_object_property_error = 5
      invalid_filename          = 6
      invalid_pivot_fields      = 7
      download_problem          = 8
      OTHERS                    = 9.

  CASE sy-subrc.
    WHEN 1.
      MESSAGE e000(yv01) WITH 'File does not exist'.
    WHEN 2.
      MESSAGE e000(yv01) WITH 'Filename expected'.
    WHEN 3.
      MESSAGE e000(yv01) WITH 'Communication error'.
    WHEN 4.
      MESSAGE e000(yv01) WITH 'OLE object method error'.
    WHEN 5.
      MESSAGE e000(yv01) WITH 'OLE object property error'.
    WHEN 6.
      MESSAGE e000(yv01) WITH 'Invalid filename'.
    WHEN 7.
      MESSAGE e000(yv01) WITH 'Invalid pivot fields'.
    WHEN 8.
      MESSAGE e000(yv01) WITH 'Download problem'.
    WHEN 9.
      MESSAGE e000(yv01) WITH 'Other problem'.
  ENDCASE.


ENDFORM.                    " DOWNLOAD_TO_EXC


La tabla interna TL_NAME son las cabeceras de las columnas. Si comentáis el parámetro de entrad de la bapi o le pasáis una tabla interna vacía, generara la hoja excel sin cabecera para las columnas.

Preguntamos donde quiere guardar la hoja excel


Tabla interna descargada a hoja excel

En este ejemplo , como todos los campos son de tipo caracter ( CONNID es NUMC, texto numérico ) , no existe ningun problema en pasar directamente la tabla a la bapi MS_EXCEL_OLE_STANDARD_DAT. Pero, si añadimos un nuevo campo numerico a la tabla interna:

TYPES: BEGIN OF type_spfli,
  carrid     TYPE spfli-carrid,    "compañía aérea
  connid     TYPE spfli-connid,    "Código de conexión de vuelo directo
  countryf   TYPE spfli-countryfr, "Clave de país
  cityfrom   TYPE spfli-cityfrom,  "Ciudad de salida
  airpfrom   TYPE spfli-airpfrom,  "Aeropuerto de salida
  countryto  TYPE spfli-countryto, "Clave de país
  cityto     TYPE spfli-cityto,    "Ciudad de llegada
  airpto     TYPE spfli-airpto,    "Aeropuerto de destino
  integer    TYPE i,               "CAMPO NUMERICO
END OF type_spfli.

Aunque el campo integer este vació en todos los registros, al descargar a excel dará el siguiente DUMP

sólo se permiten caracteres
Hay que traspasar, antes de llamar a la bapi, todo el contenido de la tabla ti_spfli a una tabla cuyos campos sean todos de tipo caracter.



*---------------------------------------------------------------------*
*      Form  DOWNLOAD_TO_EXC
*---------------------------------------------------------------------*
FORM download_to_exc  USING pi_file  TYPE string
                            ti_spfli TYPE type_t_spfli.

  TYPES: BEGIN OF tl_name,
    fldname(11) TYPE c,
   END OF tl_name.

  TYPES: BEGIN OF type_excel,
    carrid(3)    TYPE c,
    connid(4)    TYPE c,
    countryfr(3) TYPE c,
    cityfrom(20) TYPE c,
    airpfrom(3)  TYPE c,
    countryto(3) TYPE c,
    cityto(20)   TYPE c,
    airpto(3)    TYPE c,
    integer(15)  TYPE c,
  END OF type_excel.

  DATA: tl_name  TYPE STANDARD TABLE OF tl_name.
  DATA: tl_excel TYPE STANDARD TABLE OF type_excel.

  DATA: wl_file TYPE  rlgrap-filename.

  FIELD-SYMBOLS:  <FN> TYPE tl_name,
                  <FO> TYPE TYPE_spfli,
                  <FD> TYPE type_excel.

  wl_file = pi_file.

  LOOP AT gt_fieldcat .
    APPEND INITIAL LINE TO tl_name ASSIGNING <FN>.
    <FN>-fldname =  gt_fieldcat-fieldname.
  ENDLOOP.

  LOOP AT ti_spfli ASSIGNING <FO>.

    APPEND INITIAL LINE TO TL_EXCEL ASSIGNING <FD>.

    MOVE: <FO>-carrid    TO <FD>-CARRID,
          <FO>-connid    TO <FD>-CONNID,
          <FO>-countryfr TO <FD>-countryfr,
          <FO>-cityfrom  TO <FD>-cityfrom,
          <FO>-airpfrom  TO <FD-airpfrom,
          <FO>-countryto TO <FD>-countryto,
          <FO>-cityto    TO <FD>-cityto,
          <FO>-airpto    TO <FD>-airpto.

    WRITE <FO>-integer TO <FD>-INTEGER.

  ENDLOOP.

  CALL FUNCTION 'MS_EXCEL_OLE_STANDARD_DAT'
    EXPORTING
      file_name                 = wl_file
      data_sheet_name           = 'SPFLI'
      password_option           = 0
    TABLES
      data_tab                  = TL_EXCEL
      fieldnames                = tl_name
    EXCEPTIONS
      file_not_exist            = 1
      filename_expected         = 2
      communication_error       = 3
      ole_object_method_error   = 4
      ole_object_property_error = 5
      invalid_filename          = 6
      invalid_pivot_fields      = 7
      download_problem          = 8
      OTHERS                    = 9.

  CASE sy-subrc.
    WHEN 1.
      MESSAGE e000(yv01) WITH 'File does not exist'.
    WHEN 2.
      MESSAGE e000(yv01) WITH 'Filename expected'.
    WHEN 3.
      MESSAGE e000(yv01) WITH 'Communication error'.
    WHEN 4.
      MESSAGE e000(yv01) WITH 'OLE object method error'.
    WHEN 5.
      MESSAGE e000(yv01) WITH 'OLE object property error'.
    WHEN 6.
      MESSAGE e000(yv01) WITH 'Invalid filename'.
    WHEN 7.
      MESSAGE e000(yv01) WITH 'Invalid pivot fields'.
    WHEN 8.
      MESSAGE e000(yv01) WITH 'Download problem'.
    WHEN 9.
      MESSAGE e000(yv01) WITH 'Other problem'.
  ENDCASE.


ENDFORM.                    " DOWNLOAD_TO_EXC



Después de ajustar el código, si volvemos a ejecutar y descargar a excel:


Descargar a hoja excel tabla interna con campos numéricos
Notas relacionadas:
   721793 - Problems with MS_EXCEL_OLE_STANDARD_DAT
   104165 - Problems with MS EXCEL-download from HR-reports