LOS SUBFICHEROS EN LA PRÁCTICA de su registro de subfichero y los campos del registro de control...

23
LOS SUBFICHEROS EN LA PRÁCTICA Sección: Diseño y Programación - HELP400 ============================================================================== Introducción a los subficheros ------------------------------------------------------------------------------ Las aplicaciones interactivas mejoran sensiblemente si en su diseño incorporamos funciones de subfichero, por tanto, un correcto dominio de las técnicas de tratamiento de los subficheros puede incrementar significativamente la productividad de nuestra instalación. Cómo codificar subficheros Todos hemos tenido, de vez en cuando, necesidad de representar información en forma tabular. Formatear los datos de salida en filas y columnas generalmente no representa ninguna dificultad, es en la codificación de las funciones de paginación en donde reside el problema. En este campo, el Sistema 38 aportó, entre otras, una importante novedad: el tratamiento de múltiples registros mediante el uso de subficheros. Básicamente, el empleo de un subfichero permite manejar en pantalla múltiples registros del mismo tipo y emplear las teclas de paginación, bien sean controladas desde el propio sistema operativo o bien, desde el programa que trata los datos. Por ejemplo, un programa lee registros de un fichero de base de datos y los va añadiendo mediante WRITE al subfichero de salida. Cuando se ha creado el subfichero en su totalidad, el programa lo envía a pantalla mediante una sola operación de escritura. Después de que el usuario haya revisado, modificado o añadido registros al subfichero (dependiendo de la función a realizar), el programa lee todo el subfichero desde el dispositivo de representación, lo introduce en el programa y procesa individualmente cada registro del subfichero. Los subficheros gozan de gran popularidad en nuestro entorno porque, al usar funciones directamente incluidas en el microcódigo, permiten aumentar nuestra productividad y las prestaciones de nuestra aplicación. De hecho, en la vida, nada es gratuito y un uso erróneo de los subficheros puede ser la causa de una importante degradación en el rendimiento del sistema. Cuando vayamos a diseñar subficheros hemos de considerar estos posibles problemas de rendimiento. Uno de ellos se origina en la manera en cómo se cargan y leen los datos del subfichero. Hay tres formas distintas de tratar a un subfichero según sea su naturaleza: subficheros "completos", subficheros "página a página" y subficheros "de una página" (les he asignado estos nombres con el fin de poderlos denominar de alguna forma). Subficheros "completos" En algunos programas puede ser ventajoso el leer y cargar en el subfichero todos los registros a visualizar, facilitando así, la paginación total de los datos hacia adelante o hacia atrás. Codificar este tipo de subficheros "completos" es simple: leer un registro de la base de datos, escribirlo en el subfichero, repetir hasta que se llegue al final del fichero de datos y entonces visualizar el subfichero. Esta técnica es la mejor cuando se procesan un número relativamente pequeño de registros (un máximo de 50 o 60) que suelen corresponder a ficheros de tipo tablas. Emplear programas con subficheros completos no es aconsejable cuando se usa un mayor número de registros dado que la cantidad de tiempo necesaria para cargar el subfichero puede significar un tiempo de espera excesivo antes de efectuar la visualización, y por otra parte, el usuario quizás no necesite ver todos los registros para tomar una acción determinada. Desgraciadamente, muchos programas que tratan cientos de registros, están escritos bajo esta técnica, por ser la más cómoda en el momento de codificar. En este tipo de programas, la paginación está totalmente soportada por el propio sistema operativo.

Transcript of LOS SUBFICHEROS EN LA PRÁCTICA de su registro de subfichero y los campos del registro de control...

LOS SUBFICHEROS EN LA PRÁCTICA Sección: Diseño y Programación - HELP400

==============================================================================

Introducción a los subficheros ------------------------------------------------------------------------------ Las aplicaciones interactivas mejoran sensiblemente si en su diseño incorporamos funciones de subfichero, por tanto, un correcto dominio de las técnicas de tratamiento de los subficheros puede incrementar significativamente la productividad de nuestra instalación. Cómo codificar subficheros Todos hemos tenido, de vez en cuando, necesidad de representar información en forma tabular. Formatear los datos de salida en filas y columnas generalmente no representa ninguna dificultad, es en la codificación de las funciones de paginación en donde reside el problema. En este campo, el Sistema 38 aportó, entre otras, una importante novedad: el tratamiento de múltiples registros mediante el uso de subficheros. Básicamente, el empleo de un subfichero permite manejar en pantalla múltiples registros del mismo tipo y emplear las teclas de paginación, bien sean controladas desde el propio sistema operativo o bien, desde el programa que trata los datos. Por ejemplo, un programa lee registros de un fichero de base de datos y los va añadiendo mediante WRITE al subfichero de salida. Cuando se ha creado el subfichero en su totalidad, el programa lo envía a pantalla mediante una sola operación de escritura. Después de que el usuario haya revisado, modificado o añadido registros al subfichero (dependiendo de la función a realizar), el programa lee todo el subfichero desde el dispositivo de representación, lo introduce en el programa y procesa individualmente cada registro del subfichero. Los subficheros gozan de gran popularidad en nuestro entorno porque, al usar funciones directamente incluidas en el microcódigo, permiten aumentar nuestra productividad y las prestaciones de nuestra aplicación. De hecho, en la vida, nada es gratuito y un uso erróneo de los subficheros puede ser la causa de una importante degradación en el rendimiento del sistema. Cuando vayamos a diseñar subficheros hemos de considerar estos posibles problemas de rendimiento. Uno de ellos se origina en la manera en cómo se cargan y leen los datos del subfichero. Hay tres formas distintas de tratar a un subfichero según sea su naturaleza: subficheros "completos", subficheros "página a página" y subficheros "de una página" (les he asignado estos nombres con el fin de poderlos denominar de alguna forma). Subficheros "completos" En algunos programas puede ser ventajoso el leer y cargar en el subfichero todos los registros a visualizar, facilitando así, la paginación total de los datos hacia adelante o hacia atrás. Codificar este tipo de subficheros "completos" es simple: leer un registro de la base de datos, escribirlo en el subfichero, repetir hasta que se llegue al final del fichero de datos y entonces visualizar el subfichero. Esta técnica es la mejor cuando se procesan un número relativamente pequeño de registros (un máximo de 50 o 60) que suelen corresponder a ficheros de tipo tablas. Emplear programas con subficheros completos no es aconsejable cuando se usa un mayor número de registros dado que la cantidad de tiempo necesaria para cargar el subfichero puede significar un tiempo de espera excesivo antes de efectuar la visualización, y por otra parte, el usuario quizás no necesite ver todos los registros para tomar una acción determinada. Desgraciadamente, muchos programas que tratan cientos de registros, están escritos bajo esta técnica, por ser la más cómoda en el momento de codificar. En este tipo de programas, la paginación está totalmente soportada por el propio sistema operativo.

