martes, 10 de diciembre de 2013

Crear Dynpros para crear, modificar y visualizar datos en una base de datos.

Datos previos:
Objetivo:
  • Una Dynpro 9000 con tres botones (Crear, Modificar y Visualizar).
  • Una Dynpro 9001 para añadir datos a la base de datos.
  • Una Dynpro 9002 como ventana de diálogo modal, para introducir el código de socio.
  • Una Dynpro 9003, como ventana de diálogo modal, para Modificar o Visualizar un socio de la base de datos.
Esquema de las cuatro dynpros:

Esquema de los dynpros.

El primer paso es crear un Module Pool en la SE38:

Crear un Module Pool en la SE38
 Añadir una Dynpro (Screen) al Module Pool creado pulsando el botón derecho:

Añadir una Dynpro al Module Pool creado.
Indicar el número de pantalla (se recomienda a partir de 9000).
Crear el elemento tipo OK de la pantalla 9000.
Descomentar los módulos PBO y PAI, y crear ambos objetos pinchando dos veces en el nombre.
En nuestro programa principal se nos habrán creado los objetos PBO y PAI en el código del programa.

Objetos PBO y PAI en el programa.
Como se puede apreciar, en el PBO se añade un Status y un Título, y en el PAI la salida del programa cuando el usuario pulsa el botón Cancel.

Para crear el STATUS y el título se pincha dos veces en el nombre:

Descripción del Status
Activación del botón Cancel cómo mínimo para salir del programa.
Descripción del título del programa.
Pinchamos dos veces al Dynpro 9000 y vamos al Layout para editar la pantalla. Se introducirán los botones de crear, modificar y visualizar:

Ir al Layout para editar la pantalla.
Escribir el código de función del botón.
Botones creados en el Dynpro 9000.

Para poder ejecutar la pantalla creada, es necesario crear una transacción. Hay dos formas:
  1. En la SE93
  2. Directamente en el programa

Crear la transacción en la SE93.
Crear la transacción directamente en el programa.
Se indicará la descripción, el nombre del Module Pool y la pantalla.

Descripción de la transacción.
Module Pool y Dynpro para que la transacción lo ejecute.
Creamos la Dynpro (Screen) 9001 tal y como creamos la 9000. Las únicas diferencias son:
  1. Añadimos el botón BACK para volver al screen 9000 en el STATUS_9001.
  2. El campo de entrada/salida se nombra con el nombre de la tabla ZBIBLIO_SOCIOS para referenciar sus características.
Añadimos el botón Back.
Nombras el campo de entrada/salida con el mismo nombre para referenciar.
Dynpro 9001 resultante.
Se necesita comprobar que el nuevo código de socio no existe en la base de datos. Para ello recurrimos al Process After Input (PAI) para comprobar si el valor introducido existe en la base de datos. Se indica el campo con un CHAIN y el módulo correspondiente a ejecutar (ver código resultante al final).


PROCESS BEFORE OUTPUT.
  MODULE status_9001.
*
PROCESS AFTER INPUT.
  CHAIN.
    FIELD zbiblio_socios-cod_socio.
    MODULE existe_socio.
  ENDCHAIN.

  MODULE user_command_9001.

A continuación creamos la Dynpro 9002 con sus correspondientes campos como ventana de diálogo modal. En este caso, el Status tiene que ser del mismo tipo:

Status 9002 como diálogo modal.
Añadimos el código para cuando el usuario pulsa X para salir.
En este caso, dependiendo del botón pulsado en la Dynpro 9000, el botón tendrá como texto Modificar o Visualizarse, por tanto es necesario indicar el botón como campo de salida.

Botón como campo output en el Dynpro 9002.
Finalmente creamos la Dynpro 9003 como ventana de diálogo modal.

Dynpro 9003 como ventana de diálogo modal.
Esta misma Dynpro se va a utilizar para la acción de modificar o visualizar. Las diferencias con respecto a la 9001 son:
  1. El campo del código de socio es solo output (El usuario ya ha sido introducido en la Dynpro 9002).
  2. Todos los campos de entrada/salida, salvo el primero, tendrán un identificador de Grupo1 llamado ID1.
    • Si se da al botón de visualizar, ningún campo es editable, por lo tanto identificamos con ID1 los campos a modificar esa opción.
  3. El botón será un campo de salida, tal y como en el Dynpro 9002.
El campo input del código de socio es solo output.
Identificador de grupo ID1 en todos los campos de entrada/salida salvo en código de socio.
Botón como campo de salida.

Los códigos son los siguientes:
  • Dynpro 9000
