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).
Roberto, no puedo resistirme a felicitarte por la gran labor que estas haciendo en la divulgacion de SAP.
Enhorabuena y sigue así.
Ramón.
Muchas gracias Ramon.
Seguire compartiendo con vosotros cosas interesantes sobre Sap. Tengo un monton de temas en el tintero.
Un saludo.
hola roberto necesito donde puedo aprender sap gratuitamente . lo necesito en el trabajo.
si sabeis de algun sitio para poder descargar sap y practicar y con vuestra ayuda aprender . necesito este trabajo
Eres la leche. Cuánto se te echa de menos.
Gracias chaval, yo tambien echo de menos a pedazo de usuarios como tu. Yo aun mantengo la esperanza de que curremos juntos otra vez, a ver si hay suerte…jeje.
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.
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
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.
He buscado muchas notas, pero no encuentro una que me ayude a solucionar ese problema…
para prograMAR un radio button
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
Gracias por tu aportación.
Un saludo.