Truco 105. Envío de email con resultados de un ALV.


En nuestro truco de hoy inauguramos una sección donde propondremos típicos ejemplos prácticos de necesidad funcional y como solucionarlos, incluyendo en muchos casos elementos de programación Abap.

Empezaremos con un ejemplo clásico donde necesitamos que un report Z envie por email los resultados calculados y que en modo interactivo se muestran en un ALV. Por ejemplo, en una ejecución del programa en fondo queremos que se envíen los resultados a uno o varios usuarios. O incluso el mismo usuario que esta viendo los resultados de forma interactiva quiere enviar la información a otro usuario de la empresa o un contacto externo (cliente o proveedor).

Para nuestro ejemplo, partimos de un desarrollo Z que nos permite listar información de pedidos de compra.


En el informe añadiremos en los criterios de selección del programa añadiremos un campo para poder introducir los destinatarios de email donde queremos enviar los resultados del ALV ( Select-options: so_email for adr6-smtp_addr. )

Y un botón para que el usuario, cuando lo desee, pueda lanzar el envío del correo electrónico que contendrá como anexo una excel con la información.

Ahora, la parte más compleja. La programación necesaria para convertir la tabla interna que estamos utilizando en el ALV en una hoja excel, construir el correo electrónico y enviarlo a los destinatarios.

Básicamente, utilizamos los siguientes elementos de programación:

  • Clase cl_salv_bs_tt_util: nos permite convertir una tabla interna a formato excel.
  • Clase cl_bcs: para gestionar el envío del correo.
  • Clase cl_document_bcs: para crear el correo, indicar asunto y texto, anexar excel, etc.

En mi programa, he creado un FORM que se ejecuta cuando el usuario pulsa el botón de enviar correo, que se llama lanza_envio_mail.

Desde allí se llama a send_email donde se hace todas las operaciones técnicas de convertir la tabla interna a un xls (form f_build_email_data ) y la construcción del correo electrónico.

FORM lanza_envio_email.
* miro si la tabla de emails esta vacia, intento meter el email del user
  DESCRIBE TABLE so_email LINES lv_num_emails.
  IF lv_num_emails = 0.
    SELECT SINGLE adr6~smtp_addr INTO so_email-low
         FROM usr21
           INNER JOIN adr6
              ON  usr21~addrnumber = adr6~addrnumber
             AND usr21~persnumber = adr6~persnumber
                 WHERE bname = sy-uname.
    IF sy-subrc EQ 0.
      lv_num_emails = lv_num_emails + 1.
      so_email-sign = ‘I’.
      so_email-option = ‘EQ’.
      APPEND so_email.
    ENDIF.
  ENDIF.
  IF lv_num_emails > 0.
* Construimos el catalogo para poder hacer la excel.
    CALL FUNCTION ‘LVC_FIELDCATALOG_MERGE’
      EXPORTING
        i_structure_name       = ‘ZME2L’
      CHANGING
        ct_fieldcat            = gt_fieldcat
      EXCEPTIONS
        inconsistent_interface = 1
        program_error          = 2
        OTHERS                 = 3.
    PERFORM modify_fieldcat.
* Constuimos el correo desde la tabla interna.
    PERFORM send_email.
  ENDIF.
ENDFORM.

*&———————————————————————*
*&      Form  SEND_EMAIL
*&———————————————————————*
*       text
*———————————————————————-*
*  –>  p1        text
*  <–  p2        text
*———————————————————————-*
FORM send_email .
  DATA:
    lt_binary_content TYPE solix_tab,
    lv_size           TYPE so_obj_len,
    r_mail            TYPE ace_generic_range_t,
    st_mail           TYPE ace_generic_range,
    lv_count          TYPE char2,
    lv_var            TYPE char8.
  FIELD-SYMBOLS: <fs_mail> TYPE any.
  REFRESH: lt_binary_content.
  CLEAR: st_mail, lv_count, lv_var.