Para emplear subficheros completos deberemos, en la definición del SFLCTL de la DDS, especificar el tamaño del subfichero (palabra clave SFLSIZ, que señala el total de registros del SFL) mayor que el tamaño de la página de visualización (palabra clave SFLPAG, que indica el número de lineas a visualizar por página). Cuando el SFLSIZ es mayor que el SFLPAG, el subfichero automáticamente se extiende cuando grabamos más registros de los indicados en el tamaño. Para que esta función tenga lugar, como mínimo deberá ser SFLSIZ = SFLPAG + 1. Ya que el SFLSIZ indica el número de registros que el SFL puede contener, también especifica la cantidad de espacio reservada en el disco en el momento de la creación del SFL. Si el subfichero se extiende, un espacio adicional del disco se reserva de nuevo para poder admitir más registros. Este puede ser un problema de rendimiento adicional en caso de paginación, puesto que estas extensiones no están juntas. Es mejor estimar un valor determinado para el tamaño del SFL, pero tampoco demasiado grande, un gran tamaño también implica disminución del rendimiento. La codificación de la figura 1 demuestra el concepto de subfichero completo. Los campos de su registro de subfichero y los campos del registro de control deberán incluirse en donde se indica. El indicador 61 se ha asignado al SFLCLR. Esto significa que el indicador 61 deberá ponerse en ON en el programa cuando el SFL tenga que borrarse. El indicador 62 se ha asignado al SFLDSP y se pone en OFF cada vez que se borra subfichero y solamente se pone en ON si se graba uno o más registros en el subfichero. Cuando el EXFMT del programa (figura 2) tiene lugar, si el *IN62 está en ON (al menos hay un registro en el SFL), el subfichero se visualiza. Esta técnica evita el error que se produce cuando se intenta visualizar un subfichero vacío. El código RPG para borrar, leer y visualizar el subfichero completo se muestra en la figura 2. El programa lee el fichero de base de datos FICHERO para visualizarlo mediante SFL. Se asume que el registro de control WSFLCTL incorpora un campo llamado ARG en donde el usuario puede entrar el argumento de búsqueda. En la sentencia 016, este argumento se usa para situar el fichero en el primer registro a recuperar. (IBM denomina a esta función "posicionar el cursor del fichero"). Cuando el programa se inicia, el registro de control se visualiza, solicitando al operador un argumento de búsqueda. En este punto el SFL no se visualiza porque no hay registros y por tanto, el *IN62 está apagado. Después de entrar el ARG y haber pulsado INTRO, el subfichero se borra y se carga. Una vez cargado el subfichero, el programa regresa a la sentencia 011, mediante un bucle controlado por un DOUNTIL (hasta que *INKC sea 1 - pulsado F3), para visualizar el registro de control; los registros del subfichero se visualizarán si el *IN62 se ha puesto en ON durante el proceso. El subfichero se borra en las sentencias 020-023, se carga en las sentencias 027-036 y se visualiza en la sentencia 011. En RPG, el proceso mediante número relativo de registro se define como parte de la definición SFILE, palabra clave situada en las columnas 54-59 de una línea de continuación (independiente) de las especificaciones de descripción de ficheros para el fichero WORKSTN descrito externamente. La definición SFILE implica un fichero de actualización controlado en cálculo con ADD para el subfichero. El número relativo de registro (NRR) se incrementa en la sentencia 033 y se restaura a ceros en la 021, cuando se borra el subfichero. Como el SFLSIZ es 20 y mayor que el SFLPAG, si se han procesado más de 20 registros, el subfichero se extiende automáticamente para que puedan añadirse todos los registros al SFL. El programa finaliza cuando el operador pulsa F3 (en la sentencia 011, sentencias anidadas 007-015-037-038 y la 042). Subficheros "página a página" Las ventajas de usar subficheros completos se basan en la comodidad de su programación y la paginación automática que facilita el OS. Los inconvenientes son, con un volumen relativamente grande de datos, el largo tiempo de espera del operador y el consumo de recursos del ordenador. Si el número de registros es pequeño, el impacto en el sistema también es pequeño. No obstante, si la cantidad de registros es grande, el consumo de recursos también lo es. Este problema se puede solucionar usando subficheros tratados "página a página", representando una solución mejor para