PROCESS BEFORE OUTPUT.
 MODULE STATUS_9000.
*
PROCESS AFTER INPUT.
 MODULE USER_COMMAND_9000.
  • Dynpro 9001
PROCESS BEFORE OUTPUT.
  MODULE status_9001.
*
PROCESS AFTER INPUT.
  CHAIN.
    FIELD zbiblio_socios-cod_socio.
    MODULE existe_socio.
  ENDCHAIN.


  MODULE user_command_9001.
  • Dynpro 9002
PROCESS BEFORE OUTPUT.
  MODULE status_9002.
  MODULE inicial_9002.
*
PROCESS AFTER INPUT.
  CHAIN.
    FIELD zbiblio_socios-cod_socio.
    MODULE existe_socio.
  ENDCHAIN.

  MODULE user_command_9002.
  • Dynpro 9003
PROCESS BEFORE OUTPUT.
  MODULE status_9003.
  MODULE inicial_9003.
*
PROCESS AFTER INPUT.
  MODULE user_command_9003.
  • Module Pool
*&---------------------------------------------------------------------*
*& Module Pool       ZBIBLIO_CREAR_MODIF_VISUAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

PROGRAM  zbiblio_crear_modif_visual.

TABLES: zbiblio_socios.

DATA: g_st_socios TYPE zbiblio_socios.

DATA: ok_code_9000 TYPE sy-ucomm,
      ok_code_9001 TYPE sy-ucomm,
      ok_code_9002 TYPE sy-ucomm,
      ok_code_9003 TYPE sy-ucomm.

DATA: b_9002_boton(20) TYPE c, "Texto de los botones output
      b_9003_boton(20) TYPE c.

DATA: g_wa_existe_socio TYPE c,   "Búsqueda en dynpro 9002
      g_wa_vuelta TYPE i. "Al iniciar PBO del dynpro 9003

*&---------------------------------------------------------------------*
*&      Module  STATUS_9000  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE status_9000 OUTPUT.

  SET PF-STATUS 'STATUS_9000'.
  SET TITLEBAR 'TITLE_9000'.

ENDMODULE.                 " STATUS_9000  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_9000  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_9000 INPUT.

  CASE ok_code_9000.
    WHEN 'CANCEL'.
      LEAVE PROGRAM.
    WHEN 'CREAR'.
      CALL SCREEN 9001.
    WHEN 'MODIFICAR'.
      CALL SCREEN 9002 STARTING AT 10 10.
    WHEN 'VISUALIZAR'.
      CALL SCREEN 9002 STARTING AT 10 10.
  ENDCASE.

ENDMODULE.                 " USER_COMMAND_9000  INPUT
*&---------------------------------------------------------------------*
*&      Module  STATUS_9001  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE status_9001 OUTPUT.

  SET PF-STATUS 'STATUS_9001'.
  SET TITLEBAR 'TITLE_9001'.

ENDMODULE.                 " STATUS_9001  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_9001  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_9001 INPUT.

  CASE ok_code_9001.
    WHEN 'BACK'.
      CALL SCREEN 9000.
    WHEN 'CANCEL'.
      LEAVE PROGRAM.
    WHEN 'CREAR'.
      INSERT zbiblio_socios.
      MESSAGE 'Usuario creado' type 'I'.
  ENDCASE.

ENDMODULE.                 " USER_COMMAND_9001  INPUT
*&---------------------------------------------------------------------*
*&      Module  STATUS_9002  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE status_9002 OUTPUT.

  SET PF-STATUS 'STATUS_9002'.
  SET TITLEBAR 'TITLE_9002'.

ENDMODULE.                 " STATUS_9002  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  MODIFICAR_VISUALIZAR  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE inicial_9002 OUTPUT.

  PERFORM f_inicial.

ENDMODULE.                 " MODIFICAR_VISUALIZAR  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  VALIDA_SOCIO  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE existe_socio INPUT.

  PERFORM f_existe_socio.

  IF ok_code_9000 = 'CREAR' AND g_wa_existe_socio = 'X'.
    MESSAGE 'El usuario ya existe' TYPE 'E'.
  ELSEIF ( ok_code_9000 = 'MODIFICAR' OR
           ok_code_9000 = 'VISUALIZAR' ) AND
           g_wa_existe_socio <> 'X'.
    MESSAGE 'El usuario no existe' TYPE 'E'.
  ENDIF.