* Construye el objeto binario de la excel a partir de la tabla interna
  PERFORM f_build_email_data CHANGING lt_binary_content
                                       lv_size.
  DATA: v_rundate        LIKE sy-datum,
        v_runtime        LIKE sy-uzeit,
        timestamp(20),
        lcl_send_request TYPE REF TO cl_bcs,
        lcl_document     TYPE REF TO cl_document_bcs,
        lv_subject       TYPE so_obj_des,
        lt_main_text     TYPE soli_tab,
        lv_text          TYPE soli,
        lv_filename      TYPE sood-objdes,
        lv_mailto        TYPE adr6-smtp_addr,
        lcl_recipient    TYPE REF TO cl_cam_address_bcs,
        lv_sent_to_all   TYPE os_boolean.

*–Run Date and Run Time
  v_rundate = sy-datum.
  v_runtime = sy-uzeit.
*  CONCATENATE v_rundate v_runtime INTO timestamp.
  WRITE sy-datum TO timestamp MM/DD/YYYY.
  TRY.
* ——– create persistent send request ————————
      lcl_send_request = cl_bcs=>create_persistent( ).

* ——– create and set document with attachment —————

* ASUNTO CORREO
      CONCATENATE ‘Informe de pedidos’  ‘ Fecha:’ timestamp
      sy-cprog sy-sysid INTO lv_subject
      SEPARATED BY space.

* Texto de correo (cuerpo del mensaje)
      CONCATENATE ‘En el Excel anexo se detallan los pedidos pendientes’
      ‘en el sistema.’ INTO lv_text SEPARATED BY space.
      APPEND lv_text TO lt_main_text.
      APPEND text-001 TO lt_main_text.
      APPEND text-003 TO lt_main_text.
      lcl_document = cl_document_bcs=>create_document(
      i_type = ‘RAW’
      i_text = lt_main_text
      i_subject = lv_subject ).                             “#EC NOTEXT

* Añadimos la excel al mensaje, poniendo nombre al fichero
      CLEAR: lv_subject.
      CONCATENATE ‘Pedidos’_’ v_rundate
      v_runtime ‘_’ sy-sysid INTO lv_filename.
      CALL METHOD lcl_document->add_attachment
        EXPORTING
          i_attachment_type    = ‘xls’
          i_attachment_subject = lv_filename
          i_attachment_size    = lv_size   “im_size
          i_att_content_hex    = lt_binary_content. “im_tab ).

* add document object to send request
      lcl_send_request->set_document( lcl_document ).

* ——— add recipient (e-mail address) ———————–
* create recipient object

*      Añadimos los destinatarios al correo
      LOOP AT so_email.
        lv_mailto = so_email-low. “ls_recipient-low.
        lcl_recipient = cl_cam_address_bcs=>create_internet_address( lv_mailto ).

* add recipient object to send request
        lcl_send_request->add_recipient( lcl_recipient ).
*        CLEAR: ls_recipient.
      ENDLOOP.
* Send now
      lcl_send_request->set_send_immediately( ‘ ‘ ).
* Outbox
      lcl_send_request->send_request->set_link_to_outbox( ‘X’ ).
* ———- send document —————————————
      lv_sent_to_all = lcl_send_request->send( i_with_error_screen = ‘X’ ).

      COMMIT WORK.

      IF lv_sent_to_all IS INITIAL.
        MESSAGE i500(sbcoms) WITH lv_mailto.
      ELSE.
        MESSAGE s022(so).
      ENDIF.

* ———— exception handling ———————————-
* replace this rudimentary exception handling with your own one !!!
*    CATCH cx_bcs INTO lcl_bcs_exception.
*      MESSAGE i865(so) WITH lcl_bcs_exception->error_type.
  ENDTRY.
ENDFORM.