cuando se debe visualizar una gran cantidad de registros. La idea consiste en minimizar el tiempo de espera del operador en la carga de registros y en el consumo de recursos del ordenador. Con unos pocos cambios efectuados sobre el tratamiento de los subficheros completos es posible tratar subficheros "página a página", dándole al operador la impresión de que dispone de todo el fichero en todo momento. Un programa de subfichero tratado página a página prepara la primera página del subfichero y la visualiza al operador. Si se pulsa la tecla de Avance Página (Roll Up), el control vuelve al programa y este adiciona una segunda página al SFL y lo visualiza de nuevo. Si se pulsa Retroceder Página (Roll Down), el propio sistema operativo se encargará de retroceder a la primera página. Si en estas circunstancias se pulsa de nuevo Avance Página, el CPF paginará el subfichero a la segunda página. Si se insiste en Avanzar, la tercera página deberá añadirse y luego visualizarse. El truco consiste en añadir la tecla Roll Up en la DDS del fichero de pantalla. Esto hace que el CPF pagine el subfichero hacia adelante hasta que la última página añadida se visualice de forma similar a la de los subficheros completos. Sin embargo, si la última pagina se está visualizando y se pulsa de nuevo Avan Pág, el control vuelve al programa como si se hubiera pulsado una tecla de función cualquiera. El indicador asociado a la palabra clave ROLLUP se activa (ON) y el programa puede probar esta situación. La codificación para el subfichero página a página se muestra en las figuras 3 y 4. Es una versión modificada del código usado en el tratamiento de subficheros completos. En la DDS se ha añadido la línea 001 que activa la tecla Avan Pág y la asigna al indicador 60. También se ha añadido la línea 009 con un campo oculto (SFLRCD de cuatro Bytes numéricos con signo) con la palabra clave SFLRCDNBR. El campo se usa para posicionar el subfichero en la página adecuada durante la operación de visualización. En el RPG se incorporan pocos cambios: sólo las sentencias *016, *029, *038 y *042 diferencian un programa del otro. La lógica ha cambiado ligeramente para poder saltarnos la rutina de borrado del SFL cuando la tecla Avan Pág ha sido pulsada. Además, la rutina de lectura/carga del subfichero no se repite hasta que se acaba el fichero, sino que lee los próximos diez registros. Cuando se produce el EOF el indicador 99 se pone en ON y como el END de la sentencia 038 está condicionado a N99, el bucle finaliza cuando se alcanza el final de fichero. Si se produce EOF del FICHERO, como la línea 001 de la DDS está condicionada a N99, la palabra clave ROLLUP queda sin efecto y, si el operador solicita avanzar de nuevo, le aparecerá el mensaje normal de fin de subfichero. Al mismo tiempo impide que el programa intente leer más registros de los existentes. En la sentencia 042 el último NRR usado se sitúa en el campo SFLRCD asociado al SFLRCDNBR. Cuando se visualice el subfichero la palabra clave SFLRCDNBR hará que se visualice la página que contiene el numero relativo de registro cuyo valor numérico se halla en le campo SFLRCD. Si no se hubiera añadido esta función, cada vez que se visualizara el subfichero lo haría enseñando siempre la primera página. La mayor ventaja de esta técnica se obtiene cuando el operador se da por satisfecho con unas pocas páginas, si por el contrario pagina hacia adelante continuamente sin encontrar lo que busca, el consumo de recursos se asemeja al de los subficheros completos. Subficheros "de una página" El tercer tipo de tratamiento de subficheros es el mejor de todos y en algunos casos requiere muy poca codificación adicional (figuras 5 y 6), especialmente cuando la función de Retro Pág no es fundamental y puede implementarse a través de un reposicionamiento del fichero de base de datos mediante el uso del campo ARG (en el registro de control), en donde situaremos el nuevo argumento de búsqueda correspondiente a una página anterior. Si ello no es posible o no es adecuado, la mejor solución consistirá en tener este ARG dentro del propio subfichero, y una vez activado el indicador asociado a la tecla de retroceso (en la DDS, palabra clave ROLLDOWN), leer el primer registro del SFL para reposicionar el fichero de base de

datos y, desde allí, retroceder mediante READP, tantos registros como sea el tamaño de página, estando así, posicionados al inicio de la página anterior. La ventaja fundamental del uso de un subfichero "de una página" está en la poca cantidad de recursos, tanto en memoria como en disco, que emplea y en que, cuando SFLSIZ = SFLPAG puede emplearse "selección de campos", es decir, es la única forma en que podemos condicionar campos del SFL. Los principales inconvenientes vienen determinados porque el sistema operativo no soporta las funciones de paginación por lo que deberá ser el programa el que las controle mediante los indicadores asociados al ROLLUP y ROLLDOWN. Indudablemente, al planificar la pantalla hemos de tener en cuenta qué tipo de subfichero emplearemos y, además, cual será el diálogo del programa con el usuario. Si empleamos el campo ARG para un posicionamiento adecuado, tendremos que considerar si éste estará al pié del subfichero o al inicio del mismo; si está al pié y en el registro de control, la cabecera del subfichero deberá ser otro formato de pantalla y deberemos emplear OVERLAYs, etc. Como puede ver, cada método tiene sus ventajas e inconvenientes. El método a emplear dependerá de las necesidades de su aplicación y de la forma en que el subfichero será representado. Hasta aquí sólo hemos analizado los subficheros como un conjunto homogéneo de registros de salida a pantalla. En el próximo número, analizaremos el manejo y codificación de los subficheros con campos de entrada. Desde la forma más simple, el subfichero que incluye un campo de selección de registro para una función determinada (normalmente usados en un subprograma de selección de datos), hasta el más complejo, para entrar o actualizar datos en forma "masiva" mediante el empleo de un subfichero de entrada /salida. ==============================================================================

