Documentos de Académico
Documentos de Profesional
Documentos de Cultura
!1
!2
http://www.aprendeabap.com
Facebook: /AprendeAbap
Twitter: @AprendeABAP
Youtube: /AprendeABAP
!3
Agradecimientos.
!4
Introducción.
Más que darte las gracias por haber confiado tus datos, permíteme felicitarte ya
que no todas las personas, a pesar de la necesidad, son capaces de tomar las
oportunidades que se le presentan en el camino.
Si echas una mirada al mundo, notarás que no estamos pasando por momentos
felices a nivel laboral, quizá tú estés aquí por que fuiste afectado de alguna
manera, o quizá quieras evitar que “llegue la ola” y te lleve.
Este es el comienzo de lo que espero sea un largo camino, hoy comienzas con el
objetivo de aprender ABAP, el lenguaje de programación de SAP. Con este libro
darás tus primeros pasos en ABAP, pasarás de no saber nada a estar en la capacidad
de atender los requerimientos más comunes que hay en pocos días.
Esta es una carrera de fondo, en la cual debes ir superando etapas, solo así podrás
labrarte una carrera exitosa dentro de la Consultoría SAP. Como agradecimiento
por haber adquirido este libro, te quiero obsequiar un mini curso, en el cual
aprenderás cuales son los 7 Pasos que hay que cubrir para convertirte en un
Consultor de Éxito.
http://aprendeabap.com/regalo
!5
El núcleo (kernel) de SAP está escrito en lenguaje C, incluido el propio ABAP; todas
las capas superiores, es decir, los diferentes módulos del sistema, si están escritos
en lenguaje ABAP.
!6
!7
Declaración de Campos
Ejemplo:
DATA var.
Esta sentencia, (ejemplo de arriba), crea una variable llamada <var> del tipo C
tamaño 1, que es la definición por defecto.
NOTA: Todas las líneas de instrucciones que escribimos en ABAP deben estar
terminadas en un punto ‘.’; de lo contrario, el programa producirá errores de
sintaxis.
!8
DATA var(4).
Ahora, si lo que queremos es declarar una variable que no sea tipo C, por ejemplo,
queremos declarar una variable tipo entero, utilizaremos la sentencia TYPE para
indicar el tipo de dato que queremos:
Con el parámetro LIKE podemos declarar una variable con los mismos atributos de
longitud y tipo que una variable de base de datos:
Esta instrucción declara una variable tipo entero con valor inicial de 1.
La segunda opción es escribiendo la sentencia DATA una sola vez seguida de dos
puntos (: ) y terminando cada línea con coma ( , ) en vez de punto, colocando el
punto al final de la última línea de declaración; veamos el ejemplo anterior escrito
bajo esta forma:
!9
También podemos crear una Estructura de Datos, esto es, un conjunto de datos
relacionados lógicamente en una estructura. Luego de la sentencia DATA;
utilizamos las sentencias BEGIN OF y END OF para determinar el inicio y final de la
estructura. Ejemplo:
<nombre_estructura> - <campo_estructura>.
Ejemplos:
nombre_estructura-var1.
nombre_estructura-var2.
Tablas Internas.
El tema de las Tablas Internas se tocará a fondo en un capítulo posterior, por ahora
quédate con que, en ABAP existe una variante de las Tablas Tradicionales de Bases
de Datos (BD), que son llamadas las “Tablas Internas”; éstas, a diferencia de las
Tablas de BD, se guardarán en memoria y solo serán accesibles desde el Programa
que las creó, y no son Tablas guardadas en la BD general consumiendo recursos del
sistema.
En SAP, las Tablas “normales” se les conoce como Tablas Transparentes, mientras
que a estas secciones de memoria que permiten almacenar una serie de registros
dentro de un programa, con una estructura de datos determinada, se les conoce
como Tablas Internas.
Quédate con esto por ahora y si no se entendió muy bien, no te preocupes que le
dedicaremos un capítulo entero a esto más adelante.
Las Tablas en SAP, tanto las internas como las transparentes, están formadas por
Estructuras de Datos, por lo que hay dos maneras de declarar una Tabla Interna en
un programa ABAP:
!10
END OF itab.
Las dos sentencias crean una Tabla Interna llamada ITAB, con 3 campos (nombre,
ciudad y ventas), la diferencia es que la primera Tabla tiene un espacio reservado
de 100 líneas en memoria principal.
Esto no significa que el tamaño máximo de la Tabla sea el indicado, ya que si este
se desborda los datos se guardan en un fichero de paginación, bajando lógicamente
el tiempo de proceso de las Tablas Internas, pero evitando que el área global de
almacenamiento destinado por SAP para tablas internas se agote.
También podemos utilizar la misma Estructura que una Tabla de Base de Datos.
Para ello utilizaremos la instrucción INCLUDE STRUCTURE.
!11
Todas ellas empiezan por el prefijo SY- y entre las más utilizadas tenemos
Asignando valores
<var2> = <var1>.
Ejemplos:
!12
Si deseamos, por algún motivo, inicializar las variables que estamos utilizando,
(borrarles el valor que tienen y dejarlas en blanco), aplicaríamos la sentencia
CLEAR como se muestra en el ejemplo:
CLEAR var.
CLEAR inicializa al valor que tiene asignado como valor inicial (ver Tabla 1) sin
tener en cuenta las cláusulas VALUE que existan para esa variable.
Con respecto a las Tablas Internas, hay una diferencia, la instrucción CLEAR solo
inicializa la línea de cabecera (más adelante se verá que es esto); para inicializar
una Tabla Interna completa requerimos la sentencia REFRESH.
REFRESH itab.
Existen otras consideraciones para las Tablas Internas, pero las abordaremos más
adelante.
Esta instrucción mueve de <var1> a <var2> aquellos campos que tengan idéntico
nombre.
!13
Ambas instrucciones suma las variables <var2> con <var3> y guarda el resultado
en <var1>.
!14
Esta instrucción borra todos los blancos que se encuentren comenzando la cadena
por la izquierda y en caso de encontrar series de blancos intermedios dejará
únicamente uno por serie.
!15
• Dominio.
• Elemento de Datos.
• Campo.
• Estructura de Datos.
• Tablas.
!16
!17
NOTA: Desde el editor de un programa ABAP, podemos declarar una variable que
haga referencia a un Elemento de Datos; de esta forma, la variable tomará el tipo
de datos del dominio asociado a dicho Elemento de Datos. Siguiendo con el
ejemplo:
DATA: var TYPE S_PLANETYE.
DATA: var TYPE S_PLANETYE.
DATA: var TYPE char10.
!18
DATA: BEGIN OF nombre_estructura,
var1 TYPE i,
var2 TYPE i,
END OF nombre_estructura.
!19
En el capítulo de los Tipos de Datos, pudimos ver cómo se pueden crear Estructuras
de Datos directamente desde el editor ABAP.
DATA: BEGIN OF nombre_estructura,
var1 TYPE i,
var2 TYPE i,
END OF nombre_estructura.
!20
DATA BEGIN OF sociedad.
INCLUDE STRUCTURE SYST.
DATA END OF sociedad.
DATA: itab TYPE TABLE OF SYST.
!21
Tipos de tablas.
• Tablas POOL: Tablas SAP que se guardan junto a otras tablas SAP en una
única tabla física de Base de Datos. Mejorando el acceso a los registros.
Las que usaremos cada día serán las Tablas Transparentes, que es el nombre que le
da SAP a las Tablas de Base de Datos relacionales. De hecho, los dos términos más
comunes utilizados en el día a día de un Consultor ABAP son “Tablas Transparentes”
y “Tablas Internas”; ya comprendimos que las primeras son las Tablas del
Diccionario de Datos, y las segundas son espacios de memoria que se utilizan
dentro de un Programa, cuya existencia es únicamente en tiempo de ejecución del
Programa en cuestión.
• Datos del sistema o de control: Muchas Tablas con pocos datos. Se suelen
guardar en Tablas de tipo POOL.
!22
• SELECT - Lectura.
• INSERT - Insertar.
• UPDATE - Actualizar.
• MODIFY - Modificar.
• DELETE - Eliminar.
• COMMIT WORK - Asentar cambios.
• ROLLBACK WORK - Revertir cambios.
!23
Ejemplo:
SELECT *
FROM mara
WHERE matnr = itab-matnr.
WRITE: mara-matnr.
ENDSELECT.
!24
Otras lecturas:
Podemos leer una Tabla de Base de Datos y simultáneamente llenar una Tabla
Interna con el resultado de la lectura.
Esta instrucción lee la Base de Datos, obtiene todos los registros que cumplan con
la condición, y los almacena en una Tabla Interna llamada <itab>.
A diferencia del ciclo SELECT – ENDSELECT, en el que por cada acierto se procede a
leer en la Base de Datos; aquí se realiza un único acceso a las Tablas para extraer
todos los registros que cumplan con la condición.
Si bien ambas opciones cumplen con el mismo resultado, por temas de rendimiento
recomiendo utilizar esta última ya que se consumen menos recursos con un único
acceso a BD, para obtener todas las coincidencias en una Tabla Interna, y luego
procesar esos resultados desde la Tabla Interna, que como ya sabemos, es un
objeto propio del Programa en ejecución.
SELECT *
INTO TABLE itab
FROM mara
WHERE matnr = itab-matnr.
LOOP AT itab.
WRITE: itab-matnr.
ENDLOOP.
!25
INSERT <tab>.
Si existe algún registro en la BD (Base de Datos) con clave igual a algún registro de
la Tabla Interna, se producirá un error de ejecución del programa. (Por registro
duplicado).
UPDATE <tab>.
Con este UPDATE, todos los registros que cumplan <cond> modificarán el contenido
del <campo> por <valor>.
!26
MODIFY <tab>.
DELETE FROM <tab> WHERE <cond>. Para borrar más de un registro (todos
los que cumplan la condición <cond>).
!27
Debemos evitar el uso de las instrucciones INSERT, DELETE, MODIFY y UPDATE sobre
las Tablas de Datos Maestros del Diccionario; si requerimos hacer un cambio a nivel
de datos, éstos se harán vía Transacciones estándar, Módulos de Funciones (BAPI) o
Bath Input; ya que los datos que se guardan en una transacción suelen estar
replicados en diferentes Tablas (Modelo de BD Relacional), y si modificamos el
contenido de una Tabla en particular, podríamos generar inconsistencias
importantes en el sistema.
Si deseamos deshacer los cambios hechos luego del último COMMIT WORK,
utilizaremos la sentencia ROLLBACK WORK, esta sentencia nos reversa los cambios
hasta el estado en que se encontraban tras el último COMMIT WORK ejecutado.
Chequeo de autorizaciones.
Todas las consultas SQL en SAP no realizan verificación alguna sobre autorizaciones
de usuarios, siendo esto algo que debemos controlar para evitar que todos los
usuarios puedan acceder a determinado tipo de información.
!28
AUTHORITY-CHECK.
ID <Campo3> DUMMY.
...
<CampoX> son los campos de autorización del objeto. (se le indica sobre que
campos del sistema se va a evaluar la autorización).
<fX> son los valores posibles de autorización de dichos campos. (leer, modificar,
ambos, ninguno).
!29
!30
Estas Tablas Internas se crean dentro de cada Programa, por lo tanto, su vida útil
se limita al tiempo de ejecución de nuestros Programas, sus datos se pierden
cuando abandonamos dicho Programa/Transacción.
Las Estructuras de Datos que sirven de base para la construcción de las Tablas
Internas, bien pueden ser creadas internamente en el programa (Transacción SE38
o SE80), o formar parte del Diccionario de Datos del sistema; la ventaja de que las
Estructuras de Datos se creen en el Diccionario (SE11), es que la misma Estructura
nos podría ser útil en varios Programas diferentes.
¿Qué son?
Las Tablas Internas son, como su nombre lo indica, Tablas; pero se diferencian de
las Tablas del Diccionario de Datos en que éstas solo están disponibles DENTRO de
un Programa.
END OF <itab>.
!31
<campo> es el nombre del campo (columna) de la Tabla Interna, y este campo será
de tipo <tipo_campo> (entero, string, igual a algún campo del Diccionario; etc. -
ver Día 2-).
END OF <estructura>.
La cabecera es un único registro que se utiliza para añadir y recoger datos del
cuerpo de la Tabla Interna.
Debemos declarar una línea de cabecera, para leer cada registro de la Tabla, o
bien declarar la Tabla misma con línea de cabecera.
Con cabecera:
!32
Sin cabecera:
Ejemplo:
LOOP AT <itab>.
WRITE: <itab>-<campo1>.
ENDLOOP.
Con la segunda instrucción, cada registro que se lea de <itab> deberá tratarse
desde <line>, que es la línea de cabecera de la Tabla Interna.
Ejemplo:
WRITE: <line>-<campo1>.
ENDLOOP.
Work Area
Si queremos disponer de una variable que nos sirva para manipular los datos de una
<itab>, con su misma Estructura, están los que se conocen como “work area” o
“área de trabajo”.
Son Estructuras con la misma forma que un registro de una Tabla Interna, similar a
sus líneas de cabecera, y se declaran de la siguiente manera:
Esto nos creará un work area llamado <wa> del mismo tipo que la línea de
cabecera <itab>.
!33
Para ingresar datos a una Tabla Interna, tenemos las siguientes sentencias:
APPEND: Añade un registro a una Tabla Interna con los valores que tengamos en
dicho registro.
Ejemplos:
Ejemplos:
READ TABLE <itab> INTO <line> WITH KEY <condicion> (sin cabecera).
READ TABLE <itab> INDEX <n>. (Esta instrucción lee el registro ubicado en
la línea <n>).
Ejemplos:
Ejemplos:
!34
Ejemplos:
COLLECT: Añade o suma la línea de cabecera. Sumará los campos tipo P, F, I (ver
día 2), si existe una línea en la Tabla con campos idénticos (tipo C) a los del work
area.
Pero cuidado con su uso, ya que se trata de una instrucción que consume mucho en
memoria.
Para ordenar los registros de una Tabla Interna, utilizamos la instrucción SORT
(ordenar en Inglés), y le indicamos por cuales campos debe ordenar, (si se le
indican varios campos, el lenguaje le da prioridad de izquierda a derecha), luego
podremos indicarle si queremos que se ordenen de manera ascendente o
descendente. (Por defecto siempre será ascendente).
Ejemplo:
Para recorrer los registros de una Tabla Interna, utilizaremos la instrucción LOOP.
. . .
!35
. . .
Con la cláusula WHERE podemos filtrar los registros que leeremos en el LOOP, tal
cual como lo haríamos en una consulta SQL.
Mientras haya iteraciones dentro de un LOOP, con la variable del sistema SY-TABIX
podremos saber cuál es el índice del registro que se procesa en un momento dado.
Existen algunas sentencias para registros puntuales de una Tabla Interna dentro del
LOOP.
...
ENDAT.
!36
!37
Transacciones:
!38
SE38
Para efectos de este libro, solo nos interesan los siguientes campos:
!39
!40
!41
!42
SE80
Desde esta Transacción, tendremos el control de todos los objetos del Repositorio
de Objetos del sistema.
!43
Los tipos de palabras claves que se utilizan para darle inicio a una instrucción
pueden ser los siguientes:
• Declarativas.
• Eventos.
• Control.
• Operativas.
Las Declarativas nos permiten, como su nombre lo indica, declarar las variables
que vamos a utilizar a lo largo del Programa.
Las sentencias de Control nos permite inducir el flujo del Programa que estamos
creando, ejemplo de estos son las sentencias condicionales como IF, WHILE,
CASE.
!44
Veamos un ejemplo:
WRITE <campo1>.
WRITE <campo2>.
WRITE <campo3>.
WRITE: <campo1>,
<campo2>,
<campo3>.
El punto nos indicará el final de la sentencia; ésta también puede ser escrita en
una única línea:
Nótese los dos puntos que siguen a la instrucción WRITE, éstos le indican
a ABAP que la instrucción actuará sobre más de una variable.
DATA <campo1>.
DATA <campo2>.
DATA <campo3>.
DATA: <campo1>,
<campo2>,
<campo3>.
!45
Comentarios
Si queremos comentar toda una línea, colocamos un asterisco (*) como primer
carácter de dicha línea; por su parte, si solo queremos dejar un comentario al
final de una línea, éste debe comenzar en comillas (“).
Ejemplo:
*Comentario completo.
WRITE <campo1>. “comentario al final
Objetos de Datos
Literales.
Campos del Diccionario
Variables internas.
Los campos del Diccionario los declaramos con la sentencia TABLES; lo que se
busca es utilizar las propiedades de las Tablas del Diccionario para utilizarlas en
un Programa. Ejemplo:
!46
TABLES: KNA1.
(declaración de una Tabla Interna con la misma Estructura que la Tabla del
Diccionario KNA1).
NOTA: Estos no son los campos de la Tabla propiamente dicho, son variables con
su misma Estructura, tampoco se trata de una Tabla, sino de su línea de
cabecera, no contienen los registros de la Tabla a menos que los obtengamos en
una sentencia SQL.
Ejemplo:
En tercera instancia están las variables internas del Programa, estas se crean
con la sentencia DATA, y pierden su vigencia al terminarse la ejecución del
mismo; las Tablas Internas están incluidas aquí.
Ejemplo:
!47
IF <cond>.
. . A. .
ELSE.
. . B. .
ENDIF.
!48
Si tenemos que validar una serie de condicionales, existe una instrucción que
podemos utilizar en lugar de anidar varios IF-ELSE-ENDIF.
CASE <campo>.
WHEN <valor1>.
WHEN <valor2>.
ENDCASE.
Un ejemplo para entenderlo:
!49
IF <var1> EQ ‘2’.
#imprimirA.
ELSEIF <var1> EQ ‘4’.
#imprimirB.
ELSE.
#imprimirC.
ENDIF.
Podría reescribirse de la siguiente manera:
CASE <var1>.
WHEN ‘2’. #imprimirA.
WHEN ‘4’. #imprimirB.
WHEN OTHERS. #imprimirC.
ENDCASE.
Bucles o Ciclos.
DO <n> TIMES.
....
ENDDO.
!50
WHILE <cond>.
....
ENDWHILE.
!51
PARAMETERS
Dentro del Programa, podremos utilizar estas variables por el nombre que
le asignamos al momento de su declaración, <var1> y <var2>.
!52
RADIOBUTTONS
Como puedes observar, para que solo se permita seleccionar una de las
variables, las mismas deben pertenecer a un mismo grupo, esto lo controlamos
en su declaración al asignarles el grupo R1; si deseamos construir otro conjunto
de variables, de manera que el usuario seleccione una variable adicional a la
seleccionada en este grupo R1, simplemente lo que tenemos que hacer es
declarar las nuevas variables pertenecientes a otro grupo, por ejemplo, R2.
!53
CHECKBOX
<var2> AS CHECKBOX,
<var3> AS CHECKBOX.
SELECTION-SCREEN
!54
!
La ventana de arriba la logramos con el siguiente código:
Podemos darle un título descriptivo a la caja que acabamos de crear, para ello,
hacemos doble clic a la sentencia “text-002”, y aceptamos crear un nuevo
Elemento de Texto.
!55
Activamos y ya lo tenemos.
Ahora, si observamos las pestañas que nos muestran, hay una llamada “textos de
selección”, al entrar en ella, veremos todos los parámetros de entrada que
tenemos declarados en nuestro programa.
!56
SELECT-OPTIONS
La sentencia PARAMETERS nos permite solicitar por pantalla un único valor para
cada variable de entrada declarada, pero en muchos casos nos interesa poder
recibir por parámetro un rango de valores, por ejemplo, un conjunto de
clientes o un rango de fechas.
Esta sentencia responde con un Tipo de Datos que previamente debió haber sido
creado, por lo que antes de declarar un parámetro de entrada con ella, debemos
declarar el Tipo de Datos a utilizar; por ejemplo, si deseamos solicitar un rango
de fechas, se haría de la siguiente manera:
!57
Podremos también con el cuadro de la izquierda (columna P), indicar filtros del
tipo IGUAL QUE,MAYOR QUE, MAYOR IGUAL, etc.
!58
Sin duda que este tipo de parámetro nos permite una mayor cantidad de
opciones para seleccionar.
Para empezar, la variable <var1> creada es una Tabla Interna que guarda
información del rango de valores indicado, así como el operador de comparación:
!59
SING: I de In (dentro del rango); O de Out (fuera del rango); para indicar
que representa el rango indicado con respecto a los valores buscados.
Sustituiremos el “=” por el signo “IN”; para hacer referencia a que buscaremos
los valores bajo el criterio comprendido dentro (IN) del rango indicado.
!60
Para cerrar con este tema; lo haremos de una forma gráfica, para obtener la
siguiente Pantalla de Selección:
!61
!62
Para evitar tener que escribir el código varias veces en estos casos, existen los
Módulos y Sub Rutinas, trozos de código que cumplen alguna función, que se
ejecutan en un lugar apartado de nuestra secuencia de instrucciones principal, en
la que solo tenemos que invocarlas, y recibir su resultado.
Las Sub Rutinas forman parte de la Programación Modular, esto es, ejecutar cierta
porción de código en un lugar externo con respecto al flujo de sentencias
principal.
CASE <función>.
!63
ENDCASE.
Operaciones como la 'RAIZ', requiere repetir las mismas instrucciones que la
'DIVISION'; mientras que la 'POTENCIACION' utiliza instrucciones aplicadas a la
'MULTIPLICACION'; por lo que, si escribimos el código de forma lineal, estaríamos
repitiendo código, haciendo menos legible el código que creamos.
Para ello existe la Modularización, que nos permite estructurar el flujo del
Programa en Rutinas Externas para un mejor performance y entendimiento.
CASE <función>.
ENDCASE.
RUTINA 'SUMA'.
...
FINRUTINA.
RUTINA 'MULTIPLICACION'.
....
FINRUTINA.
RUTINA 'DIVISION'.
...
FINRUTINA.
!64
RUTINA 'RAIZ'.
...
Llamado a rutina 'DIVISION'.
...
FINRUTINA.
RUTINA 'POTENCIACION'.
...
Llamado a rutina 'MULTIPLICACION'.
...
FINRUTINA.
• Internas: El código de la Sub Rutina está dentro del Programa que la llama.
Las Sub Rutinas se codifican al final del Programa principal, tras todos los eventos.
No se pueden anidar. Se puede salir de una Sub Rutina con un EXIT (salida
incondicional) o un CHECK (salida condicional), si estas sentencias no están dentro
de un bucle.
Sólo dentro de una Sub Rutina se puede usarse la sentencia LOCAL <campo>, para
declarar variables locales a la Sub Rutina (sólo visibles dentro de ella). Deja oculto
!65
el valor de ese campo que tuviera antes de entrar a la Sub Rutina, y lo restaura al
salir de ésta.
Las instrucciones para llamados y declaración de Sub Rutinas son las siguientes:
FORM <modulo>
.... __Subprograma.
ENDFORM.
Los parámetros pueden ser pasados por valor o por referencia. Por defecto serán
por referencia.
Con la instrucción CHANGING, estamos permitiendo que los campos pasados como
parámetros puedan haber cambiado su valor al regresar de la Sub Rutina.
!66
Tanto las variables definidas al inicio del Programa como las Tablas son globales a
todas las Sub Rutinas y por tanto accesibles en cualquier momento, por lo que
dichas variables declaradas al comienzo no requieren ser pasadas explícitamente
en los llamados a Módulos o Sub Rutinas.
Si encontramos alguna instrucción del tipo CHECK o EXIT que signifique salir de un
cierto FORM, previamente ejecutará el ENDFORM y por tanto se pasarán los
parámetros que tenga el procedimiento.
En este caso sólo se pueden hacer operaciones con filas enteras, pero no nos
podremos referenciar sobre campos concretos de la Tabla o hacer COLLECTS
(totalizaciones), ya que no se conocerá la Estructura de la Tabla.
Dentro de cada Sub Rutina es posible declarar datos con la sentencia DATA, que
sólo serán visibles dentro del Módulo donde esté declarado. ABAP/4 creará un
espacio para esas variables que será liberado al salir del Módulo. Por tanto se
!67
podrán utilizar variables con el mismo nombre que variables globales, aunque el
valor que tengan será siempre el local en el Módulo o Sub Rutina.
NOTA: Las Tablas de Base de Datos son globales a todo el Programa, si se quiere
utilizar una Tabla localmente en una Sub Rutina, se debe declarar con LOCAL, al
inicio de la misma, en vez de con TABLES.
LOCAL <tabla>.
Módulos de Funciones.
Esta es la vía para el manejo de Sub Rutinas en un Programa ABAP; como vimos al
comienzo de este capítulo, existe una tercera vía para la comunicación modular de
parámetros, llamados "Módulos de Funciones", de ellos hablaremos en el siguiente
capítulo.
!68
Los Módulos de Función son Módulos especiales guardados en una librería central, y
agrupados por la Función que realizan. Principalmente se caracterizan por una
interface definida y porque realizan tratamiento de excepciones.
...
IMPORTING <parámetros_salida>=<valor_salida>
...
TABLES <tablas_entrada>=<tablas_internas>
...
EXCEPTIONS <excepciones>=<valor>
...
!69
Gestión de Excepciones
MESSAGE...RAISING <excepción>.
RAISE <excepción>.
!70
Para poder visualizarlo hay que acceder a los campos del sistema de la Tabla SYST,
donde se almacena el texto del mensaje, número,... pero desde el Programa
principal.
!71
!72
Veamos antes de continuar una breve descripción de cada objeto aquí encontrado:
Datos globales: Código ABAP con las sentencias declarativas del Grupo de Función.
!73
Pocas cosas debemos modificar aquí, salvo la forma en que se ejecutará dicha
Función, lo normal es dejarlo todo como está, es decir, con los checks tildados de
"Módulo de Funciones normal" y de "Inicio inmediato".
Interesante saber aquí, que si lo que nos piden es diseñar una Función que haga las
veces de interfaz entre un sistema externo y SAP, el check que debemos tildar es el
que dice "Módulo de acceso remoto", con esto será suficiente para que
desde fuera puedan comunicarse con nuestra función.
!74
!75
Nos falta declarar la excepción que manejará nuestra Función, habíamos definido
lo siguiente: Declararemos una excepción llamada BY_CERO, al cual le asignaremos
el valor de 1 cuando se produzca un intento de división por cero.
!76
1. Declararemos una variable local llamada VAR que contendrá el resultado parcial
de las operaciones a realizar.
!77
Recuerda que la instrucción RAISE activa la excepción, esto hará que si se produce
un intento de división por cero, la función devolverá, en lugar de resultado de la
operación en el campo RESUL, un código SY-SUBRC diferente de cero en el campo
de excepción BY_CERO. Este valor retornable se puede definir en el llamado a la
función, ahora veremos cómo.
!78
Obtendremos el resultado de la Función, el cual nos indica que la suma dio como
resultado 31.75:
!79
Ahora vamos a probar una división por cero, para evaluar si la Función captura la
excepción de manera correcta:
!80
Vemos que el campo RESUL no tiene valor, y en la parte posterior, el test nos indica
que se produjo la excepción BY_CERO, garantizándonos así que la Función
procesa la información de forma correcta.
Programa de Control
!81
!82
!83
!84
!85
!86
!87
!88
Ahora configuraremos la salida del resultado por pantalla, para ello nos
adelantaremos un poco en materia y crearemos un sencillo informe con la
instrucción WRITE, (esto lo veremos en detalle en el siguiente capítulo).
!89
Listo!
Ya tenemos todo el trabajo hecho, ahora vamos a probar nuestro programa con las
mismas dos pruebas que utilizamos directamente en la Función.
!90
Ahora vamos a probar una división por cero, para evaluar si la Función captura la
excepción de manera correcta:
Espero te haya sido útil esta sección práctica, ahora te invito a que practiques tú
mismo para que poco a poco vayas familiarizándote con el sistema.
!91
Muchas veces el formato final del Reporte lo podrás decidir tu, y en otras, tendrás
que adaptarte a lo requerido.
Para este tipo de Reportes, existen una serie de sentencias que nos permitirán
construir nuestro Reporte "a mano", es decir, paso por paso, línea por línea.
Todo empieza por la sentencia WRITE, con ella podremos visualizar una variable
por pantalla, su estructura es la siguiente:
Ejemplo:
Con la sentencia ULINE, podremos imprimir una línea horizontal, ideal para la
construcción de tablas en un Reporte; esta sentencia cuenta con las mismas
!92
Para saltar una o varias líneas en la impresión, contamos con la sentencia SKIP,
que por defecto, responde al salto de una única línea, a menos que se le indique
explícitamente cuantas líneas de salto se quieren con la siguiente instrucción:
Si el salto que queremos dar, es hacia la siguiente página, la instrucción que nos
sería de utilidad sería NEW-PAGE.
!93
Dejamos atrás el WRITE para entrar en otros aspectos, como añadirle colores o
estilos a ciertas variables para diferenciarlas de otras, como por ejemplo, la
cabecera de una tabla.
FORMAT RESET.
Con estas instrucciones, podemos jugar con el look y el diseño de nuestro Reporte.
Debes saber que éste último no se ejecutará si el salto de página se produce con
un NEWPAGE.
!94
Esta instrucción se debe colocar justo antes del WRITE sobre el que se quiere
"reservar" ese bloque de líneas; de no haber espacio suficiente para imprimir estas
líneas, éstas se imprimirán en la siguiente página.
Elementos de Texto.
Títulos y Cabeceras: para tratar el título y cabeceras del Reporte y las cabeceras
de columna que saldrán por pantalla e impresora.
Textos de Selección: para tratar las descripciones que acompañan a los parámetros
de entrada del tipo PARAMETERS o SELECT-OPTIONS.
Mensajes de Diálogo.
Son aquellos mensajes que aparecen en la línea de mensajes y que son manejables
desde un Programa. Estos mensajes están agrupados en áreas de mensajes. Para
indicar que área vamos a usar en un Reporte, utilizamos MESSAGE-ID en la
instrucción REPORT.
!95
Donde "nnn" es el número del mensaje dentro de su respectiva área y "T" es el tipo
de mensaje.
Los diferentes tipos de mensajes que permite el sistema son los siguientes:
!96
********************************************************************************
REPORT zrr.
START-OF-SELECTION.
SELECT *
FROM mara
END-OF-SELECTION.
* Data output
PERFORM data_output.
TOP-OF-PAGE.
NEW-LINE.
WRITE: / sy-uline.
!97
WRITE: sy-vline,
AT (15) 'Fecha',
AT (1) sy-vline,
WRITE: / sy-uline.
FORM data_output.
NEW-LINE.
WRITE: sy-vline.
AT END OF matnr.
ULINE.
ENDAT.
ENDLOOP.
********************************************************************************
!98
Reportes ALV
Incluir en el Programa la librería SLIS, que tiene definidas todas las Estructuras de
los parámetros de entrada y de salida de esta Función.
!99
Pasarle los datos que deben ser mostrados en el reporte a la Función utilizando
Tablas Internas.
En el momento que llamamos a una de las Funciones ALV para que imprima el
Reporte, perdemos el control del Programa. Esto es, cualquier Evento del Programa
como ‘Nueva página’, ‘Top of page’, ‘End of page’, etc. será controlado e
implementado por la Función, a no ser que le indiquemos qué Eventos queremos
que sean implementadas en el Programa.
Cada tipo de ALV cuenta con diferentes parámetros de entrada opcionales, pero
estos 3 son obligatorios en todos los casos.
• ALV List: permite simular el trazado de un reporte WRITE, pero con las
funcionalidades y bondades de un ALV.
• ALV Grid: Permite generar una Tabla gráfica, totalmente editable desde su
presentación (añadir y quitar columnas, agrupar y ordenar, totalizar
valores, entre otras).
Cada uno de ellos tiene su propio Módulo de Funciones con sus respectivas
Estructuras, veamos un poco como se construyen cada uno.
!100
ALV LIST
i_callback_program = g_repid
i_structure_name = gc_structure
it_fieldcat = gt_fieldcat_list
i_save = gc_save
is_layout = gs_layout
is_variant = gs_variant
is_print = gs_print
TABLES
t_outtab = gt_output_value
EXCEPTIONS
program_error =1
OTHERS = 2.
!101
La siguiente imagen es una muestra de los resultados que obtendremos para este
tipo de ALV
!102
ALV GRID
i_callback_program = v_repid
I_BACKGROUND_ID = 'ALV_BACKGROUND'
i_callback_top_of_page = l_form_cabecera
i_save = 'A'
it_fieldcat = gt_fieldcat
is_variant = variante
TABLES
t_outtab = p_output.
!103
ALV JERÁRQUICO
Este tipo de ALV consiste en anidar dos tablas (una con la estructura de cabecera y
otra con la estructura del detalle), que permite enlazar la información de ambas
tablas.
Es muy útil cuando se quiere un reporte que contenga doble cabecera; la función
necesitará recibir la información en dos Tablas Internas separadas.
i_callback_program = gv_repid
i_callback_pf_status_set = slis_ev_pf_status_set
i_callback_user_command = slis_ev_user_command
is_layout = gs_layout
it_fieldcat = gt_fieldcat
it_sort = gt_sortinfo
i_save = 'A'
!104
is_variant = gs_variant
it_events = gt_event
i_tabname_header = 'IT_HEADER'
i_tabname_item = 'ITAB'
is_keyinfo = gs_keyinfo
is_print = gs_print
TABLES
t_outtab_header = IT_HEADER
t_outtab_item = ITAB
EXCEPTIONS
program_error = 1
OTHERS = 2.
!105
IT_EVENTS: Se le indicará a la Función cuales serán los Eventos del sistema que
controlará.
IS_KEYINFO: Esta Tabla contendrá las conexiones de enlaces entre las dos Tablas,
como se puede deducir, ambas Tablas deberán contener el mismo campo con el
mismo nombre, para poder servir de enlace entre ambas.
!106
Ejemplo de ALV
Con esto ya tienes diversas vías para construir Reportes en un Programa Z, hemos
llegado al final, espero que puedas poner en práctica lo aprendido, y te invito a
formar parte de nuestra comunidad AprendeABAP.
!107
RECURSOS
RECOMENDADOS
!108
Pensando en estos dos grandes bloques, con las respectivas etapas que conforman
cada uno, contamos con una estrategia de contenidos dinámica, en la ofrecemos
contenidos gratuitos como contenidos Premium.
• Diccionario de Datos.
• Entorno de Programación.
• Reportes.
• Formularios.
• Módulos de Funciones.
• Ampliaciones.
• Module-Pool.
http://aprendeabap.com/club
!109
AprendeABAP. - Desarrollo de
Contenidos Etapa APRENDIZAJE
A lo largo del tiempo, me he encontrado mucha gente que quiere iniciarse en el
Mundo SAP, pero no tiene formación en informática, siendo esta la base para poder
triunfar dentro de este mundo. Incluso conozco muchos Consultores SAP
funcionales a quienes les gustaría aprender a debugar, pero no disponen de esta
base de programación necesaria para comprender los procesos, pensando
entonces, en aquellos que necesitan empezar de cero, aprendiendo las nociones de
lógica y de programación para ver cumplidos sus objetivos, hemos diseñado el
curso ¨Aprende a Programar¨.
http://aprendeabap.com/club/curso/aprende-programar/
Si ya cuentas con cierta experiencia dentro del sector, y buscas seguir creciendo
para cubrir el resto de las etapas del bloque de Aprendizaje, también contamos
con el ¨ClubABAP¨, el cual es un club privado en donde mensualmente nos
reuniremos para abordar temas concretos que nos permitan ir avanzando en las
diferentes etapas de tu carrera.
http://aprendeabap.com/club/clubabap/
Como puedes ver, todas las etapas del bloque de APRENDIZAJE están
estratégicamente cubiertas en AprendeABAP; por lo que no importa en que
momento de tu carrera hayas encontrado este sitio, bien seas estudiante de
Informática, un Consultor ABAP en sus primeros 4 años de carrera, o una persona
que busca reinventarse, en AprendeABAP encontrarás justo lo que se adapta al
momento en que te encuentres.
!110
• Entre otros.
http://aprendeabap.com/club/
!111
¿ Recuerdas los distintos programas detallados que cubren las dos grandes etapas ?
http://aprendeabap.com/club/courses/
http://aprendeabap.com/club/categoria-producto/servicios/
!112
!113
!114