Introducción
Aplicación de técnicas y conceptos básicos
Trabajar con clases locales
Lectura de datos de la base de datos
Trabajar con objetos de datos estructurados
Trabajar con tablas internas complejas
Implementación de actualizaciones de base de datos mediante business objects
Descripción del modelo de programación de aplicaciones ABAP RESTful

Uso de estructuras de control en ABAP

Objectives

After completing this lesson, you will be able to:
  • Implementar ramificación condicional.
  • Gestionar excepciones.
  • Implementar iteraciones.

Ramificaciones condicionales

Una ramificación condicional es una estructura de control que le permite hacer que la ejecución del código dependa de condiciones lógicas.

La ramificación condicional más común consiste en un par de palabras clave IF y ENDIF. El bloque de código entre IF y ENDIF solo se ejecuta si se cumple la condición después de IF.

Puede añadir más bloques de código ampliando la estructura IF … ENDIF con hasta una palabra clave ELSE y un número arbitrario de palabras clave ELSEIF. Al añadir la palabra clave ELSE se asegura de que siempre se ejecute exactamente uno de los bloques de código. Si falta ELSE, puede suceder que no se ejecute ninguno de los bloques de código.

El bloque de código a ejecutar se determina de la siguiente manera:

  • En primer lugar, se evalúa la condición IF. Si se cumple, se ejecuta el bloque de código relacionado y el programa continúa después de ENDIF.
  • Solo si no se cumple la condición IF, se evalúa la condición después de la primera ELSEIF. Si se cumple, se ejecuta el bloque de código relacionado y el programa continúa después de ENDIF.
  • Esto se realiza de forma consecutiva para todas las condiciones ELSEIF. Si no se cumple ninguna de las condiciones y la estructura contiene ELSE, se ejecuta el bloque de código después de ELSE. De lo contrario, no se ejecuta ninguno de los bloques de código.

Consejo

A diferencia de muchos otros lenguajes de programación, ABAP requiere un delimitador (.) después de cada una de las condiciones lógicas e incluso después de la palabra clave ELSE.

Las condiciones lógicas son una combinación de comparaciones, operaciones lógicas, expresiones y funciones que el sistema de tiempo de ejecución evalúa para decidir si la condición es verdadera o falsa.

El caso de uso más común para condiciones lógicas es después de las palabras clave IF o ELSEIF en un IF ... ENDIF. estructura.

El primer ejemplo es una comparación simple: La condición es verdadera si los dos objetos de datos x e y tienen el mismo valor.

El segundo ejemplo es un poco más sofisticado: el valor de x es mayor o igual que y y menor que dos veces el valor de y o es menor o igual a y y mayor que dos veces el valor de y.

El tercer ejemplo utiliza la función aritmética abs( ) y la expresión lógica BETWEEN <expresión1> AND <expresión2> . La condición es verdadera si el valor absoluto de x se encuentra entre el valor absoluto de y y el valor absoluto de dos veces y.

Para las comparaciones de valores simples puede utilizar los operadores =, <>, >, <, >= y <=. No solo puede comparar los valores de los objetos de datos, sino los valores de muchas otras expresiones, como la expresión aritmética 2 * y en el ejemplo.

Nota

ABAP utiliza el mismo símbolo (=) para valoraciones y para comparaciones de valores. La distinción se realiza en función de la posición.

Puede utilizar los operadores AND y OR para combinar expresiones lógicas y el operador NOT para negar una expresión. Sin paréntesis, NO se enlaza más fuerte que AND y AND más fuerte que OR.

ABAP conoce algunas expresiones lógicas especiales:

  • <objeto de datos> IS INITIAL es verdadero si <objeto de datos> contiene su valor inicial específico de tipo
  • <objeto de datos> NO ES INICIAL es verdadero si <objeto de datos> contiene un valor que es diferente del valor inicial específico de tipo
  • <objeto de datos> ENTRE <expresión1> Y <expresión2>

Algunas funciones ABAP especiales son funciones de predicado. Esto significa que son condiciones lógicas. Contiene( ) es una función que compara valores alfanuméricos y line_exist( ) realiza una verificación de existencia para una fila en una tabla interna.

Una segunda técnica para la ramificación condicional es el CASE … WHEN .. ENDCASE estructura de control.

