Académique Documents
Professionnel Documents
Culture Documents
2
Su experiencia en SAP y ABAP es de 5 años a la fecha, en los
cuales siempre ha buscado obtener lo mejor del sistema.
http://tinyurl.com/jnlfd
http://atejada.blogspot.com
3
Indice
Conociendo el entorno SAP NetWeaver 7
Introducción 7
Ingresando al sistema 8
Conociendo las transacciones más importantes 12
El Menú de SAP NetWeaver 21
Diccionario de Datos 23
Introducción 23
Elementos del Diccionario de Datos 23
Creando una tabla 26
Creando un dominio 37
Creando un elemento de datos 38
Creando una vista de actualización 50
Creando una ayuda de búsqueda 60
Creando una estructura 65
Creando una Vista 66
Programación en ABAP 70
Introducción 70
Estructura de un programa ABAP 71
Declaración de variables y tablas internas 78
Selección de datos 83
Lectura de datos en tablas internas 86
Operadores de comparación 89
Operaciones en tablas internas 98
Copiar tablas internas 104
Ordenar tablas internas 108
Estructuras de Control 110
Trabajando con Cadenas de Texto 111
Variables de Sistema 119
Modularización de programas 121
Depuración de programas 129
Programas de ejemplo 138
SapScript 159
Introducción 159
Creando un formulario 159
Crear una página principal 161
4
Crear ventana en página 163
Crear párrafo por defecto 166
Creando un programa de impresión 168
Diseñando el formulario 175
Ejecutando el formulario 182
Debugger en SAPScript 185
SmartForms 187
Introducción 187
Creando un estilo 187
Creando un formulario 191
Creando un programa de impresión 196
Ejecutando el formulario 200
Crear una tabla 202
Screen Painter y Menu Painter 210
Introducción 210
Screen Painter 210
Controles del Screen Painter 213
Ejemplo de Screen Painter 215
Menu Painter 228
Agregando componentes 235
Programación avanzada en Dynpros 240
MatchCodes dinámicos 240
Eliminar registros en un Table Control 246
Escritura/Lectura en un Table Control 249
Trabajando con subScreens 259
Utilizando listas desplegables 272
Leyendo datos de un Dynpro 278
Módulos de Función y BAPIS 280
Introducción Módulos de Función 280
Creando nuestra primera función 280
Llamando funciones desde un programa 288
Introducción BAPIS 290
ALV (ABAP List Viewer) 292
Introducción 292
Creando un ALV 292
Agregando una cabecera al reporte 301
Eventos ALV 308
Pintemos con colores 313
Barra de menú en ALV 320
ABAP Orientado a Objetos 328
5
Introducción 328
¿Qué es la Orientación a Objetos? 328
Conceptos básicos de POO 329
Como programar en ABAP Objects 335
Componentes Orientados a Objetos 351
Crear un ALV Grid OO 351
Agregar validaciones y eventos 365
Crear un ALV Tree OO 379
Agregar validaciones y eventos 399
Crear un ALV Object Model 409
Agregar validaciones y eventos 416
Cargar Imágenes en Dynpros 421
Leer PDF’s 430
Comprimir (zip) archivos 438
Crear un Control de Texto 451
WebDynpro 458
Introducción 458
Creando nuestro primer WebDynpro 458
BSP 489
Introducción 489
Creando nuestro primer BSP 489
ABAP y XML 501
Scripting in a Box 518
SAPLink 521
Integración PHP-NetWeaver 525
Introducción 525
Instalando el SAPRFC 526
Comunicándonos con NetWeaver 527
Integración Ruby-NetWeaver 539
Introducción 539
Instalando el SAP:Rfc 540
Comunicándonos con NetWeaver 540
Donde conseguir el SAP NetWeaver Sneak Preview 546
Bibliografía y agradecimientos 547
Enlaces Web 549
6
Conociendo el entorno SAP NetWeaver
Introducción
7
Ingresando al Sistema
8
9
En esta ventana es donde ingresaremos nuestro usuario y password. En
la caja de texto de Language (Idioma), solamente podremos ingresar
EN Æ Inglés o DE Æ Alemán. El inglés es el idioma por defecto.
Luego de haber ingresado al sistema, veremos la pantalla principal del
NSP.
10
O escribir directamente la transacción a la cual queremos dirigirnos.
11
Conociendo las transacciones más importantes
12
2.- SE11 (Diccionario ABAP)
13
3.- SE16 (Browser de Datos)
14
4.- SE71 (Form Painter)
15
Podemos definir páginas, ventanas, tipos de párrafo, márgenes,
tabuladores, insertar imágenes.
Por lo general se utilizan para generar Cartas de Pago a Bancos,
Facturas, Cheques, Certificados.
16
6.- SE51 (Screen Painter)
17
7.- SE41 (Menu Painter)
18
8.- SE37 (Function Builder)
19
20
El menú de SAP NetWeaver
En todas las transacciones, contamos con una barra de menú, que nos
permite interactuar con las aplicaciones de NetWeaver. Veamos
cuales son:
Æ Grabar.
Æ Imprimir.
Æ Buscar.
Æ Buscar más.
21
Æ Se habilitan en Tablas y sirven para avanzar o
retroceder registros.
Æ Ayuda.
Æ Configuraciones GUI.
22
Diccionario de Datos
Introducción
1.- Tablas
23
• Tablas Reunidas (Pooled Tables):
Las tablas están compuestas por campos, y cada campo debe de estar
asignado a un Elemento de Datos o a un Tipo Predefinido. Los
Elementos de Datos, contienen los nombres del campo, así como
también almacenan los valores de la ayuda en línea.
Una definición de Elementos de Datos, requiere a su vez de un
Dominio. Los Dominios, contienen las características técnicas de un
campo, tales como su longitud y su tipo de dato.
24
Tipos de Datos para Dominios
25
En esta transacción podremos visualizar, modificar, eliminar o crear
los siguientes elementos:
• Tablas Transparentes
• Vistas
• Estructuras
• Dominios
• Elementos de Datos
• Ayudas para búsqueda
26
tablas, vamos a trabajar todos los ejemplos del libro, así que es muy
importante que las creen para poder seguir los ejemplos con mayor
facilidad.
Como se habrán dado cuenta, ambas tablas comienzan con el prefijo
“Z”, puesto que es la única restricción que nos da NetWeaver al
momento de crear cualquier elemento o componente.
Para crear nuestra primera tabla, hacemos lo siguiente:
27
Clase de Entrega
28
utilizamos el paquete $TMP que es local y por lo tanto no
transportable (Es decir, no puede salir del ambiente DEV de
desarrollo), o podemos crear nuestro propio Package en donde
almacenaremos todos los componentes que creemos en el libro.
Obviamente, vamos a crear nuestro propio Package, así que
debemos hacer lo siguiente:
29
• Llenamos los campos y presionamos el botón Save.
30
• Ingresamos una descripción y grabamos.
31
Atributos del Package ZARTE_PROGRAMAR
32
• Podemos ingresar el nombre del Package, o solicitar que se
muestren todos los disponibles, presionando el botón Start
Search o presionando la tecla Enter.
33
• Presionamos el botón Save. Y nos va a aparecer la ventana
solicitando una Orden de Transporte. Como creamos una
orden al momento de crear el Package, entonces la misma
orden aparecerá por defecto. Presionamos el botón Continue
o la tecla Enter.
34
El primer campo que vamos a utilizar es el MANDT, que
identifica al ambiente en el cual estamos trabajando (Y que es un
campo llave). El segundo campo, se llamará Id, y será el encargado
de identificar a cada uno de los registros (También es un campo
llave).
35
• Queremos que el tipo de dato sea CHAR y tenga una
longitud de 3, además, agregamos una pequeña descripción
del campo.
36
• El tercer campo, se llamará Nombre, y no tendrá asociado un
Tipo Predefinido, sino que contará con un Elemento de
Datos y un Dominio. Para esto, abrimos una nueva ventana
en la SE11 y nos posicionamos en Domain (Dominio).
37
Lo grabamos y lo activamos utilizando el botón Activate
38
Ahora, debemos pasar a la pestaña Field Label (Etiqueta de
Campo), que no es más que la descripción del Elemento de
Datos. La llenamos como se muestra en la figura. Grabamos
y activamos.
39
llenar el Enhacement Category (Categoría de Ampliación)
Æ Extras Æ Enhacement Category.
40
Esto sirve para definir si la tabla puede ser modificada con
campos adicionales. En nuestro caso, le decimos que no,
puesto que son tablas que hemos creado como ejemplo para
el libro.
Grabamos y activamos.
41
En el campo Check Table (Tabla de Verificación), escribimos
el nombre de nuestra tabla ZENTORNOS_PROG. Y
presionamos Enter.
42
Recibimos este mensaje, porque la llave completa de la tabla
ZENTORNOS_PROG no existe en la tabla
ZLENGUAJES_PROG.
Dejamos la ventana, como se muestra en la figura.
43
vamos a crear nuevamente un Dominio (ZD_CONEX_SAP)
y un Elemento de Datos (ZE_CONEX_SAP).
44
• Grabamos, activamos y creamos nuestro Elemento de Datos.
45
Ahora que tenemos nuestras dos tablas listas, es hora de agregar
algunos datos. Nos vamos a la transacción SE16 (Browser de
Datos). Colocamos el nombre de nuestra tabla de entornos, y
46
Una vez que hemos terminado de insertar registros, retrocedemos
47
Tenemos 3 registros grabados en la base de datos. Ahora, es el turno
de la tabla ZLENGUAJES_PROG.
Seguimos el mismo procedimiento.
48
Esos son los registros que ingresamos en la tabla
ZENTORNOS_PROG y que ahora podemos insertar en nuestra
tabla ZLENGUAJES_PROG. Lo mismo sucede con el campo
CONEX_SAP.
Cabe destacar que los valores que están en la tabla
ZENTORNOS_PROG, son los únicos valores válidos, es decir, si
ingresamos cualquier otro valor, el sistema nos mostrará un mensaje
de error.
49
Ingresamos algunos datos y estamos listos.
50
Presionamos el botón Find Scr. Number(s) (Buscar Número(s) de
51
Finalmente presionamos el botón Create (Crear) o presionamos
F6. Grabamos y activamos. Ahora, debemos ir a la transacción
SM30.
52
“+”. Esto es porque al ser Tipos Predefinidos, no poseen un texto
descriptivo. Esto lo podemos solucionar fácilmente regresando a la
transacción SE11 y al Generador de Mantenimiento de Tabla.
53
Seguramente esta pantalla los asusta un poco, pero no se preocupen,
que por el momento no vamos a hacer nada con esto, puesto que es
código generado automáticamente por el NetWeaver.
54
Debemos hacer un clic en el botón Display <-> Change (Mostrar <-
Y en la segunda columna:
55
Y repetimos la operación, modificando los símbolos “+”. Grabamos,
activamos y regresamos nuevamente.
Una vez hecho esto, nos vamos a la transacción SM30 y veremos
que los símbolos “+” han sido reemplazados por los textos correctos.
Ahora, para hacer las cosas más interesantes y poder trabajar mejor
los ejemplos del libro, regresamos a la transacción SE11 para crear
una nueva y última tabla con las siguientes características.
56
La tabla se llamará ZPROGRAMAS y contendrá algunos
programas que hemos hecho utilizando los lenguajes de
programación que hemos creado.
57
Regresamos a la tabla ZPROGRAMAS y tendremos la siguiente
estructura:
58
ZLENGUAJES_PROG incluyendo el Elemento de Datos que
creamos:
Keys .
59
Grabamos, actualizamos las Características Técnicas y la Categoría
de Amplicación y activamos la tabla.
Como solamente hemos asignado el campo Id a nuestra tabla, al
momento de querer elegir un lenguaje de programación, solamente
vamos a ver el código, lo cual no nos va a ayudar de mucho, así que
hora de crear una ayuda de búsqueda.
60
Como pueden ver, el campo Nombre tiene asignamos un elemento
de datos, así que nuevamente, creamos un Dominio y un Elemento
de Datos como se muestra a continuación.
61
Grabamos y activamos nuestra ayuda de búsqueda y la probamos
62
En esta ventana, podemos filtrar por Id o por Nombre del lenguaje,
en este caso, presionamos Enter porque queremos ver todos los
registros disponibles.
Help .
63
Asignamos la ayuda de búsqueda que creamos.
Grabamos y activamos.
64
Como podemos ver, al hacer F4 en el campo Id, podremos ver tanto
el código como el nombre del Lenguaje.
Finalmente, nuestra tabla contendrá los siguientes registros.
65
Cuando presionamos Create (Crear) , se nos
muestra una ventana en donde debemos elegir Structure
(Estructura).
66
En la ventana que aparece, elegimos Database view (Vista de Base
de Datos). Los demás tipos no los vamos a ver en este libro, puesto
que el Database view es el más utilizado.
67
En la pestaña View Flds (Campos de la Vista). Definimos los
campos que queremos que se muestren en la vista.
68
Con esto, terminamos el capítulo dedicado a Diccionario de Datos.
Ahora, ya pueden crear sus propias tablas, elementos de datos,
dominios o vistas.
69
Programación en ABAP
Introducción
70
Estructura de un programa en ABAP
71
En Type (Tipo) siempre escogemos Executable program
(Programa ejecutable) y en Status (Estado), elegimos SAP
Standard Production Program (Programa Standard SAP para
Productivo).
72
En el espacio de comentario, debemos incluir por ejemplo, quien
está creando el programa y cuando.
73
*&----------------------------------------------------*
*& Report ZDUMMY_PRIMER_PROGRAMA *
*&----------------------------------------------------*
*& Creado por: Alvaro "Blag" Tejada Galindo. *
*& Fecha creación: 14 de Noviembre del 2007 *
*&----------------------------------------------------*
REPORT ZDUMMY_PRIMER_PROGRAMA.
*=====================================================*
* SELECTION-SCREEN *
*=====================================================*
SELECTION-SCREEN BEGIN OF BLOCK PRUEBA
WITH FRAME TITLE TEXT-T01.
PARAMETERS:
TEXTO(30) TYPE C.
SELECTION-SCREEN END OF BLOCK PRUEBA.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
WRITE: TEXTO.
74
TEXT-T01. TEXT-T01, lo podemos separar en dos partes TEXT,
que nos indica que es un texto del sistema y T01, es el nombre de
dicho texto. Para poder modificarlo, simplemente deberemos hacer
doble clic en el texto. Si no lo hemos creado, nos aparecerá la
siguiente ventana:
75
El parámetro que hemos utilizado en este programa, es un CHAR de
30 caracteres.
TEXTO(30) TYPE C.
76
Aquí, deberemos de ingresar el texto que queremos que tenga
nuestro parámetro, lo grabamos, lo activamos y listo.
77
El START-OF-SELECTION, nos indica que va a comenzar la
ejecución de nuestro programa, es aquí donde colocamos toda la
lógica.
WRITE: TEXTO, significa que vamos a escribir en la pantalla, el
valor que hemos ingresado en el parámetro de entrada TEXTO.
78
Aquí estamos diciendo que vamos a crear una variable llamada
TEXTO, y que va a ser de tipo C (Caracter). Además, podemos
especificar su tamaño.
C Character 1 Space
N Numeric String 1 ’00…0’
D Date 8 ‘000000000’
(YYYYMMDD)
T Time 6 ‘000000’
(HHMMSS)
X Byte 1 X’00’
(Hexadecimal)
I Integer 4 0
P Packed Integer 8 0
F Floating point 8 ‘0.0’
number
STRING String Variable Empty string
XSTRING Byte Sequence Variable Empty X
String
79
DATA: V_CARRID TYPE SPFLI-CARRID.
80
Primero, debemos crear un TYPE, es decir, un tipo de tabla interna
y luego, utilizando el DATA, creamos una tabla interna que haga
referencia a nuestro tipo de tabla.
Para los que ya conocen ABAP, se darán cuenta de que no hemos
creado la tabla con una cabecera. Es decir, no utilizamos ni
OCCURS 0, ni tampoco WITH HEADER LINE. Esto es porque,
en ABAP Objects, está prohibido utilizar cabeceras o workareas.
Para los que no conocen ABAP, en versiones anteriores, podiamos
crear tablas internas con líneas de cabecera, lo cual facilitaba la
lectura de datos, pero que al mismo tiempo ocasionaba problemas de
performance. Es por eso, que SAP decició eliminar la cabeceras
completamente.
Además de crear tablas internas, de la manera que hemos visto,
podemos también incluir estructuras completas de Base de Datos.
Esto podemos hacerlo de dos maneras, dependiendo de si queremos
o no incluir campos adicionales.
81
Claro, si queremos crear una tabla interna que tenga datos propios,
lo hacemos de la siguiente forma.
82
TEST Æ Tablas Standard. Puede ser accedida mediante un índice o
mediante campos.
TEST_H Æ Tabla de tipo hashed. De rápido acceso, pero no puede
ser accedida mediante un índice.
TEST_S Æ Sorted table. De rápido acceso, siempre está ordenada,
no puede ser accedida mediante un índice.
Selección de Datos
En Variables:
83
Declaramos una variable llamada NOMBRE del tipo del campo
NOM_PROG de la tabla ZPROGRAMAS. Hacemos un SELECT
SINGLE para obtener un registro cuyo campo ID_PROG sea igual
a 001.
En Tablas internas:
SELECT NOM_PROG
INTO TABLE T_PROGRAMAS
FROM ZPROGRAMAS.
84
DATA: T_PROGRAMAS TYPE STANDARD TABLE OF TY_PROGRAMAS.
85
Lectura de datos de Tablas Internas
• LOOP AT
86
DATA: T_PROGRAMAS TYPE STANDARD TABLE
OF TY_PROGRAMAS.
87
• READ TABLE
88
un Indice o también un Campo para leer el contenido y
asignarlo a nuestro Field-Symbol.
Operadores de Comparación
=, EQ Igual a
<>, NE Distinto a
>, GT Mayor que
<, LT Menor que
>=, GE Mayor igual
<=, LE Menor igual
IF NOMBRE EQ ‘PHP’.
WRITE:/ ‘Viva PHP!’.
ENDIF.
Que decir:
IF NOMBRE == ‘PHP’.
WRITE:/ ‘Viva PHP!’.
89
ENDIF.
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE TABLES *
*=====================================================*
TABLES: ZPROGRAMAS.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
NOMBRE TYPE ZLENGUAJES_PROG-NOMBRE,
ENTORNO TYPE ZLENGUAJES_PROG-ENTORNO,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
END OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE
OF TY_PROGRAMAS.
*=====================================================*
* FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_PROGRAMAS> LIKE LINE
90
OF T_PROGRAMAS.
*=====================================================*
* SELECTION-SCREEN *
*=====================================================*
SELECTION-SCREEN BEGIN OF BLOCK PRG
WITH FRAME TITLE TEXT-T01.
SELECT-OPTIONS:
S_ID FOR ZPROGRAMAS-ID.
SELECTION-SCREEN END OF BLOCK PRG.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
LOOP AT T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
WRITE:/ <FS_PROGRAMAS>-NOMBRE,<FS_PROGRAMAS>-ENTORNO,
<FS_PROGRAMAS>-NOM_PROG.
ENDLOOP.
91
Analicemos un poco el programa antes de ejecutarlo y ver el
resultado.
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
TABLES: ZPROGRAMAS.
TABLES indica que vamos a utilizar una tabla para hacer referencia
a un campo en el SELECTION-SCREEN.
92
DATA indica que vamos a crear una variable o una tabla interna.
T_PROGRAMAS es el nombre de nuestra tabla interna.
TYPE STANDARD TABLE indica que la tabla es de tipo
STANDARD.
OF indica a que tipo de dato va a hacer referencia nuestra tabla
interna.
TY_PROGRAMAS es el nombre del tipo de tabla que creamos y al
cual va a hacer referencia nuestra tabla interna.
93
WITH FRAME indica que nuestro bloque de parámetro debe tener
un marco (más que nada un tema de visualización).
TITLE TEXT indica que el bloque de parámetros debe tener un
título.
T01 contiene el título.
SELECT-OPTIONS indica que es un parámetros con rango de
valores.
S_ID es el nombre del SELECT-OPTION.
FOR indica que hace referencia a un campo de Base de Datos.
ZPROGRAMAS-ID es el nombre de la Base de Datos y el campo
respectivamente.
SELECTION-SCREEN END OF indica el fin del bloque de
parámetros.
START-OF-SELECTION.
94
INTO TABLE indica en que tabla interna queremos guardar los
datos.
T_PROGRAMAS es la tabla donde vamos a guardar los datos.
FROM indica de donde queremos obtener los datos.
ZLENGUAJES_PROG INNER JOIN ZPROGRAMAS indica
que queremos realizar un INNER JOIN entre estas dos tablas
ON indica el parámetro de igualdad de campos del INNER JOIN.
ZLENGUAJES~ID = ZPROGRAMAS~ID indica que el campo
ID de ambas tablas va a utilizarse como campo de igualdad.
WHERE indica el parámetro de restricción del SELECT.
ZPROGRAMAS~ID es el campo por el cual queremos hacer el
filtro.
IN indica que el campo del filtro debe de estar dentro de los valores
del SELECT-OPTION.
S_ID es el SELECT-OPTION contra el cual vamos a validar el
campo ZPROGRAMAS~ID.
95
SY-ULINE(45) es una variable del sistema que nos permite dibujar
una línea. El 45 entre paréntesis indica la longitud de la línea.
LOOP AT T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
WRITE:/ <FS_PROGRAMAS>-NOMBRE,<FS_PROGRAMAS>-ENTORNO,
<FS_PROGRAMAS>-NOM_PROG.
ENDLOOP.
96
Si queremos que nuestro programa se vea un poco más colorido,
podemos agregar un par de líneas.
FORMAT COLOR 5.
WRITE:/1 'Lenguaje',17 'Entorno',33 'Programa'.
FORMAT COLOR OFF.
WRITE:/ SY-ULINE(45).
97
FORMAT COLOR indica que queremos pintar el fondo de un
color.
5 representa al color verde.
FORMAT COLOR OFF indica que ya no queremos seguir
pintando el fondo de un color.
98
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
END OF TY_PROGRAMAS.
<FS_PROGRAMAS>-ID_PROG = '006'.
<FS_PROGRAMAS>-NOM_PROG = 'MP3 Player'.
WRITE:/ <FS_PROGRAMAS>-ID_PROG.
WRITE:/ <FS_PROGRAMAS>-NOM_PROG.
99
• Modificando registros
<FS_PROGRAMAS>-ID_PROG = '006'.
<FS_PROGRAMAS>-NOM_PROG = 'MP3 Player'.
WRITE:/ <FS_PROGRAMAS>-ID_PROG.
WRITE:/ <FS_PROGRAMAS>-NOM_PROG.
SKIP 1.
WRITE:/ 'Modificamos el registro'.
SKIP 1.
100
<FS_PROGRAMAS>-NOM_PROG = 'Web Browser'.
WRITE:/ <FS_PROGRAMAS>-ID_PROG.
WRITE:/ <FS_PROGRAMAS>-NOM_PROG.
• Eliminado registros
101
<FS_PROGRAMAS>-ID_PROG = '006'.
<FS_PROGRAMAS>-NOM_PROG = 'MP3 Player'.
<FS_PROGRAMAS>-ID_PROG = '007'.
<FS_PROGRAMAS>-NOM_PROG = 'Web Browser'.
102
FIELD-SYMBOLS: <FS_PROGRAMAS> LIKE LINE
OF T_PROGRAMAS.
<FS_PROGRAMAS>-ID_PROG = '006'.
<FS_PROGRAMAS>-NOM_PROG = 'MP3 Player'.
<FS_PROGRAMAS>-ID_PROG = '006'.
<FS_PROGRAMAS>-NOM_PROG = 'MP3 Player'.
103
DATA: T_PROGRAMAS TYPE STANDARD TABLE
OF TY_PROGRAMAS.
<FS_PROGRAMAS>-ID_PROG = '006'.
<FS_PROGRAMAS>-NOM_PROG = 'MP3 Player'.
<FS_PROGRAMAS>-ID_PROG = '006'.
<FS_PROGRAMAS>-NOM_PROG = 'Web Browser'.
104
• Copiar tablas con la misma estructura
<FS_PROGRAMAS>-ID_PROG = '006'.
<FS_PROGRAMAS>-NOM_PROG = 'MP3 Player'.
T_PROGRAMAS_AUX[] = T_PROGRAMAS[].
105
• Copiar tablas con diferente estructura
<FS_PROGRAMAS>-ID_PROG = '006'.
<FS_PROGRAMAS>-NOM_PROG = 'MP3 Player'.
LOOP AT T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
APPEND INITIAL LINE TO T_PROGRAMAS_AUX
106
ASSIGNING <FS_PROGRAMAS_AUX>.
MOVE <FS_PROGRAMAS>-ID_PROG TO
<FS_PROGRAMAS_AUX>-ID_PROG.
MOVE <FS_PROGRAMAS>-NOM_PROG TO
<FS_PROGRAMAS_AUX>-NOM_PROG.
ENDLOOP.
107
OF TY_PROGRAMAS_AUX.
<FS_PROGRAMAS>-ID_PROG = '006'.
<FS_PROGRAMAS>-NOM_PROG = 'MP3 Player'.
LOOP AT T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
APPEND INITIAL LINE TO T_PROGRAMAS_AUX
ASSIGNING <FS_PROGRAMAS_AUX>.
MOVE-CORRESPONDING <FS_PROGRAMAS> TO
<FS_PROGRAMAS_AUX>.
ENDLOOP.
108
TYPES: BEGIN OF TY_PROGRAMAS,
ID_PROG TYPE ZPROGRAMAS-ID_PROG,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
END OF TY_PROGRAMAS.
<FS_PROGRAMAS>-ID_PROG = '006'.
<FS_PROGRAMAS>-NOM_PROG = 'MP3 Player'.
<FS_PROGRAMAS>-ID_PROG = '005'.
<FS_PROGRAMAS>-NOM_PROG = 'Web Browser'.
109
Estructuras de Control
Esto significa que mientras la variable VAR sea menor o igual a 10,
imprimimos el valor. Aumentamos el valor de VAR de uno en uno,
por cada vuelta del WHILE.
También tenemos presente el DO-ENDO.
DO.
IF VAR LT 10.
WRITE:/ VAR.
VAR = VAR + 1.
ELSE.
EXIT.
ENDIF.
ENDDO.
110
El DO-ENDDO es un bucle repetitivo que avanza mientras no le
digamos que tiene que salir. Utilizando un IF preguntamos si el
valor de la variable es menor o igual a 10. En el caso afirmativo
imprimimos y aumentamos en uno. Cuando VAR es mayor a 10,
salimos del DO-ENDDO utilizando un EXIT.
Aunque, también podríamos haberlo escrito así:
DO 10 TIMES.
WRITE:/ VAR.
VAR = VAR + 1.
ENDDO.
111
ejemplo PERL), de todos modos nos brinda alguna poderosas
herramientas como estas:
• TRANSLATE
Convierte una cadena de texto a Mayúsculas o Minúsculas.
WRITE:/ VAR.
WRITE:/ VAR.
• CONCATENATE
Concatena dos o más cadenas de texto. Es decir, une cadenas
en una cadena más grande.
112
VAR = 'El Arte de Programar'.
VAR_AUX = 'SAP NETWEAVER'.
WRITE:/ VAR_TEXT.
WRITE:/ VAR_TEXT.
113
estamos diciendo que separe el texto con un espacio en
blanco.
• SPLIT
Divide una cadena en subcadenas, dependiendo de un carácter
aguja.
WRITE:/ VAR.
WRITE:/ VAR_TEXT.
114
DATA: VAR_TEXT TYPE STRING.
• SHIFT
Utilizado con la sentencia DELETING, permite eliminar los
espacios o caracteres al inicio o al final de una cadena de
texto.
DATA: VAR_TEXT TYPE STRING.
115
Utilizando el SHIFT RIGHT DELETING TRAILING
eliminamos los espacios en blanco del final de la cadena.
• CONDENSE
Elimina los espacios en blanco, como lo hace el SHIFT, pero
toma los espacios del final y del inicio al mismo tiempo.
CONDENSE VAR_TEXT.
CONDENSE VAR_TEXT NO-GAPS.
• REPLACE
Reemplaza una cadena por otra.
116
VAR_TEXT = 'SAP/NETWEAVER/PROGRAMMING'.
• FIND
Busca una subcadena en una cadena.
117
FIND 'NETWEAVER' IN VAR_TEXT
RESULTS RESULT_TAB.
IF SY-SUBRC EQ 0.
READ TABLE RESULT_TAB INDEX 1
ASSIGNING <FS_RESULT>.
WRITE:/ <FS_RESULT>-OFFSET.
ENDIF.
118
LOOP AT RESULT_TAB
ASSIGNING <FS_RESULT>.
WRITE:/ <FS_RESULT>-OFFSET.
ENDLOOP.
ENDIF.
• STRLEN
Obtiene la longitud de una cadena.
ABAP cuenta con variables internas del sistema que nos ayudan a
conocer información importante acerca de nuestro programa o del
119
sistema. Veamos cuales son las más importantes. (Todas pueden ser
encontradas en la tabla SYST).
• SY-SUBRC
Retorna un valor que determina el estado de las operaciones
en ABAP.
• SY-PAGNO
En un reporte de tipo listado, determina el número de página
en la cual nos encontramos.
• SY-TABIX
Dentro de un LOOP, nos indica el número de “vuelta” o
iteración o el índice del registro que estamos leyendo.
• SY-LANGU
Idioma de trabajo actual.
• SY-BACTH
Nos indica si el programa se está ejecutando en fondo o en
modo directo.
• SY-MANDT
120
Nos indica el número de mandante en el cual estamos
trabajando.
• SY-TCODE
El nombre de la transacción con la cual estamos trabajando.
• SY-UCOMM
Nombre del código de función lanzado por un Dynpro o por
un menú.
• SY-DATUM
Fecha actual del sistema.
• SY-UZEIT
Hora actual del sistema.
• SY-REPID
Nombre del programa que estamos creando o ejecutando.
• SY-UNAME
Nombre del usuario logeado en el sistema.
Modularización de Programas
121
Las funciones tienen el siguiente formato:
Y se llaman así:
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE TABLES *
*=====================================================*
TABLES: ZPROGRAMAS.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
NOMBRE TYPE ZLENGUAJES_PROG-NOMBRE,
122
ENTORNO TYPE ZLENGUAJES_PROG-ENTORNO,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
END OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE
OF TY_PROGRAMAS.
*=====================================================*
* FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_PROGRAMAS> LIKE LINE
OF T_PROGRAMAS.
*=====================================================*
* SELECTION-SCREEN *
*=====================================================*
SELECTION-SCREEN BEGIN OF BLOCK PRG
WITH FRAME TITLE TEXT-T01.
SELECT-OPTIONS:
S_ID FOR ZPROGRAMAS-ID.
SELECTION-SCREEN END OF BLOCK PRG.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM OBTENER_DATOS.
PERFORM MOSTRAR_REPORTE.
123
*&----------------------------------------------------*
*& Form obtener_datos *
*&----------------------------------------------------*
FORM OBTENER_DATOS.
SELECT NOMBRE ENTORNO NOM_PROG
INTO TABLE T_PROGRAMAS
FROM ( ZLENGUAJES_PROG INNER JOIN ZPROGRAMAS
ON ZLENGUAJES_PROG~ID = ZPROGRAMAS~ID )
WHERE ZPROGRAMAS~ID IN S_ID.
ENDFORM. "obtener_datos
*&----------------------------------------------------*
*& Form MOSTRAR_REPORTE *
*&----------------------------------------------------*
FORM MOSTRAR_REPORTE.
WRITE:/1 'Lenguaje',17 'Entorno',33 'Programa'.
WRITE:/ SY-ULINE(45).
LOOP AT T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
WRITE:/ <FS_PROGRAMAS>-NOMBRE,
<FS_PROGRAMAS>-ENTORNO,
<FS_PROGRAMAS>-NOM_PROG.
ENDLOOP.
ENDFORM. "MOSTRAR_REPORTE
124
START-OF-SELECTION.
PERFORM OBTENER_DATOS.
PERFORM MOSTRAR_REPORTE.
FORM OBTENER_DATOS.
SELECT NOMBRE ENTORNO NOM_PROG
INTO TABLE T_PROGRAMAS
FROM ( ZLENGUAJES_PROG INNER JOIN ZPROGRAMAS
ON ZLENGUAJES_PROG~ID = ZPROGRAMAS~ID )
WHERE ZPROGRAMAS~ID IN S_ID.
ENDFORM. "obtener_datos
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: VAR TYPE STRING.
*=====================================================*
* START-OF-SELECTION *
125
*=====================================================*
START-OF-SELECTION.
PERFORM INICIALIZAR.
PERFORM CONVERTIR USING 'U'
CHANGING VAR.
WRITE:/ VAR.
PERFORM CONVERTIR USING 'L'
CHANGING VAR.
WRITE:/ VAR.
*&----------------------------------------------------*
*& Form INICIALIZAR *
*&----------------------------------------------------*
FORM INICIALIZAR.
VAR = 'El Arte de Programar NETWEAVER'.
ENDFORM. "INICIALIZAR
*&----------------------------------------------------*
*& Form CONVERTIR *
*&----------------------------------------------------*
FORM CONVERTIR USING P_TIPO
CHANGING P_VAR.
CASE P_TIPO.
WHEN 'U'.
TRANSLATE P_VAR TO UPPER CASE.
WHEN 'L'.
TRANSLATE P_VAR TO LOWER CASE.
ENDCASE.
ENDFORM. "CONVERTIR
126
En este caso, tenemos dos FORMS, uno llamado INICIALIZAR
donde simplemente asignamos un valor a la variable VAR y otro
llamado CONVERTIR el cual recibe un valor de texto (Ya sea U o
L) y cambia el valor de la variable VAR. Dentro del FORM
CONVERTIR, utilizamos un CASE-ENDCASE para poder
determinar el valor del parámetro P_TIPO. En el caso de ser U
(Upper), entonces hacemos un TRANSLATE TO UPPER CASE y
cambiamos el valor de P_VAR. En caso contrario, si es L (Lower),
hacemos un TRANSLATE TO LOWER CASE y cambiamos el
valor de P_VAR. Luego de llamar a cada PERFORM, imprimimos
el valor de P_VAR.
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
ID_PROG TYPE ZPROGRAMAS-ID_PROG,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
END OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE
OF TY_PROGRAMAS.
*=====================================================*
127
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_PROGRAMAS> LIKE LINE
OF T_PROGRAMAS.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM INICIALIZAR.
PERFORM IMPRIMIR_REPORTE TABLES T_PROGRAMAS.
*&----------------------------------------------------*
*& Form inicializar *
*&----------------------------------------------------*
FORM INICIALIZAR.
APPEND INITIAL LINE
TO T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
<FS_PROGRAMAS>-ID_PROG = '001'.
<FS_PROGRAMAS>-NOM_PROG = 'TETRIS'.
APPEND INITIAL LINE
TO T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
<FS_PROGRAMAS>-ID_PROG = '002'.
<FS_PROGRAMAS>-NOM_PROG = 'POKEMON'.
ENDFORM. " inicializar
*&----------------------------------------------------*
*& Form IMPRIMIR_REPORTE *
*&----------------------------------------------------*
FORM IMPRIMIR_REPORTE TABLES T_TABLA.
LOOP AT T_TABLA
128
ASSIGNING <FS_PROGRAMAS>.
WRITE:/ <FS_PROGRAMAS>-ID_PROG.
WRITE: <FS_PROGRAMAS>-NOM_PROG.
ENDLOOP.
ENDFORM. "IMPRIMIR_REPORTE
Depuración de Programas
129
Como mencioné arriba, la primera forma de activar el Debugger es
utilizar la palabra clave BREAK-POINT.
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
ID_PROG TYPE ZPROGRAMAS-ID_PROG,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
130
END OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE
OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_PROGRAMAS> LIKE LINE
OF T_PROGRAMAS.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
SELECT ID_PROG NOM_PROG
INTO TABLE T_PROGRAMAS
FROM ZPROGRAMAS.
BREAK-POINT.
LOOP AT T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
WRITE:/ <FS_PROGRAMAS>-ID_PROG,
<FS_PROGRAMAS>-NOM_PROG.
ENDLOOP.
131
Cuando ejecutamos el programa, entraremos al Debugger.
132
Pero lo más importante es la parte del final, donde dice Field names
(Nombre de campos), puesto que ahí podemos colocar una variable
o una tabla interna para ver su contenido. Solo necesitamos escribir
su nombre o hacer doble clic sobre su nombre en la pantalla de
código.
Una vez que tenemos el nombre escrito, basta con que hagamos
doble clic para poder ver su contenido.
133
Con Append (Copiamos un registro).
Con Delete (Eliminamos un registro).
En el caso de las variables, podemos tomar como ejemplo
<FS_PROGRAMA>-ID_PROG.
Para avanzar entre las líneas del código, contamos con los siguientes
botones.
134
Si no queremos que nuestro programa se pare cada vez que lo
ejecutemos. Debemos reemplazar el Break-Point por un Break-
Point lógico.
135
Felizmente, tenemos una forma de guardar los break-points lógicos
para un programa. Este es un truco que aprendí hace un par de años
en el SDN ( http://sdn.sap.com ).
136
En esta pantalla podemos guardar un grupo de Break-Points
lógicos, los cuales se almacenan por defecto durante un mes.
Podemos cargarlos la próxima vez que ejecutemos el programa,
podemos extender su estadía por una semana más o podemos
eliminarlos.
Finalmente, la última manera para hace DEBUG a un programa, es
escribir /H en la barra de menú y presionar Enter.
137
Programas de ejemplo
Decimal a Binario
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: SUMA_TEXT(50) TYPE C,
SUMA TYPE I,
EXPONENTE TYPE I,
FLAG TYPE C.
*=====================================================*
* SELECTION-SCREEN *
*=====================================================*
SELECTION-SCREEN BEGIN OF BLOCK DEC_TO_BIN WITH FRAME.
PARAMETERS:
P_NUMERO TYPE I.
SELECTION-SCREEN END OF BLOCK DEC_TO_BIN.
138
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM INICIALIZAR.
PERFORM CALCULAR_BINARIO USING P_NUMERO
CHANGING SUMA_TEXT.
IF FLAG EQ SPACE.
PERFORM IMPRIMIR.
ENDIF.
*&----------------------------------------------------*
*& Form INICIALIZAR *
*&----------------------------------------------------*
FORM INICIALIZAR.
SUMA = 0.
EXPONENTE = 1.
*&----------------------------------------------------*
*& Form CALCULAR_BINARIO *
*&----------------------------------------------------*
FORM CALCULAR_BINARIO USING P_NUM
CHANGING P_SUM.
NUMERO = P_NUM.
139
CATCH SYSTEM-EXCEPTIONS ARITHMETIC_ERRORS = 5.
WHILE NUMERO GT 0.
DIGITO = NUMERO MOD 2.
NUMERO = NUMERO DIV 2.
SUMA = SUMA + DIGITO * EXPONENTE.
EXPONENTE = EXPONENTE * 10.
ENDWHILE.
P_SUM = SUMA.
CONDENSE P_SUM NO-GAPS.
ENDCATCH.
IF SY-SUBRC = 5.
WRITE / 'Error de cálculo'.
FLAG = 'X'.
ENDIF.
*&----------------------------------------------------*
*& Form IMPRIMIR *
*&----------------------------------------------------*
FORM IMPRIMIR.
140
CATCH SYSTEM-EXCEPTIONS ARITHMETIC_ERRORS = 5.
WHILE NUMERO GT 0.
DIGITO = NUMERO MOD 2.
NUMERO = NUMERO DIV 2.
SUMA = SUMA + DIGITO * EXPONENTE.
EXPONENTE = EXPONENTE * 10.
ENDWHILE.
P_SUM = SUMA.
CONDENSE P_SUM NO-GAPS.
ENDCATCH.
IF SY-SUBRC = 5.
WRITE / 'Error de cálculo'.
FLAG = 'X'.
ENDIF.
141
IF FLAG EQ SPACE.
PERFORM IMPRIMIR.
ENDIF.
Colores en ABAP
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: I TYPE I,
142
COL(15) TYPE C.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM IMPRIMIR.
*&----------------------------------------------------*
*& Form IMPRIMIR *
*&----------------------------------------------------*
FORM IMPRIMIR.
SKIP 2.
WHILE I < 8.
CASE I.
WHEN 0. COL = 'COL_BACKGROUND '.
WHEN 1. COL = 'COL_HEADING '.
WHEN 2. COL = 'COL_NORMAL '.
WHEN 3. COL = 'COL_TOTAL '.
WHEN 4. COL = 'COL_KEY '.
WHEN 5. COL = 'COL_POSITIVE '.
WHEN 6. COL = 'COL_NEGATIVE '.
WHEN 7. COL = 'COL_GROUP '.
ENDCASE.
FORMAT INTENSIFIED COLOR = I.
WRITE: /(4) I, AT 7 SY-VLINE,
COL, SY-VLINE,
143
COL INTENSIFIED OFF, SY-VLINE,
COL INVERSE.
I = I + 1.
ENDWHILE.
Lenguajes y Programas
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE INCLUDES *
*=====================================================*
INCLUDE <ICON>.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
144
TYPES: BEGIN OF TY_PROGRAMAS,
NOMBRE TYPE ZLENGUAJES_PROG-NOMBRE,
ENTORNO TYPE ZLENGUAJES_PROG-ENTORNO,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
END OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE
OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_PROGRAMAS> LIKE LINE
OF T_PROGRAMAS.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: ICONO TYPE STRING.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM SELECCIONAR_DATOS.
PERFORM IMPRIMIR_DATOS.
*&----------------------------------------------------*
*& Form SELECCIONAR_DATOS *
*&----------------------------------------------------*
145
FORM SELECCIONAR_DATOS.
*&----------------------------------------------------*
*& Form IMPRIMIR_DATOS *
*&----------------------------------------------------*
FORM IMPRIMIR_DATOS.
FORMAT COLOR 5.
WRITE:/1 'Lenguaje',15 'Entorno', 25 'Programa',
40 'Icono'.
FORMAT COLOR OFF.
SKIP 1.
LOOP AT T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
WRITE:/1 <FS_PROGRAMAS>-NOMBRE,
15 <FS_PROGRAMAS>-ENTORNO,
25 <FS_PROGRAMAS>-NOM_PROG.
CASE <FS_PROGRAMAS>-ENTORNO.
WHEN 'WEB'.
ICONO = ICON_WD_WEB_PROJECT.
WHEN 'SCRIPT'.
ICONO = ICON_HISTORY.
WHEN 'DESKTOP'.
ICONO = ICON_FOLDER.
146
ENDCASE.
WRITE: 40 ICONO.
ENDLOOP.
LOOP AT T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
WRITE:/1 <FS_PROGRAMAS>-NOMBRE,
15 <FS_PROGRAMAS>-ENTORNO,
25 <FS_PROGRAMAS>-NOM_PROG.
CASE <FS_PROGRAMAS>-ENTORNO.
WHEN 'WEB'.
ICONO = ICON_WD_WEB_PROJECT.
WHEN 'SCRIPT'.
ICONO = ICON_HISTORY.
WHEN 'DESKTOP'.
ICONO = ICON_FOLDER.
ENDCASE.
WRITE: 40 ICONO.
ENDLOOP.
147
ENDCASE sabemos que valores asignar a la variable ICON para
luego simplemente imprimirlo.
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: X_LINES TYPE STRING.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
148
DATA: T_TABLE TYPE STANDARD TABLE OF X_LINES.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_TABLE> LIKE LINE OF T_TABLE.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: TEXTO(30) TYPE C,
AUX_TEXT(30) TYPE C,
V_LEN TYPE I,
V_LONG TYPE I.
*=====================================================*
* SELECTION-SCREEN *
*=====================================================*
SELECTION-SCREEN BEGIN OF BLOCK DEC_TO_BIN WITH FRAME.
PARAMETERS:
P_TEXTO(20) TYPE C.
SELECTION-SCREEN END OF BLOCK DEC_TO_BIN.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM INICIALIZAR.
PERFORM FILL_RIGHT_CHARACTERS USING '*'
CHANGING TEXTO.
PERFORM IMPRIMIR USING TEXTO.
149
PERFORM INICIALIZAR.
PERFORM CAPITALIZE_LETTERS CHANGING TEXTO.
PERFORM IMPRIMIR USING TEXTO.
PERFORM INICIALIZAR.
PERFORM SPLIT_LONG_TEXT TABLES T_TABLE
USING TEXTO.
PERFORM IMPRIMIR_TABLA TABLES T_TABLE.
PERFORM INICIALIZAR.
PERFORM REVERSE_STRING USING TEXTO.
PERFORM IMPRIMIR USING TEXTO.
*&----------------------------------------------------*
*& Form INICIALIZAR *
*&----------------------------------------------------*
FORM INICIALIZAR.
TEXTO = P_TEXTO.
SKIP 1.
ENDFORM. "INICIALIZAR
*&----------------------------------------------------*
*& Form IMPRIMIR_TABLA *
*&----------------------------------------------------*
FORM IMPRIMIR_TABLA TABLES T_TAB.
LOOP AT T_TAB
ASSIGNING <FS_TABLE>.
WRITE:/ <FS_TABLE>.
150
ENDLOOP.
ENDFORM. "INICIALIZAR
*&----------------------------------------------------*
*& Form imprimir *
*&----------------------------------------------------*
FORM IMPRIMIR USING L_TEXTO.
WRITE:/ TEXTO.
ENDFORM. "imprimir
*&----------------------------------------------------*
*& Form FILL_RIGHT_CHARACTERS *
*&----------------------------------------------------*
* Llena una cadena con caracteres a la derecha. *
*-----------------------------------------------------*
FORM FILL_RIGHT_CHARACTERS USING L_CHAR
CHANGING L_TEXTO.
DO V_LEN TIMES.
CONCATENATE L_TEXTO L_CHAR INTO L_TEXTO.
ENDDO.
ENDFORM. "FILL_RIGHT_CHARACTERS
151
*&----------------------------------------------------*
*& Form CAPITALIZE_LETTERS *
*&----------------------------------------------------*
* Capitaliza un texto dado. *
*-----------------------------------------------------*
FORM CAPITALIZE_LETTERS CHANGING L_TEXTO.
CLEAR L_TEXTO.
LOOP AT T_TABLE
ASSIGNING <FS_TABLE>.
V_LONG = STRLEN( <FS_TABLE> ).
V_LONG = V_LONG - 1.
AUX_TEXT = <FS_TABLE>+0(1).
TRANSLATE AUX_TEXT TO UPPER CASE.
CONCATENATE AUX_TEXT <FS_TABLE>+1(V_LONG)
INTO AUX_TEXT.
CONCATENATE L_TEXTO AUX_TEXT INTO L_TEXTO
SEPARATED BY SPACE.
SHIFT L_TEXTO LEFT DELETING LEADING SPACE.
ENDLOOP.
ENDFORM. "CAPITALIZE_LETTERS
152
*&----------------------------------------------------*
*& Form SPLIT_LONG_TEXT *
*&----------------------------------------------------*
* Corta un texto largo en varios registros de *
* una tabla *
*-----------------------------------------------------*
FORM SPLIT_LONG_TEXT TABLES T_TAB
USING L_TEXTO.
ENDFORM. "SPLIT_LONG_TEXT
153
*&----------------------------------------------------*
*& Form REVERSE_STRING *
*&----------------------------------------------------*
* Invierte una cadena *
*-----------------------------------------------------*
FORM REVERSE_STRING CHANGING L_TEXTO.
ENDFORM. "REVERSE_STRING
154
V_LEN = V_LONG - V_LEN.
DO V_LEN TIMES.
CONCATENATE L_TEXTO L_CHAR INTO L_TEXTO.
ENDDO.
ENDFORM. "FILL_RIGHT_CHARACTERS
CLEAR L_TEXTO.
LOOP AT T_TABLE
ASSIGNING <FS_TABLE>.
V_LONG = STRLEN( <FS_TABLE> ).
155
V_LONG = V_LONG - 1.
AUX_TEXT = <FS_TABLE>+0(1).
TRANSLATE AUX_TEXT TO UPPER CASE.
CONCATENATE AUX_TEXT <FS_TABLE>+1(V_LONG)
INTO AUX_TEXT.
CONCATENATE L_TEXTO AUX_TEXT INTO L_TEXTO
SEPARATED BY SPACE.
SHIFT L_TEXTO LEFT DELETING LEADING SPACE.
ENDLOOP.
ENDFORM. "CAPITALIZE_LETTERS
156
CALL FUNCTION 'RSDG_WORD_WRAP'
EXPORTING
TEXTLINE = L_TEXTO
DELIMITER = SPACE
TABLES
OUT_LINES = T_TAB
EXCEPTIONS
OUTPUTLEN_TOO_LARGE = 1
OTHERS = 2.
ENDFORM. "SPLIT_LONG_TEXT
157
LANG = SY-LANGU
IMPORTING
RSTRING = L_TEXTO
EXCEPTIONS
TOO_SMALL = 1
OTHERS = 2.
ENDFORM. "REVERSE_STRING
158
SapScript
Introducción
Creando un formulario
159
En el campo formulario, ingresamos el nombre de nuestro
formulario y en el campo idioma, el idioma en el cual queremos
crearlo (Bastante simple no?). En realidad, el idioma se utiliza para
poder crear de una manera más sencilla las traducciones, puesto que
cuando uno ingresa a NetWeaver, puede hacerlo con muchos
idiomas predefinidos (Bueno, no esta versión, puesto que solamente
permite Alemán e Inglés...La versión completa del NetWeaver
incluye entre muchos otros, Español, Francés, Italiano...).
160
En esta ventana, deberemos ingresar un texto que describa
brevemente al formulario. Luego de esto, deberemos ingresar a la
sección de Basic Settings (Parametrizaciones Básicas) con el
siguiente botón .
161
En esta ventana, se nos exige especificar una Página Inicial y un
Párrafo por defecto. Como este formulario es nuevo, ninguno de
estos existe, por lo cual deberemos crearlos.
botón .
162
formas. Con un clic derecho, con el menú de la transacción o
presionando SHIFT + F6.
Menú de transacción
163
En Page (Página) ingresaremos el nombre de la página que
queremos crear y en Description (Description), una descripción de
la página. Por convención, simpre la página principal será llamada
MAIN.
Luego de haber creado el elemento, podremos verlo como se
muestra a continuación.
164
Y seguir un procedimiento similar al de la creación de la página.
Es decir, deberemos de crear un nuevo elemento.
Cuando creamos el nuevo elemento, se nos muestra la siguiente
ventana.
165
deberemos hacer clic en el botón Windows (Ventanas) y
crear un nuevo elemento.
Para poder elegir la ventana, simplemente deberemos de hacer un
doble clic sobre ella.
Por ejemplo:
166
3.- Crear párrafo por defecto
), etc.
167
Una vez que hemos creado la página y el párrafo por defecto,
deberemos regresar a la configuración de cabecera para poder
finalizar con las parametrizaciones básicas. Para esto, simplemente
. Es importante indicar
cual es la página principal.
168
Una vez que hemos terminado, debemos grabar el formulario y
activarlo mediante el menú.
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE TABLAS *
*=====================================================*
TABLES: ZPROGRAMAS,ITCPO,TOA_DARA,ITCPP.
169
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_ZPROGRAMAS TYPE STANDARD TABLE OF
ZPROGRAMAS.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_PROGRAMAS> LIKE LINE OF
T_ZPROGRAMAS.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: V_FORM(14) TYPE C,
V_SCRIPT.
*=====================================================*
* SELECTION-SCREEN *
*=====================================================*
SELECTION-SCREEN BEGIN OF BLOCK APP WITH FRAME.
SELECT-OPTIONS:
SID_PROG FOR ZPROGRAMAS-ID_PROG.
SELECTION-SCREEN END OF BLOCK APP.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM INICIALIZAR.
170
*=====================================================*
* END-OF-SELECTION *
*=====================================================*
END-OF-SELECTION.
PERFORM ABRIR_SAPSCRIPT.
*&----------------------------------------------------*
*& Form INICIALIZAR *
*&----------------------------------------------------*
FORM INICIALIZAR.
V_FORM = 'ZDUMMY_FORM'.
SELECT *
INTO TABLE T_ZPROGRAMAS
FROM ZPROGRAMAS
WHERE ID_PROG IN SID_PROG.
ENDFORM. "INICIALIZAR
*&----------------------------------------------------*
*& Form ABRIR_SAPSCRIPT *
*&----------------------------------------------------*
FORM ABRIR_SAPSCRIPT.
ITCPO-TDIMMED = '*'.
ITCPO-TDDELETE = '*'.
ITCPO-TDLIFETIME = '7'.
ITCPO-TDPREVIEW = 'X'.
IF V_SCRIPT EQ SPACE.
CALL FUNCTION 'OPEN_FORM'
EXPORTING
171
FORM = V_FORM
LANGUAGE = 'S'
OPTIONS = ITCPO
ARCHIVE_INDEX = TOA_DARA
DEVICE = 'PRINTER'
DIALOG = 'X'
EXCEPTIONS
CANCELED = 01.
IF SY-SUBRC NE 0.
EXIT.
ENDIF.
V_SCRIPT = 'X'.
ENDIF.
LOOP AT T_ZPROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
CALL FUNCTION 'WRITE_FORM'
EXPORTING
ELEMENT = 'MAIN'
WINDOW = 'MAIN'
EXCEPTIONS
OTHERS = 01.
ENDLOOP.
172
IF V_SCRIPT NE SPACE.
CALL FUNCTION 'CLOSE_FORM'.
ENDIF.
ENDFORM. "ABRIR_SAPSCRIPT
TABLES: ZPROGRAMAS,ITCPO,TOA_DARA,ITCPP.
ITCPO-TDIMMED = '*'.
ITCPO-TDDELETE = '*'.
ITCPO-TDLIFETIME = '7'.
ITCPO-TDPREVIEW = 'X'.
173
• Visualización de impresión.
IF V_SCRIPT EQ SPACE.
CALL FUNCTION 'OPEN_FORM'
EXPORTING
FORM = V_FORM
LANGUAGE = 'S'
OPTIONS = ITCPO
ARCHIVE_INDEX = TOA_DARA
DEVICE = 'PRINTER'
DIALOG = 'X'
EXCEPTIONS
CANCELED = 01.
IF SY-SUBRC NE 0.
EXIT.
ENDIF.
V_SCRIPT = 'X'.
ENDIF.
174
LOOP AT T_ZPROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
CALL FUNCTION 'WRITE_FORM'
EXPORTING
ELEMENT = 'ITEM'
WINDOW = 'MAIN'
EXCEPTIONS
OTHERS = 01.
ENDLOOP.
IF V_SCRIPT NE SPACE.
CALL FUNCTION 'CLOSE_FORM'.
ENDIF.
175
Una vez creado el programa, podemos regresar a nuestro formulario
para poder comenzar a llenar los datos que queremos mostrar cuando
sea ejecutado.
Diseñando el formulario
176
Ingresamos a nuestro formulario y presionamos el botón Layout
(Diposición) .
177
En esta ventana, podremos escribir el código para llamar a los
campos que definimos en nuestro programa (Es decir, a los campos
de la tabla interna) y mostrarlos al momento de imprimir el
formulario.
178
ampersand, no podríamos llamar a las variables de nuestro programa
dentro del formulario.
Supongamos que queremos que los textos se muestren en negrita y
los valores como un texto normal.
Primero que nada, debemos grabar nuestro código y retroceder con
Párrafo) .
Una vez ahí, hacemos clic en Character Formats (Formatos de
Caracter) .
179
Para terminar, vamos a crear una caja para que se muestre el nombre
del programa. Para esto, debemos cambiar de editor, puesto que
debemos crear la caja utilizando código.
180
Creamos una caja que empieza en la posición 0, que tenga 50
milimetros de ancho y 5 de alto, y que el borde sea de 10 TW.
Se habrán dado cuenta, de que además agregamos la línea
/E ITEM
181
impresión). Puesto que no queremos imprimirlo, sino simplemente
comprobar que está bien hecho el formulario.
Los datos son correctos, pero los textos están muy juntos los unos de
los otros, además la caja de texto simpre está en el mismo lugar,
veamos como resolvemos esto.
182
Además, agregamos una línea en blanco.
Para que esto funcione correctamente, debemo también agregar
algunas cosas en el programa.
V_FORM = 'ZDUMMY_FORM'.
POS = 0.
LOOP AT T_ZPROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
CALL FUNCTION 'WRITE_FORM'
EXPORTING
ELEMENT = 'ITEM'
WINDOW = 'MAIN'
EXCEPTIONS
OTHERS = 01.
POS = POS + 13.
ENDLOOP.
183
Para terminar, podríamos crear una tabulación, con lo cual el texto
ID Programa quedaría más centrado en la caja.
Tabs (Tabuladores) .
184
Creamos una tabulación de 5 MM con alineación a la izquierda.
Regresamos al Layout y cambiamos el formato del editor. Para
agregar un tabulador, escribimos ,, antes del texto.
185
Debugger en SAPScript
186
Simplemente presionamos OK para poder continuar con el
Debugger.
187
SmartForms
Introducción
Creando un estilo
188
Lo nombramos ZTEST_ESTILO y presionamos el botón Create
(Crear) .
En esta ventana, vamos a crear nuestro párrafo por defecto, tal como
lo hicimos en el SAPScript.
Debemos crear un nuevo nodo en la opción Paragraph Format
(Formato de Párrafo).
189
Llamemos ST a este nuevo nodo.
Y llenamos su descripción.
190
Cuando hemos terminado, hacemos doble clic en Header Data
(Datos de Cabecera).
191
Cuando terminamos, grabamos, activamos y salimos a la pantalla
inicial.
Creando un Formulario
192
Al igual que en SAPScript, necesitamos una página y una ventana.
Como vemos %PAGE1 está creada por defecto, así que podemos
dejarla así, o asignarle un nuevo nombre. Lo mismo ocurre con la
ventana MAIN.
193
Cuando creamos el texto, veremos una pantalla como esta.
194
Para poder utilizar las variables dentro del SmartForms, debemos
definir algunas variables globales, para esto nos vamos a Form
Interface (Interface de Formulario).
195
Debemos crear un LOOP para poder asignar los valores de la tabla
de parámetro a la tabla intermedia.
Una vez creado, debemos mover nuestro texto, dentro del LOOP.
196
En el LOOP debemos asignar los datos de la tabla hacia la tabla
intermedia.
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE TABLAS *
*=====================================================*
TABLES: ZPROGRAMAS.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_ZPROGRAMAS TYPE STANDARD TABLE OF
ZPROGRAMAS.
197
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: MODULO_FUNCION TYPE RS38L_FNAM.
*=====================================================*
* SELECTION-SCREEN *
*=====================================================*
SELECTION-SCREEN BEGIN OF BLOCK APP WITH FRAME.
SELECT-OPTIONS:
SID_PROG FOR ZPROGRAMAS-ID_PROG.
SELECTION-SCREEN END OF BLOCK APP.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM INICIALIZAR.
*=====================================================*
* END-OF-SELECTION *
*=====================================================*
END-OF-SELECTION.
PERFORM ABRIR_SMARTFORMS.
198
*&----------------------------------------------------*
*& Form INICIALIZAR *
*&----------------------------------------------------*
FORM INICIALIZAR.
SELECT *
INTO TABLE T_ZPROGRAMAS
FROM ZPROGRAMAS
WHERE ID_PROG IN SID_PROG.
ENDFORM. "INICIALIZAR
*&----------------------------------------------------*
*& Form ABRIR_SAPSCRIPT *
*&----------------------------------------------------*
FORM ABRIR_SMARTFORMS.
199
FORMATTING_ERROR = 1
INTERNAL_ERROR = 2
SEND_ERROR = 3
USER_CANCELED = 4
OTHERS = 5.
ENDFORM. "ABRIR_SAPSCRIPT
Revisemos el programa.
200
Utilizamos el módulo de funciones
SSF_FUNCTION_MODULE_NAME para poder obtener el
nombre del módulo de funciones que generó el SmartForms.
Ejecutando el formulario
201
Tenemos nuestra lista, impresa en color azul. Si les parece que está
un poco abajo, es cuestión simplemente de ajustar las propiedades
del texto.
202
Crear una tabla
203
En la pestaña DATA (Datos) debemos hacer lo mismo que
habíamos hecho en el LOOP, asignar la tabla de parámetro a nuestra
tabla intermedia.
204
Para crear la cabecera de nuestra tabla, nos posicionamos en Header
y con un clic derecho escogemos Create (Crear) Æ Table Line
(Línea de Tabla).
205
Como veremos, solamente tenemos un %CELL1 es decir, una sola
celda, pero nosotros necesitamos dos, así que vamos al nodo
principal %TABLE1 a la pestaña Table y dentro del Formulario
gráfico, dibujamos una línea vertical (Con esto creamos
automáticamente un %CELL2).
206
Seguimos el mismo procedimiento para Main Area (Area
Principal), es decir, creamos una Línea de Tabla, asignamos los
textos y pasamos la variables &T_AUX_PROGRAMAS-
ID_PROG& y &T_AUX_PROGRAMAS-NOM_PROG& tal
como hicimos con el SAPScript.
207
Si queremos que se note que hemos utilizado una tabla, hacemos lo
siguiente.
En el nodo principal de la tabla, hacemos clic sobre el botón Draw
208
El botón Display Framed Patterns (Mostrar patrones con marco)
.
Y seleccionamos el tipo que se muestra en la figura.
209
Cuando ejecutamos el formulario, lo veremos de la siguiente
manera.
210
Screen Painter y Menu Painter
Introducción
Screen Painter
211
En el campo Program (Programa) ingresaremos el nombre del
programa en el cual se va a utilizar el dynpro, y en el campos Screen
Number (Número de Pantalla), establecemos el número de la
pantalla, ya que podemos tener muchas pantallas relacionadas entre
si. O inclusive, llamar a pantallas distintas dependiendo de una
condición dada.
Como en el caso de los programas, deberemos hacer clic en el botón
212
En Screen Type (Tipo pantalla), debemos especificar que tipo de
Dynpro queremos crear, por lo general utilizamos Normal.
En el caso de Next Screen (Siguiente pantalla), lo llenaremos
solamente si es que luego de esta pantalla vamos a llamar a otra. En
este caso, lo dejamos con el valor por defecto.
Los demás parámetros podemos dejarlos como están.
Para poder comenzar a diseñar nuestra pantalla, debemos hacer clic
213
Controles del Screen Painter
Æ Pulsador o Botón.
214
Æ Custom Control o Control Personalizado. Nos permite
crear elementos en tiempos de ejecución. Muy utilizados para
programación en ABAP Objects.
215
Ejemplo de Screen Painter
216
Deberemos hacer clic en Yes (Sí) para que nuestra caja de texto
tome la referencia del campo ID de la tabla ZPROGRAMAS.
Para poder acceder a las propiedades de este control, simplemente
debemos hacer un doble clic.
217
218
Ahora, debemos crear nuestra tabla con el control Table Control
.
Nuestra tabla, se llamará TABLA.
219
Primero debemos crear el control Input/Output Field y luego el
Text Field. Ambos referenciando a un campo de una tabla. En este
caso, el primero T_ZPROGRAMAS-ID_PROG y el segundo
T_ZPROGRAMAS-NOM_PROG.
En este caso, vamos a asociar los campos de nuestra tabla a una tabla
interna, que vamos a crear en nuestro programa, llamada
T_ZPROGRAMAS. Esta tabla vamos a definirla en el programa
ZDUMMY_PRIMER_PROGRAMA que en este caso, es el
programa control para el Dynpro.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_ZPROGRAMAS TYPE STANDARD TABLE OF
ZPROGRAMAS.
220
Debemos descomentar ambos módulos y hacer doble clic en cada
uno de ellos para que se autogeneren en el código fuente de nuestro
programa de control y así poder utilizarlos.
Para poder llenar la tabla con los datos obtenidos en base al filtro,
deberemos incluir el siguiente código marcado en rojo.
221
En esta ventana, nos avisan que el módulo STATUS_0100 no
existe. Por lo tanto, debemos crearlo aceptando el mensaje.
222
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
ID = ZPROGRAMAS-ID.
SELECT *
INTO TABLE T_ZPROGRAMAS
FROM ZPROGRAMAS
WHERE ID EQ ID.
TABLA-LINES = LINEAS.
223
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
*=====================================================*
* DECLARACION DE TABLAS *
*=====================================================*
TABLES: ZPROGRAMAS.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_ZPROGRAMAS TYPE STANDARD TABLE OF
ZPROGRAMAS WITH HEADER LINE.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
CONTROLS TABLA TYPE TABLEVIEW USING SCREEN '100'.
CALL SCREEN '100'.
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
ID = ZPROGRAMAS-ID.
224
IF ID NE SPACE.
SELECT *
INTO TABLE T_ZPROGRAMAS
FROM ZPROGRAMAS
WHERE ID EQ ID.
TABLA-LINES = LINEAS.
ENDIF.
*&----------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT *
*&----------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
Revisemos el código.
START-OF-SELECTION.
CONTROLS TABLA TYPE TABLEVIEW USING SCREEN '100'.
CALL SCREEN '100'.
225
debemos declarar por código, que hemos creado una tabla en la
pantalla 100.
Finalmente, llamamos a la pantalla 100.
ID = ZPROGRAMAS-ID.
IF ID NE SPACE.
SELECT *
INTO TABLE T_ZPROGRAMAS
FROM ZPROGRAMAS
WHERE ID EQ ID.
TABLA-LINES = LINEAS.
ENDIF.
226
Al pasar el valor de ZPROGRAMAS-ID a la variable ID, significa
que recogemos el valor de la caja de texto del dynpro y lo
guardamos en una variable auxiliar.
Si la variable ID no está vacía (Es decir, hemos ingresado un valor
en la caja de texto), entonces podemos continuar.
Seleccionamos todos los campos de la tabla ZPROGRAMAS
siempre y cuando, el ID sea igual a nuestra variable ID.
Obtenemos la cantidad de líneas que hay en la tabla interna,
utilizando el comando DESCRIBE TABLE.
Finalmente asignamos la variable LINEAS (Que contiene la
cantidad de líneas de la tabla interna) al campo LINES de nuestra
tabla TABLA, es decir, le decimos cuantas líneas se deberían de
mostrar en la tabla.
Para poder ejecutar el programa, debemos activar tanto el Dynpro
como el programa.
227
Si ingresamos el código de un lenguage, veremos como funciona el
programa.
228
Menu Painter
229
Una vez que aceptemos, se nos mostrará la siguiente pantalla.
230
Nuevamente, para este ejemplo, solo nos interesa esta sección.
Ahora, debemos grabar y activar. Con esto, nuestro menú está listo
para utilizarse.
Para poder agregarlo a nuestro programa, simplemente deberemos
incluir la siguiente línea (O más bien, descomentarla).
231
El SET PF-STATUS le dice a nuestro Dynpro, que queremos
utilizar un menú creado por nosotros, y ‘100’ es el número de dicho
menú.
Con esto parecería ser suficiente...Pero no...Aún debemos asignar las
funciones que va a cumplir cada uno de los botones de nuestro
menú, para ello, debemos incluir el siguiente código.
OK_CODE = SY-UCOMM.
CASE OK_CODE.
WHEN 'BACK' OR 'EXIT' OR 'CANCEL'.
SET SCREEN 0.
LEAVE SCREEN.
CLEAR SY-UCOMM.
ENDCASE.
En este caso, los tres botones hacen lo mismo, así que no hay mucho
problema.
La variable del sistema SY-UCOMM, determina que valor tiene el
botón que ha sido presionado.
Aunque en este caso no es necesario, cuando tengamos más botones,
deberíamos incluir el OK_CODE dentro de nuestro Dynpro, así
que vamos a la transacción SE51.
232
Escogemos Element list (Lista de elementos) y presionamos el
233
Grabamos, activamos y ejecutamos el programa.
234
Aceptamos y continuamos.
235
Agregando componentes al ejemplo
Como podemos ver, los atributos del pulsador poseen dos campos
adicionales, que son Icon Name (Nombre de Icono) y Tooltip
(Información adicional). Para seleccionar el icono, simplemente
236
Esta ventana nos muestra todos los iconos disponibles. El Tooltip,
no es más que el mensaje que aparece cuando situamos el mouse
sobre el componente.
El valor del FctCode (Function Code – Código de Función), es
sumamente importante, puesto que nos va a ayudar a activar el
evento relacionado al botón PROCESAR.
237
MODULE USER_COMMAND_0100 INPUT.
OK_CODE = SY-UCOMM.
CASE OK_CODE.
WHEN 'BACK' OR 'EXIT' OR 'CANCEL'.
SET SCREEN 0.
LEAVE SCREEN.
CLEAR SY-UCOMM.
WHEN 'PROCESAR'.
PERFORM PROCESAR_DATOS.
ENDCASE.
FORM PROCESAR_DATOS.
ID = ZPROGRAMAS-ID.
IF ID NE SPACE.
SELECT *
INTO TABLE T_ZPROGRAMAS
FROM ZPROGRAMAS
238
WHERE ID EQ ID.
TABLA-LINES = LINEAS.
ENDIF.
239
Si han sido curiosos u observadores, se habrán dado cuenta de que
los campos de la tabla pueden modificarse, por lo tanto podríamos
cambiar los valores que obtenemos de la tabla.
Corregir esto es muy sencillo, simplemente regresamos a la
transacción SE51 y vamos a las propiedades de los campos que
conforman la tabla.
Por defecto tenemos esto.
240
Programación Avanzada en Dynpros
PROCESS ON VALUE-REQUEST.
FIELD ZPROGRAMAS-ID MODULE MATCH_CODE_ID.
241
Lo primero que debemos hacer es crear el módulo, que como ya
sabemos se hace haciendo doble clic sobre el nombre del módulo.
De vuelta en nuestro programa, debemos crear un TYPE que defina
nuestro MatchCode.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_MATCHCODE_ID,
ID TYPE ZPROGRAMAS-ID,
END OF TY_MATCHCODE_ID.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_ZPROGRAMAS TYPE STANDARD TABLE OF
ZPROGRAMAS WITH HEADER LINE,
T_MATCHCODE_ID TYPE STANDARD TABLE OF
TY_MATCHCODE_ID WITH HEADER LINE.
242
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: DYNPROFIELD TYPE HELP_INFO-DYNPROFLD,
PROGNAME TYPE SY-REPID,
DYNNUM TYPE SY-DYNNR.
243
MODULE MATCH_CODE_ID INPUT.
SELECT ID
INTO TABLE T_MATCHCODE_ID
FROM ZPROGRAMAS.
DYNPROFIELD = 'ZPROGRAMAS-ID'.
DYNNUM = '100'.
PROGNAME = SY-REPID.
CLEAR RETURN_TAB.
REFRESH RETURN_TAB.
244
DYNPNR = DYNNUM
DYNPROFIELD = DYNPROFIELD
VALUE_ORG = 'S'
TABLES
VALUE_TAB = T_MATCHCODE_ID
RETURN_TAB = RETURN_TAB
EXCEPTIONS
PARAMETER_ERROR = 1
NO_VALUES_FOUND = 2
OTHERS = 3.
IF RETURN_TAB-FIELDVAL NE SPACE.
ZPROGRAMAS-ID = RETURN_TAB-FIELDVAL.
ENDIF.
SELECT ID
INTO TABLE T_MATCHCODE_ID
FROM ZPROGRAMAS.
DYNPROFIELD = 'ZPROGRAMAS-ID'.
DYNNUM = '100'.
PROGNAME = SY-REPID.
245
El campo DYNPROFIELD almacena a que campo se va a aplicar el
MatchCode, el campo DYNNUM almacena cual es el número del
Dynpro y el campo PROGNAME almanacena cual es el nombre
del programa.
CLEAR RETURN_TAB.
REFRESH RETURN_TAB.
IF RETURN_TAB-FIELDVAL NE SPACE.
ZPROGRAMAS-ID = RETURN_TAB-FIELDVAL.
ENDIF.
246
El módulo de funciones recibe las variables con la información del
Dynpro y la tabla conteniendo los valores de los ID’s. Nos muestra
una ventana con los valores disponibles y el que hayamos elegido es
guardado en la tabla RETURN_TAB.
Si hemos escogido algún valor, entonces lo mostramos en el campo
ZPROGRAMAS-ID.
247
Debemos marcar el check w/SelColumn (con Selección de
columna) y asignarle un nombre, que en este caso, va a ser “FILA”.
La variable FILA nos a indicar cuando hayamos seleccionado un
registro. Además, vamos a agregar un botón llamado ELIMINAR.
248
Como vemos, el botón tiene un FctCode llamado “ELIMINA” y un
Icono llamado ICON_DELETE, además de un Tooltip con el texto
“Eliminar”.
249
Tenemos que ingresar al Flow Logic para crear un módulo asociado
el botón ELIMINAR.
IF SY-UCOMM EQ 'ELIMINA'.
IF FILA EQ 'X'.
DELETE T_ZPROGRAMAS INDEX TABLA-CURRENT_LINE.
ENDIF.
ENDIF.
250
valor de FILA va a ser ‘X’. Borramos este valor de nuestra tabla
interna y como consecuencia, se borra también de la tabla.
Claro, esto no lo borra de la Base de Datos, aunque sería bastante
sencillo hacer que lo haga, simplemente necesitaríamos seleccionar
la llave primaria de la tabla y hacer un DELETE TABLE.
251
MODULE ACTUALIZA_TABLA.
ENDLOOP.
252
Para esto, vamos a agregar un pulsador en el menú (Menú Painter –
SE41).
253
En esta ventana, definimos el código de función asociado al
pulsador, el texto asociado a la función, el icono asociado y
finalmente el texto informativo.
254
Debemos asignar una tecla de función a cada pulsador que creemos.
En este caso, vamos a elegir el F2.
255
Le toca ahora al pulsador con texto dinámico, veamos como crearlo.
Debemos seguir los pasos anteriores hasta que lleguemos a esta
pantalla (Claro, debemos escoger Dynamic Text esta vez).
256
Y debemos también asignarle un texto inicial.
START-OF-SELECTION.
TEXTO_DINAMICO = 'Este es un texto dinámico'.
CONTROLS TABLA TYPE TABLEVIEW USING SCREEN '100'.
CALL SCREEN '100'.
START-OF-SELECTION.
TEXTO_DINAMICO = 'Este es un texto dinámico'.
CONTROLS TABLA TYPE TABLEVIEW USING SCREEN '100'.
DATA: COLS LIKE LINE OF TABLA-COLS.
CALL SCREEN '100'.
257
(Estructura profunda), es decir, es una tabla dentro de otra tabla.
Además, solo necesitamos una cabecera y no toda la tabla.
Agregamos el evento generado por el pulsador CHANGESTAT.
OK_CODE = SY-UCOMM.
CASE OK_CODE.
WHEN 'BACK' OR 'EXIT' OR 'CANCEL'.
SET SCREEN 0.
LEAVE SCREEN.
CLEAR SY-UCOMM.
WHEN 'PROCESAR'.
PERFORM PROCESAR_DATOS.
WHEN 'CHANGESTAT'.
PERFORM CAMBIAR_ESTADO.
ENDCASE.
FORM CAMBIAR_ESTADO.
258
COLS-SCREEN-INPUT = '0'.
TEXTO_DINAMICO = 'Visualizar'.
ENDIF.
MODIFY TABLA-COLS FROM COLS.
ENDLOOP.
259
Trabajando con SubScreens
260
Algunas veces necesitamos incluir pantallas completas de otras
pantallas, sobre todo cuando tenemos que utilizar Tabs o Pestañas.
Vamos a olvidarnos de nuestro programa anterior, y vamos a crear
uno nuevo utilizando pestañas y un SubScreen.
Vamos a crear una nueva pantalla y un nuevo programa. Y por
supuesto nuestro TabStrip Control llamado “TAB”.
261
Creamos un SubScreen, y lo asignamos al control TAB. La única
propiedad que tenemos que definir para el SubScreen es el nombre.
262
Luego de haber creado las dos SubScreens, este será el Flow Logic
para la pantalla principal.
263
Como podemos ver, en el PAI también utilizamos el CALL
SUBSCREEN para llamar a las SubScreens.
Como mencioné lineas arriba, los componentes tendremos que
colocarlos dentro de cada SubScreen, por lo cual vamos a comenzar
con el número 0101.
Vamos a crear un Box o Caja con los siguientes atributos.
• ZPROGRAMAS-NOM_PROG.
• ZLENGUAJES_PROG-NOMBRE.
264
Finalmente, tendremos un botón llamado MODIFICAR con el
código de función MODIFY. Este botón nos va a servir, puesto que
una vez obtenidos los datos del programa, podremos modificarlos y
mostrarlos en el segundo SubScreen. En el cual no podrán ser
modificados.
265
Por lo tanto, vamos a tener V_NOM_PROG y V_NOMBRE.
En el programa, deberemos declarar la tablas ZPROGRAMAS y
ZLENGUAJES_PROG, crear las variables correspondientes y
crear el componente TAB_CONTROL.
START-OF-SELECTION.
CONTROLS TAB_CONTROL TYPE TABSTRIP.
TAB_CONTROL-ACTIVETAB = 'TAB_1'.
CALL SCREEN '100'.
FORM OBTENER_DATOS.
ENDFORM. "OBTENER_DATOS
266
Hacemos un INNER JOIN entre las dos tablas, y obtenemos los
valores NOMBRE y NOM_PROG, los cuales son guardados en los
Campos de Entrada/Salida del Dynpro.
No debemos olvidarnos del USER-COMMAND.
OK_CODE = SY-UCOMM.
CLEAR SY-UCOMM.
CASE OK_CODE.
WHEN 'PROCESS'.
PERFORM OBTENER_DATOS.
ENDCASE.
267
Cuando ejecutamos el programa, nos vamos a dar cuenta de algo
bastante peculiar...Cuando ingresamos el primer código, todo va
bien, pero con el segundo, los datos se quedan pegados. Esto es
porque estamos trabajando en un SubScreen y los datos no se
actualizan directamente. Por suerte, y como debe ser, existe una
función que actualiza los Dynpros.
Para esto, debemos crear los siguientes TYPES y Tablas Internas.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TAB,
FIELDNAME TYPE DYNPREAD-FIELDNAME,
STEPL TYPE DYNPREAD-STEPL,
FIELDVALUE TYPE DYNPREAD-FIELDVALUE,
268
FIELDINP TYPE DYNPREAD-FIELDINP,
END OF TAB.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: MY_TAB TYPE STANDARD TABLE OF
TAB,
MY_DYNP TYPE STANDARD TABLE OF
DYNP.
LOOP AT MY_DYNP
ASSIGNING <FS_MY_DYNP>.
CALL FUNCTION 'DYNP_UPDATE_FIELDS'
EXPORTING
DYNAME = SY-CPROG
DYNUMB = <FS_MY_DYNP>-DYNUMB
REQUEST = 'A'
TABLES
269
DYNPFIELDS = MY_TAB.
ENDLOOP.
ENDFORM. "ACTUALIZAR_DYNPRO
FORM OBTENER_DATOS.
IF SY-SUBRC EQ 0.
APPEND INITIAL LINE TO MY_TAB
ASSIGNING <FS_MY_TAB>.
<FS_MY_TAB>-FIELDNAME = 'ZPROGRAMAS-ID'.
<FS_MY_TAB>-FIELDVALUE = ZPROGRAMAS-ID.
APPEND INITIAL LINE TO MY_TAB
ASSIGNING <FS_MY_TAB>.
<FS_MY_TAB>-FIELDNAME = 'ZPROGRAMAS-NOM_PROG'.
<FS_MY_TAB>-FIELDVALUE = ZPROGRAMAS-NOM_PROG.
APPEND INITIAL LINE TO MY_TAB
270
ASSIGNING <FS_MY_TAB>.
<FS_MY_TAB>-FIELDNAME = 'ZLENGUAJES_PROG-NOMBRE'.
<FS_MY_TAB>-FIELDVALUE = ZLENGUAJES_PROG-NOMBRE.
ENDFORM. "OBTENER_DATOS
OK_CODE = SY-UCOMM.
CLEAR SY-UCOMM.
CASE OK_CODE.
WHEN 'PROCESS'.
PERFORM OBTENER_DATOS.
271
WHEN 'MODIFY'.
PERFORM TRASPASAR_VALORES.
ENDCASE.
FORM TRASPASAR_VALORES.
CLEAR: V_NOM_PROG,V_NOMBRE.
272
273
Utilizando Listas Deplegables
274
PROCESS BEFORE OUTPUT.
MODULE STATUS_0100.
MODULE LLENAR_LISTA_DESPLEGABLE.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPE-POOLS: VRM.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: VALUES TYPE VRM_VALUES,
FC_VALUES LIKE VALUES WITH HEADER LINE.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: ID TYPE VRM_ID.
275
Este es el código que utilizaremos para llenar con datos la lista, ya se
que se ve un poco redundante, pero la estructura de la función que
genera la lista así lo requiere.
IF ID EQ SPACE.
ID = 'ZPROGRAMAS-ID'.
SELECT ID NOMBRE
INTO (FC_VALUES-KEY,FC_VALUES-TEXT)
FROM ZLENGUAJES_PROG.
APPEND FC_VALUES.
ENDSELECT.
LOOP AT FC_VALUES.
APPEND FC_VALUES TO VALUES.
ENDLOOP.
ENDIF.
276
Aunque no es nada recomendable utilizarlo, en este caso
necesitamos el SELECT-ENDSELECT (El GOTO del ABAP).
Necesitamos que los valores queden almacenados en la tabla
VALUES que es la que vamos a pasar al módulo de funciones
VRM_SET_VALUES, que es el que finalmente crea la lista
despegable.
Si ejecutamos el programa, veremos que la lista está llena, pero no
hace nada, puesto que si seleccionamos un lenguaje de
programación, no nos muestra los datos, además, nos muestra el
nombre del lenguaje en un espacio muy reducido, así que
deberíamos ampliar un poco su tamaño, antes de poder continuar.
Así que vamos a hacer que cuando seleccionemos el lenguaje, se
muestren los datos, sin necesidad de un botón auxiliar.
277
Dentro del programa, agregamos una llamada al código de función.
OK_CODE = SY-UCOMM.
CLEAR SY-UCOMM.
CASE OK_CODE.
WHEN 'LISTA'.
PERFORM OBTENER_DATOS.
ENDCASE.
FORM OBTENER_DATOS.
IF SY-SUBRC NE 0.
CLEAR: ZPROGRAMAS-ID_PROG,ZPROGRAMAS-NOM_PROG.
ENDIF.
278
Ahora, cuando elegimos un valor de la lista desplegable, podemos
obtener los datos asociados.
279
Leyendo datos de un Dynpro
FREE FIELD_VALUE.
FREE DYNPRO_VALUES.
FIELD_VALUE-FIELDNAME = 'ZPROGRAMAS-ID'.
APPEND FIELD_VALUE TO DYNPRO_VALUES.
280
DYNUMB = '0100'.
IF SY-SUBRC EQ 0.
ZPROGRAMAS-ID = DYNPRO_VALUES-FIELDVALUE.
ENDIF.
281
Módulos de Función y BAPIS
282
esto, necesitaremos como parámetro de entrada la fecha de
nacimiento del usuario y como salida podemos mostrar una tabla
que contenga los campos años, meses y días. Por lo tanto,
necesitaremos crear una estructura que contenga dichos campos.
Vamos a llamarla ZEDAD_STR.
283
Como podemos ver, hay dos CheckBox, Optional (Opcional), que
indica si el campo es obligatorio o no y Pass Value (Pasar valor)
que indica si el valor es pasado por Valor o por Referencia. En este
caso, dejamos ambos como están, es decir, mantenemos los valores
por defecto.
En la pestaña Changing (Cambiando), vamos a crear nuestro
parámetro de salida, que hará referencia a la estructura que hemos
creado.
284
Luego de esto, podemos darnos cuenta de que el botón ha cambiado,
indicándonos que el texto ha sido asignado correctamente.
FUNCTION ZDUMMY_FUNCTION.
*"-----------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(FECHA_NAC) TYPE SY-DATUM
*" CHANGING
285
*" REFERENCE(TABLA_EDAD) TYPE ZEDAD_STR
*" EXCEPTIONS
*" EDAD_FUERA_RANGO
*"-----------------------------------------------------
IF FECHA_NAC GT SY-DATUM.
RAISE EDAD_FUERA_RANGO.
ENDIF.
ZYEARS = FECHA_NAC+0(4).
ZMONTHS = FECHA_NAC+4(2).
ZDAYS = FECHA_NAC+6(2).
ZYEARS = SY-DATUM+0(4) - ZYEARS.
IF SY-DATUM+4(2) LT ZMONTHS.
ZYEARS = ZYEARS - 1.
ZMONTHS = SY-DATUM+4(2) + 1.
ENDIF.
IF SY-DATUM+6(2) LT ZDAYS.
ZDAYS = 30 - ZDAYS.
ZMONTHS = ZMONTHS - 1.
ZDAYS = ZDAYS + SY-DATUM+6(2).
ENDIF.
TABLA_EDAD-ZYEARS = ZYEARS.
TABLA_EDAD-ZMONTHS = ZMONTHS.
TABLA_EDAD-ZDAYS = ZDAYS.
286
ENDFUNCTION.
IF FECHA_NAC GT SY-DATUM.
RAISE EDAD_FUERA_RANGO.
ENDIF.
ZYEARS = FECHA_NAC+0(4).
ZMONTHS = FECHA_NAC+4(2).
ZDAYS = FECHA_NAC+6(2).
ZYEARS = SY-DATUM+0(4) - ZYEARS.
287
tener nostros FECHA_NAC+0(4) estamos diciendo, “Toma 4
caracteres, comenzando desde el carácter 0”. En otras palabras 1977.
Restamos el año actual, menos el año del parámetro.
IF SY-DATUM+4(2) LT ZMONTHS.
ZYEARS = ZYEARS - 1.
ZMONTHS_AUX = 12 - ZMONTHS.
ZMONTHS = SY-DATUM+4(2) + ZMONTHS.
ENDIF.
IF SY-DATUM+6(2) LT ZDAYS.
ZDAYS = 30 - ZDAYS.
ZMONTHS = ZMONTHS - 1.
ZDAYS = ZDAYS + SY-DATUM+6(2).
ENDIF.
Si los días actuales son menores que los días del parámetro, entonces
a 30 le restamos la cantidad de días. Restamos 1 a meses y sumamos
los días actuales más los días que obtuvimos al hacer la resta de 30
menos los días del parámetro.
Para probar nuestra función, simplemente debemos ejecutarla
presionando la tecla F8 o el botón Test/Exectute (Probar/Ejecutar)
288
Ingresamos una fecha de nacimiento y lo ejecutamos, ya sea con el
Ctrl + F7 .
289
30 Años, 01 mes y 09 días.
Si queremos ver el resultado con un mayor detalle, deberemos
presionar el botón Single Entry (Entrada Individual) o presionar los
botones Shift + F7 .
Ahora que ya vimos que nuestra función hace lo que tiene que hacer,
es hora de llamarla desde un programa.
REPORT ZDUMMY_PRIMER_PROGRAMA
NO STANDARD PAGE HEADING.
290
*=====================================================*
* DECLARACION DE TABLAS *
*=====================================================*
DATA: TABLA_EDAD TYPE ZEDAD_STR.
*=====================================================*
* Selection screen *
*=====================================================*
SELECTION-SCREEN BEGIN OF BLOCK DATA WITH FRAME.
PARAMETERS:
P_FECHA TYPE SY-DATUM.
SELECTION-SCREEN END OF BLOCK DATA.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
IF SY-SUBRC <> 0.
WRITE: 'La edad ingresada está fuera del rango'.
ELSE.
WRITE: 'Su edad actual es',
TABLA_EDAD-ZYEARS, 'Años',
291
TABLA_EDAD-ZMONTHS, 'Meses',
TABLA_EDAD-ZDAYS, 'Días'.
ENDIF.
Introducción BAPIS
292
Las BAPI’s son estables, puesto que cuentan con muchos
mecanismos de control y aseguramiento. Además, encapsulan
operaciones complejas en una simple interfaz. Por eso, las BAPI’s
cuentan con su propia transacción llamada justamente BAPI.
293
ALV (ABAP List Viewer)
Introducción
Creando un ALV
294
*=====================================================*
* DECLARACION DE TABLAS *
*=====================================================*
TABLES: ZPROGRAMAS.
*=====================================================*
* DECLARACION DE TYPE-POOLS *
*=====================================================*
TYPE-POOLS: SLIS.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
ID_PROG TYPE ZPROGRAMAS-ID_PROG,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
NOMBRE TYPE ZLENGUAJES_PROG-NOMBRE,
ENTORNO TYPE ZLENGUAJES_PROG-ENTORNO,
CONEX_SAP TYPE ZLENGUAJES_PROG-CONEX_SAP,
END OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE OF
TY_PROGRAMAS.
*=====================================================*
* Selection screen *
*=====================================================*
SELECTION-SCREEN BEGIN OF BLOCK DATA WITH FRAME.
SELECT-OPTIONS:
295
S_IDPROG FOR ZPROGRAMAS-ID_PROG.
SELECTION-SCREEN END OF BLOCK DATA.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM OBTENER_DATOS.
*&----------------------------------------------------*
*& Form OBTENER_DATOS *
*&----------------------------------------------------*
FORM OBTENER_DATOS.
Vamos a necesitar crear algunas tablas internas para poder llenar las
estructuras del ALV, así como algunas variables para manejar su
formato de visualización.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE OF
TY_PROGRAMAS,
I_FIELDCAT TYPE SLIS_T_FIELDCAT_ALV,
296
I_SORT_ALV TYPE SLIS_T_SORTINFO_ALV,
GS_LAYOUT TYPE SLIS_LAYOUT_ALV.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: G_PROGRAM TYPE SY-REPID,
G_TITULO TYPE SY-TITLE,
G_REPID TYPE SY-REPID,
GS_SORT TYPE SLIS_T_SORTINFO_ALV.
*=====================================================*
* END-OF-SELECTION *
*=====================================================*
END-OF-SELECTION.
*=====================================================*
* END-OF-SELECTION *
*=====================================================*
END-OF-SELECTION.
PERFORM INIT_LAYOUT.
PERFORM FORMATEAR_DATOS_ALV_DET USING I_FIELDCAT[].
PERFORM BUILD_SORT.
PERFORM F_GENERAR_LISTA_ALV.
297
Vamos a crear y analizar cada una de estas funciones.
FORM INIT_LAYOUT.
GS_LAYOUT-ZEBRA = 'X'.
FORM BUILD_SORT.
298
DATA: L_FIELDCAT TYPE SLIS_FIELDCAT_ALV.
CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
L_FIELDCAT-FIELDNAME = 'ID_PROG'.
L_FIELDCAT-SELTEXT_L = 'Id'.
L_FIELDCAT-COL_POS = 1.
L_FIELDCAT-OUTPUTLEN = 5.
APPEND L_FIELDCAT TO T_FIELDCAT.
CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
L_FIELDCAT-FIELDNAME = 'NOM_PROG'.
L_FIELDCAT-SELTEXT_L = 'Nombre Programa'.
L_FIELDCAT-COL_POS = 2.
L_FIELDCAT-OUTPUTLEN = 15.
APPEND L_FIELDCAT TO T_FIELDCAT.
CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
L_FIELDCAT-FIELDNAME = 'NOMBRE'.
L_FIELDCAT-SELTEXT_L = 'Nombre Lenguaje'.
L_FIELDCAT-COL_POS = 3.
L_FIELDCAT-OUTPUTLEN = 15.
APPEND L_FIELDCAT TO T_FIELDCAT.
CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
L_FIELDCAT-FIELDNAME = 'ENTORNO'.
L_FIELDCAT-SELTEXT_L = 'Entorno'.
L_FIELDCAT-COL_POS = 4.
L_FIELDCAT-OUTPUTLEN = 10.
299
APPEND L_FIELDCAT TO T_FIELDCAT.
CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
L_FIELDCAT-FIELDNAME = 'CONEX_SAP'.
L_FIELDCAT-SELTEXT_L = 'Conexión con SAP'.
L_FIELDCAT-COL_POS = 5.
L_FIELDCAT-OUTPUTLEN = 15.
APPEND L_FIELDCAT TO T_FIELDCAT.
ENDFORM. "FORMATEAR_DATOS_ALV_DET
300
FORM F_GENERAR_LISTA_ALV.
G_PROGRAM = SY-REPID.
G_TITULO = 'Lista de Programas'.
IF SY-SUBRC <> 0.
EXIT.
ENDIF.
301
GS_LAYOUT almacena el formato del listado. (Esta tabla se asigna
al parámetro IS_LAYOUT).
I_FIELDCAT almacena los campos que conforman el ALV. (Esta
tabla se asigna al parámetro IT_FIELDCAT).
GS_SORT almacena el orden del ALV. (Esta tabla se asigna al
parámetro IT_SORT).
T_PROGRAMAS es la tabla que almacena todos los registros
obtenidos en el INNER JOIN. (Esta tabla se asigna al parámetro
T_OUTTAB).
Ahora, podemos ejecutar el programa.
302
Ahora que ya vimos como es un ALV, investigemos un poco.
Supongamos que no queremos que sea de tipo ZEBRA, así que
cambiamos el comando.
FORM INIT_LAYOUT.
303
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE OF
TY_PROGRAMAS,
I_FIELDCAT TYPE SLIS_T_FIELDCAT_ALV,
I_SORT_ALV TYPE SLIS_T_SORTINFO_ALV,
GS_LAYOUT TYPE SLIS_LAYOUT_ALV,
GT_LIST_TOP_OF_PAGE TYPE SLIS_T_LISTHEADER,
I_EVENTS TYPE SLIS_T_EVENT.
*=====================================================*
* END-OF-SELECTION *
*=====================================================*
END-OF-SELECTION.
PERFORM INIT_LAYOUT.
PERFORM FORMATEAR_DATOS_ALV_DET USING I_FIELDCAT[].
PERFORM F_FORMATO_PAGE CHANGING GT_LIST_TOP_OF_PAGE.
PERFORM F_FORMATEAR_EVENTOS_ALV USING I_EVENTS[].
PERFORM BUILD_SORT.
PERFORM F_GENERAR_LISTA_ALV.
304
DATA: GS_LINE TYPE SLIS_LISTHEADER.
CLEAR GS_LINE.
GS_LINE-TYP = 'H'.
CONCATENATE 'FECHA:' SY-DATUM
INTO GS_LINE-INFO
SEPARATED BY SPACE.
APPEND GS_LINE TO GT_TOP_OF_PAGE.
CLEAR GS_LINE.
GS_LINE-TYP = 'H'.
CONCATENATE 'HORA:' SY-UZEIT
INTO GS_LINE-INFO
SEPARATED BY SPACE.
APPEND GS_LINE TO GT_TOP_OF_PAGE.
ENDFORM. "F_FORMATO_PAGE
305
CLEAR L_EVENTS.
L_EVENTS-NAME = 'TOP_OF_PAGE'.
L_EVENTS-FORM = 'TOP_OF_PAGE'.
APPEND L_EVENTS TO P_EVENTS.
ENDFORM. "F_FORMATEAR_EVENTOS_ALV
FORM TOP_OF_PAGE.
ENDFORM. "TOP_OF_PAGE
FORM F_GENERAR_LISTA_ALV.
306
G_TITULO = 'Lista de Programas'.
IF SY-SUBRC <> 0.
EXIT.
ENDIF.
307
Claro que la fecha y lo hora se ven bastante mal, esto es porque se
muestran en el formato interno de SAP. Podemos corregirlos de una
manera muy sencilla.
Simplemente debemos de crear dos variables de tipo texto, obtener
los componentes de la fecha y la hora, y concatenarlos utilizando
separadores tales como “/” y “.”, para luego asignarlos a nuestra
tabla de cabecera.
308
INTO HORA SEPARATED BY ':'.
CLEAR GS_LINE.
GS_LINE-TYP = 'H'.
CONCATENATE 'FECHA:' FECHA
INTO GS_LINE-INFO
SEPARATED BY SPACE.
APPEND GS_LINE TO GT_TOP_OF_PAGE.
CLEAR GS_LINE.
GS_LINE-TYP = 'H'.
CONCATENATE 'HORA:' HORA
INTO GS_LINE-INFO
SEPARATED BY SPACE.
APPEND GS_LINE TO GT_TOP_OF_PAGE.
ENDFORM. "F_FORMATO_PAGE
309
Eventos ALV Grid
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: G_PROGRAM TYPE SY-REPID,
G_TITULO TYPE SY-TITLE,
G_REPID TYPE SY-REPID,
GS_SORT TYPE SLIS_T_SORTINFO_ALV,
G_USER_COMMAND TYPE SLIS_FORMNAME
VALUE 'USER_COMMAND'.
310
FORM INIT_LAYOUT.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_SORT> LIKE LINE OF GS_SORT,
<FS_PROGRAMAS> LIKE LINE OF T_PROGRAMAS.
CASE R_UCOMM.
WHEN 'FUNCION'.
READ TABLE T_PROGRAMAS INDEX RS_SELFIELD-TABINDEX
311
ASSIGNING <FS_PROGRAMAS>.
CONCATENATE <FS_PROGRAMAS>-ID_PROG
<FS_PROGRAMAS>-NOM_PROG
<FS_PROGRAMAS>-NOMBRE
INTO MENSAJE SEPARATED BY SPACE.
ENDCASE.
ENDFORM. "USER_COMMAND
312
FORM F_GENERAR_LISTA_ALV.
IF SY-SUBRC <> 0.
EXIT.
ENDIF.
313
El parámetro I_SAVE = ‘A’ nos permite manejar las variantes.
Cuando ejecutamos el programa, bastará con hacer un doble clic en
cualquier registro para ejecutar el evento.
FORM INIT_LAYOUT.
CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
314
L_FIELDCAT-FIELDNAME = 'ID_PROG'.
L_FIELDCAT-SELTEXT_L = 'Id'.
L_FIELDCAT-KEY = 'X'.
L_FIELDCAT-COL_POS = 1.
L_FIELDCAT-OUTPUTLEN = 5.
APPEND L_FIELDCAT TO T_FIELDCAT.
Aunque esto no es muy común, puede ser que alguna vez tengamos
que pagar un ALV de colores, es decir, pintar un registro, una fila,
una celda.
Primero, lo que vamos a hacer es pintar un registro de algún color.
Para esto, necesitamos modificar un poco nuestra tabla interna.
315
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
ID_PROG TYPE ZPROGRAMAS-ID_PROG,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
NOMBRE TYPE ZLENGUAJES_PROG-NOMBRE,
ENTORNO TYPE ZLENGUAJES_PROG-ENTORNO,
CONEX_SAP TYPE ZLENGUAJES_PROG-CONEX_SAP,
LINE_COLOR(4) TYPE C,
END OF TY_PROGRAMAS.
FORM OBTENER_DATOS.
LOOP AT T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
IF <FS_PROGRAMAS>-NOMBRE EQ 'RUBY'.
<FS_PROGRAMAS>-LINE_COLOR = 'C510'.
MODIFY T_PROGRAMAS FROM <FS_PROGRAMAS>.
ENDIF.
316
ENDLOOP.
FORM INIT_LAYOUT.
317
Ahora que ya estamos felices con nuestro colorido ALV, podemos
pasar a algo un poco más complicado, pero simple de todos modos.
Vamos a colorear celdas individuales en un ALV.
Primero, tenemos que crear una tabla interna auxiliar y modificar un
poco la tabla que teníamos, esto porque al menos en el NetWeaver
no se pueden hacer SELECT’s a una tabla interna con DEEP
STRUCTURE, es decir, una tabla interna que tiene como campo a
otra tabla interna.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS_AUX,
ID_PROG TYPE ZPROGRAMAS-ID_PROG,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
NOMBRE TYPE ZLENGUAJES_PROG-NOMBRE,
ENTORNO TYPE ZLENGUAJES_PROG-ENTORNO,
CONEX_SAP TYPE ZLENGUAJES_PROG-CONEX_SAP,
END OF TY_PROGRAMAS_AUX.
318
Debemos crear un nuevo TYPES, y modificar el original agregando
el campo COLOR_CELL que es en realidad, una tabla interna
dentro de nuestra tabla interna. WA_COLOR y IT_COLOR nos
sirven para almacenar algunos parámetros adicionales necesarios
para el color de la celda.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE OF
TY_PROGRAMAS,
T_PROGRAMAS_AUX TYPE STANDARD TABLE OF
TY_PROGRAMAS_AUX,
I_FIELDCAT TYPE SLIS_T_FIELDCAT_ALV,
I_SORT_ALV TYPE SLIS_T_SORTINFO_ALV,
GS_LAYOUT TYPE SLIS_LAYOUT_ALV,
GT_LIST_TOP_OF_PAGE TYPE SLIS_T_LISTHEADER,
I_EVENTS TYPE SLIS_T_EVENT,
WA_COLOR TYPE LVC_S_SCOL,
IT_COLOR TYPE TABLE OF LVC_S_SCOL.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_SORT> LIKE LINE OF GS_SORT,
<FS_PROGRAMAS> LIKE LINE OF
319
T_PROGRAMAS,
<FS_PROGRAMAS_AUX> LIKE LINE OF
T_PROGRAMAS_AUX.
FORM OBTENER_DATOS.
LOOP AT T_PROGRAMAS_AUX
ASSIGNING <FS_PROGRAMAS_AUX>.
REFRESH IT_COLOR.
MOVE 'NOMBRE' TO WA_COLOR-FNAME.
MOVE '6' TO WA_COLOR-COLOR-COL.
APPEND WA_COLOR TO IT_COLOR.
APPEND INITIAL LINE TO
T_PROGRAMAS ASSIGNING <FS_PROGRAMAS>.
MOVE-CORRESPONDING <FS_PROGRAMAS_AUX>
TO <FS_PROGRAMAS>.
IF <FS_PROGRAMAS_AUX>-NOMBRE EQ 'RUBY'.
320
<FS_PROGRAMAS>-COLOR_CELL[] = IT_COLOR[].
ENDIF.
ENDLOOP.
FORM INIT_LAYOUT.
321
ENDFORM. " INIT_LAYOUT
Ahora que ya sabemos como jugar con los eventos y con algunas
propiedades del ALV, sería bueno que también conocieramos un
poco de su barra de menús, que además de ser Standard, nos brinda
toda la funcionalidad que podamos necesitar, por lo cual, muy rara
vez tendremos que agregar botones adicionales.
Entre las opciones standard que nos ofrece el ALV, tenemos las
siguientes.
322
A Æ Permite mostrar una línea del reporte
B Æ Orden Ascendente
C Æ Orden Descendente
323
D Æ Permite crear filtros adicionales
324
F Æ Abre Microsoft Excel
H Æ Fichero local
325
I Æ Destinatario de Correo
326
J Æ Función Gráfica
K Æ Modificar Disposición
327
L Æ Seleccionar Disposición
M Æ Grabar disposición
328
N Æ Información
329
ABAP Orientado a Objetos
Introducción
330
Existen muchos puntos que debemos conocer primero y que son
análogos en casi todos los lenguajes de programación orientados a
objetos, y por supuesto, ABAP Objects no es la excepción.
Una vez que conozcamos estos conceptos, podremos ahondar en el
ABAP Objects, con ejemplos sencillos que ayuden a adquirir una
base sólida para programar con este nuevo modelo de negocio.
Cabe destacar, que si bien en un escenario ideal, toda la
programación debería ser orientada a objetos, esto no ocurre en los
escenarios reales. Muchas veces, se utiliza una combinación de
ambas fuerzas. Por lo cual, no es imperativo desarrollar aplicaciones
100% OO...Sino tal vez un 60-40% sería suficiente (Dependiendo
del caso, claro está).
331
través de la transacción SE24 (Class Builder). Las clases
están compuestas por diferentes secciones:
332
*-----------------------------------------------------*
* CLASS C_MATH DEFINITION *
*-----------------------------------------------------*
CLASS C_MATH DEFINITION.
*DEFINICIÓN DE LA CLASE
PUBLIC SECTION.
*SECCIÓN PÚBLICA DE LA CLASE
METHODS:
*MÉTODOS
FACTORIAL.
PRIVATE SECTION.
*SECCIÓN PRIVADA DE LA CLASE
ENDCLASS. "C_MATH DEFINITION
*-----------------------------------------------------*
* CLASS C_MATH IMPLEMENTATION *
*-----------------------------------------------------*
CLASS C_MATH IMPLEMENTATION.
*IMPLEMENTACIÓN DE LA CLASE
METHOD FACTORIAL.
*DEFINICIÓN DE UN MÉTODO
ENDMETHOD. "FACTORIAL
ENDCLASS. "C_MATH IMPLEMENTATION
333
*-----------------------------------------------------*
* CLASS C_MATH DEFINITION *
*-----------------------------------------------------*
CLASS C_MATH DEFINITION.
*DEFINICIÓN DE LA CLASE
PUBLIC SECTION.
*SECCIÓN PÚBLICA DE LA CLASE
METHODS:
*MÉTODOS
CONSTRUCTOR
IMPORTING NAME TYPE STRING,
FACTORIAL.
PRIVATE SECTION.
*SECCIÓN PRIVADA DE LA CLASE
ENDCLASS. "C_MATH DEFINITION
*-----------------------------------------------------*
* CLASS C_MATH IMPLEMENTATION *
*-----------------------------------------------------*
CLASS C_MATH IMPLEMENTATION.
*IMPLEMENTACIÓN DE LA CLASE
METHOD CONSTRUCTOR.
WRITE:/ NAME.
*ENVIAMOS EL PARÁMETRO AL CONSTRUCTOR DE LA CLASE
ENDMETHOD. "CONSTRUCTOR
METHOD FACTORIAL.
*DEFINICIÓN DE UN MÉTODO
ENDMETHOD. "FACTORIAL
ENDCLASS. "C_MATH IMPLEMENTATION
334
agregar funcionalidades que queremos que se encuentren separadas.
Es decir, nosotros podemos crear una clase que obtenga el número
de factura de un pedido, y podemos crear otra clase que herede de
nuestra clase factura, pero que además, nos de la posibilidad de
obtener la cuenta contrato de dicha factura. Así, tenemos dos clases,
una se creó heredando características de la primera, pero le agregó
una funcionalidad adicional, haciéndolas distintas e independientes.
La clase que brinda su funcionalidad, es llamada una Super Clase y
la que ha heredado dichas funcionalidades, es llamada una Sub
Clase.
Una Sub Clase se define de la siguiente manera.
*-----------------------------------------------------*
* CLASS C_SUPERMATH DEFINITION *
*-----------------------------------------------------*
CLASS C_SUPERMATH DEFINITION.
ENDCLASS. "C_SUPERMATH DEFINITION
*Definición de la clase
*-----------------------------------------------------*
* CLASS C_MATH DEFINITION *
*-----------------------------------------------------*
CLASS C_MATH DEFINITION
INHERITING FROM C_SUPERMATH .
*Hereda de C_SUPERMATH
PUBLIC SECTION.
*Sección Pública de la clase
METHODS:
*Métodos
FACTORIAL.
335
PRIVATE SECTION.
*SECCIÓN PRIVADA DE LA CLASE
ENDCLASS. "C_MATH DEFINITION
*-----------------------------------------------------*
* CLASS C_MATH IMPLEMENTATION *
*-----------------------------------------------------*
CLASS C_MATH IMPLEMENTATION.
*IMPLEMENTACIÓN DE LA CLASE
METHOD FACTORIAL.
*DEFINICIÓN DE UN MÉTODO
ENDMETHOD. "FACTORIAL
ENDCLASS. "C_MATH IMPLEMENTATION
336
Como programar en ABAP Objects
Factorial
REPORT ZDUMMY_PRIMER_PROGRAMA.
*-----------------------------------------------------*
* CLASS FACTORIAL DEFINITION
*-----------------------------------------------------*
CLASS C_FACTORIAL DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: MAIN.
METHODS:
SET_FACT IMPORTING NUM TYPE I,
GET_RESULT RETURNING VALUE(FACT) TYPE I.
PRIVATE SECTION.
DATA FACT TYPE I.
ENDCLASS. "FACTORIAL DEFINITION
337
*-----------------------------------------------------*
* CLASS FACTORIAL IMPLEMENTATION
*-----------------------------------------------------*
CLASS C_FACTORIAL IMPLEMENTATION.
METHOD MAIN.
CALL SELECTION-SCREEN '101' STARTING AT 10 10.
IF SY-SUBRC NE 0.
EXIT.
ENDIF.
ENDMETHOD. "MAIN
METHOD SET_FACT.
FACT = 1.
IF NUM GT 0.
DO NUM TIMES.
FACT = FACT * SY-INDEX.
ENDDO.
ENDIF.
ENDMETHOD. "SET_FACT
METHOD GET_RESULT.
WRITE: 'El Factorial es: ', ME->FACT.
ENDMETHOD. "GET_RESULT
ENDCLASS. "FACTORIAL IMPLEMENTATION
START-OF-SELECTION.
C_FACTORIAL=>MAIN( ).
DATA MY_OBJ TYPE REF TO C_FACTORIAL.
CREATE OBJECT MY_OBJ.
CALL METHOD
MY_OBJ->SET_FACT( EXPORTING NUM = NUMBER ).
CALL METHOD
MY_OBJ->GET_RESULT.
338
Este código se puede ver un poco complicado, extraño e innecesario,
pero creanme que con el tiempo uno se acostumbra y la verdad es
que es lo mejor programar así.
Revisemos un poco el código antes de ejecutarlo.
*-----------------------------------------------------*
* CLASS FACTORIAL DEFINITION *
*-----------------------------------------------------*
CLASS C_FACTORIAL DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: MAIN.
METHODS:
SET_FACT IMPORTING NUM TYPE I,
GET_RESULT RETURNING VALUE(FACT) TYPE I.
PRIVATE SECTION.
DATA FACT TYPE I.
ENDCLASS. "FACTORIAL DEFINITION
339
parámetro NUM y GET_RESULT que retorna el valor final del
programa.
En la sección privada, declaramos una variable llamada FACT, que
es la que va a tener el resultado del factorial y es la variable que va a
imprimir GET_RESULT.
*-----------------------------------------------------*
* CLASS FACTORIAL IMPLEMENTATION *
*-----------------------------------------------------*
CLASS C_FACTORIAL IMPLEMENTATION.
METHOD MAIN.
CALL SELECTION-SCREEN '101' STARTING AT 10 10.
IF SY-SUBRC NE 0.
EXIT.
ENDIF.
ENDMETHOD. "MAIN
METHOD SET_FACT.
FACT = 1.
IF NUM GT 0.
DO NUM TIMES.
FACT = FACT * SY-INDEX.
ENDDO.
ENDIF.
ENDMETHOD. "SET_FACT
METHOD GET_RESULT.
WRITE: 'El Factorial es: ', ME->FACT.
ENDMETHOD. "GET_RESULT
ENDCLASS. "FACTORIAL IMPLEMENTATION
340
En el método MAIN, llamamos a nuestra pantalla para poder
capturar el valor ingresado por el usuario.
En el método SET_FACT realizamos el algoritmo para determinar
el factorial.
En el método GET_RESULT imprimimos el valor de la variable
FACT. Como se darán cuenta, utilizamos ME->FACT para llamar
a la variable, esto es porque este método no recibe parámetros, por lo
cual necesita obtener el valor de la misma clase, pero como la
variable está en la sección privada, entonces necesitamos acceder a
ella definiendo el nombre de la clase y la variable, con lo cual
quedaría así C_FACTORIAL->FACT. Felizmente, y para no
escribir tanto, podemos escribirlo así ME->FACT, donde ME
equivale a C_FACTORIAL.
START-OF-SELECTION.
C_FACTORIAL=>MAIN( ).
DATA MY_OBJ TYPE REF TO C_FACTORIAL.
CREATE OBJECT MY_OBJ.
CALL METHOD
MY_OBJ->SET_FACT( EXPORTING NUM = NUMBER ).
CALL METHOD
MY_OBJ->GET_RESULT.
341
Por cuestiones de tamaño de almacenamiento de la variable, los
números pueden ir desde el 1 hasta el 12, así que veamos que pasa si
ingresamos 13.
342
En este caso, se ha producido un error, puesto que el tamaño de la
variable que utilizamos no fue lo suficientemente grande como para
poder almacenar el valor del factorial. La imagen que vemos, es la
de un ShortDump (Es decir, un error grave en la programación).
Esta ventana, nos indica porque se ha producido el error, cuando, en
donde y hasta como podríamos resolverlo.
En esta caso, vamos a utilizar una pequeña artimaña para que
nuestro programa siga funcionando a pesar de este error, para ello,
vamos a utilizar un comando llamado CATCH SYSTEM-
EXCEPTION. El cual funciona como un TRY-CATCH en Java o
.NET, y lo que hace es simplemente intentar ejecutar una sentencia
y si no puede, nos envía un error personalizado, que permite que el
programa siga funcionando a pesar del error. Para esto, debemos
hacer unas cuantas modificaciones al programa.
343
METHOD SET_FACT.
CLEAR FLAG.
FACT = 1.
IF NUM GT 0.
DO NUM TIMES.
CATCH SYSTEM-EXCEPTIONS ARITHMETIC_ERRORS = 5.
FACT = FACT * SY-INDEX.
ENDCATCH.
IF SY-SUBRC EQ 5.
FACT = 0.
FLAG = 'X'.
EXIT.
ENDIF.
ENDDO.
ENDIF.
ENDMETHOD. "SET_FACT
344
METHOD GET_RESULT.
IF FLAG EQ SPACE.
WRITE: 'El Factorial es: ', ME->FACT.
ELSE.
WRITE: 'Error, ingrese valores del 1 al 12'.
ENDIF.
ENDMETHOD. "GET_RESULT
345
346
Primero, debemos ir a la pestaña Attributes (Atributos) para
declarar nuestras variables.
(Parámetros) .
347
SET_FACT tiene el parámetro NUM de tipo IMPORTING.
348
Escribimos los códigos para cada método.
method SET_FACT.
CLEAR FLAG.
FACT = 1.
IF NUM GT 0.
DO NUM TIMES.
CATCH SYSTEM-EXCEPTIONS ARITHMETIC_ERRORS = 5.
FACT = FACT * SY-INDEX.
ENDCATCH.
IF SY-SUBRC EQ 5.
FACT = 0.
FLAG = 'X'.
EXIT.
ENDIF.
ENDDO.
ENDIF.
endmethod.
method GET_RESULT.
IF FLAG EQ SPACE.
WRITE: 'El Factorial es: ', ME->FACT.
ELSE.
WRITE: 'Error, ingrese valores del 1 al 12'.
ENDIF.
endmethod.
Con esto, solo nos queda grabar, activar. La clase está lista para ser
utilizada, pero claro, lo mejor es probarlo antes. Para esto,
349
Como sabemos que SET_FACT es el método que recibe el valor
ingreado por el usario, lo ejecutamos presionando el botón Execute
Method (Ejecutar Método) .
(Ejecutar) o presionamos F8 .
De vuelta en la pantalla principal, ejecutamos el método
GET_RESULT.
350
A pesar de que el valor de FACT aparece como 0, simplemente
debemos retroceder para ver el resultado.
REPORT ZDUMMY_PRIMER_PROGRAMA.
351
START-OF-SELECTION.
352
Componentes Orientados a Objetos
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
ID_PROG TYPE ZPROGRAMAS-ID_PROG,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
NOMBRE TYPE ZLENGUAJES_PROG-NOMBRE,
ENTORNO TYPE ZLENGUAJES_PROG-ENTORNO,
CONEX_SAP TYPE ZLENGUAJES_PROG-CONEX_SAP,
END OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE
OF TY_PROGRAMAS,
GS_LAYOUT TYPE LVC_S_LAYO,
GT_FIELDCAT TYPE LVC_T_FCAT,
GT_SORT TYPE LVC_T_SORT,
GS_VARIANT TYPE DISVARIANT.
353
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: MYCONTAINER TYPE SCRFNAME VALUE 'CUSTOM_ALV',
CUSTOM_CONTAINER TYPE REF TO
CL_GUI_CUSTOM_CONTAINER,
GRID1 TYPE REF TO CL_GUI_ALV_GRID,
X_SAVE.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM CARGAR_DATOS.
PERFORM FILL_LAYOUT.
PERFORM FILL_CATALOG.
PERFORM LLAMAR_ALV.
*&----------------------------------------------------*
*& Form cargar_datos *
*&----------------------------------------------------*
FORM CARGAR_DATOS.
354
*&----------------------------------------------------*
*& Form fill_layout *
*&----------------------------------------------------*
FORM FILL_LAYOUT.
GS_LAYOUT-SEL_MODE = 'A'.
*&----------------------------------------------------*
*& Form fill_catalog *
*&----------------------------------------------------*
FORM FILL_CATALOG.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-FIELDNAME = 'ID_PROG'.
GS_FIELDCAT-REPTEXT = 'Id'.
GS_FIELDCAT-COL_POS = 1.
GS_FIELDCAT-OUTPUTLEN = 5.
APPEND GS_FIELDCAT TO GT_FIELDCAT.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-FIELDNAME = 'NOM_PROG'.
GS_FIELDCAT-REPTEXT = 'Nombre Programa'.
GS_FIELDCAT-COL_POS = 2.
GS_FIELDCAT-OUTPUTLEN = 15.
APPEND GS_FIELDCAT TO GT_FIELDCAT.
355
CLEAR GS_FIELDCAT.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-FIELDNAME = 'NOMBRE'.
GS_FIELDCAT-REPTEXT = 'Nombre Lenguaje'.
GS_FIELDCAT-COL_POS = 3.
GS_FIELDCAT-OUTPUTLEN = 15.
APPEND GS_FIELDCAT TO GT_FIELDCAT.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-FIELDNAME = 'ENTORNO'.
GS_FIELDCAT-REPTEXT = 'Entorno'.
GS_FIELDCAT-COL_POS = 4.
GS_FIELDCAT-OUTPUTLEN = 10.
APPEND GS_FIELDCAT TO GT_FIELDCAT.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-FIELDNAME = 'CONEX_SAP'.
GS_FIELDCAT-REPTEXT = 'Conexión con SAP'.
GS_FIELDCAT-COL_POS = 5.
GS_FIELDCAT-OUTPUTLEN = 15.
APPEND GS_FIELDCAT TO GT_FIELDCAT.
*&----------------------------------------------------*
*& Form llamar_alv *
*&----------------------------------------------------*
FORM LLAMAR_ALV.
IF CUSTOM_CONTAINER IS INITIAL.
356
CREATE OBJECT CUSTOM_CONTAINER
EXPORTING
CONTAINER_NAME = MYCONTAINER
EXCEPTIONS
CNTL_ERROR = 1
CNTL_SYSTEM_ERROR = 2
CREATE_ERROR = 3
LIFETIME_ERROR = 4
LIFETIME_DYNPRO_DYNPRO_LINK = 5.
ENDIF.
357
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
*&----------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT *
*&----------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
OK_CODE = SY-UCOMM.
CASE OK_CODE.
WHEN 'BACK' OR 'EXIT' OR 'CANCEL'.
SET SCREEN 0.
LEAVE SCREEN.
CLEAR SY-UCOMM.
ENDCASE.
358
Custom Control (Control Personalizado) al cual llamaremos
CUSTOM_ALV.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
ID_PROG TYPE ZPROGRAMAS-ID_PROG,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
NOMBRE TYPE ZLENGUAJES_PROG-NOMBRE,
ENTORNO TYPE ZLENGUAJES_PROG-ENTORNO,
CONEX_SAP TYPE ZLENGUAJES_PROG-CONEX_SAP,
END OF TY_PROGRAMAS.
359
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE
OF TY_PROGRAMAS,
GS_LAYOUT TYPE LVC_S_LAYO,
GT_FIELDCAT TYPE LVC_T_FCAT,
GT_SORT TYPE LVC_T_SORT,
GS_VARIANT TYPE DISVARIANT.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: MYCONTAINER TYPE SCRFNAME VALUE 'CUSTOM_ALV',
CUSTOM_CONTAINER TYPE REF TO
CL_GUI_CUSTOM_CONTAINER,
GRID1 TYPE REF TO CL_GUI_ALV_GRID,
X_SAVE.
360
referencia al contenedor del ALV, GRID1 es un objeto de la clase
CL_GUI_ALV_GRID y X_SAVE es una variable utilizada para
determinar si se graban o no las variantes y de que modo.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM CARGAR_DATOS.
PERFORM FILL_LAYOUT.
PERFORM FILL_CATALOG.
PERFORM LLAMAR_ALV.
CALL SCREEN 0100.
*&----------------------------------------------------*
*& Form cargar_datos *
*&----------------------------------------------------*
FORM CARGAR_DATOS.
361
Hacemos un INNER JOIN para seleccionar los datos de la tablas.
*&----------------------------------------------------*
*& Form fill_layout *
*&----------------------------------------------------*
FORM FILL_LAYOUT.
GS_LAYOUT-SEL_MODE = 'A'.
*&----------------------------------------------------*
*& Form fill_catalog *
*&----------------------------------------------------*
FORM FILL_CATALOG.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-FIELDNAME = 'ID_PROG'.
GS_FIELDCAT-REPTEXT = 'Id'.
GS_FIELDCAT-COL_POS = 1.
GS_FIELDCAT-OUTPUTLEN = 5.
APPEND GS_FIELDCAT TO GT_FIELDCAT.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-FIELDNAME = 'NOM_PROG'.
362
GS_FIELDCAT-REPTEXT = 'Nombre Programa'.
GS_FIELDCAT-COL_POS = 2.
GS_FIELDCAT-OUTPUTLEN = 15.
APPEND GS_FIELDCAT TO GT_FIELDCAT.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-FIELDNAME = 'NOMBRE'.
GS_FIELDCAT-REPTEXT = 'Nombre Lenguaje'.
GS_FIELDCAT-COL_POS = 3.
GS_FIELDCAT-OUTPUTLEN = 15.
APPEND GS_FIELDCAT TO GT_FIELDCAT.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-FIELDNAME = 'ENTORNO'.
GS_FIELDCAT-REPTEXT = 'Entorno'.
GS_FIELDCAT-COL_POS = 4.
GS_FIELDCAT-OUTPUTLEN = 10.
APPEND GS_FIELDCAT TO GT_FIELDCAT.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-FIELDNAME = 'CONEX_SAP'.
GS_FIELDCAT-REPTEXT = 'Conexión con SAP'.
GS_FIELDCAT-COL_POS = 5.
GS_FIELDCAT-OUTPUTLEN = 15.
APPEND GS_FIELDCAT TO GT_FIELDCAT.
363
*&----------------------------------------------------*
*& Form llamar_alv *
*&----------------------------------------------------*
FORM LLAMAR_ALV.
IF CUSTOM_CONTAINER IS INITIAL.
CREATE OBJECT CUSTOM_CONTAINER
EXPORTING
CONTAINER_NAME = MYCONTAINER
EXCEPTIONS
CNTL_ERROR = 1
CNTL_SYSTEM_ERROR = 2
CREATE_ERROR = 3
LIFETIME_ERROR = 4
LIFETIME_DYNPRO_DYNPRO_LINK = 5.
ENDIF.
364
CALL METHOD GRID1->SET_READY_FOR_INPUT
EXPORTING
I_READY_FOR_INPUT = 0.
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
365
*&----------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT *
*&----------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
OK_CODE = SY-UCOMM.
CASE OK_CODE.
WHEN 'BACK' OR 'EXIT' OR 'CANCEL'.
SET SCREEN 0.
LEAVE SCREEN.
CLEAR SY-UCOMM.
ENDCASE.
366
Agregar validaciones y eventos
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
ID_PROG TYPE ZPROGRAMAS-ID_PROG,
NOM_PROG TYPE ZPROGRAMAS-NOM_PROG,
NOMBRE TYPE ZLENGUAJES_PROG-NOMBRE,
367
ENTORNO TYPE ZLENGUAJES_PROG-ENTORNO,
CONEX_SAP TYPE ZLENGUAJES_PROG-CONEX_SAP,
ID TYPE ZPROGRAMAS-ID,
END OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE
OF TY_PROGRAMAS,
T_NOMBRE TYPE STANDARD TABLE
OF TY_NOMBRE,
LT_F4 TYPE LVC_T_F4 WITH HEADER LINE,
RETURN_TAB TYPE STANDARD TABLE OF
DDSHRETVAL WITH HEADER LINE,
T_STABLE TYPE STANDARD TABLE OF
LVC_S_STBL WITH HEADER LINE,
GS_LAYOUT TYPE LVC_S_LAYO,
GT_FIELDCAT TYPE LVC_T_FCAT,
GT_SORT TYPE LVC_T_SORT,
GS_VARIANT TYPE DISVARIANT.
368
LT_F4 nos sirve para determinar que campos van a tener asignada
una ayuda de búsqueda.
RETURN_TAB es la tabla que nos devuelve el valor seleccionado
por la función para crear ayudas de búsqueda.
T_STABLE nos permite que el ALV mantenga su posición al
momento de actualizar los datos.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: MYCONTAINER TYPE SCRFNAME VALUE 'CUSTOM_ALV',
CUSTOM_CONTAINER TYPE REF TO
CL_GUI_CUSTOM_CONTAINER,
GRID1 TYPE REF TO CL_GUI_ALV_GRID,
EVENT_RECEIVER TYPE REF TO LCL_EVENT_RECEIVER,
X_SAVE,
W_ERROR TYPE C,
L_VALID(1) TYPE C.
369
Agregamos algunos Field-Symbols.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_NOMBRE> LIKE LINE OF T_NOMBRE,
<FS_PROGRAMAS> LIKE LINE OF
T_PROGRAMAS.
*-----------------------------------------------------*
* CLASS LCL_EVENT_RECEIVER DEFINITION *
*-----------------------------------------------------*
CLASS LCL_EVENT_RECEIVER DEFINITION.
PUBLIC SECTION.
METHODS: HANDLE_DATA_CHANGED
FOR EVENT DATA_CHANGED OF CL_GUI_ALV_GRID
IMPORTING ER_DATA_CHANGED,
HANDLE_F4_HELP
FOR EVENT ONF4 OF CL_GUI_ALV_GRID
IMPORTING E_FIELDNAME ES_ROW_NO ER_EVENT_DATA.
370
*-----------------------------------------------------*
* CLASS lcl_event_receiver IMPLEMENTATION *
*-----------------------------------------------------*
CLASS LCL_EVENT_RECEIVER IMPLEMENTATION.
METHOD HANDLE_DATA_CHANGED.
PERFORM DATA_CHANGED USING ER_DATA_CHANGED.
ENDMETHOD. "HANDLE_DATA_CHANGED
METHOD HANDLE_F4_HELP.
PERFORM HANDLE_ONF4 USING E_FIELDNAME ES_ROW_NO.
ER_EVENT_DATA->M_EVENT_HANDLED = 'X'.
ENDMETHOD. "HANDLE_F4_HELP
*&----------------------------------------------------*
*& Form cargar_datos *
*&----------------------------------------------------*
FORM CARGAR_DATOS.
371
SELECT ID NOMBRE
INTO TABLE T_NOMBRE
FROM ZLENGUAJES_PROG.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-FIELDNAME = 'NOMBRE'.
GS_FIELDCAT-EDIT = 'X'.
GS_FIELDCAT-F4AVAILABL = 'X'.
GS_FIELDCAT-REPTEXT = 'Nombre Lenguaje'.
GS_FIELDCAT-COL_POS = 3.
GS_FIELDCAT-OUTPUTLEN = 15.
APPEND GS_FIELDCAT TO GT_FIELDCAT.
*&----------------------------------------------------*
*& Form llamar_alv *
*&----------------------------------------------------*
FORM LLAMAR_ALV.
372
IF CUSTOM_CONTAINER IS INITIAL.
CREATE OBJECT CUSTOM_CONTAINER
EXPORTING
CONTAINER_NAME = MYCONTAINER
EXCEPTIONS
CNTL_ERROR = 1
CNTL_SYSTEM_ERROR = 2
CREATE_ERROR = 3
LIFETIME_ERROR = 4
LIFETIME_DYNPRO_DYNPRO_LINK = 5.
ENDIF.
LT_F4-FIELDNAME = 'NOMBRE'.
LT_F4-REGISTER = 'X' .
LT_F4-GETBEFORE = 'X' .
LT_F4-CHNGEAFTER = 'X' .
APPEND LT_F4.
373
IF SY-BATCH IS INITIAL.
CALL METHOD GRID1->REGISTER_EDIT_EVENT
EXPORTING
I_EVENT_ID = CL_GUI_ALV_GRID=>MC_EVT_MODIFIED.
ENDIF.
374
La variable SY-BATCH nos indica si estamos ejecutando el
programa en fondo o en modo directo, si es en modo directo,
entonces registramos el evento de modificación.
*&----------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT *
*&----------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
OK_CODE = SY-UCOMM.
CLEAR SY-UCOMM.
CASE OK_CODE.
WHEN 'BACK' OR 'EXIT' OR 'CANCEL'.
SET SCREEN 0.
LEAVE SCREEN.
WHEN 'SAVE'.
CALL METHOD GRID1->CHECK_CHANGED_DATA
IMPORTING
E_VALID = L_VALID.
IF L_VALID EQ 'X'.
PERFORM GRABAR_DATOS.
ENDIF.
ENDCASE.
375
*&----------------------------------------------------*
*& Form data_changed *
*&----------------------------------------------------*
FORM DATA_CHANGED USING RR_DATA_CHANGED
TYPE REF TO
CL_ALV_CHANGED_DATA_PROTOCOL.
DATA: W_NEW,
LS_MOD_CELLS TYPE LVC_S_MODI,
LS_CELLS TYPE LVC_S_MODI.
LOOP AT RR_DATA_CHANGED->MT_GOOD_CELLS
INTO LS_MOD_CELLS.
CASE LS_MOD_CELLS-FIELDNAME.
WHEN 'NOMBRE'.
CALL METHOD RR_DATA_CHANGED->GET_CELL_VALUE
EXPORTING
I_ROW_ID = LS_MOD_CELLS-ROW_ID
I_FIELDNAME = LS_MOD_CELLS-FIELDNAME
IMPORTING
E_VALUE = L_NOMBRE.
IF L_NOMBRE IS INITIAL.
CALL METHOD
RR_DATA_CHANGED->ADD_PROTOCOL_ENTRY
EXPORTING
I_MSGID = '0K'
I_MSGNO = '000'
I_MSGTY = 'E'
I_MSGV1 = 'Seleccione algún nombre'
I_FIELDNAME = LS_MOD_CELLS-FIELDNAME
376
I_ROW_ID = LS_MOD_CELLS-ROW_ID.
W_ERROR = 'X'.
ELSE.
READ TABLE T_NOMBRE WITH KEY
NOMBRE = L_NOMBRE
ASSIGNING <FS_NOMBRE>.
IF SY-SUBRC NE 0.
CALL METHOD
RR_DATA_CHANGED->ADD_PROTOCOL_ENTRY
EXPORTING
I_MSGID = '0K'
I_MSGNO = '000'
I_MSGTY = 'E'
I_MSGV1 = 'Nombre ingresado no existe'
I_FIELDNAME = LS_MOD_CELLS-FIELDNAME
I_ROW_ID = LS_MOD_CELLS-ROW_ID.
W_ERROR = 'X'.
ELSE.
CALL METHOD RR_DATA_CHANGED->MODIFY_CELL
EXPORTING
I_ROW_ID = LS_MOD_CELLS-ROW_ID
I_FIELDNAME = 'ID'
I_VALUE = <FS_NOMBRE>-ID.
ENDIF.
ENDIF.
ENDCASE.
ENDLOOP.
ENDFORM. "data_changed
377
valor. Llamamos al método GET_CELL_VALUE para validar el
nuevo contenido del campo. Si está vacío, mostramos un mensaje de
error con el método ADD_PROTOCOL_ENTRY, en caso
contrario leemos la tabla interna T_NOMBRE para validar que el
valor exista. Si no hay más problemas, llamamos al método
MODIFY_CELL para modificar el campo ID (Puesto que nosotros
hemos modificado el campo NOMBRE, pero necesitamos que a su
vez se modifique también el campo ID).
*&----------------------------------------------------*
*& Form handle_onf4 *
*&----------------------------------------------------*
FORM HANDLE_ONF4 USING P_E_FIELDNAME
P_ES_ROW_NO STRUCTURE
LVC_S_ROID.
CASE P_E_FIELDNAME.
WHEN 'NOMBRE'.
CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
EXPORTING
RETFIELD = 'NOMBRE'
VALUE_ORG = 'S'
TABLES
VALUE_TAB = T_NOMBRE
RETURN_TAB = RETURN_TAB
EXCEPTIONS
PARAMETER_ERROR = 1
NO_VALUES_FOUND = 2
OTHERS = 3.
378
IF NOT RETURN_TAB[] IS INITIAL.
READ TABLE RETURN_TAB INDEX 1.
READ TABLE T_PROGRAMAS INDEX P_ES_ROW_NO-ROW_ID
ASSIGNING <FS_PROGRAMAS>.
READ TABLE T_NOMBRE WITH KEY
NOMBRE = RETURN_TAB-FIELDVAL
ASSIGNING <FS_NOMBRE>.
<FS_PROGRAMAS>-NOMBRE = RETURN_TAB-FIELDVAL.
<FS_PROGRAMAS>-ID = <FS_NOMBRE>-ID.
CALL METHOD GRID1->REFRESH_TABLE_DISPLAY
EXPORTING
IS_STABLE = T_STABLE.
ENDIF.
ENDCASE.
ENDFORM. "handle_onf4
*&----------------------------------------------------*
*& Form grabar_datos *
*&----------------------------------------------------*
FORM GRABAR_DATOS.
379
IF SY-SUBRC EQ 0.
COMMIT WORK.
ELSE.
ROLLBACK WORK.
ENDIF.
ENDLOOP.
380
Crear un ALV Tree OO
REPORT ZDUMMY_PRIMER_PROGRAMA.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
LENGUAJE TYPE ZVLENGUAJES_PROG-LENGUAJE,
NOM_PROG TYPE ZVLENGUAJES_PROG-NOM_PROG,
ENTORNO TYPE ZVLENGUAJES_PROG-ENTORNO,
END OF TY_PROGRAMAS.
381
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE OF
TY_PROGRAMAS,
T_TREE TYPE STANDARD TABLE OF
TY_PROGRAMAS WITH HEADER LINE,
T_HEADER TYPE STANDARD TABLE OF
TY_HEADER,
GT_FIELDCAT_TREE TYPE LVC_T_FCAT.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: OK_CODE TYPE SY-UCOMM,
G_ALV_TREE TYPE REF TO CL_GUI_ALV_TREE,
G_CUSTOM_CONTAINER TYPE REF TO
CL_GUI_CUSTOM_CONTAINER,
L_HIERARCHY_HEADER TYPE TREEV_HHDR.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_PROGRAMAS> LIKE LINE OF
T_PROGRAMAS,
<FS_HEADER> LIKE LINE OF
T_HEADER,
<FS_TREE> LIKE LINE OF
T_PROGRAMAS.
382
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM CARGAR_DATOS.
PERFORM INIT_TREE.
*&----------------------------------------------------*
*& Form CARGAR_DATOS *
*&----------------------------------------------------*
FORM CARGAR_DATOS.
LOOP AT T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
APPEND INITIAL LINE TO
T_HEADER ASSIGNING <FS_HEADER>.
<FS_HEADER>-LENGUAJE = <FS_PROGRAMAS>-LENGUAJE.
ENDLOOP.
SORT T_HEADER.
DELETE ADJACENT DUPLICATES FROM T_HEADER.
383
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
*&----------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT *
*&----------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
OK_CODE = SY-UCOMM.
CLEAR SY-UCOMM.
CASE OK_CODE.
WHEN 'BACK' OR 'STOP' OR 'CANCEL'.
SET SCREEN 0.
LEAVE SCREEN.
ENDCASE.
384
*&----------------------------------------------------*
*& Form INIT_TREE *
*&----------------------------------------------------*
FORM INIT_TREE.
L_TREE_CONTAINER_NAME = 'CUSTOM_ALV'.
385
LIFETIME_ERROR = 4
ILLEGAL_NODE_SELECTION_MODE = 5
FAILED = 6
ILLEGAL_COLUMN_NAME = 7.
PERFORM FILL_CATALOG_TREE.
PERFORM BUILD_HIERARCHY_HEADER CHANGING
L_HIERARCHY_HEADER.
PERFORM CREATE_HIERARCHY.
*&----------------------------------------------------*
*& Form fill_catalog_tree *
*&----------------------------------------------------*
FORM FILL_CATALOG_TREE.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-COL_POS = 1.
GS_FIELDCAT-FIELDNAME = 'NOM_PROG'.
GS_FIELDCAT-SCRTEXT_S = 'Nom. Programa'.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-OUTPUTLEN = 20.
386
APPEND GS_FIELDCAT TO GT_FIELDCAT_TREE.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-COL_POS = 2.
GS_FIELDCAT-FIELDNAME = 'ENTORNO'.
GS_FIELDCAT-SCRTEXT_S = 'Entorno'.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-OUTPUTLEN = 15.
APPEND GS_FIELDCAT TO GT_FIELDCAT_TREE.
ENDFORM. "fill_catalog_tree
*&----------------------------------------------------*
* FORM build_hierarchy_header *
*&----------------------------------------------------*
FORM BUILD_HIERARCHY_HEADER CHANGING
P_HIERARCHY_HEADER
TYPE TREEV_HHDR.
CLEAR P_HIERARCHY_HEADER.
P_HIERARCHY_HEADER-HEADING = 'Código'(300).
P_HIERARCHY_HEADER-WIDTH = 60.
P_HIERARCHY_HEADER-WIDTH_PIX = ' '.
ENDFORM. "BUILD_HIERARCHY_HEADER
*&----------------------------------------------------*
*& Form create_hierarchy *
*&----------------------------------------------------*
FORM CREATE_HIERARCHY.
387
L_LAST_KEY TYPE LVC_NKEY,
HEADER TYPE STRING,
W_MENGE_TEXT(13) TYPE C.
CLEAR L_ROOT_KEY.
ENDFORM. "CREATE_HIERARCHY
*&----------------------------------------------------*
* FORM ADD_NODE *
*&----------------------------------------------------*
FORM ADD_NODE USING L_NAME L_ROOT_KEY
CHANGING L_NEXT_KEY.
388
DATA: L_NODE_TEXT TYPE LVC_VALUE,
LS_TREE TYPE TY_PROGRAMAS.
L_NODE_TEXT = L_NAME.
CALL METHOD G_ALV_TREE->ADD_NODE
EXPORTING
I_RELAT_NODE_KEY = L_ROOT_KEY
I_RELATIONSHIP =
CL_GUI_COLUMN_TREE=>RELAT_LAST_CHILD
I_NODE_TEXT = L_NODE_TEXT
IS_OUTTAB_LINE = LS_TREE
IMPORTING
E_NEW_NODE_KEY = L_NEXT_KEY.
ENDFORM. "ADD_NODE
*&----------------------------------------------------*
* FORM ADD_LEAF *
*&----------------------------------------------------*
FORM ADD_LEAF USING L_TREE TYPE TY_PROGRAMAS
L_NEXT_KEY
CHANGING L_LAST_KEY.
389
ENDFORM. "ADD_LEAF
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
LENGUAJE TYPE ZVLENGUAJES_PROG-LENGUAJE,
NOM_PROG TYPE ZVLENGUAJES_PROG-NOM_PROG,
ENTORNO TYPE ZVLENGUAJES_PROG-ENTORNO,
END OF TY_PROGRAMAS.
Declaramos dos TYPE’s, uno para crear la tabla que guardará los
datos del ALV y otro para crear la tabla que guardará los datos de la
cabecera del programa.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE OF
TY_PROGRAMAS,
T_TREE TYPE STANDARD TABLE OF
TY_PROGRAMAS WITH HEADER LINE,
T_HEADER TYPE STANDARD TABLE OF
390
TY_HEADER,
GT_FIELDCAT_TREE TYPE LVC_T_FCAT.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: OK_CODE TYPE SY-UCOMM,
G_ALV_TREE TYPE REF TO CL_GUI_ALV_TREE,
G_CUSTOM_CONTAINER TYPE REF TO
CL_GUI_CUSTOM_CONTAINER,
L_HIERARCHY_HEADER TYPE TREEV_HHDR.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_PROGRAMAS> LIKE LINE OF
T_PROGRAMAS,
<FS_HEADER> LIKE LINE OF
391
T_HEADER,
<FS_TREE> LIKE LINE OF
T_PROGRAMAS.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM CARGAR_DATOS.
PERFORM INIT_TREE.
*&----------------------------------------------------*
*& Form CARGAR_DATOS *
*&----------------------------------------------------*
FORM CARGAR_DATOS.
LOOP AT T_PROGRAMAS
ASSIGNING <FS_PROGRAMAS>.
APPEND INITIAL LINE TO
T_HEADER ASSIGNING <FS_HEADER>.
<FS_HEADER>-LENGUAJE = <FS_PROGRAMAS>-LENGUAJE.
392
ENDLOOP.
SORT T_HEADER.
DELETE ADJACENT DUPLICATES FROM T_HEADER.
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
*&----------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT *
*&----------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
OK_CODE = SY-UCOMM.
CLEAR SY-UCOMM.
393
CASE OK_CODE.
WHEN 'BACK' OR 'STOP' OR 'CANCEL'.
SET SCREEN 0.
LEAVE SCREEN.
ENDCASE.
*&----------------------------------------------------*
*& Form INIT_TREE *
*&----------------------------------------------------*
FORM INIT_TREE.
L_TREE_CONTAINER_NAME = 'CUSTOM_ALV'.
394
EXPORTING
PARENT = G_CUSTOM_CONTAINER
NODE_SELECTION_MODE =
CL_GUI_COLUMN_TREE=>NODE_SEL_MODE_SINGLE
ITEM_SELECTION = ''
NO_HTML_HEADER = 'X'
NO_TOOLBAR = ''
EXCEPTIONS
CNTL_ERROR = 1
CNTL_SYSTEM_ERROR = 2
CREATE_ERROR = 3
LIFETIME_ERROR = 4
ILLEGAL_NODE_SELECTION_MODE = 5
FAILED = 6
ILLEGAL_COLUMN_NAME = 7.
PERFORM FILL_CATALOG_TREE.
PERFORM BUILD_HIERARCHY_HEADER
CHANGING L_HIERARCHY_HEADER.
PERFORM CREATE_HIERARCHY.
395
Creamos el contenedor G_CUSTOM_CONTAINER pasando
como parámetro el nombre de nuestro CUSTOM_CONTROL
contenido en la variable L_TREE_CONTAINER_NAME.
Creamos el objeto G_ALV_TREE asignándolo a nuestro
contenedor G_CUSTOM_CONTAINER.
Llamámos al FORM FILL_CATALOG_TREE donde llenaremos
el catálogo del ALV.
Llamámos al FORM BUILD_HIERARCHY_HEADER, donde
establecemos los detalles de la cabecera.
Llamámos al método SET_TABLE_FOR_FIRST_DISPLAY para
llamar al ALV.
Finalmemte llamámos al FORM CREATE_HIERARCHY, donde
creamos la estructura del ALV.
*&----------------------------------------------------*
*& Form fill_catalog_tree *
*&----------------------------------------------------*
FORM FILL_CATALOG_TREE.
CLEAR GS_FIELDCAT.
GS_FIELDCAT-COL_POS = 1.
GS_FIELDCAT-FIELDNAME = 'NOM_PROG'.
GS_FIELDCAT-SCRTEXT_S = 'Nom. Programa'.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-OUTPUTLEN = 20.
APPEND GS_FIELDCAT TO GT_FIELDCAT_TREE.
396
CLEAR GS_FIELDCAT.
GS_FIELDCAT-COL_POS = 2.
GS_FIELDCAT-FIELDNAME = 'ENTORNO'.
GS_FIELDCAT-SCRTEXT_S = 'Entorno'.
GS_FIELDCAT-TABNAME = 'T_PROGRAMAS'.
GS_FIELDCAT-OUTPUTLEN = 15.
APPEND GS_FIELDCAT TO GT_FIELDCAT_TREE.
ENDFORM. "fill_catalog_tree
*&----------------------------------------------------*
* FORM build_hierarchy_header *
*&----------------------------------------------------*
FORM BUILD_HIERARCHY_HEADER CHANGING
P_HIERARCHY_HEADER
TYPE TREEV_HHDR.
CLEAR P_HIERARCHY_HEADER.
P_HIERARCHY_HEADER-HEADING = 'Código'(300).
P_HIERARCHY_HEADER-WIDTH = 60.
P_HIERARCHY_HEADER-WIDTH_PIX = ' '.
ENDFORM. "BUILD_HIERARCHY_HEADER
*&----------------------------------------------------*
*& Form create_hierarchy *
397
*&----------------------------------------------------*
FORM CREATE_HIERARCHY.
CLEAR L_ROOT_KEY.
ENDFORM. "CREATE_HIERARCHY
398
Recorremos los registros de la tabla T_HEADER, asignamos el
valor del campo LENGUAJE al campo HEADER (Esta variable
dará un texto al NODO). Llamamos al FORM ADD_NODE para
agregar un nuevo nodo.
Luego recorremos todos los registros de la tabla T_PROGRAMAS
buscando los registros que tengan el campo LENGUAJE igual que
el nodo, esto para poder agregarlos utilizando el FORM
ADD_LEAF.
Una vez que terminamos llamámos al método
FRONTEND_UPDATE para refrescar los valores del ALV.
*&----------------------------------------------------*
* FORM ADD_NODE *
*&----------------------------------------------------*
FORM ADD_NODE USING L_NAME L_ROOT_KEY
CHANGING L_NEXT_KEY.
L_NODE_TEXT = L_NAME.
CALL METHOD G_ALV_TREE->ADD_NODE
EXPORTING
I_RELAT_NODE_KEY = L_ROOT_KEY
I_RELATIONSHIP =
CL_GUI_COLUMN_TREE=>RELAT_LAST_CHILD
I_NODE_TEXT = L_NODE_TEXT
IS_OUTTAB_LINE = LS_TREE
IMPORTING
E_NEW_NODE_KEY = L_NEXT_KEY.
399
ENDFORM. "ADD_NODE
ENDFORM. "ADD_LEAF
400
Agregar validaciones y eventos
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: OK_CODE TYPE SY-UCOMM,
G_ALV_TREE TYPE REF TO CL_GUI_ALV_TREE,
G_CUSTOM_CONTAINER TYPE REF TO
CL_GUI_CUSTOM_CONTAINER,
L_HIERARCHY_HEADER TYPE TREEV_HHDR,
G_LINE_BEHAVIOUR TYPE REF TO CL_DRAGDROP,
G_FAV_BEHAVIOUR TYPE REF TO CL_DRAGDROP,
L_LAST_KEY TYPE LVC_NKEY,
W_NODE_KEY TYPE LVC_NKEY.
401
Agregamos algunas variables, G_LINE_BEHAVIOUR objeto que
determina que el nodo puede moverse. G_FAV_BEHAVIOUR
objeto que determina que el folder puede aceptar un nuevo nodo.
L_LAST_KEY determina el nodo padre.
W_NODE_KEY variable para almacenar el nodo que se ha movido
de carpeta.
*-----------------------------------------------------*
* CLASS LCL_DRAGDROPOBJ DEFINITION *
*-----------------------------------------------------*
CLASS LCL_DRAGDROPOBJ DEFINITION.
PUBLIC SECTION.
DATA: CPS_PROGRAMAS TYPE TY_PROGRAMAS,
CP_NODE_TEXT TYPE LVC_VALUE,
CP_NODE_KEY TYPE LVC_NKEY.
*-----------------------------------------------------*
* CLASS lcl_dnd_event_receiver DEFINITION *
*-----------------------------------------------------*
CLASS LCL_DND_EVENT_RECEIVER DEFINITION.
PUBLIC SECTION.
METHODS:
402
HANDLE_LINE_DRAG
FOR EVENT ON_DRAG
OF CL_GUI_ALV_TREE
IMPORTING SENDER NODE_KEY FIELDNAME
DRAG_DROP_OBJECT,
HANDLE_FAV_DROP
FOR EVENT ON_DROP
OF CL_GUI_ALV_TREE
IMPORTING SENDER NODE_KEY DRAG_DROP_OBJECT.
ENDCLASS. "lcl_dnd_event_receiver DEFINITION
*-----------------------------------------------------*
* CLASS lcl_dnd_event_receiver IMPLEMENTATION *
*-----------------------------------------------------*
CLASS LCL_DND_EVENT_RECEIVER IMPLEMENTATION.
METHOD HANDLE_LINE_DRAG.
DATA: DATAOBJ TYPE REF TO LCL_DRAGDROPOBJ.
403
DRAG_DROP_OBJECT->OBJECT = DATAOBJ.
ENDMETHOD. "HANDLE_LINE_DRAG
METHOD HANDLE_FAV_DROP.
DATA: DATAOBJ TYPE REF TO LCL_DRAGDROPOBJ,
L_NEW_KEY TYPE LVC_NKEY.
W_NODE_KEY = DATAOBJ->CP_NODE_KEY.
404
CPS_PROGRAMAS y CP_NODE_TEXT con los valores
correspondientes al nodo.
Asignamos el nodo al evento de Drag & Drop.
En el método HANDLE_FAV_DROP, hacemos un CATCH
SYSTEM-EXCEPTION por si hay algún problema al mover el
nodo de una carpeta a otra.
Asignamos el evento de Drag & Drop a una variable. Asignamos el
valor del nodo que hemos movido a una variable auxiliar
W_NODE_KEY.
Llamamos al FORM ADD_LEAF con el nodo que hemos movido
de una carpeta a otra.
Llamamos al método DELETE_SUBTREE con el valor de la
variable W_NODE_KEY para poder eliminar al nodo de su
posición original.
Llamamos al método FRONTEND_UPDATE para actualizar el
ALV.
PERFORM DEFINE_DND_BEHAVIOUR.
405
EXPORTING
EVENTS = LT_EVENTS
EXCEPTIONS
CNTL_ERROR = 1
CNTL_SYSTEM_ERROR = 2
ILLEGAL_EVENT_COMBINATION = 3.
406
Finalmente, llamamos al método FRONTEND_UPDATE para
actualizar el ALV.
*&----------------------------------------------------*
* FORM ADD_NODE *
*&----------------------------------------------------*
FORM ADD_NODE USING L_NAME L_ROOT_KEY
CHANGING L_NEXT_KEY.
L_LAYOUT_NODE-ISFOLDER = 'X'.
L_NODE_TEXT = L_NAME.
CALL METHOD G_ALV_TREE->ADD_NODE
EXPORTING
I_RELAT_NODE_KEY = L_ROOT_KEY
I_RELATIONSHIP =
CL_GUI_COLUMN_TREE=>RELAT_LAST_CHILD
I_NODE_TEXT = L_NODE_TEXT
IS_NODE_LAYOUT = L_LAYOUT_NODE
IS_OUTTAB_LINE = LS_TREE
IMPORTING
E_NEW_NODE_KEY = L_NEXT_KEY.
407
ENDFORM. "ADD_NODE
*&----------------------------------------------------*
* FORM ADD_LEAF *
*&----------------------------------------------------*
FORM ADD_LEAF USING L_TREE TYPE TY_PROGRAMAS
L_NEXT_KEY
CHANGING L_LAST_KEY.
408
L_LAYOUT_NODE-DRAGDROPID = L_HANDLE_LINE.
ENDFORM. "ADD_LEAF
*&----------------------------------------------------*
*& Form DEFINE_DND_BEHAVIOUR
**&---------------------------------------------------*
FORM DEFINE_DND_BEHAVIOUR.
409
EXPORTING
FLAVOR = 'X' "#EC NOTEXT
DRAGSRC = 'X'
DROPTARGET = ' '
EFFECT = EFFECT.
410
Crear un ALV Object Model
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
ID_PROG TYPE ZVLENGUAJES_PROG-ID_PROG,
LENGUAJE TYPE ZVLENGUAJES_PROG-LENGUAJE,
411
NOM_PROG TYPE ZVLENGUAJES_PROG-NOM_PROG,
ENTORNO TYPE ZVLENGUAJES_PROG-ENTORNO,
END OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE OF
TY_PROGRAMAS,
T_TABLE TYPE REF TO CL_SALV_TABLE,
T_FUNCTIONS TYPE REF TO CL_SALV_FUNCTIONS,
T_DSPSET TYPE REF TO CL_SALV_DISPLAY_SETTINGS,
LR_COLUMN TYPE REF TO CL_SALV_COLUMN_TABLE,
LV_SALV_COLUMNS_TABLE TYPE REF TO
CL_SALV_COLUMNS_TABLE.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM CARGAR_DATOS.
PERFORM LLAMAR_ALV.
*&----------------------------------------------------*
*& Form CARGAR_DATOS *
*&----------------------------------------------------*
FORM CARGAR_DATOS.
412
ENDFORM. " CARGAR_DATOS
*&----------------------------------------------------*
*& Form LLAMAR_ALV *
*&----------------------------------------------------*
FORM LLAMAR_ALV.
TRY.
CL_SALV_TABLE=>FACTORY(
IMPORTING
R_SALV_TABLE = T_TABLE
CHANGING
T_TABLE = T_PROGRAMAS ).
CATCH CX_SALV_MSG .
ENDTRY.
LV_SALV_COLUMNS_TABLE = T_TABLE->GET_COLUMNS( ).
LR_COLUMN ?=
LV_SALV_COLUMNS_TABLE->GET_COLUMN( 'ID_PROG' ).
LR_COLUMN->SET_LONG_TEXT( 'Id' ).
LV_SALV_COLUMNS_TABLE = T_TABLE->GET_COLUMNS( ).
LR_COLUMN ?=
LV_SALV_COLUMNS_TABLE->GET_COLUMN( 'NOM_PROG' ).
LR_COLUMN->SET_LONG_TEXT( 'Programa' ).
T_FUNCTIONS = T_TABLE->GET_FUNCTIONS( ).
T_FUNCTIONS->SET_ALL( ABAP_TRUE ).
T_DSPSET = T_TABLE->GET_DISPLAY_SETTINGS( ).
T_DSPSET->SET_LIST_HEADER( 'Programas' ).
413
T_TABLE->DISPLAY( ).
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_PROGRAMAS,
ID_PROG TYPE ZVLENGUAJES_PROG-ID_PROG,
LENGUAJE TYPE ZVLENGUAJES_PROG-LENGUAJE,
NOM_PROG TYPE ZVLENGUAJES_PROG-NOM_PROG,
ENTORNO TYPE ZVLENGUAJES_PROG-ENTORNO,
END OF TY_PROGRAMAS.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE OF
TY_PROGRAMAS,
T_TABLE TYPE REF TO CL_SALV_TABLE,
T_FUNCTIONS TYPE REF TO CL_SALV_FUNCTIONS,
T_DSPSET TYPE REF TO CL_SALV_DISPLAY_SETTINGS,
LR_COLUMN TYPE REF TO CL_SALV_COLUMN_TABLE,
LV_SALV_COLUMNS_TABLE TYPE REF TO
CL_SALV_COLUMNS_TABLE.
414
Declaramos varias tablas internas, T_PROGRAMAS que guardará
los datos que obtengamos de la vista. T_TABLE es un parámetro
para el método FACTORY y sirve para crear la estructura del ALV.
T_FUNCTIONS sirve para asignar las funciones de la barra de
menús del ALV. T_DSPSET nos sirve para las opciones de
visualización. LR_COLUMN nos permite tomar las características
de una columna del ALV. LV_SALV_COLUMNS_TABLE nos
permite tomar todas las columnas de ALV.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM CARGAR_DATOS.
PERFORM LLAMAR_ALV.
*&----------------------------------------------------*
*& Form CARGAR_DATOS *
*&----------------------------------------------------*
FORM CARGAR_DATOS.
415
ENDFORM. " CARGAR_DATOS
*&----------------------------------------------------*
*& Form LLAMAR_ALV *
*&----------------------------------------------------*
FORM LLAMAR_ALV.
TRY.
CL_SALV_TABLE=>FACTORY(
IMPORTING
R_SALV_TABLE = T_TABLE
CHANGING
T_TABLE = T_PROGRAMAS ).
CATCH CX_SALV_MSG .
ENDTRY.
LV_SALV_COLUMNS_TABLE = T_TABLE->GET_COLUMNS( ).
LR_COLUMN ?=
LV_SALV_COLUMNS_TABLE->GET_COLUMN( 'ID_PROG' ).
LR_COLUMN->SET_LONG_TEXT( 'Id' ).
LV_SALV_COLUMNS_TABLE = T_TABLE->GET_COLUMNS( ).
LR_COLUMN ?=
LV_SALV_COLUMNS_TABLE->GET_COLUMN( 'NOM_PROG' ).
LR_COLUMN->SET_LONG_TEXT( 'Programa' ).
T_FUNCTIONS = T_TABLE->GET_FUNCTIONS( ).
T_FUNCTIONS->SET_ALL( ABAP_TRUE ).
416
T_DSPSET = T_TABLE->GET_DISPLAY_SETTINGS( ).
T_DSPSET->SET_LIST_HEADER( 'Programas' ).
T_TABLE->DISPLAY( ).
417
Obtenemos las características de salida.
T_DSPSET->SET_LIST_HEADER( 'Programas' ).
Asignamos un título al reporte.
T_TABLE->DISPLAY( ).
Llamamos y mostramos el ALV.
418
*-----------------------------------------------------*
* CLASS lcl_handle_events DEFINITION *
*-----------------------------------------------------*
CLASS LCL_HANDLE_EVENTS DEFINITION.
PUBLIC SECTION.
METHODS:
ON_DOUBLE_CLICK FOR EVENT DOUBLE_CLICK OF
CL_SALV_EVENTS_TABLE
IMPORTING ROW COLUMN.
ENDCLASS. "lcl_handle_events DEFINITION
*-----------------------------------------------------*
* CLASS lcl_handle_events IMPLEMENTATION *
*-----------------------------------------------------*
CLASS LCL_HANDLE_EVENTS IMPLEMENTATION.
METHOD ON_DOUBLE_CLICK.
PERFORM MOSTRAR_DETALLE USING ROW COLUMN.
ENDMETHOD. "on_double_click
ENDCLASS. "lcl_handle_events IMPLEMENTATION
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_PROGRAMAS TYPE STANDARD TABLE OF
TY_PROGRAMAS,
T_TABLE TYPE REF TO CL_SALV_TABLE,
419
T_FUNCTIONS TYPE REF TO CL_SALV_FUNCTIONS,
T_DSPSET TYPE REF TO CL_SALV_DISPLAY_SETTINGS,
LR_COLUMN TYPE REF TO CL_SALV_COLUMN_TABLE,
LV_SALV_COLUMNS_TABLE TYPE REF TO
CL_SALV_COLUMNS_TABLE,
GR_EVENTS TYPE REF TO LCL_HANDLE_EVENTS.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_PROGRAMAS> LIKE LINE OF
T_PROGRAMAS.
Declaramos un Field-Symbol.
PERFORM PROCESS_EVENTS.
T_TABLE->DISPLAY( ).
420
*-----------------------------------------------------*
*& Form mostrar_detalle *
*-----------------------------------------------------*
FORM MOSTRAR_DETALLE USING P_ROW
P_COLUMN.
IF P_COLUMN EQ 'NOM_PROG'.
READ TABLE T_PROGRAMAS INDEX P_ROW
ASSIGNING <FS_PROGRAMAS>.
CONCATENATE <FS_PROGRAMAS>-ID_PROG
<FS_PROGRAMAS>-NOM_PROG
<FS_PROGRAMAS>-LENGUAJE
<FS_PROGRAMAS>-ENTORNO
INTO MENSAJE SEPARATED BY SPACE.
ENDIF.
421
*&----------------------------------------------------*
*& Form process_events *
*&----------------------------------------------------*
FORM PROCESS_EVENTS.
422
Cargar imágenes en Dynpros
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_GRAPHIC_TABLE,
LINE(255) TYPE X,
END OF TY_GRAPHIC_TABLE.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_GRAPHIC_TABLE TYPE STANDARD TABLE OF
TY_GRAPHIC_TABLE.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: OK_CODE TYPE SY-UCOMM,
URL(255) TYPE C,
CONTAINER1 TYPE REF TO CL_GUI_CUSTOM_CONTAINER,
PICTURE TYPE REF TO CL_GUI_PICTURE,
L_BYTECOUNT TYPE I,
L_CONTENT TYPE STANDARD TABLE OF BAPICONTEN
INITIAL SIZE 0,
GRAPHIC_SIZE TYPE I.
423
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
*&----------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT *
*&----------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
OK_CODE = SY-UCOMM.
CLEAR SY-UCOMM.
CASE OK_CODE.
WHEN 'BACK' OR 'STOP' OR 'CANCEL'.
SET SCREEN 0.
LEAVE SCREEN.
ENDCASE.
ENDMODULE. " USER_COMMAND_0100 INPUT
424
*&----------------------------------------------------*
*& Form load_image *
*&----------------------------------------------------*
FORM LOAD_IMAGE.
425
TABLES
BDS_BITMAP_FILE = L_CONTENT
BITMAP_FILE = T_GRAPHIC_TABLE
EXCEPTIONS
OTHERS = 1.
426
Declaramos un TYPE llamado TY_GRAPHIC_TABLE que
contiene un único campo, llamado LINE de 255 caracteres y de tipo
X. Esto es porque las imágenes de almacenan en formato
hexadecimal.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_GRAPHIC_TABLE TYPE STANDARD TABLE OF
TY_GRAPHIC_TABLE.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: OK_CODE TYPE SY-UCOMM,
URL(255) TYPE C,
CONTAINER1 TYPE REF TO CL_GUI_CUSTOM_CONTAINER,
PICTURE TYPE REF TO CL_GUI_PICTURE,
L_BYTECOUNT TYPE I,
L_CONTENT TYPE STANDARD TABLE OF BAPICONTEN
INITIAL SIZE 0,
GRAPHIC_SIZE TYPE I.
427
CONTAINER1 contiene el nombre de nuestro
CUSTOM_CONTROL.
PICTURE objeto que cargará y mostrará la imagen en el Dynpro.
L_BYTECOUNT cuenta el número de bytes de la imagen que
queremos visualizar.
L_CONTENT almacena el contenido de la imagen.
GRAPHIC_SIZE es el tamaño de la imagen luego de convetirla a
BMP.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
428
Llamamos a la barra de menús y al título del programa. Además, en
el FORM LOAD_IMAGE vamos a cargar la imagen en el Dynpro.
*&----------------------------------------------------*
*& Form load_image *
*&----------------------------------------------------*
FORM LOAD_IMAGE.
429
BITMAP_FILE_BYTECOUNT_IN = L_BYTECOUNT
IMPORTING
BITMAP_FILE_BYTECOUNT = GRAPHIC_SIZE
TABLES
BDS_BITMAP_FILE = L_CONTENT
BITMAP_FILE = T_GRAPHIC_TABLE
EXCEPTIONS
OTHERS = 1.
430
Llamamos a la función SAPSCRIPT_GET_GRAPHIC_BDS para
obtener los datos de la imagen que queremos mostrar, que en este
caso es “ENJOY”.
Llamamos a la función SAPSCRIPT_CONVERT_BITMAP para
convertir la imagen a un Bitmap.
Llamamos a la función DP_CREATE_URL para generar una
dirección donde se encuentra almacenada temporalmente la imagen
BMP.
Llamamos al método LOAD_PICTURE_FROM_URL para cargar
la imagen en memoria.
Llamamos al método SET_DISPLAY_MODE para mostrar la
imagen.
431
Leer PDF’s
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_FILETAB TYPE FILETABLE.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: OK_CODE TYPE SY-UCOMM,
MY_PDF_VIEWER TYPE REF TO CL_GUI_PDFVIEWER,
CONTAINER TYPE REF TO CL_GUI_CUSTOM_CONTAINER,
W_SUBRC TYPE SY-SUBRC,
V_URL TYPE CHAR255.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_FILETAB> LIKE LINE OF T_FILETAB.
*&----------------------------------------------------*
*& SELECTION-SCREEN *
*&----------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK TEST WITH FRAME.
PARAMETERS:
FILE LIKE RLGRAP-FILENAME.
432
SELECTION-SCREEN END OF BLOCK TEST.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
*&----------------------------------------------------*
*& AT SELECTION-SCREEN *
*&----------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR FILE.
CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_OPEN_DIALOG
EXPORTING
WINDOW_TITLE = 'Seleccionar archivo'
DEFAULT_FILENAME = '*.pdf'
FILE_FILTER = '*.pdf'
CHANGING
FILE_TABLE = T_FILETAB
RC = W_SUBRC.
IF FILE IS INITIAL.
EXIT.
ENDIF.
433
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
IF CONTAINER IS INITIAL.
CREATE OBJECT CONTAINER
EXPORTING
CONTAINER_NAME = 'CUSTOM_ALV'
EXCEPTIONS
CNTL_ERROR = 1
OTHERS = 2.
434
ENDIF.
ENDMODULE. " STATUS_0100 OUTPUT
*&----------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT *
*&----------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
OK_CODE = SY-UCOMM.
CLEAR SY-UCOMM.
CASE OK_CODE.
WHEN 'BACK' OR 'STOP' OR 'CANCEL'.
SET SCREEN 0.
LEAVE SCREEN.
ENDCASE.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_FILETAB TYPE FILETABLE.
435
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: OK_CODE TYPE SY-UCOMM,
MY_PDF_VIEWER TYPE REF TO CL_GUI_PDFVIEWER,
CONTAINER TYPE REF TO CL_GUI_CUSTOM_CONTAINER,
W_SUBRC TYPE SY-SUBRC,
V_URL TYPE CHAR255.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_FILETAB> LIKE LINE OF T_FILETAB.
436
*&----------------------------------------------------*
*& SELECTION-SCREEN *
*&----------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK TEST WITH FRAME.
PARAMETERS:
FILE LIKE RLGRAP-FILENAME.
SELECTION-SCREEN END OF BLOCK TEST.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
*&----------------------------------------------------*
*& AT SELECTION-SCREEN *
*&----------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR FILE.
CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_OPEN_DIALOG
EXPORTING
WINDOW_TITLE = 'Seleccionar archivo'
DEFAULT_FILENAME = '*.pdf'
437
FILE_FILTER = '*.pdf'
CHANGING
FILE_TABLE = T_FILETAB
RC = W_SUBRC.
IF FILE IS INITIAL.
EXIT.
ENDIF.
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
IF CONTAINER IS INITIAL.
CREATE OBJECT CONTAINER
EXPORTING
CONTAINER_NAME = 'CUSTOM_ALV'
EXCEPTIONS
438
CNTL_ERROR = 1
OTHERS = 2.
439
Comprimir (zip) archivos
440
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: DATA_TAB TYPE STANDARD TABLE OF T_XLINE,
T_FILETAB TYPE FILETABLE,
RESULT_TAB TYPE MATCH_RESULT_TAB.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: CL_ZIP TYPE REF TO CL_ABAP_ZIP,
SIZE TYPE I,
INPUT_X TYPE XSTRING,
OUTPUT_X TYPE XSTRING,
W_SUBRC TYPE SY-SUBRC,
W_FILE_IN TYPE STRING,
W_FILE_OUT TYPE STRING,
W_SIZE TYPE I,
W_LINE TYPE STRING,
W_EXT(4) TYPE C.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_FILETAB> LIKE LINE OF T_FILETAB,
<FS_RESULT_TAB> LIKE LINE OF RESULT_TAB.
*&----------------------------------------------------*
*& SELECTION-SCREEN *
*&----------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK TEST WITH FRAME.
PARAMETERS:
FILE_IN LIKE RLGRAP-FILENAME,
441
FILE_OUT LIKE RLGRAP-FILENAME.
SELECTION-SCREEN END OF BLOCK TEST.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
442
CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
EXPORTING
INPUT_LENGTH = SIZE
IMPORTING
BUFFER = INPUT_X
TABLES
BINARY_TAB = DATA_TAB.
IF CL_ZIP IS INITIAL.
CREATE OBJECT CL_ZIP.
ENDIF.
REFRESH DATA_TAB.
443
CALL METHOD CL_GUI_FRONTEND_SERVICES=>GUI_DOWNLOAD
EXPORTING
BIN_FILESIZE = SIZE
FILENAME = W_FILE_OUT
FILETYPE = 'BIN'
CHANGING
DATA_TAB = DATA_TAB.
*&----------------------------------------------------*
*& AT SELECTION-SCREEN *
*&----------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR FILE_IN.
CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_OPEN_DIALOG
EXPORTING
WINDOW_TITLE = 'Seleccionar archivo'
DEFAULT_FILENAME = '*.*'
FILE_FILTER = '*.*'
CHANGING
FILE_TABLE = T_FILETAB
RC = W_SUBRC.
IF FILE_IN IS INITIAL.
EXIT.
ENDIF.
CLEAR T_FILETAB.
444
REFRESH T_FILETAB.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR FILE_OUT.
CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_OPEN_DIALOG
EXPORTING
WINDOW_TITLE = 'Seleccionar archivo'
DEFAULT_FILENAME = '*.zip'
FILE_FILTER = '*.zip'
CHANGING
FILE_TABLE = T_FILETAB
RC = W_SUBRC.
IF FILE_OUT IS INITIAL.
EXIT.
ELSE.
W_SIZE = STRLEN( W_FILE_OUT ).
W_SIZE = W_SIZE - 4.
W_EXT = W_FILE_OUT+W_SIZE(4).
IF W_EXT NE '.zip'.
CONCATENATE W_FILE_OUT '.zip'
INTO W_FILE_OUT.
FILE_OUT = W_FILE_OUT.
ENDIF.
ENDIF.
445
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: T_XLINE(2048) TYPE X.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: DATA_TAB TYPE STANDARD TABLE OF T_XLINE,
T_FILETAB TYPE FILETABLE,
RESULT_TAB TYPE MATCH_RESULT_TAB.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: CL_ZIP TYPE REF TO CL_ABAP_ZIP,
SIZE TYPE I,
INPUT_X TYPE XSTRING,
OUTPUT_X TYPE XSTRING,
446
W_SUBRC TYPE SY-SUBRC,
W_FILE_IN TYPE STRING,
W_FILE_OUT TYPE STRING,
W_SIZE TYPE I,
W_LINE TYPE STRING,
W_EXT(4) TYPE C.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
447
FIELD-SYMBOLS: <FS_FILETAB> LIKE LINE OF T_FILETAB,
<FS_RESULT_TAB> LIKE LINE OF RESULT_TAB.
*&----------------------------------------------------*
*& SELECTION-SCREEN *
*&----------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK TEST WITH FRAME.
PARAMETERS:
FILE_IN LIKE RLGRAP-FILENAME,
FILE_OUT LIKE RLGRAP-FILENAME.
SELECTION-SCREEN END OF BLOCK TEST.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
448
W_SIZE = STRLEN( W_FILE_IN ) –
<FS_RESULT_TAB>-OFFSET.
<FS_RESULT_TAB>-OFFSET = <FS_RESULT_TAB>-OFFSET +
<FS_RESULT_TAB>-LENGTH.
W_SIZE = W_SIZE - <FS_RESULT_TAB>-LENGTH.
W_LINE = W_FILE_IN+<FS_RESULT_TAB>-OFFSET(W_SIZE).
IF CL_ZIP IS INITIAL.
CREATE OBJECT CL_ZIP.
ENDIF.
449
CALL METHOD CL_ZIP->SAVE
RECEIVING
ZIP = OUTPUT_X.
REFRESH DATA_TAB.
450
Obtenemos la longitud del archivo de entrada con STRLEN y le
restamos el valor OFFSET de la tabla RESULT_TAB (Este valor
OFFSET es la ubicación del último símbolo “\” encontrado).
Reemplazamos el valor del OFFSET, sumándole a este el valor del
campo LENGTH (Es decir, la longitud del símbolo “\”).
Restamos a W_SIZE el valor del campo LENGTH.
Finalmente, guardamos en W_LINE la subcadena empezando con el
valor del OFFSET y tomando el valor de W_SIZE en cantidad de
caracteres.
Llamamos al método GUI_UPLOAD para subir el contenido del
archivo de entrada.
Con el módulo de funciones SCMS_BINARY_TO_XSTRING
convertimos el contenido del archivo de Binario a Hexadecimal.
Creamos el objeto CL_ZIP y llamamos al método ADD para
agregar el archivo de entrada al nuevo ZIP, llamamos al método
SAVE para crear el archivo ZIP con el archivo de entrada.
Con el método SCMS_XSTRING_TO_BINARY convertimos el
archivo ZIP de Hexadecimal a Binario y finalmente llamamos al
método GUI_DOWNLOAD para descargarlo con el nombre del
archivo de salida.
*&----------------------------------------------------*
*& AT SELECTION-SCREEN *
*&----------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR FILE_IN.
CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_OPEN_DIALOG
EXPORTING
WINDOW_TITLE = 'Seleccionar archivo'
451
DEFAULT_FILENAME = '*.*'
FILE_FILTER = '*.*'
CHANGING
FILE_TABLE = T_FILETAB
RC = W_SUBRC.
IF FILE_IN IS INITIAL.
EXIT.
ENDIF.
CLEAR T_FILETAB.
REFRESH T_FILETAB.
452
Crear un Control de Texto
*=====================================================*
* DECLARACION DE CONSTANTES *
*=====================================================*
CONSTANTS: LINE_LENGTH TYPE I VALUE 254.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: OK_CODE TYPE SY-UCOMM,
CUSTOM_CONTAINER TYPE REF TO
CL_GUI_CUSTOM_CONTAINER,
TEXT_EDITOR TYPE REF TO CL_GUI_TEXTEDIT.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
453
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
PERFORM CALL_EDITOR.
*&----------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT *
*&----------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
OK_CODE = SY-UCOMM.
CLEAR SY-UCOMM.
CASE OK_CODE.
WHEN 'BACK' OR 'STOP' OR 'CANCEL'.
SET SCREEN 0.
LEAVE SCREEN.
ENDCASE.
454
*&----------------------------------------------------*
*& Form CALL_EDITOR *
*&----------------------------------------------------*
FORM CALL_EDITOR .
IF TEXT_EDITOR IS INITIAL.
CREATE OBJECT CUSTOM_CONTAINER
EXPORTING
CONTAINER_NAME = 'CUSTOM_ALV'
EXCEPTIONS
CNTL_ERROR = 1
CNTL_SYSTEM_ERROR = 2
CREATE_ERROR = 3
LIFETIME_ERROR = 4
LIFETIME_DYNPRO_DYNPRO_LINK = 5.
455
CALL METHOD CL_GUI_CFW=>FLUSH.
ENDFORM. " CALL_EDITOR
*=====================================================*
* DECLARACION DE CONSTANTES *
*=====================================================*
CONSTANTS: LINE_LENGTH TYPE I VALUE 254.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: OK_CODE TYPE SY-UCOMM,
CUSTOM_CONTAINER TYPE REF TO
CL_GUI_CUSTOM_CONTAINER,
TEXT_EDITOR TYPE REF TO CL_GUI_TEXTEDIT.
456
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
*&----------------------------------------------------*
*& Module STATUS_0100 OUTPUT *
*&----------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
PERFORM CALL_EDITOR.
*&----------------------------------------------------*
*& Form CALL_EDITOR *
*&----------------------------------------------------*
FORM CALL_EDITOR .
IF TEXT_EDITOR IS INITIAL.
CREATE OBJECT CUSTOM_CONTAINER
457
EXPORTING
CONTAINER_NAME = 'CUSTOM_ALV'
EXCEPTIONS
CNTL_ERROR = 1
CNTL_SYSTEM_ERROR = 2
CREATE_ERROR = 3
LIFETIME_ERROR = 4
LIFETIME_DYNPRO_DYNPRO_LINK = 5.
458
Limpiamos los controles con el método FLUSH.
Como podemos ver, contamos con dos botones Load Local File
459
WebDynpro
Introducción
460
Elegimos de la lista Web Dynpro Comp. / Intf. (Componente o
Interface Web Dynpro).
461
Asignamos una descripción y aceptamos.
Creamos una vista, donde van a estar los componentes que muestran
la información.
Para esto, hacemos un clic derecho sobre ZDUMMY_DYPRO y
seleccionamos Create Æ View (Crear Æ Vista).
462
Asignamos un nombre y una descripción a nuestra vista.
463
Una vez logeados, tenemos acceso al editor de vistas del
WebDynpro.
464
Al nodo lo llamamos ZLENG_NODE y como Dictionary
Structure (Estructura del Diccionario) le pasamos la vista
ZVLENGUAJES_PROG.
465
Como parámetro de entrada para nuestro programa, vamos a tener
un campo que represente el ID, así que creamos un Attribute
(Atributo) llamado ID_PROG.
466
Grabamos y regresamos a la pestaña Layout (Disposición).
Seleccionamos Standard Container (Contenedor Estándar) del
menú izquierdo y luego Group (Grupo).
467
Seleccionamos Create Container Form (Crear formulario
contenedor).
468
Elegimos el nodo ID_PROG.
469
Finalmente, tendríamos esto.
470
Grabamos y al momento de activar veremos una ventana como esta.
471
Seleccionamos todos y aceptamos. Una vez que todo se ha activado,
debemos crear una WebDynpro Application (Aplicación
WebDynpro).
472
Presionamos el botón Test/Execute (Probar/Ejecutar) o
presionamos F8.
El navegador nos muestra una pantalla de login, así que debemos
logearnos. Para esto, presionamos el botón Log On .
473
Como podemos ver, nuestro parámetro de entrada aparece
perfectamente en el browser de internet.
474
Regresamos a la vista ZDUMMY_VIEW, pestaña Layout.
Elegimos el componente Table (Tabla) de la pestaña Standard
Complex (Complejos Estándar).
475
Escogemos el Context ZLENG_NODE y dejamos todos los
registro seleccionados y continuamos.
476
Regresamos a la pestaña Standard Simple y seleccionamos el
control Button (Botón), el cual tendrá el texto “Mostrar!”.
477
Debemos asignar una acción al botón, por lo cual presionamos el
botón OnAction.
478
Debemos presionar el botón ABAP Routine (Rutina ABAP)
para poder asignar el código a nuestra acción.
METHOD ONACTIONSHOW.
WD_CONTEXT->GET_ATTRIBUTE(
exporting NAME = 'ID_PROG'
importing VALUE = ID_PROG ).
479
WD_CONTEXT->GET_CHILD_NODE( NAME = 'ZLENG_NODE' ).
NODE_LENG->BIND_TABLE( ITAB_LENG ).
ENDMETHOD.
WD_CONTEXT->GET_ATTRIBUTE(
exporting NAME = 'ID_PROG'
importing VALUE = ID_PROG ).
NODE_LENG =
WD_CONTEXT->GET_CHILD_NODE( NAME = 'ZLENG_NODE' ).
NODE_LENG->BIND_TABLE( ITAB_LENG ).
480
Hay algo más que debemos hacer y que es muy importante.
Debemos ir a la pestaña Methods (Métodos) y seleccionar
WDDOINIT que es una acción que se lanza cuando se ejecuta el
programa por primera vez.
method WDDOINIT.
NODE_LENG =
WD_CONTEXT->GET_CHILD_NODE( NAME = 'ZLENG_NODE' ).
NODE_LENG->BIND_TABLE( ITAB_LENG ).
endmethod.
481
Todo se ve muy bien, pero estamos limitados a buscar solamente un
valor...Así que vamos a agregar otra caja de texto para poder crear
un rango de búsqueda.
482
Regresamos a la pestaña Context.
483
Lo que hacemos es arrastrar los atributos a nuestro nodo
PARAMETROS.
484
Regresamos al Layout y eliminamos el campo de texto ID_PROG.
Creamos un nuevo Container Form.
485
Regresamos a la pestaña Actions y al código del método Show.
METHOD ONACTIONSHOW.
NODE_LENG = WD_CONTEXT->GET_CHILD_NODE(
NAME = 'PARAMETROS' ).
486
WD_CONTEXT->GET_ATTRIBUTE(
EXPORTING NAME = 'ID_PROG_INI'
IMPORTING VALUE = ID_PROG_INI ).
WD_CONTEXT->GET_ATTRIBUTE(
EXPORTING NAME = 'ID_PROG_FIN'
IMPORTING VALUE = ID_PROG_FIN ).
NODE_LENG =
WD_CONTEXT->GET_CHILD_NODE( NAME = 'ZLENG_NODE' ).
NODE_LENG->BIND_TABLE( ITAB_LENG ).
ENDMETHOD.
487
DATA: ID_PROG TYPE RANGE OF ZVLENGUAJES_PROG-ID_PROG.
FIELD-SYMBOLS: <FS_IDPROG> LIKE LINE OF ID_PROG.
NODE_LENG = WD_CONTEXT->GET_CHILD_NODE(
NAME = 'PARAMETROS' ).
NODE_LENG->GET_ATTRIBUTE(
EXPORTING NAME = 'ID_PROG_INI'
IMPORTING VALUE = ID_PROG_INI ).
NODE_LENG->GET_ATTRIBUTE(
EXPORTING NAME = 'ID_PROG_FIN'
IMPORTING VALUE = ID_PROG_FIN ).
488
<FS_IDPROG>-LOW = ID_PROG_INI.
<FS_IDPROG>-HIGH = ID_PROG_FIN.
489
490
BSP
Introducción
491
Creamos nuestra aplicación ZDUMMY_BSP.
492
En la pestaña Layout (Disposición) colocamos el siguiente código.
<%@page language="abap"%>
<html>
<head>
</head>
<body>
<form method="post">
Id <input type="text" name="ID_PROG" value="">
<input type="submit" name="onInputProcessing(show)"
value="Enviar!">
</form>
<!--navigation->set_parameter( 'ID_PROG' )-->
</body>
</html>
Como podemos ver esta página, nos es más que HTML con un par
de características adicionales.
493
Este es el código de la página.
<%@page language="abap"%>
<html>
<body>
<%
data: w_id_prog type zvlenguajes_prog-id_prog,
t_leng type standard table of ZVLENGUAJES_PROG.
field-symbols: <fs_leng> like line of t_leng.
w_id_prog = request->get_form_field( 'ID_PROG' ).
select ID_PROG NOM_PROG LENGUAJE ENTORNO
INTO TABLE T_LENG
FROM ZVLENGUAJES_PROG
WHERE ID_PROG EQ W_ID_PROG.
%>
<table border=”1”>
<tr>
<b><td>Id</td><td>Nombre</td>
<td>Lenguaje</td><td>Entorno</td></b>
</tr>
<%
loop at t_leng assigning <fs_leng>.
%>
494
<tr>
<td><%= <fs_leng>-ID_PROG %></td>
<td><%= <fs_leng>-NOM_PROG %></td>
<td><%= <fs_leng>-LENGUAJE %></td>
<td><%= <fs_leng>-ENTORNO %></td>
</tr>
<%
endloop.
%>
</table>
</body>
</html>
495
Agregamos el siguiente código.
CASE EVENT_ID.
WHEN 'show'.
NAVIGATION->SET_PARAMETER('ID_PROG').
NAVIGATION->NEXT_PAGE('SHOW_DATA').
ENDCASE.
496
Establecemos que index.bsp llama al alias SHOW_DATA que
representa a la página Show_Data.bsp
497
498
Al ser HTML, podemos hacer lo que queramos con el formato de
salida de la tabla, pero lo que vamos a hacer, al igual que con el
WebDynpro, es crear un rango de valores para poder hacer una
mejor selección en el programa.
Regresamos a la página index.bsp y modificamos ligeramente el
código.
<%@page language="abap"%>
<html>
<head>
</head>
<body>
<form method="post">
Id desde <input type="text" name="ID_PROG_INI"
value="">
Id hasta <input type="text" name="ID_PROG_FIN"
value="">
<input type="submit" name="onInputProcessing(show)"
value="Enviar!">
</form>
<!--navigation->set_parameter( 'ID_PROG_INI' )-->
<!--navigation->set_parameter( 'ID_PROG_FIN' )-->
</body>
</html>
499
CASE EVENT_ID.
WHEN 'show'.
NAVIGATION->SET_PARAMETER('ID_PROG_INI').
NAVIGATION->SET_PARAMETER('ID_PROG_FIN').
NAVIGATION->NEXT_PAGE('SHOW_DATA').
ENDCASE.
500
select ID_PROG NOM_PROG LENGUAJE ENTORNO
INTO TABLE T_LENG
FROM ZVLENGUAJES_PROG
WHERE ID_PROG in r_leng.
%>
<table border="1">
<tr>
<b><td>Id</td><td>Nombre</td>
<td>Lenguaje</td><td>Entorno</td></b>
</tr>
<%
loop at t_leng assigning <fs_leng>.
%>
<tr>
<td><%= <fs_leng>-ID_PROG %></td>
<td><%= <fs_leng>-NOM_PROG %></td>
<td><%= <fs_leng>-LENGUAJE %></td>
<td><%= <fs_leng>-ENTORNO %></td>
</tr>
<%
endloop.
%>
</table>
</body>
</html>
501
502
ABAP y XML
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_TAB,
LINE(100) TYPE C,
END OF TY_TAB.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_TAB TYPE STANDARD TABLE OF TY_TAB,
T_ZLENG TYPE STANDARD TABLE OF
ZVLENGUAJES_PROG,
T_FILETAB TYPE FILETABLE.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_FILETAB> LIKE LINE OF T_FILETAB.
503
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: XML_OUT TYPE STRING,
W_SUBRC TYPE SY-SUBRC,
SIZE TYPE I,
W_FILE TYPE STRING.
*&----------------------------------------------------*
*& SELECTION-SCREEN *
*&----------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK TEST WITH FRAME.
PARAMETERS:
FILE LIKE RLGRAP-FILENAME.
SELECTION-SCREEN END OF BLOCK TEST.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM OBTENER_DATOS.
PERFORM GENERAR_XML.
PERFORM DESCARGAR_XML.
*&----------------------------------------------------*
*& AT SELECTION-SCREEN *
*&----------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR FILE.
CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_OPEN_DIALOG
EXPORTING
WINDOW_TITLE = 'Seleccionar archivo'
DEFAULT_FILENAME = '*.xml'
504
FILE_FILTER = '*.xml'
CHANGING
FILE_TABLE = T_FILETAB
RC = W_SUBRC.
IF FILE IS INITIAL.
EXIT.
ELSE.
W_FILE = FILE.
ENDIF.
*&----------------------------------------------------*
*& Form OBTENER_DATOS *
*&----------------------------------------------------*
FORM OBTENER_DATOS.
*&----------------------------------------------------*
*& Form GENERAR_XML *
*&----------------------------------------------------*
FORM GENERAR_XML.
505
SOURCE TAB = T_ZLENG[]
RESULT XML XML_OUT.
*&----------------------------------------------------*
*& Form DESCARGAR_XML *
*&----------------------------------------------------*
FORM DESCARGAR_XML.
506
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_TAB,
LINE(100) TYPE C,
END OF TY_TAB.
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_TAB TYPE STANDARD TABLE OF TY_TAB,
T_ZLENG TYPE STANDARD TABLE OF
ZVLENGUAJES_PROG,
T_FILETAB TYPE FILETABLE.
Creamos algunas tablas internas, una para guardar el XML, otra para
guardar los datos de la Base de Datos y el último para guardar la ruta
del archivo de salida.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_FILETAB> LIKE LINE OF T_FILETAB.
Declaramos un field-symbol.
507
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: XML_OUT TYPE STRING,
W_SUBRC TYPE SY-SUBRC,
SIZE TYPE I,
W_FILE TYPE STRING.
*&----------------------------------------------------*
*& SELECTION-SCREEN *
*&----------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK TEST WITH FRAME.
PARAMETERS:
FILE LIKE RLGRAP-FILENAME.
SELECTION-SCREEN END OF BLOCK TEST.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM OBTENER_DATOS.
PERFORM GENERAR_XML.
PERFORM DESCARGAR_XML.
508
OBTENER_DATOS nos sirve para seleccionar los datos de la
vista.
GENERAR_XML crea el archivo XML.
DESCARGAR_XML guarda el archivo en la ruta especificada.
*&----------------------------------------------------*
*& AT SELECTION-SCREEN *
*&----------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR FILE.
CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_OPEN_DIALOG
EXPORTING
WINDOW_TITLE = 'Seleccionar archivo'
DEFAULT_FILENAME = '*.xml'
FILE_FILTER = '*.xml'
CHANGING
FILE_TABLE = T_FILETAB
RC = W_SUBRC.
IF FILE IS INITIAL.
EXIT.
ELSE.
W_FILE = FILE.
ENDIF.
509
*&----------------------------------------------------*
*& Form OBTENER_DATOS *
*&----------------------------------------------------*
FORM OBTENER_DATOS.
*&----------------------------------------------------*
*& Form GENERAR_XML *
*&----------------------------------------------------*
FORM GENERAR_XML.
510
*&----------------------------------------------------*
*& Form DESCARGAR_XML *
*&----------------------------------------------------*
FORM DESCARGAR_XML.
511
Ahora que ya vimos como podemos generar un archivo XML a
partir de una tabla interna, veamos como hacer lo contrario, es decir,
generemos una tabla interna en base a un archivo XML.
El código es practicamente el mismo, solo cambia el orden.
*=====================================================*
* DECLARACION DE TYPES *
*=====================================================*
TYPES: BEGIN OF TY_TAB,
LINE(100) TYPE C,
END OF TY_TAB.
512
*=====================================================*
* DECLARACION DE TABLAS INTERNAS *
*=====================================================*
DATA: T_TAB TYPE STANDARD TABLE OF TY_TAB,
T_ZLENG TYPE STANDARD TABLE OF
ZVLENGUAJES_PROG,
T_FILETAB TYPE FILETABLE.
*=====================================================*
* DECLARACION DE FIELD-SYMBOLS *
*=====================================================*
FIELD-SYMBOLS: <FS_FILETAB> LIKE LINE OF T_FILETAB,
<FS_ZLENG> LIKE LINE OF T_ZLENG.
*=====================================================*
* DECLARACION DE VARIABLES *
*=====================================================*
DATA: XML_OUT TYPE STRING,
W_SUBRC TYPE SY-SUBRC,
SIZE TYPE I,
W_FILE TYPE STRING.
*&----------------------------------------------------*
*& SELECTION-SCREEN *
*&----------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK TEST WITH FRAME.
PARAMETERS:
FILE LIKE RLGRAP-FILENAME.
SELECTION-SCREEN END OF BLOCK TEST.
513
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM CARGAR_XML.
PERFORM GENERAR_TABLA_INTERNA.
PERFORM IMPRIMIR.
*&----------------------------------------------------*
*& AT SELECTION-SCREEN *
*&----------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR FILE.
CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_OPEN_DIALOG
EXPORTING
WINDOW_TITLE = 'Seleccionar archivo'
DEFAULT_FILENAME = '*.xml'
FILE_FILTER = '*.xml'
CHANGING
FILE_TABLE = T_FILETAB
RC = W_SUBRC.
IF FILE IS INITIAL.
EXIT.
ELSE.
W_FILE = FILE.
ENDIF.
514
*&----------------------------------------------------*
*& Form GENERAR_TABLA_INTERNA *
*&----------------------------------------------------*
FORM GENERAR_TABLA_INTERNA.
*&----------------------------------------------------*
*& Form CARGAR_XML *
*&----------------------------------------------------*
FORM CARGAR_XML.
515
*&----------------------------------------------------*
*& Form IMPRIMIR *
*&----------------------------------------------------*
FORM IMPRIMIR.
LOOP AT T_ZLENG
ASSIGNING <FS_ZLENG>.
WRITE:/ <FS_ZLENG>-ID_PROG, <FS_ZLENG>-NOM_PROG,
<FS_ZLENG>-LENGUAJE, <FS_ZLENG>-ENTORNO.
ENDLOOP.
*=====================================================*
* START-OF-SELECTION *
*=====================================================*
START-OF-SELECTION.
PERFORM CARGAR_XML.
PERFORM GENERAR_TABLA_INTERNA.
PERFORM IMPRIMIR.
516
*&----------------------------------------------------*
*& Form CARGAR_XML *
*&----------------------------------------------------*
FORM CARGAR_XML.
517
*&----------------------------------------------------*
*& Form GENERAR_TABLA_INTERNA *
*&----------------------------------------------------*
FORM GENERAR_TABLA_INTERNA.
*&----------------------------------------------------*
*& Form IMPRIMIR *
*&----------------------------------------------------*
FORM IMPRIMIR.
LOOP AT T_ZLENG
ASSIGNING <FS_ZLENG>.
WRITE:/ <FS_ZLENG>-ID_PROG, <FS_ZLENG>-NOM_PROG,
<FS_ZLENG>-LENGUAJE, <FS_ZLENG>-ENTORNO.
ENDLOOP.
518
519
Scripting in a Box
https://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/e5
0bd86e-0a01-0010-53bd-857585234a6a
520
521
522
SAPLink
http://code.google.com/p/saplink/
http://code.google.com/p/saplink/wiki/pluginList
523
524
525
526
Integración PHP-NetWeaver
Introducción
527
Como este es un libro sobre NetWeaver y no sobre PHP (Para eso
está, El Arte de Programar PHP), no vamos a enseñar a instalar el
PHP o el Apache, ni tampoco a programar en PHP, lo que vamos a
hacer es configurar el SAPRFC e integrarlo con NetWeaver.
Instalando el SAPRFC
extension = php_saprfc.dll;
<?php
phpinfo();
?>
528
Estableciendo la comunicación con NetWeaver
<?php
Class Login
{
var $Login, $rfc;
function Login_Page()
{
PRINT("<DIV ALIGN='CENTER'><BR><BR><BR><BR><H1>PHP & SAP
- SE16 Emulator</H1>");
PRINT("<BR><TABLE BORDER='1' BORDERCOLOR='BLUE'
BGCOLOR='WHITE'>");
PRINT("<FORM ACTION='index.php' METHOD='POST'>");
PRINT("<TR><TD>Server</TD><TD><INPUT TYPE='TEXT'
NAME='Server'></TD></TR>");
PRINT("<TR><TD>System Number</TD><TD><INPUT TYPE='TEXT'
NAME='Sysnum' SIZE='3'></TD></TR>");
PRINT("<TR><TD>Client</TD><TD><INPUT TYPE='TEXT'
529
NAME='Client' SIZE='3'></TD></TR>");
PRINT("<TR><TD>User</TD><TD><INPUT TYPE='TEXT'
NAME='User'></TD></TR>");
PRINT("<TR><TD>Password</TD><TD><INPUT TYPE='PASSWORD'
NAME='Pass'></TD></TR>");
PRINT("<TR><TD COLSPAN='2' ALIGN='CENTER'><INPUT
TYPE='SUBMIT' value='Log In' NAME='LOG_IN'>");
PRINT("<INPUT TYPE='RESET' value='Clear'></TD></TR>");
PRINT("</FORM>");
PRINT("<TABLE>");
PRINT("</DIV>");
}
function Log_In($Server,$Sysnum,$Client,$User,$Pass)
{
$this->Login = array ("ASHOST"=>$Server,
"SYSNR"=>$Sysnum,
"CLIENT"=>$Client,
"USER"=>$User,
"PASSWD"=>$Pass,
"CODEPAGE"=>"1404");
return $this->Login;
}
function RFC_Connection($Login)
{
$this->rfc = saprfc_open($Login);
IF ( !$this->rfc )
{
ECHO "The connection fails with the following
530
error:".saprfc_error();
EXIT;
}
else
{
return $this->rfc;
}
}
}
?>
<?php
Class SE16
{
var $fce;
531
function Show_Table($Table,$RFC_Me)
{
$this->fce = saprfc_function_discover($RFC_Me,
"RFC_READ_TABLE");
IF (! $this->fce )
{
ECHO "The function module had failed.";
EXIT;
}
$Table = STRTOUPPER($Table);
saprfc_import ($this->fce,"QUERY_TABLE",$Table);
saprfc_import ($this->fce,"DELIMITER","/");
saprfc_table_init ($this->fce,"OPTIONS");
saprfc_table_init ($this->fce,"FIELDS");
saprfc_table_init ($this->fce,"DATA");
$rfc_rc = "";
532
$data_row = saprfc_table_rows ($this->fce,"DATA");
$field_row = saprfc_table_rows ($this->fce,"FIELDS");
ECHO "<BR>";
ECHO "Table: " . $Table;
ECHO "<BR><BR>";
ECHO "<TR>";
for($i=1; $i<=$field_row ; $i++)
{
$FIELDS = saprfc_table_read ($this->fce,"FIELDS",$i);
ECHO "<TD BGCOLOR='#4D80F6'>";
ECHO $FIELDS['FIELDNAME'];
ECHO "</TD>";
}
ECHO "</TR>";
533
for($j=0; $j<$field_row; $j++)
{
ECHO "<TD>";
ECHO $TEST[$j];
ECHO "</TD>";
}
ECHO "</TR>";
}
ECHO "</TABLE>";
ECHO "<CENTER>";
PRINT("<FORM ACTION='index.php' METHOD='POST'>");
PRINT("<INPUT TYPE='HIDDEN' NAME='LOG_IN'><BR>");
PRINT("<INPUT TYPE='SUBMIT' value='Back' NAME='Back'>&nbs
p; ");
PRINT("</FORM>");
ECHO "</CENTER>";
}
}
?>
$fce = saprfc_function_discover($rfc,”RFC_READ_TABLE”);
534
Verificamos que el módulo de funciones exista.
saprfc_import($fce,”QUERY_TABLE”,$Table);
saprfc_table_init($fce,”OPTIONS”);
$rc = saprfc_call_and_recieve($fce);
$data_row = saprfc_table_rows($fce,”DATA”);
$DATA = saprfc_table_read($fce,”DATA”,$i);
echo($DATA[WA].”\n”);
535
saprfc_function_free($fce);
saprfc_close($fce);
<?php
session_start();
include("Login_Class.php");
?>
<html>
<head>
<title>SE16 Simulation</title>
<style>
body {background: #F5F9FF;text-align: center;}
#login {background: #E5EAF6;border: 1px solid
#C7D3EA;}
</style>
</head>
<body>
<?php
if(isset($_POST['LOG_IN']) || (isset($_POST['Table'])))
536
{
if(!isset($_SESSION["Server"]))
{
$_SESSION["Server"] = $_POST["Server"];
$_SESSION["Sysnum"] = $_POST["Sysnum"];
$_SESSION["Client"] = $_POST["Client"];
$_SESSION["User"] = $_POST["User"];
$_SESSION["Pass"] = $_POST["Pass"];
}
ECHO "<CENTER>";
PRINT("<FORM ACTION='Operation.php' METHOD='POST'>");
PRINT("<INPUT TYPE='TEXT' NAME='Table'><BR>");
PRINT("<INPUT TYPE='SUBMIT' value='Show Table'
NAME='Show_Table'> ");
PRINT("</FORM>");
ECHO "<A HREF='index.php'>Log Out</A>";
ECHO "</CENTER>";
}
else
{
$_SESSION = array();
session_destroy();
537
$Login = new Login();
$Login->Login_Page();
}
?>
</body>
</html>
<?php
session_start();
include("Login_Class.php");
include("SE16.php");
?>
<html>
<head>
<title>SE16 Simulation</title>
<style>
body {background: #F5F9FF;text-align: left;}
#login {background: #E5EAF6;border: 1px solid
#C7D3EA;}
</style>
</head>
<body>
538
<?php
if(isset($_POST['Table']))
{
$Table = $_POST['Table'];
$SE16->Show_Table($Table,$RFC_Me);
}
?>
</body>
</html>
539
540
Integración Ruby-NetWeaver
Introducción
541
Instalando el SAP::Rfc
542
require 'rubygems'
gem 'saprfc'
require "SAP/Rfc"
543
$Table = gets
print "\n"
itab.query_table.value = $Table.chop!
itab.delimiter.value = "|"
$Fields = Array.new
$Data = Array.new
$Data_Fields = Array.new
$Data_Split = Array.new
for i in 0...$Data_Len
$Data_Fields = $Data[i]
$Data_Split = $Data_Fields.split("|")
for i in 1...$Fields_Len
print $Data_Split[i].to_s.strip, "|"
end
print "\n\n"
end
print "Exit"
544
Veamos un poco el código.
require ‘rubygems’
gem ‘saprfc’
require ‘SAP/Rfc’
itab = rfc.discover("RFC_READ_TABLE")
itab.query_table.value = $Table.chop!
itab.delimiter.value = "|"
545
Llenamos los parámetros del módulo de funciones.
rfc.call(itab)
for i in 0...$Data_Len
$Data_Fields = $Data[i]
$Data_Split = $Data_Fields.split("|")
for i in 1...$Fields_Len
print $Data_Split[i].to_s.strip, "|"
end
print "\n\n"
end
546
547
Donde conseguir el SAP NetWeaver Sneak
Preview
548
Bibliografía y agradecimientos
549
• Al SDN (SAP Developer Network) por haberme eligido
como Mentor de SAP.
• A Mark Finnern por la confianza en mi que siempre ha
demostrado.
• A Marilyn Pratt por haberme demostrado que “Las abuelitas
también pueden rockear”.
550
Enlaces Web
Para terminar, quiero agregar algunos enlaces web que pienso que
pueden ser bastante útiles.
551