ENDMODULE.                 " EXISTE_SOCIO  INPUT
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_9002  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_9002 INPUT.

  CASE ok_code_9002.
    WHEN 'BACK'.
      CALL SCREEN 9000.
    WHEN 'CANCEL'.
      LEAVE PROGRAM.
      CLEAR: g_st_socios, g_wa_existe_socio.
    WHEN 'ACCION'.
      IF g_wa_existe_socio = 'X'.
        g_wa_vuelta = 1.
        CALL SCREEN 9003 STARTING AT 10 10.
      ENDIF.
  ENDCASE.

ENDMODULE.                 " USER_COMMAND_9002  INPUT
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_9003  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_9003 INPUT.

  CASE ok_code_9003.
    WHEN 'BACK'.
      CALL SCREEN 9000.
    WHEN 'CANCEL'.
      LEAVE PROGRAM.
    WHEN 'ACCION'.
      IF ok_code_9000 = 'MODIFICAR'.
        PERFORM f_modificar.
      ENDIF.
  ENDCASE.

ENDMODULE.                 " USER_COMMAND_9003  INPUT
*&---------------------------------------------------------------------*
*&      Module  STATUS_9003  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE status_9003 OUTPUT.

  SET PF-STATUS 'STATUS_9003'.

  IF ok_code_9000 = 'MODIFICAR'.
    SET TITLEBAR 'TITLE_9003_1'.
  ELSEIF ok_code_9000 = 'VISUALIZAR'.
    SET TITLEBAR 'TITLE_9003_2'.
  ENDIF.

ENDMODULE.                 " STATUS_9002  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  INICIAL_9003  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE inicial_9003 OUTPUT.

  PERFORM f_inicial.
  IF g_wa_vuelta = 1.
    PERFORM f_ver_socio.
    g_wa_vuelta = g_wa_vuelta + 1.
  ENDIF.

ENDMODULE.                 " INICIAL_9003  OUTPUT
*&---------------------------------------------------------------------*
*&      Form  F_INICIAL
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM f_inicial.

* Cambiar el texto del botón
  IF ok_code_9000 = 'MODIFICAR'.
    b_9002_boton = 'Modificar'.
    b_9003_boton = 'Modificar'.

  ELSEIF ok_code_9000 = 'VISUALIZAR'.
    b_9002_boton = 'Visualizar'.
    b_9003_boton = 'Visualizar'.

*   No editable cuando es visualización
    LOOP AT SCREEN.
      IF screen-group1 = 'ID1'.
        screen-input = 0.
        MODIFY SCREEN.
      ENDIF.
    ENDLOOP.
  ENDIF.

ENDFORM.                    " F_INICIAL
*&---------------------------------------------------------------------*
*&      Form  F_EXISTE_SOCIO
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM f_existe_socio  .

  DATA: l_st_socios TYPE zbiblio_socios.

  IF zbiblio_socios-cod_socio IS NOT INITIAL.

    SELECT SINGLE * FROM zbiblio_socios
                    INTO l_st_socios
                    WHERE cod_socio = zbiblio_socios-cod_socio.
    IF sy-subrc = 0.
      g_wa_existe_socio = 'X'.
    ELSEIF sy-subrc <> 0.
      CLEAR g_wa_existe_socio.
    ENDIF.
  ENDIF.

ENDFORM.                    " F_EXISTE_SOCIO
*&---------------------------------------------------------------------*
*&      Form  F_MODIFICAR_9002
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM f_modificar.

* Los datos del input se actualizan a la base datos (mismo nombre)
  UPDATE zbiblio_socios.
  MESSAGE 'Usuario modificado' TYPE 'I'.

ENDFORM.                    " F_MODIFICAR
*&---------------------------------------------------------------------*
*&      Form  F_VER_SOCIO
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM f_ver_socio .

  DATA l_st_socio TYPE zbiblio_socios.

  SELECT SINGLE * FROM zbiblio_socios
                  INTO l_st_socio
                  WHERE cod_socio = zbiblio_socios-cod_socio.

  zbiblio_socios = l_st_socio.

ENDFORM.                    " F_VER_SOCIO

domingo, 8 de diciembre de 2013

Clave externa en bases de datos

Introducir la clave externa en los siguientes campos de la tabla 3 (Crear tablas):
  • Código Socio
  • Código Libro
1. Tabla: ZBIBLIO_SOCIOS
Campo Tipo
Código de socio NUMC-4
DNI CHAR-9
Nombre CHAR-30
Apellido CHAR-30
Teléfono CHAR-15
Dirección 1 CHAR-75
Dirección 2 CHAR-75
Dirección 3 CHAR-75
Dirección 4 CHAR-75

2. Tabla: ZBIBLIO_LIBROS
Campo Tipo
Código de libro NUMC-8
Autor CHAR-75
Título CHAR-125
Ejemplares disponibles INT-4
Ejemplares totales INT-4