Ramificación condicional con CASE .. ENDCASE es un caso especial de ramificación más general con IF … ENDIF. Puede utilizar CASE en situaciones en las que la ramificación depende del valor de un objeto de datos individual, que se compara consecutivamente con un conjunto de valores posibles, utilizando una comparación igual cada vez.

En el ejemplo, el valor del número de objeto de datos se compara con los valores 1 y 2. Si el valor es igual a 1, se ejecuta <code_block_1> y si el valor euqals 2, <code_blocl_2> se ejecuta en su lugar. Para cualquier otro valor, se ejecuta el bloque de código después de WHEN OTHERS.

Cualquier ramificación condicional con CASE … ENDCASE también se puede implementar con una estructura IF … ENDIF. Esto se ilustra con el ejemplo de la derecha.

Consejo

Debe utilizar CASE … ENDCASE al tratar el caso especial para aumentar la legibilidad de su código.

Pruébelo: Ramificaciones condicionales

  1. Como en el primer ejercicio de este curso, cree una nueva clase global que implemente la interfaz IF_OO_ADT_CLASSRUN.
  2. Copie el siguiente fragmento de código en la parte de implementación del método if_oo_adt_classrun~main( ):
    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
    * Declarations ********************************************************************** CONSTANTS c_number TYPE i VALUE 0. * CONSTANTS c_number TYPE i VALUE 1. * CONSTANTS c_number TYPE i VALUE 2. * CONSTANTS c_number TYPE i VALUE -1. * CONSTANTS c_number TYPE i VALUE -2. * Example 1: Simple IF ... ENDIF. ********************************************************************** out->write( `--------------------------------` ). out->write( `Example 1: Simple IF ... ENDIF.` ). out->write( `-------------------------------` ). IF c_number = 0. out->write( `The value of C_NUMBER equals zero` ). ELSE. out->write( `The value of C_NUMBER is NOT zero` ). ENDIF. * Example 2: Optional Branches ELSEIF and ELSE ********************************************************************** out->write( `--------------------------------------------` ). out->write( `Example 2: Optional Branches ELSEIF and ELSE` ). out->write( `--------------------------------------------` ). IF c_number = 0. out->write( `The value of C_NUMBER equals zero` ). ELSEIF c_number > 0. out->write( `The value of C_NUMBER is greater than zero` ). ELSE. out->write( `The value of C_NUMBER is less than zero` ). ENDIF. * Example 3: CASE ... ENDCASE ********************************************************************** out->write( `---------------------------` ). out->write( `Example 3: CASE ... ENDCASE` ). out->write( `---------------------------` ). CASE c_number. WHEN 0. out->write( `The value of C_NUMBER equals zero` ). WHEN 1. out->write( `The value of C_NUMBER equals one` ). WHEN 2. out->write( `The value of C_NUMBER equals two` ). WHEN OTHERS. out->write( `The value of C_NUMBER equals non of the above` ). ENDCASE.
  3. Pulse CTRL + F3 para activar la clase y F9 para ejecutarla como una aplicación de consola.
  4. Analice la salida de la consola. Juega con el código fuente para familiarizarte con los conceptos; Descomentar diferentes declaraciones de la constante c_number con diferentes valores para ver, qué ramas del código se ejecutan.

Tratamiento de excepciones

Excepciones

En ABAP, una excepción es una situación de error durante la ejecución de un programa ABAP. El código que detecta la situación de error genera una excepción.

Dependiendo de quién emite la excepción, distinguimos entre excepciones del sistema y excepciones de la aplicación.

Sin más medidas, las excepciones provocan errores de tiempo de ejecución. Un error en tiempo de ejecución cancela el programa y se documenta por defecto en un dump breve.

Puede evitar el error en tiempo de ejecución si la excepción en cuestión es interceptable. Una excepción interceptable se puede tratar en el programa mediante las sentencias TRY … CATCH … ENDTRY.

Todas las excepciones de la aplicación y muchas excepciones del sistema son interceptables. Más adelante en este curso, aprenderá a emitir excepciones de solicitud de empleo. En este punto, nos centraremos en el tratamiento de las excepciones del sistema interceptable.

El siguiente vídeo muestra algunos ejemplos de errores de tiempo de ejecución.

Tratamiento de excepciones

Para evitar que un programa se cancele debido a una excepción interceptable, debe rodear el código desde donde se origina la excepción con las sentencias TRY y ENDTRY. Al hacerlo, el código se convierte en parte del bloque TRY de la estructura TRY … ENDTRY.

