jueves, 6 de marzo de 2008

Entradas en tabla con la SE16N

La transacción SE16N permite modificar, sin programas de carga, las entradas de una tabla. Para ello, hay que seguir los siguientes pasos:

1. Introducir la transacción SE16N (evidentemente).

2. Introducimos el nombre de la tabla (ZTABLA), y le damos a INTRO para que aparezcan los campos de dicha tabla


3. En la ventana donde introducimos las transacciones de la barra de herramientas, escribimos &SAP_EDIT



4. Finalmente, introducimos los criterios de selección que querramos modificar, ejecutamos (con F8) y nos aparecerá el modo de edición, donde podremos crear entradas, borrarlas o modificarlas.



Modificar denominaciones de campo sin la SE11

En ocasiones, nos es imposible modificar las denominaciones de campo de un elemento de datos.

Normalmente, introducimos en la transacción SE11 el nombre del elemento (en este caso, ZANIO), le damos a MODIFICAR y a la pestaña Denom. Campo








Pero habrá casos en los cuales la opción de modificar textos estará deshabilitada. ¿Qué hacemos entonces?

Pues fácil: nos vamos a la transacción CMOD, y navegamos por
Pasar a > Ampliaciones glob. > Palabras clave > Modificar




En la ventana, introducimos el Elemento de datos


Y desde aquí, podremos modificar todas las denominaciones de campo, así como la descripción, del elemento de datos.


martes, 4 de marzo de 2008

Inserción/modificación masiva o línea a línea - LUW

A la hora de insertar/modificar registros en una tabla del diccionario a partir de otra tabla (cuyo contenido podría venir de un fichero de texto, o de una consulta de selección) podemos elegir entre insertar los registros uno a uno, o de forma masiva.

Si se hace de registro en registro, corremos el riesgo de que se abra una unidad lógica de trabajo (LUW, por sus siglas en inglés), que bloquea la tabla momentáneamente. Se trata de unos microsegundos, pero si se intenta cualquier otra modificación sobre la tabla, tendremos un fallo de ejecución.
Por el contrario, si lo hacemos de forma masiva podemos pedir al programa que acabe el trabajo (que finalice la LUW) y que se espere, con la sentencia
COMMIT WORK AND WAIT.

Esto también lo podemos hacer registro a registro, pero el WAIT hará que la espera se extienda y, probablemente, tengamos un dump por tiempo de ejecución sobrepasado.

Aunque recomiendo siempre la segunda opción (es decir, un insert/update masivo) veremos ambas.

Para el ejemplo, tendremos dos tablas Z: ZORIGEN y ZDESTINO. Ambas tienen la misma estructura: el mandante de toda la vida, un campo clave llamado ZCLAVE, de tipo N y longitud 5, y dos campos para almacenar textos pequeñitos (25 caracteres) ZTEXTO1 y ZTEXTO2.

En la pantalla de selección, podremos elegir entre hacer la inserción masiva o línea a línea.

He aquí el programa:

*&---------------------------------------------------------------------*
*& Report Z_LUW
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT z_luw.

*&---------------------------------------------------------------------*
*& TOP
*&---------------------------------------------------------------------*
TABLES:
zorigen,
zdestino.

DATA:
"Para selección de datos
gt_origen LIKE TABLE OF zorigen WITH HEADER LINE,
"Para leer ZDESTINO
gt_destino LIKE TABLE OF zdestino WITH HEADER LINE,
"Para insertar en zdestino masivamente
gt_inser LIKE TABLE OF zdestino WITH HEADER LINE,
"Para modificar zdestino masivamente
gt_modif LIKE TABLE OF zdestino WITH HEADER LINE,

"Para insertar/modificar zdestino línea a línea, un work-area
wa LIKE LINE OF zorigen,

"Variables para los resultados
gv_leidas LIKE sy-dbcnt, "Leidas
gv_inser1 LIKE sy-dbcnt, "Deberían haberse insertado
gv_modif1 LIKE sy-dbcnt, "Deberían haberse modificado
gv_inser2 LIKE sy-dbcnt, "Se insertaron realmente
gv_modif2 LIKE sy-dbcnt. "Se modificaron realmente