3. Tabla: ZBIBLIO_PRESTAM
Campo Tipo
Código de préstamo NUMC-12
Código de socio (Clave externa con tabla de socios)
Código de libro (Clave externa con tabla de socios)
Fecha inicio préstamo DAT
Fecha estimada devolución DAT
Fecha real devolución DAT

En la tabla 3, seleccionamos el campo para indicar como clave externa y pinchamos en el botón de la llave:

Campo socio seleccionado y pinchar en el botón de clave externa.
Introducir la tabla donde está definido el campo y pinchar en el botón de generar propuesta.
Comprobación de las claves externas:

Comprobación de la clave externa en la tabla.

Crear bases de datos

Crear las siguientes tablas:

1. Tabla: ZBIBLIO_SOCIOS
Campo Tipo
Código de socio NUMC-4
DNI CHAR-9
Nombre CHAR-30
Apellido CHAR-30
Teléfono CHAR-15
Dirección 1 CHAR-75
Dirección 2 CHAR-75
Dirección 3 CHAR-75
Dirección 4 CHAR-75

2. Tabla: ZBIBLIO_LIBROS
Campo Tipo
Código de libro NUMC-8
Autor CHAR-75
Título CHAR-125
Ejemplares disponibles INT-4
Ejemplares totales INT-4

3. Tabla: ZBIBLIO_PRESTAM
Campo Tipo
Código de préstamo NUMC-12
Código de socio (Clave externa con tabla de socios)
Código de libro (Clave externa con tabla de socios)
Fecha inicio préstamo DAT
Fecha estimada devolución DAT
Fecha real devolución DAT

El primer paso es crear todos los dominios en la SE11. Habrá tantos dominios como tipo de variables, es decir, un dominio para CHAR-9, otro para CHAR-15 y así sucesivamente con cada uno de los tipos de las tres tablas.

Creación de un dominio.
Características de un dominio. 
Finalmente se habrán creado los siguientes dominios:

Lista de dominios creados.
A continuación, se crean los tipos de datos. Por tanto, volvemos a la SE11 para crear los tipos de datos.
Creación del tipo de datos.

En este ejemplo, tendremos que crear todos los tipos de datos de las tres tablas y asignarle el dominio correspondiente. Este dominio se puede repetir, como es el caso de los campos Nombre y Apellido en la tabla Z_BIBLIO_SOCIOS, ya que su tipo es un CHAR-30. La única diferencia entre los tipos de datos Nombre y Apellido es las descripciones.
Asignando un dominio creado al tipo de datos.
Se aconseja rellenar las descripciones del campo, ya que ayudará a la visualización cuando se utilicen ALVs.
Creando etiquetas de descripción para mostrar en ALVs. 
Una vez con todos los tipos de datos creados, pasamos a crear la base de datos en la SE11. Seleccionamos la clase e introducimos los campos de la tabla.

Creamos una base de datos.
Asignamos la clase y navegación de datos.
Todo tabla debe de comenzar por el mandante, con lo que asignamos el elemento MANDT al primer campo.
Añadimos el mandante y los campos (asignando los tipos creados previamente).
Pulsamos el botón de ajustes técnicos de la tabla para asignar la clase APPL0 y un tamaño de registro categoría 0 (780 registros).
Asignar clase de datos y el número de registros que tendrá la tabla.
A continuación, seleccionamos la categoría de ampliación de la tabla en Detalles:

Categoría de ampliación en Detalles.
Seleccionamos ampliable de cualquier manera.
Y finalmente, vamos al generador de actualizador de tabla en Utilidades:

Ir al generador de mantenimiento de tabla en utilidades.
Seleccionamos el grupo de autorización y el grupo de funciones. Se recomienda que para cada tabla tenga su propio grupo de funciones. En este caso, la llamamos igual que el nombre de la tabla. Además, asignamos la imagen resumen con un 9000 (Se recomienda que se empiece a contar a partir de ese número).
Seleccionamos categoría de actualización, el grupo de funciones y la imagen resumen.
Pinchamos en crear, grabamos y activamos la tabla.

Se repite cada uno de los pasos con las otras dos tablas.

Las claves externas se explican en esta entrada.

Para introducir datos en la tabla de forma manual, iremos a la transacción SM30


jueves, 28 de noviembre de 2013

ALV Report de una base de datos (I_STRUCTURE_NAME)

Cuando consultamos una base de datos, es posible que las descripciones de los campos hayan sido añadidas en los elementos de datos de cada campo, por tanto no será necesario rellenar el FIELDCAT como en el primer ejemplo ALV. Sólo hay que indicar el nombre de la estructura y la tabla interna.