Antes de la sentencia ENDTRY debe añadir una sentencia CATCH seguida del ID de la excepción que desea tratar. Opcionalmente, puede añadir más de una sentencia CATCH para gestionar varias excepciones diferentes. Cada sentencia CATCH debe ir seguida de un código para tratar esta excepción. Este código se denomina bloque CATCH.

Cuando la ejecución del programa alcanza la sentencia TRY, continúa con el código en el bloque TRY. Tres cosas pueden suceder entonces:

  1. Si no se emite ninguna excepción durante el bloque TRY, los bloques CATCH se ignoran. La ejecución continúa después de la sentencia ENDTRY.
  2. Si se emite una excepción durante el bloque TRY, para el que existe un CATCH coincidente, se finaliza la ejecución del bloque TRY y se ejecuta el bloque CATCH para esta excepción. A continuación, la ejecución continúa después de la sentencia ENDTRY.
  3. Si se emite una excepción durante el bloque TRY para el que no existe ningún CATCH coincidente, el programa se cancela con un error de tiempo de ejecución.

Ahora que ha aprendido sobre las excepciones, veamos cómo puede gestionarlas.

Pruébelo: Tratamiento de excepciones

  1. Como en el primer ejercicio de este curso, cree una nueva clase global que implemente la interfaz IF_OO_ADT_CLASSRUN.
  2. Copie el siguiente fragmento de código en la parte de implementación del método if_oo_adt_classrun~main( ):
    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
    * Declarations ********************************************************************** DATA result TYPE i. DATA numbers TYPE TABLE OF i. * Preparation ********************************************************************** APPEND 123 TO numbers. * Example 1: Conversion Error (no Number) ********************************************************************** CONSTANTS c_text TYPE string VALUE 'ABC'. * CONSTANTS c_text TYPE string VALUE '123'. out->write( `---------------------------` ). out->write( `Example 1: Conversion Error` ). out->write( `---------------------------` ). TRY. result = c_text. out->write( |Converted content is { result }| ). CATCH cx_sy_conversion_no_number. out->write( |Error: { c_text } is not a number!| ). ENDTRY. * Example 2: Division by Zero ********************************************************************** CONSTANTS c_number TYPE i VALUE 0. * CONSTANTS c_number TYPE i VALUE 7. out->write( `---------------------------` ). out->write( `Example 2: Division by Zero` ). out->write( `---------------------------` ). TRY. result = 100 / c_number. out->write( |100 divided by { c_number } equals { result }| ). CATCH cx_sy_zerodivide. out->write( `Error: Division by zero is not defined!` ). ENDTRY. * Example 3: Itab Error (Line Not Found) ********************************************************************** CONSTANTS c_index TYPE i VALUE 2. * CONSTANTS c_index TYPE i VALUE 1. out->write( `-------------------------` ). out->write( `Example 3: Line Not Found` ). out->write( `-------------------------` ). TRY. result = numbers[ c_index ]. out->write( |Content of row { c_index } equals { result }| ). CATCH cx_sy_itab_line_not_found. out->write( `Error: Itab has less than { c_index } rows!` ). ENDTRY. * Example 4: Combination of Different Exceptions ********************************************************************** * CONSTANTS c_char TYPE c LENGTH 1 VALUE 'X'. * CONSTANTS c_char TYPE c length 1 value '0'. CONSTANTS c_char TYPE c LENGTH 1 VALUE '1'. * CONSTANTS c_char TYPE c length 1 value '2'. out->write( `----------------------` ). out->write( `Example 4: Combination` ). out->write( `----------------------` ). TRY. result = numbers[ 2 / c_char ]. out->write( |Result: { result } | ). CATCH cx_sy_zerodivide. out->write( `Error: Division by zero is not defined` ). CATCH cx_sy_conversion_no_number. out->write( |Error: { c_char } is not a number! | ). CATCH cx_sy_itab_line_not_found. out->write( |Error: Itab contains less than { 2 / c_char } rows| ). ENDTRY.
  3. Pulse CTRL + F3 para activar la clase y F9 para ejecutarla como una aplicación de consola.
  4. Analice la salida de la consola. Juega con el código fuente para familiarizarte con el concepto:
    • Comente el tratamiento de excepciones para que el sistema emita un error en tiempo de ejecución.
    • Modifique los valores de las constantes c_number, c_text, c_index y c_charin de forma que no se generen excepciones.