*&---------------------------------------------------------------------*
*& PANTALLA DE SELECCIÓN
*&---------------------------------------------------------------------*
PARAMETERS:
p_mas RADIOBUTTON GROUP gr1, "Masivamente
p_1a1 RADIOBUTTON GROUP gr1. "Línea a línea

*&---------------------------------------------------------------------*
*& EVENTOS
*&---------------------------------------------------------------------*
INITIALIZATION.
REFRESH: gt_origen, gt_destino, gt_inser, gt_modif.
CLEAR: gt_origen, gt_destino, gt_inser, gt_modif,
gv_leidas, gv_insertadas, gv_modificadas.
*&---------------------------------------------------------------------*
START-OF-SELECTION.
"Seleccionamos todo ZORIGEN y ZDESTINO
SELECT * FROM zorigen INTO CORRESPONDING FIELDS OF TABLE gt_origen.
SELECT * FROM zdestino INTO CORRESPONDING FIELDS OF TABLE gt_destino.

"Número de líneas leidas
DESCRIBE TABLE gt_origen LINES gv_leidas.

"Ahora, insertamos/modificamos
IF p_mas = 'X'. "Masivamente
LOOP AT gt_origen.
"Leemos la tabla zdestino con el mismo campo clave,
"Si existe el registro lo modificamos y si no lo insertamos
READ TABLE gt_destino WITH KEY zclave = gt_origen-zclave.
IF sy-subrc EQ 0. "Modificamos
MOVE-CORRESPONDING gt_origen TO gt_modif.
APPEND gt_modif. CLEAR gt_modif.
ELSE. "Insertamos
MOVE-CORRESPONDING gt_origen TO gt_inser.
APPEND gt_modif. CLEAR gt_modif.
ENDIF.
ENDLOOP.

"Número de líneas insertadas/modificadas
DESCRIBE TABLE gt_inser LINES gv_inser1.
DESCRIBE TABLE gt_modif LINES gv_modif1.
"Ahora llega la modificación e inserción masiva
INSERT zdestino FROM TABLE gt_inser.
MOVE sy-dbcnt TO gv_inser2.
COMMIT WORK AND WAIT.

UPDATE zdestino FROM TABLE gt_modif.
MOVE sy-dbcnt TO gv_modif2.
COMMIT WORK AND WAIT.

ELSE. "p_1a1 = 'X'

LOOP AT gt_origen.
"Leemos la tabla zdestino con el mismo campo clave,
"Si existe el registro lo modificamos y si no lo insertamos
MOVE-CORRESPONDING gt_origen TO wa.
READ TABLE gt_destino WITH KEY zclave = wa-zclave.
IF sy-subrc EQ 0. "Modificamos
UPDATE zdestino FROM wa.
IF sy-subrc EQ 0.
ADD 1 TO gv_modif2.
ELSE.
ADD 1 TO gv_modif1.
ENDIF.
ELSE. "Insertamos
INSERT into zdestino values wa.
IF sy-subrc EQ 0.
ADD 1 TO gv_inser2.
ELSE.
ADD 1 TO gv_inser1.
ENDIF.
ENDIF.
ENDLOOP.

gv_modif1 = gv_modif1 + gv_modif2.
gv_inser1 = gv_inser1 + gv_inser2.

ENDIF.

*&---------------------------------------------------------------------*
END-OF-SELECTION.
"Mostramos resultados
"OJO! Quizá habría que restar 1 a alguna variable...

WRITE: /,
'Se insertaron......: ', gv_inser2, /,
'Se modificaron.....:', gv_modif2.

IF gv_inser1 NE gv_inser2.
WRITE: /, 'Error!, deberían haberse insertado ', gv_inser1, ' líneas.'.
ENDIF.
IF gv_modif1 NE gv_modif2.
WRITE: /, 'Error!, deberían haberse modificado, ' gv_modif1, ' líneas.'.
ENDIF.