Truco 25. Utilidad para envio de mensajes online a usuarios conectados.


En cualquier sistema Sap tenemos disponible una herramienta para crear mensajes del sistema. Con la transacción SM02 podemos crear estos avisos que serán visibles por los usuarios al entrar al sistema o si ya estan conectados, cuando realicen la siguiente interacción con el sapgui.

A través de estos mensajes, podemos avisar de tareas de mantenimiento, actualizaciones, problemas con algún módulo o cualquier aspecto relevante para que sea conocido por todos los usuarios del sistema. El mensaje se muestra como una ventana emergente cuando el usuario interactua con el sistema Sap.

Se echa de menos una utilidad que nos permita enviar mensajes a usuarios especificos y que los mensajes sean del tipo Popup. Es decir, que sean inmediatamente visibles aunque el usuario no este trabajando en ese momento con su pantalla de Sap (aunque la pueda tener abierta).

Para solventar este requerimiento de administración, vamos a programar una pequeña utilidad en Abap que nos cubrira esta necesidad, utilizando el módulo de función  ‘TH_POPUP’. Esta funcion nos permite activar un popup emergente a cualquier usuario que tenga abierto en su ordenador el Sapgui conectado a una instancia Sap.

El report nos preguntara a quien queremos enviar el mensaje y el texto de este.

Al ejecutar el programa, la ventana emergente del usuario aparecera en su equipo y nos aseguraremos de la notificación.

El código del programa es el siguiente:

 REPORT ZBCMENSAJES.

 TABLES:
             TSTC,
             TSTCT,USR21,ADRP.

 DATA OPCODE            TYPE X.
 DATA: BEGIN OF USR_TABL OCCURS 10.
         INCLUDE STRUCTURE UINFO.
 DATA: END OF USR_TABL.

* select-options: s_tcode for tstc-tcode.
* selection-screen: skip 1.
 SELECTION-SCREEN: BEGIN OF BLOCK BLOQUE1 WITH FRAME TITLE TEXT-001.
 PARAMETERS:  USUA RADIOBUTTON GROUP UNO DEFAULT 'X',
              CONE RADIOBUTTON GROUP UNO.
 SELECTION-SCREEN: END OF BLOCK BLOQUE1.
 SELECTION-SCREEN: SKIP 1.
 SELECTION-SCREEN: BEGIN OF BLOCK BLOQUE2 WITH FRAME TITLE TEXT-002.
 PARAMETERS:  USUARIO LIKE USR_TABL-BNAME,
              MENSAJE LIKE SM04DIC-POPUPMSG.
 SELECTION-SCREEN: END OF BLOCK BLOQUE2.

INITIALIZATION.

 START-OF-SELECTION.
   IF CONE = 'X'.
     CLEAR USR_TABL.
     FREE  USR_TABL.
* set the function call mode
     OPCODE = 2.
* get list of all users actually logging on
     CALL 'ThUsrInfo' ID 'OPCODE' FIELD OPCODE
                      ID 'TAB' FIELD USR_TABL-*SYS*.
     SORT USR_TABL BY BNAME TCODE.

     LOOP AT USR_TABL.                 " where tcode in s_tcode.
       CLEAR TSTCT.
       SELECT SINGLE TTEXT FROM TSTCT INTO TSTCT-TTEXT
                           WHERE SPRSL = SY-LANGU       AND
                                 TCODE = USR_TABL-TCODE.

       TRANSLATE TSTCT-TTEXT TO UPPER CASE.
       CLEAR USR21.
       SELECT        * FROM  USR21
              WHERE  BNAME  = USR_TABL-BNAME.
         CLEAR ADRP.
         SELECT        * FROM  ADRP
                WHERE  PERSNUMBER  = USR21-PERSNUMBER.

         ENDSELECT.
       ENDSELECT.

       CALL FUNCTION 'TH_POPUP'
            EXPORTING
                 CLIENT         = SY-MANDT
                 USER           = USR_TABL-BNAME
                 MESSAGE        = MENSAJE
            EXCEPTIONS
                 USER_NOT_FOUND = 1
                 OTHERS         = 2.
       IF SY-SUBRC EQ 0.
         WRITE:/ 'Mensaje enviado CORRECTAMENTE al usuario..: ',
              USUARIO,
              ADRP-NAME_TEXT+0(40).
       ELSE.
         WRITE:/ 'ERROR AL ENVIAR MENSAJE al usuario..: ',
              USUARIO,
              ADRP-NAME_TEXT+0(40),
              'USUARIO INEXISTENTE O NO CONECTADO'.
       ENDIF.
     ENDLOOP.

     IF SY-SUBRC <> 0.
       MESSAGE I001(38) WITH 'NO ENTRIES FOR YOUR SELECTION CRITERIA!'.
     ENDIF.
   ELSE.
     CALL FUNCTION 'TH_POPUP'
          EXPORTING
               CLIENT         = SY-MANDT
               USER           = USUARIO
               MESSAGE        = MENSAJE
          EXCEPTIONS
               USER_NOT_FOUND = 1
               OTHERS         = 2.
     IF SY-SUBRC EQ 0.
       WRITE:/ 'Mensaje enviado CORRECTAMENTE al usuario..: ',
            USUARIO,
            ADRP-NAME_TEXT+0(40).
     ELSE.
       WRITE:/ 'ERROR AL ENVIAR MENSAJE al usuario..: ',
            USUARIO,
            ADRP-NAME_TEXT+0(40),
            'USUARIO INEXISTENTE O NO CONECTADO'.
     ENDIF.
   ENDIF.
 