Iteraciones

Las iteraciones son estructuras de control que definen un bloque de código que se ejecuta varias veces.

La forma más simple de iteración consiste en un bloque de código rodeado por un par de sentencias DO y ENDDO. Sin más medidas, esto establece un bucle sin fin que debe evitarse mediante una de las siguientes posibilidades:

Número especificado de iteraciones

Al ampliar la sentencia DO con una expresión de número entero seguida de la palabra clave TIMES, puede especificar explícitamente la frecuencia con la que se debe iterar el bloque de código. La expresión de número entero puede ser tan simple como el literal numérico, pero también los cálculos aritméticos son una opción. Si el valor de la expresión es igual a 0, el bloque de código entre DO y ENDDO no se ejecuta y el programa continúa inmediatamente con el código después de ENDDO.

Cancelación basada en una condición lógica

Puede cancelar una iteración en cualquier momento mediante la sentencia EXIT. A continuación, el programa continúa con el código después de ENDDO. Tenga en cuenta que fuera de las iteraciones EXIT tiene un efecto diferente. Allí finaliza el procesamiento del bloque de procesamiento actual, por ejemplo, el método actual.

Normalmente, EXIT está rodeado por IF y ENDIF para finalizar la iteración en función de una condición de cancelación. Tenga en cuenta que tales iteraciones pueden convertirse en bucles sin fin, si la condición abortar nunca se vuelve verdadera.

Por supuesto, es posible combinar las dos técnicas, es decir, especificar explícitamente el número de iteraciones y luego dejar la iteración con EXIT. Por lo tanto, el número de iteraciones se convierte en un número máximo que puede que no se alcance en el tiempo de ejecución.

Basado en una tabla interna

Un tercer tipo de iteración es la estructura LOOP … ENDLOOP que se utiliza para leer consecutivamente las filas de una tabla interna. Aquí, el número de iteraciones se determina mediante el número de filas en la tabla interna.

En el bloque de código entre DO y ENDDO, puede implementar accesos de lectura al índice de sistema del objeto de datos integrado ABAP. Esta variable entera sirve como contador de iteración, es decir, el tiempo de ejecución ABAP la aumenta en uno al principio de cada nueva iteración.

En contradicción con lo que se puede utilizar desde otros lenguajes de programación, sy-index comienza con el valor 1 durante la primera iteración.

La variable incorporada de ABAP sy-tabix puede cumplir un propósito similar para las iteraciones con LOOP. Pero tenga en cuenta que hablando estrictamente sy-tabix no es realmente un contador, pero identifica la posición de la fila de la tabla que se procesa en la iteración actual. Más adelante veremos la diferencia cuando no se procesen todas las filas de una tabla interna en una estructura LOOP … ENDLOOP.

Pruébelo: iteraciones

  1. Como en el primer ejercicio de este curso, cree una nueva clase global que implemente la interfaz IF_OO_ADT_CLASSRUN.
  2. Copie el siguiente fragmento de código en la parte de implementación del método if_oo_adt_classrun~main( ):
    Code Snippet
    12345678910111213141516171819202122232425262728293031323334353637383940414243
    * Declarations ********************************************************************** CONSTANTS c_number TYPE i VALUE 3. * CONSTANTS c_number TYPE i VALUE 5. * CONSTANTS c_number TYPE i VALUE 10. DATA number TYPE i. * Example 1: DO ... ENDDO with TIMES ********************************************************************** out->write( `----------------------------------` ). out->write( `Example 1: DO ... ENDDO with TIMES` ). out->write( `----------------------------------` ). DO c_number TIMES. out->write( `Hello World` ). ENDDO. * Example 2: DO ... ENDDO with Abort Condition ********************************************************************** out->write( `-------------------------------` ). out->write( `Example 2: With Abort Condition` ). out->write( `-------------------------------` ). number = c_number * c_number. " count backwards from number to c_number. DO. out->write( |{ sy-index }: Value of number: { number }| ). number = number - 1. "abort condition IF number <= c_number. EXIT. ENDIF. ENDDO.
  3. Pulse CTRL + F3 para activar la clase y F9 para ejecutarla como una aplicación de consola.
  4. Analice la salida de la consola. Juega con el código fuente para familiarizarte con los conceptos; Descomente las diferentes declaraciones de la constante c_number para ver cómo los diferentes valores afectan al resultado.