Epílogo a los subficheros ------------------------------------------------------------------------------ Los subficheros en la práctica Las aplicaciones interactivas mejoran sensiblemente si en su diseño incorporan funciones de subfichero, pero un uso inadecuado de los mismos puede ser la causa de una importante degradación en el rendimiento del sistema. - Tipos de subficheros Cuando codifique un subfichero de pantalla, el programador debe seleccionar el método apropiado para crear el subfichero, es decir, el método de extracción y almacenamiento de los registros del archivo de base de datos que se van a procesar mediante la técnica de subficheros. El método seleccionado dependerá de la aplicación y deberá tener en cuenta el rendimiento de los programas en el ordenador. En la primera parte de este artículo (HELP400 número 4) estudiamos con detalle la codificación de las DDS y RPG correspondientes a los tres métodos de paginación que resumimos a continuación. Si el número de registros a presentar es relativamente pequeño (unos cien por termino medio), lo más simple es leerlos todos y visualizarlos de una sola vez (a este método lo denominamos "subficheros completos"); si por el contrario, el número de registros a procesar es potencialmente grande, lo mejor será leer los registros necesarios para completar una página y, en caso de que el usuario desee ver más registros, al pulsar ROLLUP ceder el control al programa para que procese y añada una nueva página de registros al subfichero (le denominamos "subficheros página a página"); una tercera posibilidad consistirá en presentar siempre una nueva página de registros, el subfichero equivale a esta página (subficheros "de una página") y el programa deberá controlar tanto el retroceso como el avance de páginas. En el cuadro adjunto al final del artículo, tenemos unos pequeños apuntes que pretenden presentar, en un reducido resumen, lo más esencial de los subficheros. - Leyendo subficheros

Ahora que ya conocemos los diferentes tipos de subficheros y el impacto que pueden causar en el rendimiento del ordenador, echemos una mirada a las diferentes maneras de usarlos. Muchas veces el subfichero se emplea como visualización de una lista de registros para que el usuario pueda hacer una selección de entre los mismos. Por ejemplo, podemos escribir un programa con un subfichero para que visualice, por número de pedido, las notas de envío pendientes de confirmar e imprimir. En las líneas del subfichero podríamos poner el número de nota, la fecha, el número de cliente, la cantidad de líneas de la nota y el valor actual de la misma. Adicionalmente, podríamos situar un campo de entrada de una sola posición, a la izquierda de cada registro del subfichero, para que el usuario pudiera entrar un código de acción. El usuario podría poner una "C" en varios de los registros visualizados para confirmar e imprimir varias notas a la vez. Para que el proceso pueda continuar, el programa ha de ser capaz de leer los registros que han sido modificados en el subfichero. El método usado para leer los registros modificados es francamente cómodo. En RPG, el código de operación usado para leer registros modificados de un subfichero es el READC. La operación READC, empleada dentro de un bucle, efectúa una lectura de cada registro modificado y hace que los datos del registro modificado del subfichero "entren de nuevo" en el programa. Un registro se considera modificado si algún dato (incluido blancos) se entra desde el teclado en un campo del registro del subfichero que sea susceptible de entrada. El hecho de modificar uno o varios campos en un registro de pantalla altera el contenido de un campo interno del registro de pantalla, llamado "Modified Data TAG" (MDT -un simple bit por cada uno de los campos de la pantalla). El bit correspondiente se pone en ON si el campo ha sido modificado por el usuario de la pantalla. Si un MDT está en ON para un campo del subfichero, el registro se considera modificado y por tanto, el READC lo procesará. Si un registro no ha sido modificado por el usuario, no podrá ser recuperado usando el código de operación READC. Asumamos que el método empleado para cargar y representar el subfichero en pantalla es el que hemos denominado "página a página", la figura 7 nos muestra la codificación del programa en RPG, resaltando la rutina empleada para leer y procesar los registros cambiados del subfichero. Si se recupera un registro, el campo de entrada SEL se compara mediante un grupo CASE con "C" y si coincide, se ejecutará la subrutina correspondiente. Si el usuario ha entrado cualquier otro código (incluido blancos) en el campo de selección, el registro se considerará modificado y también será recuperado por el READC, por eso debe probarse el campo SEL con los valores predeterminados. Por supuesto, se puede extender el grupo CASE para que ejecute otras subrutinas en función de otros códigos predeterminados para el programa, en nuestro ejemplo podríamos incorporar una "R" para revisar alguna nota de las no confirmadas y, eventualmente, modificarla o completarla. El uso más generalizado de esta técnica suele ser el empleado en subprogramas de selección. En el programa principal hay una serie de campos que pueden ser llenados a partir de un subprograma con un subfichero de selección. La técnica empleada para llamar al subprograma puede variar según la metodología de la empresa, pero el mecanismo siempre es el mismo. Supongamos que el usuario desconoce el valor a introducir. En el campo de entrada puede teclear un "?" y pulsar INTRO (como en los mandatos de nuestro sistema operativo), el programa principal llama entonces al subprograma adecuado que interrumpirá la pantalla (o bien abrirá una ventana en la misma), ofreciendo un subfichero de selección. La recuperación mediante READC del registro seleccionado, permitirá devolver al programa principal el valor adecuado empleando PARMS. Por ejemplo (figura 8), supongamos que el campo a rellenar corresponde al código de los diferentes lugares de entrega para un cliente determinado; el "?" llamará al subprograma pasando el código de cliente empleando un primer PARM. El subprograma, mediante SETLL y READE, montará un subfichero con todos los lugares de entrega del cliente indicado (en este caso parece indicado emplear la técnica de subfichero "completo") y los mostrará en pantalla para que el usuario seleccione el adecuado.

