lunes, 26 de enero de 2015

ALV como PDF en correo adjunto



El día de hoy me pidieron una solución rápida para la ejecución de reportes y su notificación, y mirando las características de los reportes existentes, probamos con una solución muy fácil, que es tomar la ALV imprimirla y enviarla por correo, bueno bonito y barato.
Acá les dejo un ejemplo, no es tan prolijo como mis otras publicaciones, pero si muy fácil de entender.





*---------------------------------------------------------------------*
REPORT  zhr_local_dev MESSAGE-ID sy.
*----------------------------------------------------------------------*
*Componentes de ALV                                                    *
*----------------------------------------------------------------------*
TYPE-POOLS: slis.
CONSTANTS:
  c_fm_top_of_page  TYPE slis_formname VALUE 'TOP_OF_PAGE'"#EC NEEDED
  c_fm_list_modify  TYPE slis_formname VALUE 'LIST_MODIFY'"#EC NEEDED
  c_fm_data_changed TYPE slis_formname VALUE 'DATA_CHANGED',"#EC NEEDED
  c_probclass_very_high TYPE bal_s_msg-probclass VALUE '1'"#EC NEEDED
  c_probclass_high      TYPE bal_s_msg-probclass VALUE '2'"#EC NEEDED
  c_probclass_medium    TYPE bal_s_msg-probclass VALUE '3'"#EC NEEDED
  c_probclass_low       TYPE bal_s_msg-probclass VALUE '4'"#EC NEEDED
  c_probclass_none      TYPE bal_s_msg-probclass VALUE ' '"#EC NEEDED