FORM f_build_email_data  CHANGING p_lt_binary_content
         TYPE STANDARD TABLE
                             p_size TYPE so_obj_len.
  DATA: e_xstring TYPE xstring.
  DATA: mt_fcat     TYPE lvc_t_fcat,
        ms_fcat     TYPE lvc_s_fcat,
        st_fieldcat TYPE slis_fieldcat_alv.
  DATA: mt_data       TYPE REF TO data.
  DATA: m_flavour TYPE string.
  DATA: m_version TYPE string.
  DATA: mo_result_data TYPE REF TO cl_salv_ex_result_data_table.
  DATA: mo_columns  TYPE REF TO cl_salv_columns_table.
  DATA: mo_aggreg   TYPE REF TO cl_salv_aggregations.
  DATA: mo_salv_table  TYPE REF TO cl_salv_table.
  DATA: m_file_type TYPE salv_bs_constant.
  DATA: out_length TYPE i.
  FIELD-SYMBOLS <tab> TYPE ANY TABLE.

  CLEAR: e_xstring, ms_fcat, st_fieldcat, m_flavour, m_version,
         mo_result_data, mo_columns, mo_aggreg, mo_salv_table,
         m_file_type, out_length, mt_data.
*  REFRESH: it_fieldcat[].

*-It_final here is the final itab same parameter you pass in
* your alv grid
  GET REFERENCE OF gt_eban INTO mt_data.

*-Move your field catalog to mt_fcat make sure to populate
*-ms_fcat-seltext, because it can be that in your field cat the headings

*-are in seltext_l or seltext_m or seltext_s
  LOOP AT gt_fieldcat INTO ms_fcat.  “st_fieldcat.
*    MOVE-CORRESPONDING st_fieldcat TO ms_fcat.
*    MOVE: st_fieldcat-seltext_l TO ms_fcat-seltext.
    APPEND ms_fcat TO mt_fcat.
    CLEAR: ms_fcat, st_fieldcat.
  ENDLOOP.

  IF cl_salv_bs_a_xml_base=>get_version( ) EQ if_salv_bs_xml=>version_25 OR
     cl_salv_bs_a_xml_base=>get_version( ) EQ if_salv_bs_xml=>version_26.

    mo_result_data = cl_salv_ex_util=>factory_result_data_table(
        r_data                      = mt_data
        t_fieldcatalog              = mt_fcat
    ).

    CASE cl_salv_bs_a_xml_base=>get_version( ).
      WHEN if_salv_bs_xml=>version_25.
        m_version = if_salv_bs_xml=>version_25.
      WHEN if_salv_bs_xml=>version_26.
        m_version = if_salv_bs_xml=>version_26.
    ENDCASE.

    m_file_type = if_salv_bs_xml=>c_type_xlsx.
    m_flavour = if_salv_bs_c_tt=>c_tt_xml_flavour_export.

    “transformation of data to excel
    CALL METHOD cl_salv_bs_tt_util=>if_salv_bs_tt_util~transform
      EXPORTING
        xml_type      = m_file_type
        xml_version   = m_version
        r_result_data = mo_result_data
        xml_flavour   = m_flavour
        gui_type      = if_salv_bs_xml=>c_gui_type_gui
      IMPORTING
        xml           = e_xstring.
  ENDIF.

  CALL FUNCTION ‘SCMS_XSTRING_TO_BINARY’
    EXPORTING
      buffer        = e_xstring
    IMPORTING
      output_length = out_length
    TABLES
      binary_tab    = p_lt_binary_content.

  MOVE: out_length TO p_size.

ENDFORM.                    ” F_BUILD_EMAIL_DATA

El resultado el correo enviado podría ser algo parecido a esto, donde podemos personalizar en el código la información del asunto, texto del correo, nombre del fichero anexado, etc.

Con el fichero excel anexado con la información del ALV, todo construido con un desarrollo más o menos sencillo.

Espero que os sea de utilidad.

Bibliografia:

Gracias a Ralph Vincent Ferraren por su aporte en la Wiki del SCN de SAP:

https://wiki.scn.sap.com/wiki/display/ABAP/Send+an+Internal+Table+as+an+excel+attachment+via+email

Anuncios
Esta entrada fue publicada en Abap, Formacion y etiquetada , . Guarda el enlace permanente.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.