Después de leído y procesado el registro cambiado, el código del lugar de entrega se pasa al programa principal mediante un segundo PARM. - Usando el SFLNXTCHG La correcta interpretación de la función de esta palabra clave asociada a la DDS de un subfichero, puede ser difícil si no se siguen detenidamente unos pocos ejemplos que expliquen su uso más habitual. Tomemos de nuevo el ejemplo de las notas no confirmadas. Asumamos que lo que pretendemos es que nuestro programa confirme e imprima automáticamente todas las notas que tengan menos de diez líneas, a excepción de aquellas que explícitamente nos señale el usuario, y que para ello, y sólo como ejemplo explicativo del uso del SFLNXTCHG, vamos a emplear una técnica parecida a la del programa de la figura 7. La primera cosa que necesitaríamos hacer es que el programa pusiera una "C" en el campo de selección SEL (definido como de entrada/salida) en el momento en que cada uno de los registros fuera grabado en el subfichero. Esto cumpliría el requisito de una "C" para la rutina de confirmación. Puesto que el usuario no modifica los registros del subfichero, la operación READC no recuperará ni procesará los registros marcados con una "C". La solución para recuperar estos registros consiste en emplear la palabra clave SFLNXTCHG en el registro de control de la DDS, que, si está activada cuando grabamos el registro en el subfichero, hará que este registro se comporte (en la próxima lectura) como si hubiera sido modificado por el usuario. La palabra clave SFLNXTCHG puede ser activada para cada registro (individualmente) en el momento en que éste se graba en el subfichero. Así el READC recuperará el registro y la nota se confirmará e imprimirá automáticamente. Si el usuario decide no confirmar una o varias notas determinadas, puede blanquear el código "C". El READC recuperará también estos registros "blanqueados", pero como el campo SEL está en blanco, no actuará la rutina de confirmación. Supongamos que la aplicación requiere que el campo de total líneas parpadee cuando la nota de entrega sea inferior a diez líneas. Esta es una tarea simple porque los atributos de campo pueden emplearse también con los registros del subfichero. La función de parpadeo se activa usando en la DDS la palabra clave DSPATR(BL). En la DDS de la figura 9 el campo TOTLIN tiene DSPATR(BL) condicionado por el indicador 41. El indicador 41 se pone en ON si el total de líneas es menor que 10, haciendo que el campo parpadee al grabarse en el subfichero con este indicador activado. El registro de control del subfichero debe tener la palabra clave SFLNXTCHG condicionada por un indicador, en nuestro ejemplo está condicionada por el indicador 40. El código RPG de la figura 10 complementa nuestra DDS y vemos que, para cada registro que se lee del archivo de base de datos, se compara el total de líneas, si el total de líneas es inferior a 10, se activan los indicadores 40 y 41 y se mueve una "C" al campo SEL. Si son 10 o más las líneas de la nota, es necesario restablecer los indicadores y dejar en blanco el campo SEL antes de grabar el registro en el subfichero. - El SFLNXTCHG en la depuración de errores La palabra SFLNXTCHG también puede usarse para efectuar la depuración de errores en los campos de entrada de los registros del subfichero. Si no empleamos el SFLNXTCHG, los errores pueden entrar en nuestro sistema de una forma totalmente incontrolada. Veamos un ejemplo en donde el usuario actualiza, mediante el uso de un subfichero, el código de situación de un cliente determinado. Cuando pulsa INTRO, el programa ejecuta un bucle con READC para obtener los registros modificados. En este momento se comprueba la validez del código de situación para este tipo de cliente (se entiende que no puede validarse desde la DDS con VALUE, RANGE, etc.). Si no es válido, el programa pone en ON un indicador para el mensaje de error y cuando todos los registros han sido procesados, si el indicador de error está activado, se visualizará de nuevo el subfichero. En este momento el usuario puede, en lugar de repasar y cambiar los registros erróneos, pulsar simplemente INTRO de nuevo y, como

los registros no han sido modificados, el bucle READC no los procesará, por tanto, la técnica empleada en el párrafo anterior es inadecuada. La solución correcta para el tratamiento de errores (figura 11) consistirá en activar, además del indicador general de errores, un indicador individual que condicione un DSPATR(RI) para cada campo erróneo y un indicador único para condicionar un SFLNXTCHG, y a continuación, actualizar en el subfichero el registro que se está procesando con estos indicadores activados. El contenido de los campos no tiene por qué variar (al menos que se desee hacerlo expresamente) pero los MDTs del registro actualizado con SFLNXTCHG estarán activos, haciendo que en la próxima lectura, una vez dado el INTRO, se lea de nuevo este registro como si hubiera sido variado por el usuario, independientemente de que el usuario corrija o no los errores. - Otras consideraciones Desde el momento en que sabemos controlar los posibles errores de una entrada de datos efectuada a través de un subfichero, podemos concebir programas cuya función principal sea la entrada y/o modificación de registros en un determinado archivo de base de datos. Normalmente esta posibilidad inquieta a más de un programador experimentado que preferirá emplear un registro de entrada/actualización al pie de la pantalla y un subfichero que vaya representando los registros tratados. No es que esta técnica no sea válida, al contrario, en muchos casos suele ser la mejor solución, pero nunca debemos descartar otras posibilidades por miedo a posibles complicaciones que por otra parte, sólo se presentarán en caso de tener poca práctica. Si la cantidad de registros a procesar es reducida y el riesgo de pérdida de datos, mínimo, el mejor sistema será emplear un subfichero. Para ello usaremos un subfichero "completo" que, si lo usamos para una entrada pura, deberemos inicializar mediante el SFLINZ. El usuario irá añadiendo todos los datos de cada uno de los registros y cuando pulse INTRO, estos se depurarán y procesarán adecuadamente mediante un bucle de READC. Esta técnica puede emplearse perfectamente en un programa de entrada de pedidos en donde sabemos que la cantidad de líneas no será excesiva. Un poco más complejo resultará el programa de modificación de más de un registro a la vez y que use un subfichero para ello. Mi técnica favorita consiste en inicializar primero el subfichero y luego cargarle, mediante CHAIN por NRR y UPDAT, los registros leídos de la base de datos. La forma en que luego los registros del subfichero "vuelven" al archivo de base de datos, dependerá principalmente de si han habido supresiones y/o adiciones de nuevas líneas, si en el subfichero se han añadido más, estos deberán adicionarse al archivo y si hay menos, los que sobran de la base de datos deberán suprimirse. El método usado depende de los requisitos del programa de la aplicación que se esté desarrollando y de la forma en que los datos del subfichero serán representados. El dominio de los subficheros puede representar un empujón significativo en la productividad de programación, y si se codifican y usan adecuadamente, la incidencia en el rendimiento del ordenador será mínima. --- CUADRO RESUMEN SUBFICHEROS Permiten manejar en pantalla múltiples registros del mismo tipo mediante teclas ROLL controladas desde el CPF o desde el PGM. - DOS FORMATOS EN LA DDS: SFL: Contiene los campos a aparecer bajo el control del CTL SFLCTL: Hace que tengan lugar las operaciones físicas (preparación, representación, lectura), puede además, contener campos propios.