* ALV
DATA: v_fieldtab     TYPE slis_t_fieldcat_alv.              "#EC NEEDED
DATA: v_sortinfo     TYPE slis_t_sortinfo_alv. "Sort Table  "#EC NEEDED
DATA: v_sp_group     TYPE slis_t_sp_group_alv. "List Groups "#EC NEEDED
DATA: v_alv_keyinfo  TYPE slis_keyinfo_alv.                 "#EC NEEDED
DATA: v_alv_layout   TYPE slis_layout_alv.                  "#EC NEEDED
DATA: v_alv_print    TYPE slis_print_alv.                   "#EC NEEDED
DATA: v_alv_repid    LIKE sy-repid.                         "#EC NEEDED
DATA: v_events       TYPE slis_t_event.                     "#EC NEEDED
DATA: v_heading      TYPE slis_t_listheader.                "#EC NEEDED
DATA: v_layout       TYPE slis_layout_alv.                  "#EC NEEDED
DATA: v_alv_variant  TYPE disvariant.                       "#EC NEEDED
DATA: v_repname      LIKE sy-repid.                         "#EC NEEDED
DATA: v_alv_colourize_fields   LIKE  mmim_rep_print-color.  "#EC NEEDED
DATA: v_alv_detail_func(30).                                "#EC NEEDED
*----------------------------------------------------------------------*
DATA: i_output_list TYPE t100 OCCURS 0 WITH HEADER LINE.
DATA: gt_pdf   LIKE tline OCCURS 0 WITH HEADER LINE.
DATA: p_mode(6TYPE c.
*----------------------------------------------------------------------*
*
SELECTION-SCREEN BEGIN OF BLOCK b00 WITH FRAME TITLE text-t01.
PARAMETERS:     p_back RADIOBUTTON GROUP rbt1 DEFAULT 'X' USER-COMMAND u1,
                p_fron RADIOBUTTON GROUP rbt1 .
PARAMETERS:     p_email TYPE string DEFAULT 'correo@correo.cl'
                MODIF ID aaa.
SELECTION-SCREEN END OF BLOCK b00.
*----------------------------------------------------------------------*
*----------------------------------------------------------------------*
* at selection-screen output
*----------------------------------------------------------------------*
AT SELECTION-SCREEN OUTPUT.
  LOOP AT SCREEN.
    IF ( p_fron EQ 'X' ).
      IF ( screen-group1 EQ 'AAA' ).
        screen-active = '0'.
        MODIFY SCREEN.
      ENDIF.
    ELSEIF  ( p_back EQ 'X' ).
      IF ( screen-group1 EQ 'AAA' ).
        screen-active = '1'.
        MODIFY SCREEN.
      ENDIF.
    ENDIF.
  ENDLOOP.
*----------------------------------------------------------------------*
INITIALIZATION.
*----------------------------------------------------------------------*
  SELECT * UP TO 200 ROWS
    INTO TABLE i_output_list
    FROM t100
   WHERE SPRSL eq sy-langu.

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




*----------------------------------------------------------------------*
END-OF-SELECTION.
*----------------------------------------------------------------------*
  IF ( p_fron EQ 'X' ).
    p_mode = 'VER'.
    PERFORM muestra_alv using p_mode.
  ELSEIF (  p_back EQ 'X' ).
    p_mode = 'ALVPDF'.
    PERFORM muestra_alv using p_mode.
  ENDIF.
*======================================================================*
* ALV                                                                  *
*======================================================================*
FORM muestra_alv USING p_mode.
  DESCRIBE TABLE i_output_list LINES sy-tfill.
  PERFORM alv_init.
  IF ( sy-tfill > 0 ).
    PERFORM initialize_fieldcat USING v_fieldtab[].
    PERFORM ordenamiento        USING v_sortinfo[].
    PERFORM build_eventtab      USING v_events[].
    PERFORM build_comment       USING v_heading[].
    PERFORM build_layout        USING v_layout.
    PERFORM write_output        USING p_mode.
  ELSE.
    MESSAGE i499 WITH text-001.
  ENDIF.
ENDFORM.                    "Muestra_Resultados
*&---------------------------------------------------------------------*
FORM alv_init.
  DATA : l_s_mmim_rep_print  TYPE  mmim_rep_print.
  CLEAR: v_alv_keyinfo, v_alv_variant, v_alv_layout, v_alv_print.
  v_alv_repid = sy-repid.
  CLEAR v_alv_variant.
  v_alv_variant-report           = v_alv_repid.
* Printing settings
  v_alv_layout-get_selinfos      = 'X'.
  v_alv_layout-group_change_edit = 'X'.

  SELECT SINGLE *
    FROM mmim_rep_print
    INTO l_s_mmim_rep_print
   WHERE report = sy-repid.

  IF ( sy-subrc = 0 ).
    IF ( l_s_mmim_rep_print-selinfo EQ 'X' ).
      v_alv_print-no_print_selinfos = ' '.
    ELSE.
      v_alv_print-no_print_selinfos = 'X'.
    ENDIF.
*
    IF ( l_s_mmim_rep_print-coverpage EQ 'X' ).
      v_alv_print-no_coverpage = ' '.
    ELSE.
      v_alv_print-no_coverpage = 'X'.
    ENDIF.
*
    IF ( l_s_mmim_rep_print-listinfo EQ 'X' ).
      v_alv_print-no_print_listinfos = ' '.
    ELSE.
      v_alv_print-no_print_listinfos = 'X'.
    ENDIF.
*
    IF ( l_s_mmim_rep_print-gridcontrol EQ 'X' ).
      v_alv_detail_func = 'REUSE_ALV_GRID_DISPLAY'.
    ELSE.
      v_alv_detail_func = 'REUSE_ALV_LIST_DISPLAY'.
    ENDIF.
*   consider customizing settings regarding the
*   colourization of numeric fields
    IF ( l_s_mmim_rep_print-color EQ 'X' ).
*     the customizing says : use no colors
      CLEAR v_alv_colourize_fields.
    ELSE.
*     no restrictions -> work with colours
      MOVE  'X' TO v_alv_colourize_fields.
    ENDIF.
  ELSE.
*   MMIM_REP_PRINT entry missing / work with colours
    MOVE  'X' TO v_alv_colourize_fields.
    v_alv_print-no_print_selinfos  = 'X'.
    v_alv_print-no_coverpage       = ' '.
    v_alv_print-no_print_listinfos = 'X'.
    v_alv_detail_func = 'REUSE_ALV_LIST_DISPLAY'.
  ENDIF.
*
ENDFORM.                    "alv_init
*&---------------------------------------------------------------------*
FORM initialize_fieldcat USING p_fieldtab TYPE slis_t_fieldcat_alv.
  DATA: li_fieldtab TYPE slis_t_fieldcat_alv.
  DATA: wa_fieldtab TYPE LINE OF slis_t_fieldcat_alv.
  v_repname = sy-repid.
  FREE: li_fieldtab,  wa_fieldtab.
*
  CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'
    EXPORTING
      i_structure_name       = 'T100'
    CHANGING
      ct_fieldcat            = li_fieldtab
    EXCEPTIONS
      inconsistent_interface = 1
      program_error          = 2
      OTHERS                 = 3.
  IF ( sy-subrc NE 0 ).
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ELSE.
    p_fieldtab[] = li_fieldtab[].
  ENDIF.
*
ENDFORM.                    "initialize_fieldcat
*&---------------------------------------------------------------------*
FORM ordenamiento  USING sortinfo TYPE slis_t_sortinfo_alv.
  DATA : ls_sort TYPE slis_sortinfo_alv.
  CLEAR ls_sort.
  ls_sort-fieldname   = 'SPRSL'.
  ls_sort-up          = 'X'.
  ls_sort-group       = '0'.
  APPEND ls_sort TO sortinfo.
*
ENDFORM.                    "ordenamiento
*&---------------------------------------------------------------------*
FORM build_eventtab USING p_events TYPE slis_t_event.
  DATA: ls_event TYPE slis_alv_event.
  CALL FUNCTION 'REUSE_ALV_EVENTS_GET'
    EXPORTING
      i_list_type = 0
    IMPORTING
      et_events   = p_events.
  READ TABLE p_events WITH KEY name = slis_ev_top_of_page
                          INTO ls_event.
  IF ( sy-subrc = 0 ).
    MOVE c_fm_top_of_page TO ls_event-form.
    APPEND ls_event TO p_events.
  ENDIF.
ENDFORM.                    "build_eventtab
*&---------------------------------------------------------------------*
FORM build_comment USING  p_heading TYPE slis_t_listheader.
  DATA: hline TYPE slis_listheader.
  CLEAR p_heading. REFRESH p_heading.
*Cabecera
  hline-typ = 'H'.
  hline-info = 'Titulo ALV'.
  APPEND hline TO p_heading.
*
ENDFORM.                    "build_comment
*&---------------------------------------------------------------------*
FORM build_layout USING p_layout TYPE slis_layout_alv.
* p_layout-f2code        = f2code.
  p_layout-zebra         = 'X'.
* p_layout-box_fieldname = 'CMAK'."Campo de Marcage
  p_layout-box_tabname   = 'i_output_list'.
ENDFORM.                    "build_layout
*&---------------------------------------------------------------------*
FORM write_output USING p_mode.
  DATA: agrupa_alv TYPE slis_sortinfo_alv OCCURS 5 WITH HEADER LINE.
                                                            "#EC NEEDED

  DATA: v_isprint TYPE  slis_print_alv."solo Imprime en spool
  IF ( p_mode(3EQ 'ALV').
    v_isprint-print = 'X'.
    v_isprint-no_print_selinfos = 'X'."No Validado
    v_isprint-no_print_listinfos = 'X'."No Validado
  ENDIF.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
    EXPORTING
      i_background_id          = ''
      i_interface_check        = ''"'X'
      i_callback_program       = v_repname
      i_callback_pf_status_set = 'SET_PF_STATUS'
      i_callback_user_command  = 'USER_COMMAND'
      i_callback_top_of_page   = 'TOP_OF_PAGE'
      is_layout                = v_layout
      it_fieldcat              = v_fieldtab
      it_special_groups        = v_sp_group[]
      i_save                   = 'A'
      i_default                = 'X'
      it_sort                  = v_sortinfo
      it_events                = v_events[]
      is_variant               = v_alv_variant
      is_print                 = v_isprint
    TABLES
      t_outtab                 = i_output_list
    EXCEPTIONS
      program_error            = 1
      OTHERS                   = 2.
  IF sy-subrc <> 0.
    WRITE'SY-SUBRC: ', sy-subrc, 'REUSE_ALV_LIST_DISPLAY'.
  ENDIF.
*
  IF ( p_mode+3(3eq 'PDF' ).
    DATA: lv_spoolid  LIKE  tsp01-rqident.
    lv_spoolid = sy-spono.
    CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
      EXPORTING
        src_spoolid = lv_spoolid
      TABLES
        pdf         = gt_pdf.
    "Envio via Mail
    PERFORM send_email USING p_email.
  ENDIF.
ENDFORM.                    "write_output
*&---------------------------------------------------------------------*
FORM set_pf_status USING rt_extab TYPE slis_t_extab.        "#EC CALLED
  SET PF-STATUS 'STANDARD'.
ENDFORM.                    "set_pf_status
*&---------------------------------------------------------------------*
FORM top_of_page.                                           "#EC CALLED
  CALL FUNCTION 'REUSE_ALV_COMMENTARY_WRITE'
    EXPORTING
      it_list_commentary = v_heading.
ENDFORM.                    "top_of_page
*&---------------------------------------------------------------------*
FORM user_command USING r_ucomm LIKE sy-ucomm               "#EC CALLED
                        rs_selfield TYPE slis_selfield.     "#EC CALLED
  CLEAR: r_ucomm.
ENDFORM.                    "user_command
*======================================================================*
*---------------------------------------------------------------------*
FORM send_email USING p_email.
  DATA: gd_subject   LIKE sodocchgi1-obj_descr,
        it_mess_bod LIKE solisti1 OCCURS 0 WITH HEADER LINE,
        it_mess_att LIKE solisti1 OCCURS 0 WITH HEADER LINE,
        gd_sender_type     LIKE soextreci1-adr_typ,
        gd_attachment_desc TYPE so_obj_nam,
        gd_attachment_name TYPE so_obj_des,
        p_sender TYPE somlreci1-receiver,
        gd_error    TYPE sy-subrc,
        gd_reciever TYPE sy-subrc,
         vl_desde(10TYPE c,
         vl_hasta(10TYPE c.
  REFRESH it_mess_bod.
* Default subject matter
  gd_subject         = 'Asunto del correo'.
  gd_attachment_desc = 'Desc. Adjunto'.

  CLEAR it_mess_bod.
  it_mess_bod = 'Cuerpo del correo'.
  APPEND it_mess_bod.


* If no sender specified - default blank
  IF p_sender EQ space.
    gd_sender_type  = space.
  ELSE.
    gd_sender_type  = 'INT'.
  ENDIF.
*.documento pdf------
* Transfer the 132-long strings to 255-long strings
  DATA: gd_buffer TYPE string.
  LOOP AT gt_pdf.
*    translate it_pdf_output using ' ~'.
    CONCATENATE gd_buffer gt_pdf INTO gd_buffer.
  ENDLOOP.

  TRANSLATE gd_buffer USING '~ '.

  DO.
    it_mess_att = gd_buffer.
    APPEND it_mess_att.
    SHIFT gd_buffer LEFT BY 255 PLACES.
    IF gd_buffer IS INITIAL.
      EXIT.
    ENDIF.
  ENDDO.
*-

* Send file by email as .xls speadsheet
  PERFORM send_file_as_email_attachment
                               TABLES it_mess_bod
                                      it_mess_att
                                USING p_email
                                      'Informe Aprob Comisiones'
                                      'PDF'
                                      gd_attachment_name
                                      gd_attachment_desc
                                      p_sender
                                      gd_sender_type
                             CHANGING gd_error
                                      gd_reciever.
ENDFORM.                    "send_email

*---------------------------------------------------------------------*
FORM send_file_as_email_attachment TABLES it_message
                                          it_attach
                                    USING p_email
                                          p_mtitle
                                          p_format
                                          p_filename
                                          p_attdescription
                                          p_sender_address
                                          p_sender_addres_type
                                 CHANGING p_error
                                          p_reciever.


  DATA: ld_error    TYPE sy-subrc,
        ld_reciever TYPE sy-subrc,
        ld_mtitle LIKE sodocchgi1-obj_descr,
        ld_email LIKE  somlreci1-receiver,
        ld_format TYPE  so_obj_tp ,
        ld_attdescription TYPE  so_obj_nam ,
        ld_attfilename TYPE  so_obj_des ,
        ld_sender_address LIKE  soextreci1-receiver,
        ld_sender_address_type LIKE  soextreci1-adr_typ,
        ld_receiver LIKE  sy-subrc.

  DATA:   t_packing_list LIKE sopcklsti1 OCCURS 0 WITH HEADER LINE,
          t_contents LIKE solisti1 OCCURS 0 WITH HEADER LINE,
          t_receivers LIKE somlreci1 OCCURS 0 WITH HEADER LINE,
          t_attachment LIKE solisti1 OCCURS 0 WITH HEADER LINE,
          t_object_header LIKE solisti1 OCCURS 0 WITH HEADER LINE,
          w_cnt TYPE i,
          w_sent_all(1TYPE c,
          w_doc_data LIKE sodocchgi1.


  ld_email   = p_email.
  ld_mtitle = p_mtitle.
  ld_format              = p_format.
  ld_attdescription      = p_attdescription.
  ld_attfilename         = p_filename.
  ld_sender_address      = p_sender_address.
  ld_sender_address_type = p_sender_addres_type.


* Fill the document data.
  w_doc_data-doc_size = 1.

* Populate the subject/generic message attributes
  w_doc_data-obj_langu = sy-langu.
  w_doc_data-obj_name  = 'SAPRPT'.
  w_doc_data-obj_descr = ld_mtitle .
  w_doc_data-sensitivty = 'F'.

* Fill the document data and get size of attachment
  CLEAR w_doc_data.
  READ TABLE it_attach INDEX w_cnt.
  w_doc_data-doc_size =
     ( w_cnt - 1 ) * 255 + STRLEN( it_attach ).
  w_doc_data-obj_langu  = sy-langu.
  w_doc_data-obj_name   = 'SAPRPT'.
  w_doc_data-obj_descr  = ld_mtitle.
  w_doc_data-sensitivty = 'F'.
  CLEAR t_attachment.
  REFRESH t_attachment.
  t_attachment[] = it_attach[].

* Describe the body of the message
  CLEAR t_packing_list.
  REFRESH t_packing_list.
  t_packing_list-transf_bin = space.
  t_packing_list-head_start = 1.
  t_packing_list-head_num = 0.
  t_packing_list-body_start = 1.
  DESCRIBE TABLE it_message LINES t_packing_list-body_num.
  t_packing_list-doc_type = 'RAW'."'HTM'.
  APPEND t_packing_list.

* Create attachment notification
  t_packing_list-transf_bin = 'X'.
  t_packing_list-head_start = 1.
  t_packing_list-head_num   = 1.
  t_packing_list-body_start = 1.

  DESCRIBE TABLE t_attachment LINES t_packing_list-body_num.
  t_packing_list-doc_type   =  ld_format.
  t_packing_list-obj_descr  =  ld_attdescription.
  t_packing_list-obj_name   =  ld_attfilename.
  t_packing_list-doc_size   =  t_packing_list-body_num * 255.
  APPEND t_packing_list.

* Add the recipients email address
  CLEAR t_receivers.
  REFRESH t_receivers.
  t_receivers-receiver = ld_email.
  t_receivers-rec_type = 'U'.
  t_receivers-com_type = 'INT'.
  t_receivers-notif_del = 'X'.
  t_receivers-notif_ndel = 'X'.
  APPEND t_receivers.

  CALL FUNCTION 'SO_DOCUMENT_SEND_API1'
    EXPORTING
      document_data              = w_doc_data
      put_in_outbox              = 'X'
      sender_address             = ld_sender_address
      sender_address_type        = ld_sender_address_type
      commit_work                = 'X'
    IMPORTING
      sent_to_all                = w_sent_all
    TABLES
      packing_list               = t_packing_list
      contents_bin               = t_attachment
      contents_txt               = it_message
      receivers                  = t_receivers
    EXCEPTIONS
      too_many_receivers         = 1
      document_not_sent          = 2
      document_type_not_exist    = 3
      operation_no_authorization = 4
      parameter_error            = 5
      x_error                    = 6
      enqueue_error              = 7
      OTHERS                     = 8.

* Populate zerror return code
  ld_error = sy-subrc.

* Populate zreceiver return code
  LOOP AT t_receivers.
    ld_receiver = t_receivers-retrn_code.
  ENDLOOP.
ENDFORM.                    "send_file_as_email_attachment
*----------------------------------------------------------------------*

si miramos la SOST