En este ejemplo se va a mostrar la SFLIGHT.

REPORT  z_sflight.

* Cargar la tabla SFLIGHT de la base de datos
TABLES: sflight.

* Definición de variables
DATA: g_it_sflight TYPE TABLE OF sflight.

* Copiado de los datos a la tabla con los filtros
SELECT * FROM sflight INTO TABLE g_it_sflight.

* ALV
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
  EXPORTING
    i_structure_name = 'SFLIGHT'
  TABLES
    t_outtab         = g_it_sflight.

ALV Report de una base de datos

jueves, 21 de noviembre de 2013

Añadir un botón en un ALV Report

En la transacción SE80, visualizamos el programa SAPLKKBL.

Visualizamos el programa SAPLKKBL.

Navegamos en el árbol hasta la pestaña GUI Status>STANDARD. Pinchamos con el botón derecho y lo copiamos a nuestro programa.

Copiamos STANDARD en la pestaña Status GUI.

Añadimos el nombre de nuestro programa.

Volvemos a nuestro programa principal, y comprobamos que tenemos el STANDARD en la pestaña GUI Status.

Comprobamos que tenemos GUI Status>Standard en nuestro programa.
Pinchamos dos veces en STANDARD y veremos los botones disponibles. En esta nueva ventana añadimos un nuevo botón, asignándole un nombre, un icono y un atajo del teclado (No asignar el atajo F4, ya que el botón no funcionaría).

Añadimos un botón con el nombre &BT1.

Asignamos un icono.
Asignamos un atajo del teclado.


Ya tenemos el GUI Status listo para incorporar. Se va a mostrar un código en el que se muestran los cuatro primeros campos de la tabla SFLIGHT con un nuevo botón en el menú. Cuando se pulsa el botón, saldrá un mensaje de notificación.

El código es el siguiente:


REPORT  z_test.

* Cargar la tabla SFLIGHT de la base de datos
TABLES: sflight.

* Cargamos los datos tipo slis
TYPES: slis.

* Definición de variables
DATA: g_it_sflight TYPE TABLE OF sflight,
      g_st_sflight TYPE sflight.

DATA: g_it_fieldcat TYPE slis_t_fieldcat_alv,
      g_st_fieldcat TYPE slis_fieldcat_alv.

DATA: g_repid TYPE sy-repid.

* SQL para copiar la tabla sflight a la tabla interna
SELECT * FROM sflight INTO TABLE g_it_sflight.

* Variable con el nombre del programa
g_repid = sy-repid.

* Datos del fieldcat para el ALV
g_st_fieldcat-fieldname = 'CARRID'.
g_st_fieldcat-seltext_s = 'Comp.'.
APPEND g_st_fieldcat TO g_it_fieldcat.

g_st_fieldcat-fieldname = 'CONNID'.
g_st_fieldcat-seltext_s = 'Vuelo'.
APPEND g_st_fieldcat TO g_it_fieldcat.

g_st_fieldcat-fieldname = 'FLDATE'.
g_st_fieldcat-seltext_s = 'Fecha'.
APPEND g_st_fieldcat TO g_it_fieldcat.

g_st_fieldcat-fieldname = 'PRICE'.
g_st_fieldcat-seltext_s = 'Tarifa'.
APPEND g_st_fieldcat TO g_it_fieldcat.

CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
  EXPORTING
    i_callback_program       = g_repid
    i_callback_pf_status_set = 'MI_STANDARD'
    i_callback_user_command  = 'MI_USER_COMMAND'
    it_fieldcat              = g_it_fieldcat[]
  TABLES
    t_outtab                 = g_it_sflight[]
  EXCEPTIONS
    program_error            = 1
    OTHERS                   = 2.

*&---------------------------------------------------------------------*
*&      Form  mi_user_command
*&---------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
FORM mi_user_command USING r_ucomm LIKE sy-ucomm
                                   rs_selfield TYPE slis_selfield.
  CASE r_ucomm. 
    WHEN '&BT1'. "Se ha hecho click en el botón
      MESSAGE 'Has pulsado el botón creado' TYPE 'I'.
  ENDCASE.
ENDFORM.                    "mi_user_command

*&---------------------------------------------------------------------*
*&      Form  mi_standard
*&---------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
FORM mi_standard USING rt_extab TYPE slis_t_extab.
  SET PF-STATUS 'STANDARD'. "Nombre del Status GUI
ENDFORM.                    "mi_standard

Nuestro botón y el mensaje monstrado.