- MINIMO DE PALABRAS CLAVE ASOCIADAS (EN EL SFLCTL): SFL ........... define los campos del SUBFILE SFLCTL......... define el CONTROL del subfile SFLSIZ......... tamaño subfile en disco SFLPAG......... tamaño página en pantalla SFLDSPCTL ..... visualizar SFLCTL y sus campos SFLDSP ........ visualizar los registros del SFL SFLCLR ........ limpiar SFL - OTRAS PALABRAS CLAVE FRECUENTES: SFLEND (+) registros en SFL SFLINZ para inicializar todo el SFL SFLLIN indicar espacio entre columnas SFLDLT para que pgm lo suprima SFLDROP doblar o truncar registros SFLRCDNBR página a visualizar s/NRR - TRES TECNICAS DIFERENTES DE ALMACENAMIENTO: SFLSIZ= SFLPAG ... Máximo prestaciones, control completo por pgm SFLSIZ= SFLPAG + 1 Prestaciones normales, control CPF y pgm SFLSIZ= SFLPAG * x Prestaciones s/num. registros, control TOTAL por CPF. - FORMA SIMPLE: Control ROLLs por CPF (Sólo para SFLs pequeños < 100 reg.) Las prestaciones disminuyen si la carga inicial es grande o el espacio no es contiguo. - FORMA MIXTA: Control ROLLUP por pgm y ROLLDOWN por CPF. En ambos casos se define el SFLSIZ mayor que el SFLPAG. El CPF extiende el espacio del SFL automáticamente pero decrece el rendimiento. - FORMA COMPLEJA: Control de la paginación por programa. (SFLSIZ = SFLPAG) hay funciones (condicionado de campos del SFL, etc.) sólo validas en esta modalidad. - OPERACIONES BASICAS a realizar por el PGM: * Leer registros de un fichero, WRITE de uno en uno en el SFL * Enviar el SFL a pantalla mediante operación salida del SFLCTL * Leer el SFLCTL después de que el usuario haya revisado, modificado o añadido registros (dependiendo de la función del SFL) * Procesar cada registro del SFL individualmente. - SUBFICHEROS EN RPG El SFILE implica proceso mediante NRR de un fichero de actualización controlado en cálculo con ADD. Las operaciones válidas para el registro del subfichero son: CHAIN, UPDAT, WRITE y READC. Las operaciones en pantalla van controladas a través del SFLCTL. Alberto C. Blanch ============================================================================== HELPNET -> Un servicio informativo para los suscriptores de la revista HELP400 ==============================================================================

Archivo: figura_01.dsp

SUBFIC_A DSPF Pantala de subfichero A* Figura 1 A* A R WSFL SFL A* A* INSERTE LOS CAMPOS DE SU SUBFICHERO AQUI A* A R WSFLCTL SFLCTL(WSFL) A SFLSIZ(0020) A SFLPAG(0010) A CA03(03 'Salir') A N61 62 SFLDSP A N61 SFLDSPCTL A 61 SFLCLR A* A* INSERTE LOS CAMPOS DE SU REG. DE CONTROL AQUI A*

Página: 1

Archivo: figura_02.rpg

SUBFIC_A RPG Ejemplo de programa de tratamiento de subficheros F*/FILE F* Figura 2 FWRKSTN CF E WORKSTN F NRR KSFILE WSFL FFICHERO IF E K DISK C*/CALC C* C*-- EJECUTAR HASTA QUE SE PULSE F3 C*-- ---------------------------------- C*--HASTA CA03 C *INKC DOUEQ*ON C* C*-- REPRESENTAR PANTALLA C*-- -------------------- C*--- DISPLAY C EXFMTWSFLCTL C* C*-- POSICIONARSE EN EL FICHERO CON ARGUMENTO BUSQUEDA (SI NO F3) C*-- ---------------------------------------------------------------- C*--- NO CA03 C *INKC IFEQ *OFF C*--- 1ER REG C ARG SETLLFICHERO C* C*-- CLEAR SUBFILE C*-- ------------- C*--- IN 61-62 C MOVE *ON *IN,61 C MOVE *OFF *IN,62 C*--- INIT C Z-ADD*ZEROS NRR 50 C*--- SFLCLR C WRITEWSFLCTL C*--- IN 61-62 C MOVE *OFF *IN,61 C MOVE *OFF *IN,62 C* C*-- LEER FICHERO DATOS C*-- ------------------ C*--- HASTA EOF C *IN99 DOUEQ*ON C*--- READ C READ FICHERO 99 C* C*-- WRITE REGISTRO AL SUBFILE SI NO FIN-DE-FICHERO (EOF) C*-- ---------------------------------------------------- C*--- NO EOF C *IN99 IFEQ *OFF C*--- IND.POSIT C ADD 1 NRR 50 62 C*--- WRITE C WRITEWSFL C ENDIF C ENDDO C ENDIF C ENDDO C* C*-- TERMINAR PROGRAMA C* C*--- TERMINAR

Página: 1

Archivo: figura_02.rpg

C MOVE *ON *INLR

Página: 2

Archivo: figura_03.dsp