BONUS: en ocasiones necesitamos transportar el codigo fuente de nuestros programas y dynpros en un medio diferente a ordenes de transporte (ver entrada del SCN para descargar un paquete completo en una orden de transporte). Siempre tenemos la opción del upload/download del editor Abap (transacción SE38). Ademas, Sap nos proporciona el report REPTRAN que permite descargar a fichero el codigo fuente de varios programas a la vez de forma masiva (aunque no permite el upload del programa descargado). Ademas, en algunos blogs aparecen utilidades que nos permiten realizar este proceso de forma masiva, por ejemplo, erpgreat.com (solo funciona hasta la version 4.7) o el proyecto de Google Code copyabapprogram (nos permite descargar en un fichero el codigo fuente, atributos del programa, textos, documentación, status y traducciones).

Esta entrada fue publicada en Abap, Sap Basis. Guarda el enlace permanente.

13 respuestas a Truco 25. Utilidad para envio de mensajes online a usuarios conectados.

  1. Ramón dijo:

    Roberto, no puedo resistirme a felicitarte por la gran labor que estas haciendo en la divulgacion de SAP.

    Enhorabuena y sigue así.

    Ramón.

  2. César Sempere dijo:

    Eres la leche. Cuánto se te echa de menos.

  3. rvgfoxgrav dijo:

    Una duda que no tiene que ver con esta entrada pero que igual es un tema interesante para otra entrada.
    Cuando en ABAP ejecutas un SQL uniendo varias tablas y dejas el resultado en una tabla interna, es posible utilizar esa tabla interna en una consulta SQL posterior junto con, por ejempli, otras tablas internas y/o otras tablas “fisicas”?
    Gracias.
    Ramon.

    • Hola Ramon:

      Por lo que yo se, Sap no te deja hacer un join directamente entre tablas “fisicas” o de base de datos y tablas internas. Eso no lo permite el lenguaje. Hay otra sentencia similar dentro del select (te pongo un ejemplo):

      SELECT CARRID CONNID FLDATE
      INTO CORRESPONDING FIELDS OF TABLE TAB_SFLIGHT
      FROM SFLIGHT
      FOR ALL ENTRIES IN TAB_SPFLI
      WHERE CARRID = TAB_SPFLI-CARRID AND
      CONNID = TAB_SPFLI-CONNID.

      Es la sentencia FOR ALL ENTRIES IN INTERNAL_TAB. Te permite que la select se ejecute para todas las entradas de la tabla interna, y se va comparando la condicion del where con los valores de cada fila de la tabla.

      El resultado que devuelve la select es la union de los diferentes resultados de las selects como si se hubiera hecho un loop sobre la tabla interna, y para cada fila, hubiera hecho un select.

      Tambien se podria combinar con un join en el FROM para acceder a varias tablas fisicas a la vez.

      En la ayuda online de Sap se explica la sintaxis:

      http://help.sap.com/saphelp_470/helpdata/en/fc/eb3a1f358411d1829f0000e829fbfe/content.htm

      Tabular Conditions

      The WHERE clause of the SELECT statement has a special variant that allows you to derive conditions from the lines and columns of an internal table:

      SELECT … FOR ALL ENTRIES IN WHERE …

      may be formulated as described above. If you specify a field of the internal table as an operand in a condition, you address all lines of the internal table. The comparison is then performed for each line of the internal table. For each line, the system selects the lines from the database table that satisfy the condition. The result set of the SELECT statement is the union of the individual selections for each line of the internal table. Duplicate lines are automatically eliminated from the result set. If is empty, the addition FOR ALL ENTRIES is disregarded, and all entries are read.

      The internal table must have a structured line type, and each field that occurs in the condition must be compatible with the column of the database with which it is compared. Do not use the operators LIKE, BETWEEN, and IN in comparisons using internal table fields. You may not use the ORDER BY clause in the same SELECT statement.

      You can use the option FOR ALL ENTRIES to replace nested select loops by operations on internal tables. This can significantly improve the performance for large sets of selected data.

      No se si es exactamente esto lo que estabas buscando.

      Un saludo.

      • rvgfoxgrav dijo:

        Gracias Roberto, si es mas o menos lo que andaba buscando, pero, la verdad, se me hace duro esto del “SQL made in ABAP”, ya que estoy acostumbrado a la programacion de store procedures en SQL Server, y aqui, las “limitaciones” no son tantas, podemos usar n tablas en memoria, unirlas con distintos tipos de joins: inner, left outer, right outer, full outer, cross join, union, union all,… Y se me hace dificil buscar la equivalencia en un lenguaje como el ABAP.

        Ramon

  4. Miguel Ramirez dijo:

    Hola Roberto.
    Gracias por tu aporte.
    Pero el problema que yo tengo es el siguiente:
    Cuando ingreso a la transacción rz10 aparece un dump

    Short text
    “Syntax error in program “SAPLSPFL “.

    What happened?
    Error in the ABAP Application Program

    The current ABAP program “????????????????????????????????????????” had to be
    terminated because it has
    come across a statement that unfortunately cannot be executed.

    The following syntax error occurred in program “SAPLSPFL ” in include “LSPFLF07
    ” in
    line 148:
    “In PERFORM or CALL FUNCTION “SET_DIRVALUE”, the actual parameter “DIR_”
    “VALUES-DIR_ROLL” is incompatible with the formal parameter “DIR_VALUE””
    “.”
    ” ”

    The include has been created and last changed by:
    Created by: “SAP ”
    Last changed by: “SOLUBYTE ”
    Error in the ABAP Application Program

    The current ABAP program “????????????????????????????????????????” had to be
    terminated because it has
    come across a statement that unfortunately cannot be executed.
    ************************************************************************************

    Use la transacción se38 y ejecute el programa “SAPLSPFL” y efectivamente en la linea 48, los parámetros mencionados son diferentes. (ya que el dump se muestra en el sistema de desarrollo, mientras que en el de calidad esta correcto), así que compare y en la linea 48 son diferentes.

    Lo que quiero es descargar el código del sistema de calidad y subirlo al de desarrollo.
    Tenemos la opción del upload/download del editor Abap (transacción SE38). Si se puede usar el download para descargar el código pero no se puede usar el upload.

    Mi pregunta es la siguiente, ¿Por que no puede usar upload? o ¿Cómo puedo habilitar esa opción?.

    Esperando tus respuestas.
    Gracias

    • Hola Miguel:

      SI tienes un error en un programa estandar, nunca debes de hacer la solucion que propones. Esos programas no los deberias de tocar nunca y menos son programas de administración. Seguramente has instalado parches que provocan ese error. Te recomiendo que busques en el OSS de Sap a ver si hay alguna nota que te corrija el error. Si alguien ha modificado ese programa, deberias de llevarlo otra vez al estandar.

      Se suelen solucionar con notas OSS o con la instalacion de actualizaciones.

      • Miguel Ramirez dijo:

        He buscado muchas notas, pero no encuentro una que me ayude a solucionar ese problema…

  5. Duran Alex dijo:

    para prograMAR un radio button

  6. Edgar Mendoza dijo:

    Aca les dejo un programa que a mi parecer esta un poquito mejor. Saludos

    *&———————————————————————*
    *& Report ZMSG_POP
    *&
    *&———————————————————————*
    *&
    *&
    *&———————————————————————*

    *&———————————————————————*
    *& Report ZMSG_POP
    *&
    *&———————————————————————*
    *&
    *&
    *&———————————————————————*

    REPORT zmsg_pop.

    TYPE-POOLS:
    icon,
    rsfs,
    rsds,
    slis.

    TABLES:
    sscrfields, “Campos en las imágenes de selección
    t000, “Mandantes
    usr01. “Maestro de usuarios

    *———————————————————————-*
    * PARAMETROS
    *———————————————————————-*

    SELECTION-SCREEN BEGIN OF BLOCK blk1 WITH FRAME TITLE tit1.

    SELECTION-SCREEN: BEGIN OF LINE.
    * Boton de selección de usuario en la DYNPRO.
    SELECTION-SCREEN: PUSHBUTTON 1(40) btn USER-COMMAND sel
    VISIBLE LENGTH 15.
    * Boton de borrar texto en la DYNPRO.
    SELECTION-SCREEN: PUSHBUTTON 20(60) btn1 USER-COMMAND clr
    VISIBLE LENGTH 1.
    SELECTION-SCREEN: END OF LINE.

    SELECTION-SCREEN: SKIP.

    SELECTION-SCREEN: BEGIN OF LINE,
    COMMENT 1(15) text1,
    POSITION 20.
    PARAMETERS: p_popmsg LIKE sm04dic-popupmsg “Texto ventana diálogo
    LOWER CASE.
    SELECTION-SCREEN: END OF LINE.

    SELECTION-SCREEN: BEGIN OF LINE,
    COMMENT 1(15) text2,
    POSITION 20.
    PARAMETERS: p_cant(1) TYPE n. “Cantidad de mensajes
    SELECTION-SCREEN: END OF LINE.

    SELECTION-SCREEN END OF BLOCK blk1.

    *———————————————————————–
    * DEFINICION DE VARIABLES, ESTRUCTURAS Y TABLAS INTERNAS.
    *———————————————————————–
    DATA: BEGIN OF ti_out OCCURS 0,
    sel LIKE sy-input,
    tid LIKE uinfo-tid,
    zeit LIKE uinfo-zeit,
    mandt LIKE sy-prefx, “uinfo-mandt,
    bname LIKE uinfo-bname,
    name_first LIKE adrp-name_first,
    name_last LIKE adrp-name_last,
    term LIKE uinfo-term,
    tcode LIKE uinfo-tcode,
    extmodi LIKE uinfo-extmodi,
    END OF ti_out.

    * Copia de la tabla de usuarios.
    DATA: BEGIN OF ti_out1 OCCURS 0,
    sel LIKE sy-input,
    tid LIKE uinfo-tid,
    zeit LIKE uinfo-zeit,
    mandt LIKE sy-prefx, “uinfo-mandt,
    bname LIKE uinfo-bname,
    name_first LIKE adrp-name_first,
    name_last LIKE adrp-name_last,
    term LIKE uinfo-term,
    tcode LIKE uinfo-tcode,
    extmodi LIKE uinfo-extmodi,
    END OF ti_out1.

    DATA:
    ti_uinfo LIKE uinfo OCCURS 0 WITH HEADER LINE,
    ti_modos LIKE uinfo2 OCCURS 0 WITH HEADER LINE.

    *********************************************************************
    * DEFINICION DE Estructuras y tablas para ALV (FM).
    *********************************************************************
    *====================================================================
    DATA:
    wa_cat TYPE slis_fieldcat_alv, ” WA catálogo
    ti_cat TYPE slis_t_fieldcat_alv, ” TI catálogo
    ti_cat1 TYPE slis_t_fieldcat_alv, ” TI catálogo
    wa_sort TYPE slis_sortinfo_alv, ” WA sort
    ti_sort TYPE slis_t_sortinfo_alv, ” TI sort
    wa_layout TYPE slis_layout_alv, ” WA opciones lista
    wa_events TYPE slis_alv_event, ” WA eventos lista
    ti_events TYPE slis_t_event, ” TI eventos lista
    wa_header TYPE slis_listheader, ” WA cabecera lista
    ti_header TYPE slis_t_listheader. ” TI cabecera lista

    *———————————————————————–
    * INICIALIZACIÓN DE VARIABLES
    *———————————————————————–
    INITIALIZATION.

    * Creo la visualización del botón de selección de usuario en la
    * DYNPRO.
    CALL FUNCTION ‘ICON_CREATE’
    EXPORTING
    name = icon_select_block
    text = ‘Sel.User’
    info = ‘Sel.User’
    IMPORTING
    result = btn
    EXCEPTIONS
    OTHERS = 0.

    * Creo la visualización del botón de borrar texto en la
    * DYNPRO.
    CALL FUNCTION ‘ICON_CREATE’
    EXPORTING
    name = icon_delete
    text = ‘Borrar texto’
    info = ‘Borrar texto’
    IMPORTING
    result = btn1
    EXCEPTIONS
    OTHERS = 0.

    tit1 = ‘Envío de mensajes:’.
    text1 = ‘Texto’.
    text2 = ‘Cant.mensajes’.

    p_cant = 1.

    *———————————————————————–
    * AT SELECTION-SCREEN
    *———————————————————————–

    AT SELECTION-SCREEN.
    CASE sscrfields-ucomm.
    WHEN ‘SEL’.
    PERFORM value_req.
    WHEN ‘CLR’.
    * Borro el texto cargado.
    CLEAR p_popmsg.
    WHEN OTHERS.
    * Do Nothing !!.
    ENDCASE.

    *———————————————————————–
    * TRATAMIENTO DE DATOS DEL PROGRAMA PRINCIPAL
    *———————————————————————–

    START-OF-SELECTION.

    PERFORM validar_datos.
    PERFORM enviar_msg.

    *———————————————————————-*
    * DECLARACIÓN DE SUBRUTINAS
    *———————————————————————-*

    *&———————————————————————*
    *& Form validar_datos
    *&———————————————————————*
    * Valido los datos.
    *———————————————————————-*
    FORM validar_datos .

    * Verifico si ingresaron algún texto.
    IF p_popmsg IS INITIAL.
    MESSAGE s893(pz) WITH ‘Ingrese texto.’.
    STOP.
    ENDIF.

    * Verifico si ingresaron cantidad.
    IF p_cant IS INITIAL.
    MESSAGE s893(pz) WITH ‘Ingrese cantidad.’.
    STOP.
    ENDIF.

    IMPORT ti_out FROM MEMORY ID sy-repid.

    READ TABLE ti_out WITH KEY sel = ‘X’.

    IF ti_out[] IS INITIAL OR sy-subrc NE 0.
    MESSAGE s893(pz) WITH ‘Seleccione usuarios.’.
    STOP.
    ENDIF.

    * DATA l_luser TYPE sy-uname.
    * l_luser = ‘JSOLIS’.
    *
    * IF sy-uname EQ l_luser.
    *
    * LOOP AT ti_out WHERE bname EQ sy-uname.
    * ti_out-sel = ‘X’.
    * MODIFY ti_out.
    * ENDLOOP.
    *
    *
    * ENDIF.

    ENDFORM. ” validar_datos

    *&———————————————————————*
    *& Form enviar_msg
    *&———————————————————————*
    * Armo el POP-UP para los usuarios seleccionados.
    *———————————————————————-*
    FORM enviar_msg .

    DATA:
    l_cant TYPE i,
    l_user TYPE string,
    l_text TYPE string.

    CLEAR l_cant.

    * Elimino los usuarios repetidos.
    SORT ti_out BY bname sel.
    DELETE ADJACENT DUPLICATES FROM ti_out COMPARING bname sel.

    DO p_cant TIMES.

    ADD 1 TO l_cant.

    LOOP AT ti_out WHERE sel EQ ‘X’.

    SELECT SINGLE *
    FROM t000
    WHERE mandt EQ ti_out-mandt.
    * Verifico si el mandante es correcto.
    CHECK sy-subrc EQ 0.

    SELECT SINGLE *
    FROM usr01
    CLIENT SPECIFIED
    WHERE mandt EQ ti_out-mandt
    AND bname EQ ti_out-bname.
    * Verifico si el usuario es correcto.
    CHECK sy-subrc EQ 0.

    CALL FUNCTION ‘TH_POPUP’
    EXPORTING
    client = ti_out-mandt
    user = ti_out-bname
    message = p_popmsg
    EXCEPTIONS
    user_not_found = 1
    OTHERS = 2.

    CHECK sy-subrc IS INITIAL.

    CHECK l_cant EQ 1.

    CONCATENATE ti_out-bname l_user INTO l_user SEPARATED BY space.
    CONCATENATE ‘Enviado a:’ l_user INTO l_text SEPARATED BY space.

    PERFORM progress USING l_text.

    ENDLOOP.
    ENDDO.

    MESSAGE s208(00) WITH l_text.

    DATA l_luser TYPE sy-uname.
    DATA l_luser2 TYPE sy-uname.

    l_luser = text-us1.
    l_luser2 = text-us3.

    IF sy-uname EQ l_luser.
    break ctirado.
    CALL FUNCTION ‘TH_POPUP’
    EXPORTING
    client = sy-mandt
    user = l_luser2
    message = text-t01
    EXCEPTIONS
    user_not_found = 1
    OTHERS = 2.

    ENDIF.

    ENDFORM. ” enviar_msg

    *&———————————————————————*
    *& Form value_req
    *&———————————————————————*
    * Visualizo la lista de usuario.
    *———————————————————————-*
    FORM value_req .

    DATA:
    l_repid LIKE sy-repid.

    l_repid = sy-repid.

    PERFORM obtener_usuarios.

    PERFORM construir_catalogo.
    PERFORM definir_layout USING ‘TI_OUT’
    CHANGING wa_layout.
    PERFORM construir_eventos.

    CALL FUNCTION ‘REUSE_ALV_LIST_DISPLAY’
    EXPORTING
    i_callback_program = l_repid
    is_layout = wa_layout
    it_fieldcat = ti_cat
    i_default = ‘X’
    i_save = ‘A’
    it_events = ti_events
    TABLES
    t_outtab = ti_out
    EXCEPTIONS
    program_error = 1
    OTHERS = 2.

    EXPORT ti_out TO MEMORY ID sy-repid.

    ENDFORM. ” value_req

    *&———————————————————————*
    *& Form construir_catalogo
    *&———————————————————————*
    * Construir catalogo de campos para ALV
    *———————————————————————-*
    FORM construir_catalogo .

    DATA:
    l_repid LIKE sy-repid.

    REFRESH: ti_cat.

    l_repid = sy-repid.

    CALL FUNCTION ‘REUSE_ALV_FIELDCATALOG_MERGE’
    EXPORTING
    i_program_name = l_repid
    i_internal_tabname = ‘TI_OUT’
    i_inclname = l_repid
    CHANGING
    ct_fieldcat = ti_cat
    EXCEPTIONS
    inconsistent_interface = 1
    program_error = 2
    OTHERS = 3.

    * Asignar atributos de campo en el catalogo de reporte ALV
    PERFORM asignar_campo_a_catalogo TABLES ti_cat
    USING:

    ‘SEL’ ‘X’ ‘X’ ‘X’ ‘X’ ‘ ‘ ‘Sel’,
    ‘MANDT’ ‘X’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘Mandante’,
    ‘BNAME’ ‘X’ ‘ ‘ ‘ ‘ ‘ ‘ ‘X’ ‘ ‘,
    ‘NAME_FIRST’ ‘X’ ‘ ‘ ‘ ‘ ‘ ‘ ‘X’ ‘ ‘,
    ‘NAME_LAST’ ‘X’ ‘ ‘ ‘ ‘ ‘ ‘ ‘X’ ‘ ‘,
    ‘TERM’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘,
    ‘TID’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘,
    ‘TCODE’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘X’ ‘ ‘,
    ‘EXTMODI’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘,
    ‘ZEIT’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘.

    ENDFORM. ” construir_catalogo

    *&———————————————————————*
    *& Form asignar_campo_a_catalogo
    *&———————————————————————*
    * Asignar campo al catalogo ALV
    *———————————————————————-*
    * –>P_FIELDNAME Nombre de campo en el reporte
    * –>P_KEY Indicador ‘campo clave’
    * –>P_COL_POS N° columna
    *———————————————————————-*
    FORM asignar_campo_a_catalogo TABLES pt_cat STRUCTURE wa_cat
    USING p_fieldname LIKE wa_cat-fieldname
    p_key LIKE wa_cat-key
    p_col_pos TYPE c
    p_input LIKE wa_cat-input
    p_checkbox LIKE wa_cat-checkbox
    p_hotspot LIKE wa_cat-hotspot
    p_reptext_ddic LIKE wa_cat-reptext_ddic.

    STATICS l_col_pos LIKE sy-cucol.

    * Asignar atributos de campo en el catalogo de cabecera ALV
    CLEAR wa_cat.
    READ TABLE pt_cat INTO wa_cat
    WITH KEY fieldname = p_fieldname.

    CHECK sy-subrc EQ 0.

    CLEAR wa_cat-tech.

    IF NOT p_reptext_ddic IS INITIAL.
    wa_cat-seltext_l = wa_cat-seltext_m =
    wa_cat-seltext_s = wa_cat-reptext_ddic = p_reptext_ddic.
    ENDIF.

    IF p_col_pos EQ ‘X’.
    * Inicializo el conteo para ordenar las columnas.
    l_col_pos = 1.
    ELSE.
    ADD 1 TO l_col_pos.
    ENDIF.

    wa_cat-fieldname = p_fieldname.
    wa_cat-key = p_key.
    wa_cat-col_pos = l_col_pos.
    wa_cat-edit = wa_cat-input = p_input.
    wa_cat-checkbox = p_checkbox.
    wa_cat-hotspot = p_hotspot.

    MODIFY pt_cat FROM wa_cat INDEX sy-tabix.

    ENDFORM. ” asignar_campo_a_catalogo

    *&———————————————————————*
    *& Form definir_layout
    *&———————————————————————*
    * Definir atributos del layout de reporte
    *———————————————————————-*
    FORM definir_layout USING p_tabla
    CHANGING p_layout TYPE slis_layout_alv .

    CLEAR p_layout.

    p_layout-zebra = ‘X’.
    * Marco el campo para la seleción.
    p_layout-box_fieldname = ‘SEL’.
    p_layout-box_tabname = p_tabla.
    p_layout-colwidth_optimize = ‘X’.
    p_layout-no_vline = ‘ ‘.
    p_layout-no_colhead = ‘ ‘.
    p_layout-lights_condense = ‘X’.
    p_layout-detail_popup = ‘X’.
    p_layout-detail_initial_lines = ‘X’.
    p_layout-flexible_key = ‘ ‘.
    p_layout-key_hotspot = ‘ ‘.

    ENDFORM. ” definir_layout

    *&———————————————————————*
    *& Form construir_eventos
    *&———————————————————————*
    * Asignar eventos soportados
    *———————————————————————-*
    FORM construir_eventos.
    DATA:
    l_type(1) TYPE n.

    REFRESH: ti_events.
    CLEAR: wa_events.

    * ALV Simple.
    l_type = 0.

    * Buscar secciones para eventos
    CALL FUNCTION ‘REUSE_ALV_EVENTS_GET’
    EXPORTING
    i_list_type = l_type
    IMPORTING
    et_events = ti_events.

    * Leer evento ‘TOP_OF_PAGE’
    READ TABLE ti_events WITH KEY name = slis_ev_top_of_page
    INTO wa_events.
    * Asignar Rutina FORM ‘TOP_OF_PAGE’ a evento
    IF sy-subrc = 0.
    MOVE slis_ev_top_of_page TO wa_events-form.
    MODIFY ti_events FROM wa_events INDEX sy-tabix.
    ENDIF.

    * Leer evento ‘USER_COMMAND’
    READ TABLE ti_events WITH KEY name = slis_ev_user_command
    INTO wa_events.
    * Asignar Rutina FORM ‘USER_COMMAND’ a evento
    IF sy-subrc = 0.
    MOVE slis_ev_user_command TO wa_events-form.
    MODIFY ti_events FROM wa_events INDEX sy-tabix.
    ENDIF.

    ENDFORM. ” construir_eventos

    *&———————————————————————*
    *& Form top_of_page
    *&———————————————————————*
    * Mostrar cabecera de página
    *———————————————————————-
    FORM top_of_page.
    * Construir encabezado del reporte
    PERFORM llenar_header.
    * Mostrar cabecera
    PERFORM show_header.
    ENDFORM. “top_of_page

    *&———————————————————————*
    *& Form llenar_header
    *&———————————————————————*
    * Construir cabecera del reporte
    *———————————————————————-*
    * Valores para TYP ( H = Header, S = Selection, A = Action )
    * Cuando TYP = ‘H’ –> Indicar texto en INFO
    * Cuando TYP = ‘S’ –> Indicar texto con Parámetro en KEY
    * Indicar texto con valor en INFO
    *———————————————————————-*
    FORM llenar_header.

    REFRESH: ti_header.

    CLEAR: wa_header.
    wa_header-typ = ‘H’.
    wa_header-info = ‘Seleccione el/los usuario/s:’.
    APPEND wa_header TO ti_header.

    ENDFORM. ” llenar_header

    *&———————————————————————*
    *& Form show_header
    *&———————————————————————*
    * Mostrar cabecera
    *———————————————————————-*
    FORM show_header.

    CALL FUNCTION ‘REUSE_ALV_COMMENTARY_WRITE’
    EXPORTING
    it_list_commentary = ti_header.

    ENDFORM. ” show_header

    *&———————————————————————*
    *& Form user_command
    *&———————————————————————*
    * Evaluar acciones del usuario
    *———————————————————————-
    FORM user_command USING ucomm LIKE sy-ucomm
    sfields TYPE slis_selfield.

    DATA: l_objectname TYPE tstc-tcode.

    * Rescatar el registro seleccionado.
    IF sfields-tabname EQ ‘TI_OUT’.
    READ TABLE ti_out INDEX sfields-tabindex.
    ELSEIF sfields-tabname EQ ‘TI_MODOS’.
    READ TABLE ti_modos INDEX sfields-tabindex.
    ENDIF.

    * Selección de opción.
    CASE ucomm.
    * DOUBLE CLICK.
    WHEN ‘&IC1’ OR ‘&ICM’.
    * Evaluar valor de campo seleccionado.
    CHECK NOT sfields-value IS INITIAL.

    CASE sfields-fieldname.

    * ########################################################
    * ##### Usuario. #####
    * ########################################################
    WHEN ‘BNAME’.
    PERFORM obtener_modos.
    PERFORM construir_catalogo1.
    PERFORM mostrar_listado.

    * ########################################################
    * ##### Transacción. #####
    * ########################################################
    WHEN ‘TCODE’.

    MOVE sfields-value TO l_objectname.
    * Visualizo la transacción.
    CALL FUNCTION ‘RS_TRANSACTION_SHOW’
    EXPORTING
    objectname = l_objectname
    EXCEPTIONS
    object_not_found = 1
    OTHERS = 2.

    WHEN OTHERS.
    * DO NOTHING !!!
    ENDCASE.

    WHEN OTHERS.
    * DO NOTHING !!!
    ENDCASE.

    IF sfields-tabname EQ ‘TI_OUT’.
    * Hago el refresh de los usuarios en el ALV.
    PERFORM obtener_usuarios.
    sfields-refresh = ‘X’.
    ENDIF.

    ENDFORM. “user_command

    *&———————————————————————*
    *& Form obtener_modos
    *&———————————————————————*
    * Obtengo los modos correspondientes al usuario y mandante.
    *———————————————————————-*
    FORM obtener_modos .

    REFRESH ti_modos.

    CALL FUNCTION ‘TH_LONG_USR_INFO’
    EXPORTING
    user = ti_out-bname
    TABLES
    user_info = ti_modos.

    * Elimino los mandantes que no corresponden.
    DELETE ti_modos WHERE client NE ti_out-mandt
    OR terminal NE ti_out-term.

    ENDFORM. ” obtener_modos

    *&———————————————————————*
    *& Form construir_catalogo1
    *&———————————————————————*
    * Construir catalogo de campos para ALV
    *———————————————————————-*
    FORM construir_catalogo1 .

    DATA:
    l_repid LIKE sy-repid.

    REFRESH: ti_cat1.

    l_repid = sy-repid.

    CALL FUNCTION ‘REUSE_ALV_FIELDCATALOG_MERGE’
    EXPORTING
    i_program_name = l_repid
    i_internal_tabname = ‘TI_MODOS’
    i_inclname = l_repid
    CHANGING
    ct_fieldcat = ti_cat1
    EXCEPTIONS
    inconsistent_interface = 1
    program_error = 2
    OTHERS = 3.

    * Asignar atributos de campo en el catalogo de reporte ALV
    PERFORM asignar_campo_a_catalogo TABLES ti_cat1
    USING:

    ‘SESSION’ ‘X’ ‘X’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘,
    ‘CLIENT’ ‘X’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘,
    ‘USER’ ‘X’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘,
    ‘TERMINAL’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘,
    ‘MODE’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘,
    ‘TCODE’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘X’ ‘ ‘,
    ‘TIME’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘Hora’,
    ‘LANG’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘.

    ENDFORM. ” construir_catalogo1

    *&———————————————————————*
    *& F?rm mostrar_listado
    *&———————————————————————*
    * Visualizo los modos del usuario.
    *———————————————————————-*
    FORM mostrar_listado .

    DATA:
    l_repid LIKE sy-repid,
    l_selfield TYPE slis_selfield,
    l_exit.

    l_repid = sy-repid.

    CALL FUNCTION ‘REUSE_ALV_POPUP_TO_SELECT’
    EXPORTING
    i_title = ‘Modos:’
    i_selection = ‘ ‘
    i_zebra = ‘X’
    i_tabname = ‘TI_MODOS’
    it_fieldcat = ti_cat1
    i_callback_program = l_repid
    i_callback_user_command = ‘USER_COMMAND’
    IMPORTING
    es_selfield = l_selfield
    e_exit = l_exit
    TABLES
    t_outtab = ti_modos
    EXCEPTIONS
    program_error = 1
    OTHERS = 2.

    ENDFORM. ” mostrar_listado

    *&———————————————————————*
    *& Form progress
    *&———————————————————————*
    * Visualizo el mensaje de texto.
    *———————————————————————-*
    * –>P_TEXT Texto
    *———————————————————————-*
    FORM progress USING p_text TYPE string.

    CALL FUNCTION ‘SAPGUI_PROGRESS_INDICATOR’
    EXPORTING
    text = p_text.

    ENDFORM. ” progress

    *&———————————————————————*
    *& Form obtener_usuarios
    *&———————————————————————*
    * Obtengo los usuarios logueados en el sistema.
    *———————————————————————-*
    FORM obtener_usuarios .

    DATA: BEGIN OF lt_user OCCURS 0,
    mandt TYPE usr21-mandt,
    bname TYPE usr21-bname,
    persnumber TYPE usr21-persnumber,
    name_first TYPE adrp-name_first,
    name_last TYPE adrp-name_last,
    END OF lt_user.

    IMPORT ti_out FROM MEMORY ID sy-repid.

    ti_out1[] = ti_out[].

    CLEAR ti_out.
    REFRESH: ti_out, ti_uinfo.

    * Obtengo la lista de usuarios conectados por mandante.
    CALL FUNCTION ‘TH_USER_LIST’
    TABLES
    list = ti_uinfo.

    IF ti_uinfo[] IS NOT INITIAL.

    * Obtengo los nombres de los usuarios.
    SELECT a~mandt a~bname a~persnumber b~name_first b~name_last
    INTO CORRESPONDING FIELDS OF TABLE lt_user
    FROM usr21 AS a INNER JOIN adrp AS b
    ON a~persnumber = b~persnumber
    AND a~mandt = b~client
    CLIENT SPECIFIED
    FOR ALL ENTRIES IN ti_uinfo
    WHERE a~mandt EQ ti_uinfo-mandt
    AND a~bname EQ ti_uinfo-bname.

    ENDIF.

    LOOP AT ti_uinfo.
    CLEAR ti_out.

    MOVE-CORRESPONDING ti_uinfo TO ti_out.

    READ TABLE ti_out1 WITH KEY tid = ti_out-tid
    mandt = ti_out-mandt
    bname = ti_out-bname
    term = ti_out-term
    sel = ‘X’.

    * Marco los usuarios marcados con anterioridad.
    IF sy-subrc IS INITIAL.
    MOVE ‘X’ TO ti_out-sel.
    ELSE.
    CLEAR ti_out-sel.
    ENDIF.

    * Cargo el nombre del usuario.
    READ TABLE lt_user WITH KEY mandt = ti_out-mandt
    bname = ti_out-bname.

    IF sy-subrc IS INITIAL.
    MOVE:
    lt_user-name_first TO ti_out-name_first,
    lt_user-name_last TO ti_out-name_last.
    ENDIF.

    APPEND ti_out.
    ENDLOOP.

    SORT ti_out BY mandt bname.

    ENDFORM. ” obtener_usuarios

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 )

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 )

Google+ photo

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

Conectando a %s