SUBFIC_B DSPF Pantala de subfichero * Figura 3 * A N99 ROLLUP(60) A R WSFL SFL * * INSERTE LOS CAMPOS DE SU SUBFICHERO AQUI * A R WSFLCTL SFLCTL(WSFL) A SFLSIZ(0011) A SFLPAG(0010) A CA03(03 'SALIR') A N61 62 SFLDSP A N61 SFLDSPCTL A 61 SFLCLR A SFLRCD 4S 0H SFLRCDNBR * INSERTE LOS CAMPOS DE SU REG. DE CONTROL AQUI

Página: 1

Archivo: figura_04.rpg

SUBFIC_B RPG Programa de subficheros F*/FILE F* Figura 4 FWRKSTN CF E WORKSTN F NRR KSFILE WSFL FFICHERO IF E K DISK C*/CALC C* C*-- EJECUTAR HASTA QUE SE PULSE MDTO-3 C*-- ---------------------------------- C*--HASTA CA03 C *INKC DOUEQ'1' C* C*-- REPRESENTAR PANTALLA C*-- -------------------- C*--- DISPLAY C EXFMTWSFLCTL C* C*-- POSICIONARSE EN EL FICHERO CON ARGUMENTO BUSQUEDA (SI NO MDTO-3) C*-- ---------------------------------------------------------------- C*--- NO CA03 C *INKC IFEQ '0' C*--- NO ROLL C *IN60 IFEQ '0' C*--- 1ER REG C ARG SETLLFICHERO C* C*-- CLEAR SUBFILE C*-- ------------- C*--- IN 61-62 C MOVEA'10' *IN,61 C*--- INIT C Z-ADD0 NRR 50 C*--- SFLCLR C WRITEWSFLCTL C*--- IN 61-62 C MOVEA'00' *IN,61 C ENDIF C* C*-- LEER FICHERO DATOS C*-- ------------------ C*--- 10 REGS. C DO 10 C*--- READ / EOF C READ FICHERO 99 C* C*-- WRITE REGISTRO AL SUBFILE SI NO FIN-DE-FICHERO (EOF) C*-- ---------------------------------------------------- C*--- NO EOF C *IN99 IFEQ '0' C*--- IND.POSIT C ADD 1 NRR 62 C*--- WRITE C WRITEWSFL C ENDIF C N99 ENDDO C* C*-- INICIALIZAR EL SFLRCDNBR PARA POSICIONAR PAGINA C*-- ----------------------------------------------- C*--- INICIAR C Z-ADDNRR SFLRCD

Página: 1

Archivo: figura_04.rpg

C ENDIF C ENDDO C*-- TERMINAR PROGRAMA C*--- TERMINAR C MOVE '1' *INLR

Página: 2

Archivo: figura_05.dsp

SUBFIC_C DSPF Pantala de subfichero * Figura 5 * A ROLLUP(60) A R WSFL SFL * * INSERTE LOS CAMPOS DE SU SUBFICHERO AQUI * A R WSFLCTL SFLCTL(WSFL) A SFLSIZ(0010) A SFLPAG(0010) A CA03(03 'SALIR') A N61 62 SFLDSP A N61 SFLDSPCTL A 61 SFLCLR * * INSERTE LOS CAMPOS DE SU REG. DE CONTROL AQUI

Página: 1

Archivo: figura_06.rpg

SUBFIC_D RPG Programa de subfichero F*/FILE F* Figura 6 FWRKSTN CF E WORKSTN F NRR KSFILE WSFL FFICHERO IF E K DISK C*/CALC C* C*-- EJECUTAR HASTA QUE SE PULSE MDTO-3 C*-- ---------------------------------- C*--HASTA CA03 C *INKC DOUEQ'1' C* C*-- REPRESENTAR PANTALLA C*-- -------------------- C*--- DISPLAY C EXFMTWSFLCTL C* C*-- POSICIONARSE EN EL FICHERO CON ARGUMENTO BUSQUEDA (SI NO MDTO-3) C*-- ---------------------------------------------------------------- C*--- NO CA03 C *INKC IFEQ '0' C*--- NO ROLL C *IN60 IFEQ '0' C*--- 1ER REG C ARG SETLLFICHERO C ENDIF C* C*-- CLEAR SUBFILE C*-- ------------- C*--- IN 61-62 C MOVEA'10' *IN,61 C*--- INIT C Z-ADD0 NRR 50 C*--- SFLCLR C WRITEWSFLCTL C*--- IN 61-62 C MOVEA'00' *IN,61 C* C*-- LEER FICHERO DATOS C*-- ------------------ C*--- 10 REGS. C DO 10 C*--- READ / EOF C READ FICHERO 99 C* C*-- WRITE REGISTRO AL SUBFILE SI NO FIN-DE-FICHERO (EOF) C*-- ---------------------------------------------------- C*--- NO EOF C *IN99 IFEQ '0' C*--- IND.POSIT C ADD 1 NRR 62 C*--- WRITE C WRITEWSFL C ENDIF C N99 ENDDO C* C ENDIF C ENDDO C*-- TERMINAR PROGRAMA C*--- TERMINAR C MOVE '1' *INLR

Página: 1

Archivo: figura_07.rpg

SUBFIC_E RPG Programa de subfichero F*/FILE F* Figura 1: Ejemplo empleo READC F* FWRKSTN CF E WORKSTN F NRR KSFILE WSFL FARCHIVO IF E K DISK FLIST O F 180 OF PRINTER C*/CALC C*--- Inicio C*--INICIALIZA C MOVE *LOVAL ARG C* C*--HASTA CA03 C *INKC DOUEQ'1' C*--- DISPLAY C EXFMTWSFLCTL C* C*--- Procesar C* C*--- NO CA03 C *INKC IFEQ '0' C*--- NO ROLL C *IN60 IFEQ '0' C* C*--- Leer posibles cambiados C* C*-- <-- C NRR IFNE 0 C*--- UNTIL EOF . C *IN92 DOUEQ'1' C*--- LEER CAMBIO . C READCWSFL 92 C*--- HAY CAMBIOS . C *IN92 IFEQ '0' C*--->CONFIRMAR . C SEL CASEQ'C' SRCONF C*-- . C ENDCS C*-- . C ENDIF C*-- . C ENDDO C*-- <-- C ENDIF C* C*--- Posiciona y Nuevo Sfl C* C ARG SETLLARCHIVO C*--- IN 61-62 C MOVEA'10' *IN,61 C*--- INIT C Z-ADD0 NRR 30 C*--- SFLCLR C WRITEWSFLCTL C*--- IN 61-62 C MOVEA'00' *IN,61 C ENDIF C*--- Leer/Cargar C DO 10 C*--- READ

Página: 1

Archivo: figura_07.rpg

C READ ARCHIVO 99 C*--- NO EOF C *IN99 IFEQ '0' C*--- HAY REGS C ADD 1 NRR 62 C*--- WRITE SFL C WRITEWSFL C ENDIF C*--->ENDDO C N99 ENDDO C*--- Situar C*--- SFLRCDNBR C Z-ADDNRR SFLRCD C*--- INKC = 0 C ENDIF C ENDDO C* C*--- Terminar PGM C* C*--- TERMINAR C MOVE '1' *INLR C RETRN C*-------------------------------------------------------------------* C*-- SRCONF: CONFIRMAR NOTAS / ACTUALIZAR ARCHIVO * C*-------------------------------------------------------------------* C SRCONF BEGSR C*--...

Página: 2

Archivo: figura_08.rpg

SUBFIC_G RPG Programa de subfichero * Subprograma de seleccion * F*/FILE FWRKSTN CF E WORKSTN F NRR KSFILE WSFL FLUGARES IF E K DISK C*/CALC C*-- Parametros de enlace C* C *ENTRY PLIST C PARM PCODCL C PARM PLUGAR 2 C*-- Clave C KEY KLIST C KFLD PCODCL C*-- Borrar Sfl C*--- IN 61-62 C MOVEA'10' *IN,61 C*--- INIT C Z-ADD0 NRR 50 C*--- SFLCLR C WRITEWSFLCTL C*--- IN 61-62 C MOVEA'00' *IN,61 C* C*-- Posicionar C* C MOVE *BLANK SEL C KEY SETLLLUGARES C* C*-- Leer y cargar hasta fin-de-grupo C* C*--- HASTA EOG C *IN99 DOUEQ'1' C*--- READ C KEY READELUGARES 99 C*--- NO EOF C *IN99 IFEQ '0' C*--- 62=DISPLAY C ADD 1 NRR 62 C*--- WRITE C WRITEWSFL C ENDIF C ENDDO C* C*-- Representar y leer posible marcado C* C EXFMTWSFLCTL C*-- Leer marcado C*-- EOF C READCWSFL 65 C *IN,65 IFEQ *OFF C MOVE LUGAR PLUGAR C ENDIF C*-- Fin programa C SETON LR C LR RETRN

Página: 1

Archivo: figura_08a.rpg

SUBFIC_F RPG Programa de subfichero * Figura 2: Ejemplo subprograma de selecci¢n * Programa Principal C*/CALC C* C WLUGAR IFEQ '? ' C CALL 'SUBPGM' C PARM CODCLI PCODCL C PARM PLUGAR C PLUGAR IFNE *BLANKS C MOVE PLUGAR WLUGAR C ENDIF C ENDIF

Página: 1

Archivo: figura_09.dsp

SUBFIC_G DSPF Pantala de subfichero * Figura 3: Ejemplo de la DDS * A R WSFL SFL A TOTLIN A 41 DSPATR(BL) * Inserte otros campos aqui * A R WSFLCTL SFLCTL(WSFL) A SFLSIZ(0011) A SFLPAG(0010) A CA03(03 'SALIR') A N61 62 SFLDSP A N61 SFLDSPCTL A 61 SFLCLR A 40 SFLNXTCHG * Campos del Reg. de control

Página: 1

Archivo: figura_10.rpg

SUBFIC_I RPG Programa de subfichero C*/CALC C*-- Figura 4.: Codificaci¢n en RPG C* C*--- HASTA EOF C *IN99 DOUEQ'1' C*--- EOF C READ ARCHIVO 99 C*--- HAY C *IN99 IFEQ '0' C* C*--- < 10 C TOTLIN IFLT 10 C*--- MARCAR C MOVE 'C' SEL C*--- SFLNXTCHG C MOVE '1' *IN40 C*--- DSPATR(BL) C MOVE '1' *IN41 C*--- INCREMENTA C ADD 1 NRR C WRITEWSFL C*--- RESTAURA C MOVE ' ' SEL C*--- " C MOVE '0' *IN40 C*--- " C MOVE '0' *IN41 C ENDIF C ENDIF C ENDDO C*

Página: 1

Archivo: figura_11.rpg

SUBFIC_C RPG Programa de subfichero * Figura 5: Depuraci¢n de errores * C*/CALC C*--- DEPURACION C VERIF BEGSR C SETOF 72 C *IN72 DOWEQ'0' C READCWSFL 72 C *IN72 IFEQ '0' C MOVEA*ZEROS *IN,91 C* C*--- ERROR C CODSIT COMP 'A' 9191 C*--- ERROR C CANT COMP *ZEROS 92 C* C 91 C*--55=SFLMSG COR 92 SETON 4055 C UPDATWSFL C*--40=SFLNXTCHG C SETOF 40 C*--<- IN72=0 C ENDIF C*--<- DOW C ENDDO C ENDSR C*--------------------------------------------------------------------*

Página: 1