Anda di halaman 1dari 55

Manual Cobol

Esquema de un programa cobol


Los programas cobol se dividen en partes llamadas "DIVISION" que a su vez se separan en secciones llamadas "SECTION". Vamos a ver el esquema bsico que todo programa cobol debe tener: IDENTIFICATION DIVISION. PROGRAM-ID. PRUEBA1. Nombre del programa. Debe coincidir con el nombre externo del programa. ENVIRONMENT DIVISION. CONFIGURATION SECTION. SPECIAL-NAMES. DECIMAL-POINT IS COMMA. Nosotros usamos los puntos como separadores de miles y la coma como el separador de decimales. INPUT-OUTPUT SECTION. FILE-CONTROL. En esta parte se definen los ficheros en caso de que los haya. SELECT FICHERO1 Nombre de fichero. ACCES MODE IS SEQUENTIAL Tipo de acceso: SEQUENTIAL para los planos, INDEXED para los indexados. FILE STATUS IS FS-FICHERO1 Variable donde guardar el file-status (cdigo de control de errores de acceso a ficheros). DATA DIVISION. FILE SECTION. FD FICHERO1 RECORDING MODE IS F Fichero con longitud fija. Si fuese de longitud variable pondramos V. BLOCK CONTAINS 0 RECORDS RECORD CONTAINS 129 CHARACTERS. Longitud del fichero. 01 REG-FICHERO1 PIC X(129). Donde guardaremos la informacin. WORKING-STORAGE SECTION. En ella definimos las variables que usaremos en el programa. 01 WX-VARIABLE PIC X. Definicin de variables lo veremos ms adelante. LINKAGE SECTION. rea de comunicacin con otros programas 01 AREA-LINKAGE PIC X.

PROCEDURE DIVISION. / PROCEDURE DIVISION USING AREA-LINKAGE. Si hay un rea definida en la linkage debemos incluir el USING en la procedure. Aqu es donde va el programa en s. La estructura general ser: 0000-PRINCIPAL. PERFORM 1000-INICIO PERFORM 2000-PROCESO UNTIL CUMPLE-CONDICION PERFORM 3000-FINAL . La numeracin de prrafos suele ser esa, pero cada empresa puede tener su propia nomenclatura estndar. El proceso en un programa se suele repetir n veces, hasta que se cumple la condicin indicada en el UNTIL. En el prrafo de final se incluye la instruccin de finalizacin de ejecucin: STOP RUN para programas principales. GOBACK para rutinas. Se pueden definir tantos prrafos como queramos, pero la estructura de todos ellos ser la siguiente: 1000-INICIO. cdigo con instrucciones a realizar . Es decir, todos los prrafos terminan con un punto "." que indica el final de prrafo. A tener en cuenta: En cobol no podemos empezar a escribir donde queramos, pues cada cosa tiene su sitio^^ Un programa cobol mide de ancho 80 posiciones, aunque slo escribiremos hasta la 72.
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-01 WX-CAMPOS. 05 WX-CAMPO1 PIC X. 05 WX-LITERAL PIC X(40) VALUE 'LITERAL TAN GRANDE QUE NO CABE ' 'EN UNA LINEA Y LO TENEMOS QUE PARTIR'. * PROCEDURE DIVISION. ****************************************************************** 00000-PRINCIPAL. * PERFORM 10000-INICIO.

* De la posicin 1 a la 6: no se codifica nada. * Posicin 7: se escribir un * si queremos comentar la lnea. En caso de que un texto no nos quepa en una lnea, se escribir en esta posicin un guin "-" para continuarlo. * De la posicin 8 a la 11: se denomina rea A. Aqu escribiremos las "divisiones" y "secciones", los niveles 01 y los descriptores de ficheros "FD". * De la 12 a la 72: se denomina rea B. Aqu se escribirn el resto de instrucciones del programa, y los niveles 05 en adelante. * De la 73 a la 80: no se codifica nada.

Esto que acabamos de ver es algo muuuuy general, pero iremos vindolo mejor con ejemplos.

Y hasta aqu la primera leccin. En el siguiente artculo veremos la WORKING-STORAGE, donde se definen las varibles que vamos a usar a lo largo del programa. Veremos los diferentes tipos de variables, el clculo de longitudes y como se visualizan en un fichero.

WORKING-STORAGE: definiendo variables.


Las variables que se usan en un programa cobol deben haber sido previamente definidas en la WORKING-STORAGE SECTION. Existen diferentes tipos de variables en cobol. Cada variable que definamos debe terminar con un punto ".". Si la variable va a tener un valor inicial lo indicaremos con la clusula VALUE. Alfanumricas: se indican con un PIC X(nmero de caracteres). Podrn tener como valores nmeros y letras. 01 WX-VARIABLE-ALFNUM PIC X(10) VALUE 'LOQUESEA10'. Numricas normales: se indican con un PIC 9(nmero de dgitos). Slo tendrn valor numrico. La V indica la coma decimal. 01 WX-VARIABLE-NUM PIC 9(5)V9(2) VALUE 12345,67. (value sin las comillas) Numricos comprimidos: se indican con un PIC 9(nmero de dgitos) COMP-3. Slo valores numricos. Estas variables ocuparn, en espacio, menos que un numrico normal. El clculo de longitudes lo veremos ms adelante. La S indica que lleva signo decimal que puede ser positivo o negativo. 01 WX-VARIABLE-COMP3 PIC S9(5)V9(2) COMP-3 VALUE 12345,67. Numricos hexadecimales: se indican con un PIC 9(nmero de dgitos) COMP. Slo valor numrico. OJO! Aceptan letras porque el nmero va en formato hexadecimal, pero eso no significa que podamos informarlas con caracteres alfabticos. 01 WX-VARIABLE-COMP PIC 9(5)V9(2) COMP VALUE 12345,67. Editados: se indican con la clusula PIC seguida por tantas "zetas" Z como necesitemos. Se utilizan para dar formato a campos numricos. 01 WX-VARIABLE-EDI PIC -Z.ZZZ.ZZ9,99. Esto equivaldra a un campo numrico PIC S9(7)V9(2). El ltimo dgito antes de la coma decimal se indica con un 9 para que aparezca el valor numrico del 0 al 9. Las Zs sustituirn los "ceros" 0 a la izquierda por espacios. 01 WX-VARIABLE-NUM PIC S9(7)V9(2) VALUE -0001234,56. 01 WX-VARIABLE-EDI PIC -Z.ZZZ.ZZ9,99 DISPLAY 'WX-VARIABLE-NUM:'WX-VARIABLE-NUM MOVE WX-VARIABLE-NUM TO WX-VARIABLE-EDI DISPLAY 'WX-VARIABLE-EDI:'WX-VARIABLE-EDI

El resultado sera: WX-VARIABLE-NUM:00012345O WX-VARIABLE-EDI:1.234,56

Ahora que sabemos definir variables, vamos a ver que las variables pueden estar definidas en diferentes "niveles". Estos niveles vienen indicados por un nmero a la izquierda: 01 WX-INFORMACION-PERSONA. 05 WX-NOMBRE PIC X(10). 05 WX-APELLIDO1 PIC X(10). 05 WX-APELLIDO2 PIC X(10). 05 WX-DIRECCION. 10 WX-CALLE PIC X(10). 10 WX-NUMERO PIC 9(3). 10 WX-PISO PIC 9(2). Y as sucesivamente. Si tenemos algn subnivel que sea una constante, en lugar de ponerle nombre al campo podemos utilizar la clusala FILLER: 01 WX-FECHA. 05 WX-DIA 05 FILLER 05 WX-MES 05 FILLER 05 WX-ANO PIC PIC PIC PIC PIC 9(2). X VALUE '-'. 9(2). X VALUE '-'. 9(4).

La diferencia del FILLER con un campo "con nombre", es que el FILLER no se puede utilizar para "mover" la informacin que contenga. Es un campo fijo (la traduccin sera "RELLENO") que no se puede informar (a no ser que informsemos el nivel superior y nos cargsemos todo, claro... xd). El resultado del campo informado sera por ejemplo: Fecha = 01-01-2011 Existe una forma de definir variables con dos o ms tipos de formato (PIC) distintos. Se trata de la clusula REDEFINES. Se suele utilizar para evitar mover campos alfanumricos a numricos, o bien para agrupar un campo que tenga subniveles: 01 WX-CAMPO1 PIC X(3). 01 WX-CAMPO2 REDEFINES WX-CAMPO1 PIC 9(3). 01 WX-CAMPO1. 05 WX-SUBCAMPO1 PIC X(3). 05 WX-SUBCAMPO2 PIC 9(5). 01 WX-CAMPO2 REDEFINES WX-CAMPO1 PIC X(8). IMPORTANTE: slo se pueden "redefinir" campos que estn al mismo nivel, es decir, para redefinir un campo de un nivel 01, tendremos que hacerlo en otro campo de nivel 01.

Tambin podemos definir tablas o arrays: 01 WX-TABLA-INTERNA OCCURS 5 TIMES. 05 WX-CAMPO1 PIC X VALUE 'A'. 05 WX-CAMPO2 PIC X VALUE 'B'. De tal manera que el conjunto de los campos 1 y 2 se repiten 5 veces: ABABABABAB Existen otro tipo de niveles que son los niveles "88": 01 WX-RESPUESTA PIC X. 88 RESPUESTA-SI VALUE 'S'. 88 RESPUESTA-NO VALUE 'N'. De tal forma que la variable WX-RESPUESTA podr tomar los valores S N segn queramos. Para hacer que la variable tome un valor: SET RESPUESTA-SI TO TRUE SET RESPUSETA-NO TO TRUE tomar el valor S. tomar el valor N.

Imaginemos que tenemos una serie de campos que definen la estructura de un fichero. Si tenemos varios programas que usan ese fichero, tendremos que escribir esos campos tantas veces como programas tengamos. Para ahorrarnos trabajo tenemos la clusula COPY. Una "COPY" es un trozo de cdigo cobol que puede contener la definicin de variables (COPY de WORKING) o una parte del cdigo del programa (COPY de PROCEDURE): COPY WORKING Se incluirn dentro de la WORKING-STORAGE. COPY WSCOPY. Donde WSCOPY contendr algo de este estilo: 01 WX-WSCOPY. 05 WX-CAMPO1 PIC X(5). 05 WX-CAMPO2 PIC X(5). 05 WX-CAMPO3 PIC X(5). 05 WX-CAMPO4 PIC X(5). COPY PROCEDURE Se incluirn dentro de la PROCEDURE DIVISION. COPY PDCOPY. Donde PDCOPY contendr algo de este estilo: MOVE WX-CAMPO1 TO WX-REGISTRO1 MOVE WX-CAMPO2 TO WX-REGISTRO2 MOVE WX-CAMPO3 TO WX-REGISTRO3 MOVE WX-CAMPO4 TO WX-REGISTRO4 MOVE WX-CAMPO5 TO WX-REGISTRO5

CLCULO DE LONGITUDES Numricos y alfanumricos: lo que venga indicado en el PIC X(n) PIC 9(n) respectivamente. 01 WX-VARIABLE-ALFNUM PIC X(5). 01 WX-VARIABLE-NUM PIC 9(5). longitud = 5

Numricos COMP-3: si tenemos un PIC 9(n) COMP-3, la longitud ser (n+1)/2. Si el resultado tiene decimales redondeamos hacia arriba. Hay que tener en cuenta que la coma decimal no ocupa espacio, y que el signo ocupa slo media posicin. 01 WX-VARIABLE-COMP3 PIC S9(5) COMP-3. longitud = (5 + 1)/2 = 3 Numricos COMP: Un campo con PICTURE numrica y COMP se almacena en formato binario puro (base 2); el signo lo representa el bit de la derecha. El nmero de bytes que se reservan en memoria para cada campo es: 2 posiciones para nmeros de 1 a 4 dgitos. 4 posiciones para nmeros de 5 a 9 dgitos. 8 posiciones para nmeros de 10 a 18 dgitos. 01 WX-VARIABLE-COMP PIC 9(5) COMP. longitud = 4

VISUALIZANDO CAMPOS Como ya hemos comentado, existen campos en cobol q no se ven "tal cual", como son los comprimidos o los hexadecimales. Vamos a ver como se veran en un fichero estos campos: ----+----1----+----2----+----3----+----4 999999999 q % 00000 S FFFFFFFFF444444444493716000000FFFFF00E2 99999999900000000008265C000000000000122 ---------------------------------------* El campo que va de la posicin 1 a la 9 sera un campo numrico normal con valor 999999999. * El campo que va de la posicin 10 a la 19 sera un campo alfanumrico con valor ' ' (9 espacios). * El campo que va de la posicin 20 a la 24 sera un campo numrico COMP-3 con valor 983276156 positivo (letra C, letra D para negativos*). * El campo que va de la posicin 25 a la 30 sera un campo informado con low-values. * El campo que va de la posicin 31 a la posicin 35 sera un campo informado con 5 ceros 00000. * El campo que va de la posicin 36 a la 39 sera un campo numrico COMP con valor 1E222 (en hexadecimal) / 123426(en decimal). *Para campos numricos con signo del tipo S9(3)V99, podemos distinguir el signo fijndonos en la ltima posicin: A = +1 B = +2 C = +3 D = +4 E = +5 F = +6 G = +7 H = +8 I = +9 J = -1 K = -2

L M N O P Q R { }

= = = = = = = = =

-3 -4 -5 -6 -7 -8 -9 +0 -0

En el prximo artculo veremos la PROCEDURE DIVISION, donde se codifica la "miga" del programa. Veremos como informar campos, como inicializarlos y como codificar bucles y condiciones.

PROCEDURE DIVISION: proceso del programa.


La PROCEDURE DIVISION es la parte del programa donde se codifica el proceso en s. Es decir, aqu escribiremos las sentencias cobol para llevar a cabo la funcin del programa. INFORMANDO VARIABLES En cobol lo que se hace es "mover" la informacin de una variable a otra utilizando la sentencia MOVE. A la hora de mover informacin tendremos que tener en cuenta 2 cosas: Formato(PIC) de ambas variables Longitud de ambas variables Ejemplo 1. 01 WX-TELEFONO PIC X(9) VALUE '666111333'. 01 WX-TELEFONO-2 PIC X(9). Tienen mismo formato y misma longitud, por lo que no habr problemas. La sentencia sera: MOVE WX-TELEFONO TO WX-TELEFONO-2 Ahora WX-TELEFONO-2 tendr el valor '666111333'. Ejemplo 2. 01 WX-TELEFONO PIC X(9) VALUE '666111333'. 01 WX-TELEFONO-NUM PIC 9(9). Ahora tenemos misma longitud pero distinto formato. En este caso la variable alfanumrica slo tiene nmeros, por lo que no habr problema. MOVE WX-TELEFONO TO WX-TELEFONO-NUM Ahora WX-TELEFONO-NUM tendr el valor 666111333. Ejemplo 3. 01 WX-TELEFONO PIC X(9) VALUE 'AAA111333'. 01 WX-TELEFONO-NUM PIC 9(9). Ahora tenemos caracteres alfabticos en la variable alfanumrica, esto no dar error, aunque no tiene mucho sentido hacerlo. Dependiendo de la instalacin, este tipo de movimientos donde pasamos caracteres alfabticos a campos numricos darn, o no, un error en ejecucin: el MOVE dar un estupendo "casque" al ejecutar con cdigo error S0C7. Lo mismo ocurre si lo movemos a un campo COMP-3 o COMP. En cualquier caso, NO debemos mover caracteres alfabticos a un campo numrico, COMP o COMP-3.

Ejemplo 4. 01 WX-TELEFONO PIC X(9) VALUE '666111333'. 01 WX-TELEFONO-NUM PIC 9(6). En este caso no coinciden ni las longitudes ni los formatos. Como el campo alfanumrico slo lleva nmeros no habr problema, pero al no coincidir las longitudes el campo se "truncar". MOVE WX-TELEFONO TO WX-TELEFONO-NUM Ahora el campo WX-TELEFONO-NUM tendr valor 111333. Hemos perdido los 3 primeros dgitos. Si fuese al revs: 01 WX-TELEFONO-NUM PIC 9(9) VALUE 666111333. 01 WX-TELEFONO PIC X(6). MOVE WX-TELEFONO-NUM TO WX-TELEFONO El valor del campo WX-TELEFONO sera 666111. Cuando se mueve a un campo alfanumrico, el movimiento se hace de la posicin 1 del campo inicial a la posicin 1 del campo alfanumrico. Cuando se mueve a un campo numrico, el movimiento se hace de la ltima posicin del campo inicial a la ltima posicin del campo numrico. Ejemplo 5. 01 WX-NUMERO-ALF PIC X(4) VALUE '12 '. 01 WX-NUMERO PIC 9(4). Puede darse el caso de que valores numricos nos vengan con espacios en lugar de ceros a la izquierda. Una manera de solventar esto es utilizando el COMPUTE FUNCTION NUMVAL: COMPUTE WX-NUMERO = FUNCTION NUMVAL(WX-NUMERO-ALF) Ahora la variable WX-NUMERO tendr el valor 0012. Es una manera de asegurarnos de que no casque el programa porque algn vago no haya escrito los ceros^^ El movimiento en s no dara error, pero no debe hacerse. Un ejemplo ms claro: 01 WX-NUMERO-ALF PIC X(4) VALUE '12,00 01 WX-NUMERO PIC 9(4)V9(2). '.

Con el COMPUTE FUNCTION NUMVAL conseguiramos que WX-NUMERO tuviese el valor 00120{ (aplantillado con la coma decimal). Campos COMP-3 y COMP. Ejemplo 6. 01 WX-SUELDO-COMP3 PIC S9(6) COMP-3 VALUE 100000. 01 WX-SUELDO-NUM PIC 9(6). MOVE WX-SUELDO-COMP3 TO WX-SUELDO-NUM Sin problema. WX-SUELDO-NUM valdr 100000. Ejemplo 7. 01 WX-SUELDO-COMP3 PIC S9(6) COMP-3 VALUE 100000. 01 WX-SUELDO-ALF PIC X(6).

MOVE WX-SUELDO-COMP3 TO WX-SUELDO-ALF Sin problema. WX-SUELDO-ALF valdr 100000. Ejemplo 8. 01 WX-SUELDO-COMP PIC S9(6) COMP VALUE 100000. 01 WX-SUELDO-NUM PIC 9(6). MOVE WX-SUELDO-COMP TO WX-SUELDO-NUM Sin problema. WX-SUELDO-ALF valdr 100000. Ejemplo 9. 01 WX-SUELDO-COMP PIC S9(6) COMP VALUE 100000. 01 WX-SUELDO-ALF PIC X(6). MOVE WX-SUELDO-COMP TO WX-SUELDO-ALF Sin problema. WX-SUELDO-ALF valdr 100000. Ejemplo 10. 01 WX-SUELDO-COMP3 PIC S9(6) COMP-3 VALUE 100000. 01 WX-SUELDO-COMP PIC 9(6) COMP. MOVE WX-SUELDO-COMP3 TO WX-SUELDO-COMP Sin problema, WX-SUELDO-COMP valdr 100000 pero en formato hexadecimal: 186A0 Ejemplo 11. 01 WX-SUELDO-COMP PIC 9(6) COMP VALUE 100000. 01 WX-SUELDO-COMP3 PIC S9(6) COMP-3. MOVE WX-SUELDO-COMP TO WX-SUELDO-COMP3 Sin problema, WX-SUELDO-COMP valdr 100000. Para campos numricos existe tambin la sentencia COMPUTE para pasar informacin de uno a otro: Ejemplo 12. 01 WX-NUMERO-1 PIC 9(5) VALUE 12345. 01 WX-NUMERO-2 PIC 9(5). COMPUTE WX-NUMERO-2 = WX-NUMERO-1 Ahora WX-NUMERO-2 valdr 12345. Aunque la sentencia COMPUTE se usa en general para operaciones aritmticas: suma, resta, multiplicacin, divisin, potencia... COMPUTE WX-NUMERO1 = ((WX-NUMERO2 + WX-NUMERO3) - (WX-NUMERO4 * WX-NUMERO5) / WX-NUMERO6) ** 2 Y se aplican las mismas reglas de prioridades que en matemticas.(el doble asterisco es la potencia) Es en estos casos cuando un campo numrico que lleve caracteres o espacios pierde su sentido, pues adivinad que sucede si intentamos dividir 'ABC?%&' entre 1000 al ejecutar el programa... Premio! Un S0C7!!

Nunca va a tener sentido dividor letras entre nmeros, imagino que en esto estamos todos de acuerdo : P Para operaciones aritmticas existen tambin: ADD: operador suma. "ADD 1 TO WX-CAMPO" SUBTRACT: operador resta. "SUBTRACT 1 FROM WX-CAMPO" MULTIPLY: operador multiplicacin. "MULTIPLY WX-CAMPO BY 1" DIVIDE: operador divisin. "DIVIDE WX-CAMPO BY 1" REMAINDER: es el resto de una divisin. "DIVIDE WX-CAMPO BY 1 REMINDER WX-RESTO"

Ejemplo 13. 01 WX-TELEFONO-NUM PIC 9(9) VALUE 666111333. 01 WX-TELEFONO-ALF PIC X(9) VALUE '666111333'. 01 WX-TELEFONO PIC X(6). Para campos alfanumricos y numricos sin comprimir existe la posibilidad de mover slo determinadas posiciones del campo. MOVE WX-TELEFONO-NUM(1:6) TO WX-TELEFONO En este caso estamos cogiendo 6 posiciones, empezando desde la posicin 1. Ahora WXTELEFONO valdr '666111'. MOVE WX-TELEFONO-ALF(4:) TO WX-TELEFONO En este caso estamos cogiendo todas las posiciones hasta final de campo desde la posicin 4. Ahora WX-TELEFONO valdr '111333'.

CONCATENANDO CAMPOS En COBOL tambin existe la opcin de concatenar campos usando la sentencia STRING. Lo que haremos ser indicar las variables a concatenar, el modo en que se unirn y el campo donde se guardar el resultado. 01 WX-CAMPO1 PIC X(17) VALUE 'CONSULTORIO COBOL'. 01 WX-CAMPO2 PIC X(10) VALUE ' SON GUAYS'. 01 WX-RESULTADO PIC X(41). STRING 'LOS TIPOS DEL ' WX-CAMPO1 WX-CAMPO2 DELIMITED BY SIZE INTO WX-RESULTADO Donde DELIMITED BY SIZE indica que los campos se unirn segn el tamao que ocupen, y el INTO indicar el campo donde guardar la informacin concatenada. Si por ejemplo tuvisemos campos con espacios al final podramos indicarle un DELIMITED BY SPACES, para que cortase la informacin al encontrarse el primer espacio. Vamos a ver el ejemplo: 01 WX-DIA PIC 9(2) VALUE 31. 01 WX-MES PIC X(10). 01 WX-FECHA PIC X(19). MOVE 'MAYO' TO WX-MES Ahora WX-MES valdr 'MAYO '.

STRING 'HOY ES ' WX-DIA ' DE ' DELIMITED BY SIZE WX-MES DELIMITED BY SPACE '.' DELIMITED BY SIZE INTO WX-FECHA El resultado: HOY ES 31 DE MAYO. Si no hubisemos indicado el DELIMITED BY SPACE, el resultado sera: HOY ES 31 DE MAYO . Recordad: el DELIMITED BY se aplica a todos los campos que lo preceden. Usad el DELIMITED BY correcto en cada caso

INICIALIZANDO CAMPOS Para "vaciar" un campo podramos moverle ceros o espacios (segn su formato). Pero en cobol existe una instruccin ms sencilla que es el INITIALIZE. 01 WX-NUMERO PIC 9(5) VALUE 12345. (...) INITIALIZE WX-NUMERO Ahora WX-NUMERO valdr 00000. Si fuese alfanumrico valdra ' Las variables "vacas" en cobol pueden tener 3 tipos de informacin: ceros: 00000 espacios: ' ' low-values: '.....' Por eso a la hora de preguntar si un campo est vaco en cobol preguntaremos: IF WX-CAMPO EQUAL ZEROES OR SPACES OR LOW-VALUES (...) Nota: Tanto LOW-VALUES como HIGH-VALUES son palabras reservadas en cobol, y se pueden definir como "el valor ms bajo posible" y "el valor ms alto posible" respectivamente. Veremos su uso en otros artculos. ' (cinco espacios).

BUCLES Y CONDICIONES Las condiciones en cobol se escriben de la siguiente manera: IF WX-CAMPO = 1 MOVE 1 TO WX-CAMPO2 ELSE MOVE WX-CAMPO TO WX-CAMPO2 END-IF Podemos escribir IFs dentro de IFs (IFs anidados) y La sentencia ELSE no es obligatoria: IF WX-CAMPO1 = 1 IF WX-CAMPO2 = 2 MOVE WX-CAMPO1 TO WX-CAMPO3 END-IF

ELSE MOVE 1 TO WX-CAMPO3 END-IF No tienen ms ciencia que cualquier IF de cualquier otro lenguaje. Los operadores lgicos sern OR, AND, EQUAL, NOT EQUAL. Los operadores de mayor, menor, sern GREATER y LESS. Tambin se pueden utilizar combinaciones como GREATER OR EQUAL (mayor o igual), y tambin con smbolos: >= (mayor o igual), <= (menor o igual). Los bucles son diferentes debido a que en cobol no existe la sentencia "while" de otros lenguajes. Aqu los bucles son siempre "UNTIL", es decir, hasta que se cumpla la condicin especificada. MOVE 0 TO WX-CAMPO PERFORM UNTIL WX-CAMPO = 5 -> aqu es donde pregunta por la condicin proceso a realizar ADD 1 TO WX-CAMPO END-PERFORM El proceso se realizar para: WX-CAMPO = 0 WX-CAMPO = 1 WX-CAMPO = 2 WX-CAMPO = 3 WX-CAMPO = 4 MOVE 5 TO WX-CAMPO PERFORM UNTIL WX-CAMPO = 5 -> aqu es donde pregunta por la condicin proceso a realizar END-PERFORM El proceso no se llega a realizar. Si quisisemos preguntar por la condicin al final del bucle, tendramos que codificar el bucle con un "WITH TEST AFTER": MOVE 0 TO WX-CAMPO PERFORM WITH TEST AFTER UNTIL WX-CAMPO = 5 proceso a realizar ADD 1 TO WX-CAMPO END-PERFORM -> aqu es donde pregunta por la condicin El proceso se realizar para: WX-CAMPO = 0 WX-CAMPO = 1 WX-CAMPO = 2 WX-CAMPO = 3 WX-CAMPO = 4 MOVE 5 TO WX-CAMPO

PERFORM WITH TEST AFTER UNTIL WX-CAMPO = 5 proceso a realizar ADD 1 TO WX-CAMPO END-PERFORM -> aqu es donde pregunta por la condicin El proceso se realiza una vez, antes de comprobar si se cumple la codicin. Como veamos en la estructura general de un programa cobol, un prrafo entero tambin se puede repetir hasta que se cumpla una condicin: PERFORM 2000-PROCESO UNTIL CUMPLA-CONDICION Otro tipo de bucles son los "PERFORM VARYING". En este caso tendremos un contador que se ir incrementando automticamente segn le indiquemos: PERFORM VARYING WI-INDICE FROM 1 BY 1 UNTIL WI-INDICE = 10 cdigo a ejecutar END-PERFORM El "FROM" le indica desde que valor empezar. El "BY" le indica cuanto le ha de sumar cada vez. Como en el otro caso, el "UNTIL" le indicar la condicin de final de bucle. Con todo esto, ya podemos empezar a ver un ejemplo de un programa sencillo

Ejemplo 1: Leer de SYSIN y escribir en SYSOUT.


En cobol hay que diferenciar entre los programas que acceden a DB2 y los que no, pues se compilarn de maneras diferentes y se ejecutarn de forma diferente. Empezaremos por ver el programa sin DB2 ms sencillo: El programa ms sencillo es aquel que recibe datos por SYSIN del JCL y los muestra por SYSOUT. JCL:
//PROG1 EXEC PGM=PRUEBA1 //SYSOUT DD SYSOUT=* //SYSIN DD * JOSE LOPEZ VAZQUEZ HUGO CASILLAS DIAZ JAVIER CARBONERO PACO GONZALEZ /*

donde EXEC PGM= indica el programa SIN DB2 que vamos a ejecutar SYSOUT DD SYSOUT=* indica que la informacin "displayada" se quedar en la cola del SYSOUT (no lo vamos a guardar en un fichero) en SYSIN DD * metemos la informacin que va a recibir el programa Fijaos en las posiciones de los nombres de la SYSIN, para entender bien el programa:
----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8 JOSE LOPEZ VAZQUEZ HUGO CASILLAS DIAZ JAVIER CARBONERO PACO GONZALEZ

Como veis, la longitud mxima que se puede pasar a un programa a travs de la SYSIN es de 80. En nuestro caso la hemos dividido en 4 trozos de 20 posiciones, cada uno con un nombre. PROGRAMA: IDENTIFICATION DIVISION.

PROGRAM-ID. PRUEBA1. *==========================================================* * PROGRAMA QUE LEE DE SYSIN Y ESCRIBE EN SYSOUT *==========================================================* * ENVIRONMENT DIVISION. * CONFIGURATION SECTION. * SPECIAL-NAMES. DECIMAL-POINT IS COMMA. * DATA DIVISION. * WORKING-STORAGE SECTION. * 01 WI-INDICE PIC 9(4) COMP. 01 WX-SYSIN PIC X(80). 01 WX-TABLA-NOMBRES. 05 WX-NOMBRE PIC X(20) OCCURS 4 TIMES. * ************************************************************ PROCEDURE DIVISION. ************************************************************ * | 0000 - PRINCIPAL *--|------------------+----------><----------+-------------* * 1| EJECUTA EL INICIO DEL PROGRAMA * 2| EJECUTA EL PROCESO DEL PROGRAMA * 3| EJECUTA EL FINAL DEL PROGRAMA ************************************************************ 00000-PRINCIPAL. * PERFORM 10000-INICIO * PERFORM 20000-PROCESO * PERFORM 30000-FINAL . ************************************************************ * | 10000 - INICIO *--|------------+----------><----------+-------------------* * | SE REALIZA EL TRATAMIENTO DE INICIO: * 1| Inicializacin de reas de Trabajo * 2| Primera lectura de SYSIN ************************************************************ 10000-INICIO. * INITIALIZE WX-SYSIN ACCEPT WX-SYSIN FROM SYSIN . ************************************************************ * | 20000 - PROCESO *--|------------------+----------><------------------------* * | SE REALIZA EL TRATAMIENTO DE LOS DATOS: * 1| Realiza el tratamiento de cada registro leido

************************************************************ 20000-PROCESO. * MOVE WX-SYSIN TO WX-TABLA-NOMBRES MOVE 1 TO WI-INDICE PERFORM UNTIL WI-INDICE GREATER 4 DISPLAY 'WX-NOMBRE:'WX-NOMBRE(WI-INDICE) ADD 1 TO WI-INDICE END-PERFORM . ************************************************************ * | 30000 - FINAL *--|------------------+----------><----------+-------------* * | FINALIZA LA EJECUCION DEL PROGRAMA ************************************************************ 30000-FINAL. * STOP RUN .

En el programa podemos ver las siguientes divisiones/secciones: IDENTIFICATION DIVISION: existir siempre. ENVIRONMENT DIVISION: existir siempre. CONFIGURATION SECTION: existir siempre. En este caso no existir la INPUT-OUTPUT SECTION, pues nuestro programa no utiliza ficheros. DATA DIVISION: existir siempre. En este caso no existir la FILE SECTION, pues nuestro programa no utiliza ficheros. WORKING-STORAGE SECTION: existir siempre. En este caso no existir la LINKAGE SECTION pues el programa no se comunica con otros programas. PROCEDURE DIVISION: existir siempre.

En el programa podemos ver las siguientes sentencias: PERFORM: llamada a prrafo INITIALIZE: para inicializar variable ACCEPT: esta sentencia recoge la informacin del campo indicado en el "FROM". En este caso recoge la informacin almacenada en "SYSIN"; la que nosotros hemos introducido en el JCL. MOVE/TO: movemos la informacin de un campo a otro PERFORM UNTIL: bucle DISPLAY: escribe el contenido del campo indicado en la SYSOUT del JCL. ADD: Operador de adicin (suma) STOP RUN: sentencia de finalizacin de ejecucin.

Descripcin del programa: En el prrafo de inicio, inicializamos WX-SYSIN para guardar posteriormente mediante un ACCEPT la informacin que hemos escrito en la SYSIN del JCL. En el prrafo de proceso, informamos la tabla interna WX-TABLA-NOMBRES, donde el campo WX-NOMBRES se repetir 4 veces (occurs 4 times).

Informamos el campo WI-INDICE con un 1, pues vamos a utilizar los campos de la tabla interna: Para utilizar un campo que pertenezca a una tabla interna (tiene occurs), debemos acompaar el campo de un "ndice" entre parntesis. De tal forma que indiquemos a que "ocurrencia" de la tabla nos estamos refiriendo. Por ejemplo, WX-NOMBRE (1) sera el primer nombre guardado (JOSE LOPEZ VAZQUEZ). Como queremos desplazar todas las ocurrencias de la tabla, haremos que el ndice sea una variable que va aumentando. A continuacin montamos un bucle (perform until) con la condicin WI-INDICE mayor (greater) de 4, pues la primera vez WI-INDICE valdr 1, y necesitamos que el bucle se repita 4 veces: WI-INDICE = 1: WX-NOMBRE(1) = JOSE LOPEZ VAZQUEZ WI-INDICE = 2: WX-NOMBRE(2) = HUGO CASILLAS DIAZ WI-INDICE = 3: WX-NOMBRE(3) = JAVIER CARBONERO WI-INDICE = 4: WX-NOMBRE(4) = PACO GONZALEZ WI-INDICE = 5: salimos del bucle porque se cumple WI-INDICE GREATER 4 NOTA: el ndice de una tabla interna NUNCA puede ser cero, pues no existe la ocurrencia cero. Si no informsemos WI-INDICE con 1, el DISPLAY de WX-NOMBRE(0) nos dara un estupendo casque, de este estilo:
IGZ0006S The reference to table WX-NOMBRE by verb number 01 on line 001099 addressed an area outside the region of the table. From compile unit R2BCTAN1 at entry point R2BCTAN1 at compile unit offset +00001122 at entry offset +00001122 at address 1965BBAA.

Aunque ahora ya sabemos cmo encontrar la lnea que nos da el OFFSET :D RESULTADO: WX-NOMBRE: JOSE LOPEZ VAZQUEZ WX-NOMBRE: HUGO CASILLAS DIAZ WX-NOMBRE: JAVIER CARBONERO WX-NOMBRE: PACO GONZALEZ

Ejemplo 2: leer de SYSIN y escribir en fichero.


En este ejemplo vamos a ejecutar un programa SIN DB2, que recoge informacin de la SYSIN del JCL del mismo modo que vimos en el ejemplo 1. La diferencia estar en que en esta ocasin vamos a escribir la informacin en un fichero en lugar de en la SYSOUT. JCL:
//****************************************************** //**************************** BORRADO ***************** //BORRADO EXEC PGM=IDCAMS //SYSPRINT DD SYSOUT=* //SYSIN DD * DEL FICHERO.CON.NOMBRES SET MAXCC = 0 //****************************************************** //*********** EJECUCION DEL PROGRAMA PRUEBA2 *********** //PROG1 EXEC PGM=PRUEBA2

//SYSOUT DD SYSOUT=* //FICHERO DD DSN=FICHERO.CON.NOMBRES, // DISP=(NEW, CATLG, DELETE),SPACE=(TRK,(50,10)) //SYSIN DD * JOSE LOPEZ VAZQUEZ HUGO CASILLAS DIAZ JAVIER CARBONERO PACO GONZALEZ /*

En este ejemplo aadimos un nuevo paso, el IDCAMS. Este programa sirve para borrar ficheros que se crean a lo largo del JCL. En nuestro caso borrar el fichero que se va a crear en el programa. As podremos ejecutarlo tantas veces como queramos sin generar el mismo fichero una y otra vez. El paso de ejecucin del programa PRUEBA2 es similar al del ejemplo 1, slo le hemos aadido la definicin del fichero de salida "FICHERO". PROGRAMA: IDENTIFICATION DIVISION. PROGRAM-ID. PRUEBA2. *==========================================================* * PROGRAMA QUE LEE DE SYSIN Y ESCRIBE EN FICHERO *==========================================================* * ENVIRONMENT DIVISION. * CONFIGURATION SECTION. * SPECIAL-NAMES. DECIMAL-POINT IS COMMA. * INPUT-OUTPUT SECTION. * FILE-CONTROL. * SELECT FICHERO ASSIGN TO FICHERO STATUS IS FS-FICHERO. * DATA DIVISION. * FILE SECTION. * * Fichero de salida de longitud fija (F) igual a 20. FD FICHERO RECORDING MODE IS F BLOCK CONTAINS 0 RECORDS RECORD CONTAINS 20 CHARACTERS. 01 REG-FICHERO PIC X(20). * WORKING-STORAGE SECTION. * FILE STATUS 01 FS-STATUS. 05 FS-FICHERO PIC X(2). 88 FS-FICHERO-OK VALUE '00'. * * VARIABLES 01 WI-INDICE PIC 9(4) COMP. 01 WX-SYSIN PIC X(80). 01 WX-TABLA-NOMBRES. 05 WX-NOMBRE PIC X(20) OCCURS 4 TIMES. 01 WX-REGISTRO-SALIDA PIC X(20).

* ************************************************************ PROCEDURE DIVISION. ************************************************************ * | 0000 - PRINCIPAL *--|------------------+----------><----------+-------------* * 1| EJECUTA EL INICIO DEL PROGRAMA * 2| EJECUTA EL PROCESO DEL PROGRAMA * 3| EJECUTA EL FINAL DEL PROGRAMA ************************************************************ 00000-PRINCIPAL. * PERFORM 10000-INICIO * PERFORM 20000-PROCESO * PERFORM 30000-FINAL . ************************************************************ * | 10000 - INICIO *--|------------+----------><----------+-------------------* * | SE REALIZA EL TRATAMIENTO DE INICIO: * 1| Inicializacin de reas de Trabajo * 2| Primera lectura de SYSIN ************************************************************ 10000-INICIO. * INITIALIZE WX-SYSIN WX-REGISTRO-SALIDA WX-TABLA-NOMBRES ACCEPT WX-SYSIN FROM SYSIN PERFORM 11000-ABRIR-FICHERO . * ************************************************************ * 11000 - ABRIR FICHEROS *--|------------------+----------><----------+-------------* * Abrimos el fichero de salida ************************************************************ 11000-ABRIR-FICHERO. * OPEN OUTPUT FICHERO * IF NOT FS-FICHERO-OK DISPLAY 'ERROR EN OPEN DEL FICHERO:'FS-FICHERO END-IF . * ************************************************************ * | 20000 - PROCESO *--|------------------+----------><------------------------* * | SE REALIZA EL TRATAMIENTO DE LOS DATOS: * 1| Realiza el tratamiento de cada registro recuperado de * la SYSIN ************************************************************

20000-PROCESO. * MOVE WX-SYSIN TO WX-TABLA-NOMBRES MOVE 1 TO WI-INDICE PERFORM UNTIL WI-INDICE GREATER 4 PERFORM 21000-INFORMAR-REGISTRO PERFORM 22000-ESCRIBIR-FICHERO ADD 1 TO WI-INDICE END-PERFORM . * ************************************************************ * 21000 - INFORMAR REGISTRO *--|------------------+----------><----------+-------------* * MOVEMOS LA INFORMACION DESDE NUESTRA TABLA INTERNA A LA * VARIABLE WX-REGISTRO-SALIDA ************************************************************ 21000-INFORMAR-REGISTRO. * MOVE WX-NOMBRE(WI-INDICE) TO WX-REGISTRO-SALIDA . * ************************************************************ * 22000 - ESCRIBIR FICHERO *--|------------------+----------><----------+-------------* * ESCRIBIMOS EN EL FICHERO DE SALIDA LA INFORMACION GUARDADA * WX-REGISTRO-SALIDA ************************************************************ 22000-ESCRIBIR-FICHERO. * WRITE REG-FICHERO FROM WX-REGISTRO-SALIDA IF NOT FS-FICHERO-OK DISPLAY 'ERROR EN WRITE DEL FICHERO:'FS-FICHERO END-IF . * ************************************************************ * | 30000 - FINAL *--|------------------+----------><----------+-------------* * | FINALIZA LA EJECUCION DEL PROGRAMA ************************************************************ 30000-FINAL. * PERFORM 31000-CERRAR-FICHERO STOP RUN . * ************************************************************ * | 31000 - CERRAR FICHERO *--|------------------+----------><----------+-------------*

* | CERRAMOS EL FICHERO DE SALIDA ************************************************************ 31000-CERRAR-FICHERO. * CLOSE FICHERO IF NOT FS-FICHERO-OK DISPLAY 'ERROR EN CLOSE DEL FICHERO:'FS-FICHERO END-IF . En el programa podemos ver las siguientes divisiones/secciones: IDENTIFICATION DIVISION: existir siempre. ENVIRONMENT DIVISION: existir siempre. CONFIGURATION SECTION: existir siempre. INPUT-OUTPUT SECTION: en este ejemplo existir porque utilizamos un fichero de salida. DATA DIVISION: existir siempre. FILE SECTION: en este ejemplo existir pues utilizamos un fichero de salida. WORKING-STORAGE SECTION: exisitir siempre. En este caso no exisistir la LINKAGE SECTION pues el programa no se comunica con otros programas. PROCEDURE DIVISION: exisitir siempre. En el programa podemos ver las siguientes sentencias: PERFORM: llamada a prrafo INITIALIZE: para inicializar variable ACCEPT: esta sentencia recoge la informacin del campo indicado en el "FROM". En este caso recoge la informacin almacenada en "SYSIN"; la que nosotros hemos introducido en el JCL. OPEN: "Abre" los ficheros del programa. Lo acompaaremos de "INPUT" para los ficheros de entrada y "OUTPUT" para los ficheros de salida. DISPLAY: escribe el contenido del campo indicado en la SYSOUT del JCL. MOVE/TO: movemos la informacin de un campo a otro PERFORM UNTIL: bucle ADD: Operador de adicin (suma) WRITE: Escribe la informacin indicada en el "FROM" en el fichero indicado. STOP RUN: sentencia de finalizacin de ejecucin. CLOSE: "Cierra" los ficheros del programa. Descripcin del programa: En el prrafo de inicio, inicializamos las variables que utilizaremos a lo largo del programa: WX-SYSIN: donde guardaremos posteriormente mediante un ACCEPT la informacin que hemos escrito en la SYSIN del JCL. WX-TABLA-NOMBRES: donde moveremos la informacin de la SYSIN para dividirla en los diferentes nombres. WX-REGISTRO-SALIDA: donde guardaremos la informacin que vamos a escribir en el fichero de salida. Abriremos el fichero de salida (OPEN OUTPUT) y controlaremos el file-status. Si todo va bien el cdigo del file-status valdr '00'. Podis ver la lista de los file-status ms comunes. En el prrafo de proceso, informamos la tabla interna WX-TABLA-NOMBRES, donde el campo WX-NOMBRES se repetir 4 veces (occurs 4 times). Recordad que el tratamiento de las tablas internas est explicado en detalle en el ejemplo 1. Montaremos un bucle para escribir cada uno de los nombres guardados en la tabla interna en el fichero de salida. Informaremos la variable WX-REGISTRO-SALIDA con cada uno de los nombres de la tabla.

Escribiremos el fichero de salida. Para ellos indicaremos a continuacin del WRITE la variable definida en la FILE-SECTION, y a continuacin del FROM la variable donde tenemos guardada la informacin que queremos escribir. Controlaremos el file-status. Nota: es importante controlar el FILE-STATUS en los accesos a ficheros (OPEN, READ, WRITE, CLOSE...) para, en caso de fallo en la ejecucin, tener informacin sobre la causa del error.

Ejemplo 3: leer de fichero y escribir en fichero.


Para este ejemplo crearemos un programa que lea un fichero de entrada, formatee la informacin y escriba en un fichero de salida. JCL:
//****************************************************** //******************** BORRADO ************************* //BORRADO EXEC PGM=IDCAMS //SYSPRINT DD SYSOUT=* //SYSIN DD * DEL FICHERO.DE.SALIDA SET MAXCC = 0 //****************************************************** //*********** EJECUCION DEL PROGRAMA PRUEBA3 *********** //PROG3 EXEC PGM=PRUEBA3 //SYSOUT DD SYSOUT=* //ENTRADA DD DSN=FICHERO.DE.ENTRADA,DISP=SHR //SALIDA DD DSN=FICHERO.DE.SALIDA, // DISP=(NEW, CATLG, DELETE),SPACE=(TRK,(50,10)) /*

En este caso volvemos a utilizar el IDCAMS para borrar el fichero de salida que se genera en el segundo paso. Sigue siendo un programa sin DB2, as que utilizamos el EXEC PGM. Para definir el fichero de entrada "ENTRADA" indicaremos que es un fichero ya existente y compartida al indicar DISP=SHR. En la SYSOUT veremos los mensajes de error en caso de que los haya. Fichero de entrada: ----+----1----+ 11111AA100A 22222BB100B 33333CC100K 44444DD100M campo1: nmero de cliente campo2: cdigo de empresa campo3: saldo

PROGRAMA: IDENTIFICATION DIVISION. PROGRAM-ID. PRUEBA3. *==========================================================* * PROGRAMA QUE LEE DE FICHERO Y ESCRIBE EN FICHERO *==========================================================* * ENVIRONMENT DIVISION. *

CONFIGURATION SECTION. * SPECIAL-NAMES. DECIMAL-POINT IS COMMA. * INPUT-OUTPUT SECTION. * FILE-CONTROL. * SELECT ENTRADA ASSIGN TO ENTRADA STATUS IS FS-ENTRADA. SELECT SALIDA ASSIGN TO SALIDA STATUS IS FS-SALIDA. * DATA DIVISION. * FILE SECTION. * * Fichero de entrada de longitud fija (F) igual a 11. FD ENTRADA RECORDING MODE IS F BLOCK CONTAINS 0 RECORDS RECORD CONTAINS 11 CHARACTERS. 01 REG-ENTRADA PIC X(11). * * Fichero de salida de longitud fija (F) igual a 28. FD SALIDA RECORDING MODE IS F BLOCK CONTAINS 0 RECORDS RECORD CONTAINS 28 CHARACTERS. 01 REG-SALIDA PIC X(28). * WORKING-STORAGE SECTION. * FILE STATUS 01 FS-STATUS. 05 FS-ENTRADA PIC X(2). 88 FS-ENTRADA-OK VALUE '00'. 88 FS-FICHERO1-EOF VALUE '10'. 05 FS-SALIDA PIC X(2). 88 FS-SALIDA-OK VALUE '00'. * * VARIABLES 01 WB-FIN-ENTRADA PIC X(1) VALUE 'N'. 88 FIN-ENTRADA VALUE 'S'. * 01 WB-SIGNOS PIC X. 88 SIGNO-MAS VALUE 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', '{'. 88 SIGNO-MENOS VALUE 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', '}'. 01 WX-TABLA-EMPRESAS. 05 PIC X(11) VALUE 'AAEMPRESA 1'.

05 PIC X(11) VALUE 'BBEMPRESA 2'. 05 PIC X(11) VALUE 'CCEMPRESA 3'. 05 PIC X(11) VALUE 'DDEMPRESA 4'. 01 REDEFINES WX-TABLA-EMPRESAS. 05 WX-ELEMENTOS OCCURS 4 TIMES INDEXED BY WI-ELEM. 10 WX-CODIGO-EMPRESA PIC X(2). 10 WX-NOMBRE-EMPRESA PIC X(9). * 01 WX-REGISTRO-ENTRADA. 05 WX-ENT-CLIENTE 05 WX-ENT-COD-EMPRESA 05 WX-ENT-SALDO * 01 WX-REGISTRO-SALIDA. 05 WX-SAL-CLIENTE PIC 9(5). 05 WX-SAL-COD-EMPRESA PIC X(2). 05 WX-SAL-NOMBRE-EMPRESA PIC X(9). 05 WX-SAL-SALDO PIC 9(4). 05 WX-SAL-SIGNO PIC X(8). * CONSTANTES 01 WK-POSITIVO PIC X(8) VALUE 'positivo'. 01 WK-NEGATIVO PIC X(8) VALUE 'negativo'. * ************************************************************ PROCEDURE DIVISION. ************************************************************ * | 0000 - PRINCIPAL *--|------------------+----------><----------+-------------* * 1| EJECUTA EL INICIO DEL PROGRAMA * 2| EJECUTA EL PROCESO DEL PROGRAMA * 3| EJECUTA EL FINAL DEL PROGRAMA ************************************************************ 00000-PRINCIPAL. * PERFORM 10000-INICIO * PERFORM 20000-PROCESO UNTIL FIN-ENTRADA * PERFORM 30000-FINAL . ************************************************************ * | 10000 - INICIO *--|------------+----------><----------+-------------------* * | SE REALIZA EL TRATAMIENTO DE INICIO: * 1| Inicializacin de reas de Trabajo * 2| Primera lectura de SYSIN ************************************************************ 10000-INICIO. * INITIALIZE WX-REGISTRO-SALIDA PERFORM 11000-ABRIR-FICHERO PERFORM LEER-ENTRADA PIC 9(5). PIC X(2). PIC S9(4).

IF FIN-ENTRADA DISPLAY 'FICHERO DE ENTRADA VACIO' PERFORM 30000-FINAL END-IF . * ************************************************************ * 11000 - ABRIR FICHEROS *--|------------------+----------><----------+-------------* * Abrimos los ficheros del programa ************************************************************ 11000-ABRIR-FICHEROS. * OPEN INPUT ENTRADA OUTPUT SALIDA * IF NOT FS-ENTRADA-OK DISPLAY 'ERROR EN OPEN DEL FICHERO DE ENTRADA:'FS-ENTRADA END-IF IF NOT FS-SALIDA-OK DISPLAY 'ERROR EN OPEN DEL FICHERO DE SALIDA:'FS-SALIDA END-IF . * ************************************************************ * | 20000 - PROCESO *--|------------------+----------><------------------------* * | SE REALIZA EL TRATAMIENTO DE LOS DATOS: * 1| Realiza el tratamiento de cada registro recuperado de * | la ENTRADA ************************************************************ 20000-PROCESO. * PERFORM 21000-BUSCAR-NOMBRE-EMPRESA PERFORM 22000-BUSCAR-SIGNO-SALDO PERFORM 23000-INFORMAR-SALIDA PERFORM ESCRIBIR-SALIDA PERFORM LEER-ENTRADA . * ************************************************************ * 21000 - BUSCAR NOMBRE EMPRESA *--|------------------+----------><----------+-------------* * BUSCAMOS EL CODIGO DE EMPRESA DEL FICHERO DE ENTRADA EN * NUESTRA TABLA INTERNA PARA RECUPERAR EL NOMBRE ************************************************************ 21000-BUSCAR-NOMBRE-EMPRESA. * *Ponemos el ndice WI-ELEM a 1 y se ir incrementando de 1 en 1 SET WI-ELEM TO 1 *Buscamos en WX-TABLA-EMPRESAS el nombre de empresa que tenga

*el mismo cdigo que el del fichero de entrada. *Si no lo encuentra, movemos espacios al nombre de la empresa SEARCH WX-TABLA-EMPRESAS AT END MOVE SPACES TO WX-SAL-NOMBRE-EMPRESA WHEN WX-CODIGO-EMPRESA(WI-ELEM) EQUAL WX-ENT-COD-EMPRESA MOVE WX-NOMBRE-EMPRESA(WI-ELEM) TO WX-SAL-NOMBRE-EMPRESA END-SEARCH . * ************************************************************ * 22000-BUSCAR-SIGNO-SALDO *--|------------------+----------><----------+-------------* * COMPROBAMOS EL SIGNO DEL SALDO E INFORMAMOS EL CAMPO: * WX-SAL-SIGNO ************************************************************ 22000-BUSCAR-SIGNO-SALDO. * *El signo viene dado por la ltima posicin. La movemos al *switch WB-SIGNOS. Segn su valor informar positivo o negativo MOVE WX-SALDO(4:1) TO WB-SIGNOS EVALUATE TRUE WHEN SIGNO-MAS MOVE WK-POSITIVO TO WX-SAL-SIGNO WHEN SIGNO-MENOS MOVE WK-NEGATIVO TO WX-SAL-SIGNO WHEN OTHER MOVE SPACES END-EVALUATE . TO WX-SAL-SIGNO

* ************************************************************ * 23000-INFORMAR-SALIDA *--|------------------+----------><----------+-------------* * INFORMAMOS EL RESTO DE CAMPOS DEL FICHERO DE SALIDA ************************************************************ 23000-INFORMAR-SALIDA. * MOVE WX-ENT-CLIENTE TO WX-SAL-CLIENTE MOVE WX-ENT-COD-EMPRESA TO WX-SAL-COD-EMPRESA MOVE WX-ENT-SALDO TO WX-SAL-SALDO . * ************************************************************ * LEER ENTRADA *--|------------------+----------><----------+-------------* * Leemos del fichero de entrada ************************************************************ LEER-ENTRADA. *

READ ENTRADA INTO WX-REGISTRO-ENTRADA EVALUATE TRUE WHEN FS-ENTRADA-OK CONTINUE WHEN FS-ENTRADA-EOF SET FIN-ENTRADA TO TRUE WHEN OTHER DISPLAY 'ERROR EN READ DE ENTRADA:'FS-ENTRADA END-EVALUATE . * ************************************************************ * - ESCRIBIR SALIDA *--|------------------+----------><----------+-------------* * ESCRIBIMOS EN EL FICHERO DE SALIDA LA INFORMACION GUARDADA * WX-REGISTRO-SALIDA ************************************************************ ESCRIBIR-SALIDA. * WRITE REG-SALIDA FROM WX-REGISTRO-SALIDA IF FS-SALIDA-OK INITIALIZE WX-REGISTRO-SALIDA ELSE DISPLAY 'ERROR EN WRITE DEL FICHERO:'FS-SALIDA END-IF . * ************************************************************ * | 30000 - FINAL *--|------------------+----------><----------+-------------* * | FINALIZA LA EJECUCION DEL PROGRAMA ************************************************************ 30000-FINAL. * PERFORM 31000-CERRAR-FICHEROS STOP RUN . * ************************************************************ * | 31000 - CERRAR FICHEROS *--|------------------+----------><----------+-------------* * | CERRAMOS LOS FICHEROS DEL PROGRAMA ************************************************************ 31000-CERRAR-FICHEROS. * CLOSE ENTRADA SALIDA IF NOT FS-ENTRADA-OK DISPLAY 'ERROR EN CLOSE DE ENTRADA:'FS-ENTRADA END-IF

IF NOT FS-SALIDA-OK DISPLAY 'ERROR EN CLOSE DE SALIDA:'FS-SALIDA END-IF .

En el programa podemos ver las siguientes divisiones/secciones: IDENTIFICATION DIVISION: existir siempre. ENVIRONMENT DIVISION: existir siempre. CONFIGURATION SECTION: existir siempre. INPUT-OUTPUT SECTION: en este ejemplo existir porque utilizamos un fichero de entrada y uno de salida. DATA DIVISION: existir siempre. FILE SECTION: en este ejemplo existir pues utilizamos un fichero de entrada y uno de salida. WORKING-STORAGE SECTION: exisitir siempre. En este caso no exisistir la LINKAGE SECTION pues el programa no se comunica con otros programas. PROCEDURE DIVISION: exisitir siempre.

En el programa podemos ver las siguientes sentencias: PERFORM: llamada a prrafo INITIALIZE: para inicializar variable OPEN: "Abre" los ficheros del programa. Lo acompaaremos de "INPUT" para los ficheros de entrada y "OUTPUT" para los ficheros de salida. DISPLAY: escribe el contenido del campo indicado en la SYSOUT del JCL. MOVE/TO: movemos la informacin de un campo a otro. SEARCH: esta sentencia se utiliza para buscar un dato dentro de una tabla interna, recorrindola usando un ndice y comparando alguno de sus campos con el campo que buscamos. PERFORM UNTIL: bucle SET: Activa los niveles 88 de un campo tipo "switch". READ: Lee cada registro del fichero de entrada. En el "INTO" le indicamos donde debe guardar la informacin. WRITE: Escribe la informacin indicada en el "FROM" en el fichero indicado. STOP RUN: sentencia de finalizacin de ejecucin. CLOSE: "Cierra" los ficheros del programa. Descripcin del programa: En el prrafo de inicio, inicializamos el registro de salida: WX-REGISTRO-SALIDA Abriremos los ficheros del programa (OPEN INPUT para la enrtada, y OUTPUT para la salida) y controlaremos el file-status. Si todo va bien el cdigo del file-status valdr '00'. Podis ver lalista de los file-status ms comunes. Adems comprobamos que el fichero de entrada no venga vaco (en caso de que as sea, finalizamos la ejecucin). En el prrafo de proceso, que se repetir hasta que se termine el fichero de entrada (FINENTRADA), tenemos varias llamadas a prrafos: 21000-BUSCAR-NOMBRE-EMPRESA: Busca en la taba interna WX-TABLA-EMPRESAS utilizando la sentencia SEARCH. 22000-BUSCAR-SIGNO-SALDO: La ltima posicin del campo saldo (S9(4)) nos indica el signo. Podis ver la referencia a lossignos

en campos numricos. Guardaremos esa ltima posicin en el nivel superior de un campo tipo switch (WB-SIGNOS). Si el valor se corresponde con alguno de los indicados en los niveles 88, ese nivel se activar a "TRUE". En el "EVALUATE TRUE", el programa entrar por la sentencia "WHEN" que est activa (que sea "TRUE"). 23000-INFORMAR-SALIDA: Informamos el resto de campos. ESCRIBIR-SALIDA: Escribimos nuestro registro ya informado en el fichero de salida. LEER-ENTRADA: Leemos el siguiente registro del fichero de entrada. Fichero de salida: ----+----1----+----2----+----3 11111AAEMPRESA 11001positivo 22222BBEMPRESA 21002positivo 33333CCEMPRESA 31002negativo 44444DDEMPRESA 41004negativo campo1: nmero de cliente campo2: cdigo de empresa campo3: nombre de empresa campo4: saldo campo5: signo del saldo En este programa adems de ver como crear un PROCESO que trate todos los registros de un fichero de entrada, hemos visto varias sentencias como el EVALUATE y el SEARCH. As aprovechamos para ir introduciendo ms sentencias tiles del COBOL en forma de ejemplos. Y si os queda cualquier duda, estamos aqu para resolverlas

Ejemplo 4: generando un listado.


Un programa tpico que nos encontraremos en cualquier aplicacin es aquel que genera un listado. Que a qu nos referimos con listado? Mejor verlo para hacernos una idea: ----+----1----+----2----+----3----+----4----+ LISTADO DE EJEMPLO DEL CONSULTORIO COBOL DIA: 23-03-11 PAGINA: 1 -----------------------------------------NOMBRE --------ANA ANA ANA ANA TOTAL ANA APELLIDO --------------LOPEZ MARTINEZ PEREZ RODRIGUEZ : 04

LISTADO DE EJEMPLO DEL CONSULTORIO COBOL DIA: 23-03-11 PAGINA: 2 ------------------------------------------

NOMBRE --------BEATRIZ BEATRIZ BEATRIZ

APELLIDO --------------GARCIA MOREDA OTERO

TOTAL BEATRIZ : 03 TOTAL NOMBRES: 07 Aqu vemos un listado de 2 pginas. Ambas pginas tienen una parte comn que se denomina cabecera y que, por lo general, ser la misma en todas las pginas. Suele contener un ttulo que describa al listado y la fecha en que ha sido generado. Lo nico que cambia es el nmero de pgina en el que estamos^^ Despus tenemos una "subcabecera" tambin comn en cada pgina, en este caso la subcabecera incluye a "NOMBRE" y "APELLIDO". En nuestro listado de ejemplo hemos querido que cada nombre salga en una pgina distinta. Al final de cada pgina de nombre escribimos un "subtotal" con el nmero de registros que hemos escrito para ese nombre. Al final del listado escribiremos una linea de "totales" con el total de registros escritos. El fichero de partida para este programa ser el siguiente: ----+----1----+----2 ANA LOPEZ ANA MARTINEZ ANA PEREZ ANA RODRIGUEZ BEATRIZ GARCIA BEATRIZ MOREDA BEATRIZ OTERO Los ficheros que se usan en listados siempre estn ordenados por algn campo. En nuestro caso por "nombre" y "apellido". En el JCL incluiremos el paso de SORT para ordenarlo. Vamos all! Fichero de entrada desordenado: ----+----1----+----2 ANA LOPEZ BEATRIZ MOREDA ANA PEREZ BEATRIZ OTERO ANA RODRIGUEZ BEATRIZ GARCIA ANA MARTINEZ JCL:
//****************************************************** //******************** BORRADO ************************* //BORRADO EXEC PGM=IDCAMS //SYSPRINT DD SYSOUT=* //SYSIN DD * DEL FICHERO.NOMBRES.APELLIDO.ORDENADO DEL FICHERO.CON.LISTADO SET MAXCC = 0

//****************************************************** //* ORDENAMOS EL FICHERO POR NOMBRE Y APELLIDO ********* //SORT01 EXEC PGM=SORT //SORTIN DD DSN=FICHERO.NOMBRES.APELLIDO,DISP=SHR //SORTOUT DD DSN=FICHERO.NOMBRES.APELLIDO.ORDENADO, // DISP=(,CATLG),SPACE=(TRK,(50,10)) //SYSOUT DD SYSOUT=* //SYSPRINT DD SYSOUT=* //SYSIN DD * SORT FIELDS=(1,9,CH,A,10,10,CH,A) //****************************************************** //*********** EJECUCION DEL PROGRAMA PRUEBA3 *********** //PROG4 EXEC PGM=PRUEBA4 //SYSOUT DD SYSOUT=* //ENTRADA DD DSN=FICHERO.NOMBRES.APELLIDO.ORDENADO,DISP=SHR //SALIDA DD DSN=FICHERO.CON.LISTADO, // DISP=(NEW, CATLG, DELETE),SPACE=(TRK,(50,10)), // DCB=(RECFM=FBA,LRECL=133) /*

En este JCL tenemos 3 pasos: Paso 1: Borrado de ficheros que se generan durante la ejecucin, visto ya en otros ejemplos. Paso 2: Ordenacin del fichero de entrada usando el SORT. Toda la informacin sobre el SORT la tenis en SORT vol.1: SORT, INCLUDE. Paso 3: Ejecucin del programa que genera el listado. Tenemos como fichero de entrada el fichero de salida del SORT, y como fichero de salida ojito: indicaremos RECFM=FBA siempre para listados. Esto significa que el fichero contiene caracteres ASA, que son los que le indican a la impresora los saltos de lnea que tiene que hacer al imprimir. Lo iremos viendo con el programa de ejemplo. La longitud del fichero(LRECL) suele ser 133, debido a que se imprimen en hojas A4 en formato apaisado. Programa: IDENTIFICATION DIVISION. PROGRAM-ID. PRUEBA3. *==========================================================* * PROGRAMA QUE LEE DE FICHERO Y ESCRIBE EN FICHERO *==========================================================* * ENVIRONMENT DIVISION. * CONFIGURATION SECTION. * SPECIAL-NAMES. DECIMAL-POINT IS COMMA. * INPUT-OUTPUT SECTION. * FILE-CONTROL. * SELECT ENTRADA ASSIGN TO ENTRADA STATUS IS FS-ENTRADA. SELECT LISTADO ASSIGN TO LISTADO STATUS IS FS-LISTADO. * DATA DIVISION. * FILE SECTION. * * FICHERO DE ENTRADA DE LONGITUD FIJA (F) IGUAL A 20.

FD ENTRADA RECORDING MODE IS F BLOCK CONTAINS 0 RECORDS RECORD CONTAINS 20 CHARACTERS. 01 REG-ENTRADA PIC X(20). * * FICHERO DE LISTADO DE LONGITUD FIJA (F) IGUAL A 132. FD LISTADO RECORDING MODE IS F BLOCK CONTAINS 0 RECORDS RECORD CONTAINS 132 CHARACTERS. 01 REG-LISTADO PIC X(132). * WORKING-STORAGE SECTION. * * FILE STATUS * 01 FS-STATUS. 05 FS-ENTRADA PIC X(2). 88 FS-ENTRADA-OK VALUE '00'. 88 FS-ENTRADA-EOF VALUE '10'. 05 FS-LISTADO PIC X(2). 88 FS-LISTADO-OK VALUE '00'. * * SWITCHES * 01 WB-FIN-ENTRADA PIC X(1) VALUE 'N'. 88 FIN-ENTRADA VALUE 'S'. * * CONTADORES * 01 WC-LINEAS PIC 9(2). 01 WC-NOMBRES PIC 9(2). 01 WC-TOTALES PIC 9(2). * * VARIABLES * 01 WX-REGISTRO-ENTRADA. 05 WX-NOMBRE PIC X(9). 05 WX-APELLIDO PIC X(10). 01 WX-NOMBRE-ANT 01 WX-FEC-DDMMAA. 05 WX-FEC-DD 05 FILLER 05 WX-FEC-MM 05 FILLER 05 WX-FEC-AA PIC X(9). PIC PIC PIC PIC PIC 9(2). X VALUE '-'. 9(2). X VALUE '-'. 9(2).

01 WX-FECHA PIC 9(6). * * REGISTRO LISTADO * 01 CABECERA1. 05 FILLER PIC X(40) VALUE 'LISTADO DE EJEMPLO DEL CONSULTORIO - 'COBOL'. 01 CABECERA2.

05 05 05 05 05 *

FILLER LT-FECHA FILLER FILLER LT-NUMPAG

PIC PIC PIC PIC PIC

X(5) VALUE 'DIA: '. X(8). X(16) VALUE ALL SPACES. X(8) VALUE 'PAGINA: '. 9.

01 CABECERA3. 05 FILLER * 01 SUBCABECERA1. 05 FILLER 05 FILLER 05 FILLER * 01 SUBCABECERA2. 05 FILLER 05 FILLER 05 FILLER *

PIC X(42) VALUE ALL '-'. PIC X(6) PIC X(9) PIC X(8) VALUE 'NOMBRE'. VALUE ALL SPACES. VALUE 'APELLIDO'.

PIC X(9) VALUE ALL '-'. PIC X(3) VALUE ALL SPACES. PIC X(15) VALUE ALL '-'.

01 DETALLE. 05 LT-NOMBRE PIC X(9). 05 FILLER PIC X(3) VALUE ALL SPACES. 05 LT-APELLIDO PIC X(15). * 01 SUBTOTAL. 05 FILLER 05 LT-NOMTOT 05 FILLER 05 LT-NUMNOM 01 TOTALES. 05 FILLER 05 LT-TOTALES PIC PIC PIC PIC X(6) VALUE 'TOTAL '. X(9). X(2) VALUE ': '. 9(2).

PIC X(15) VALUE 'TOTAL NOMBRES: '. PIC 9(2).

* ************************************************************ PROCEDURE DIVISION. ************************************************************ * | 0000 - PRINCIPAL *--|------------------+----------><----------+-------------* * 1| EJECUTA EL INICIO DEL PROGRAMA * 2| EJECUTA EL PROCESO DEL PROGRAMA * 3| EJECUTA EL FINAL DEL PROGRAMA ************************************************************ 00000-PRINCIPAL. * PERFORM 10000-INICIO * PERFORM 20000-PROCESO UNTIL FIN-ENTRADA * PERFORM 30000-FINAL . * ************************************************************ * | 10000 - INICIO *--|------------+----------><----------+-------------------* * | SE REALIZA EL TRATAMIENTO DE INICIO: * 1| INICIALIZACIN DE REAS DE TRABAJO

* 2| PRIMERA LECTURA DEL FICHERO DE ENTRADA * 3| INFORMAMOS CABECERA Y ESCRIBIMOS CABECERA ************************************************************ 10000-INICIO. * INITIALIZE DETALLE WX-REGISTRO-ENTRADA PERFORM 11000-ABRIR-FICHEROS PERFORM LEER-ENTRADA IF FIN-ENTRADA DISPLAY 'FICHERO DE ENTRADA VACIO' PERFORM 30000-FINAL END-IF MOVE WX-NOMBRE TO WX-NOMBRE-ANT PERFORM INFORMAR-CABECERA PERFORM ESCRIBIR-CABECERAS . * ************************************************************ * 11000 - ABRIR FICHEROS *--|------------------+----------><----------+-------------* * ABRIMOS LOS FICHEROS DEL PROGRAMA ************************************************************ 11000-ABRIR-FICHEROS. * OPEN INPUT ENTRADA OUTPUT LISTADO * IF NOT FS-ENTRADA-OK DISPLAY 'ERROR EN OPEN DE ENTRADA:'FS-ENTRADA END-IF IF NOT FS-LISTADO-OK DISPLAY 'ERROR EN OPEN DE LISTADO:'FS-LISTADO END-IF . * ************************************************************ * 12000 - INFORMAR CABECERA *--|------------------+----------><----------+-------------* * INFORMAMOS EL CAMPO FECHA DE LA CABECERA ************************************************************ INFORMAR-CABECERA. * ACCEPT WX-FECHA FROM DATE MOVE WX-FECHA(1:2) TO WX-FEC-AA MOVE WX-FECHA(3:2) TO WX-FEC-MM MOVE WX-FECHA(5:2) TO WX-FEC-DD MOVE WX-FEC-DDMMAA TO LT-FECHA * Inicializamos el contador de pginas MOVE 1 TO LT-NUMPAG

. * ************************************************************ * | 20000 - PROCESO *--|------------------+----------><------------------------* * | SE REALIZA EL TRATAMIENTO DE LOS DATOS: * 1| ESCRIBIMOS LAS LINEAS DE DETALLE Y CONTROLAMOS LOS * | SALTOS DE PAGINA ************************************************************ 20000-PROCESO. * INITIALIZE DETALLE IF WC-LINEAS GREATER 64 ADD 1 TO LT-NUMPAG PERFORM ESCRIBIR-CABECERAS END-IF IF WX-NOMBRE NOT EQUAL WX-NOMBRE-ANT PERFORM ESCRIBIR-SUBTOTAL ADD 1 TO LT-NUMPAG

PERFORM ESCRIBIR-CABECERAS MOVE ZEROES TO WC-NOMBRES END-IF PERFORM 21000-INFORMAR-DETALLE PERFORM ESCRIBIR-DETALLE MOVE WX-NOMBRE TO WX-NOMBRE-ANT PERFORM LEER-ENTRADA . * ************************************************************ * ESCRIBIR CABECERAS *--|------------------+----------><----------+-------------* * ESCRIBE LA CABECERA Y SUBCABECERA DEL LISTADO ************************************************************ ESCRIBIR-CABECERAS. * WRITE REG-LISTADO FROM CABECERA1 AFTER ADVANCING PAGE WRITE REG-LISTADO FROM CABECERA2 WRITE REG-LISTADO FROM CABECERA3 WRITE REG-LISTADO FROM SUBCABECERA1 AFTER ADVANCING 2 LINES WRITE REG-LISTADO FROM SUBCABECERA2 MOVE 6 . TO WC-LINEAS

* ************************************************************ * ESCRIBIR SUBTOTAL *--|------------------+----------><----------+-------------* * ESCRIBIMOS LINEA DE SUBTOTAL

************************************************************ ESCRIBIR-SUBTOTAL. * MOVE WX-NOMBRE-ANT TO LT-NOMTOT MOVE WC-NOMBRES TO LT-NUMNOM WRITE REG-LISTADO FROM SUBTOTAL AFTER ADVANCING 2 LINES . * ************************************************************ * 21000 INFORMAR DETALLE *--|------------------+----------><----------+-------------* * INFORMAMOS LOS CAMPOS DE LA LINEA DE DETALLE CON LA * INFORMACION DEL FICHERO DE ENTRADA ************************************************************ 21000-INFORMAR-DETALLE. * MOVE WX-NOMBRE TO LT-NOMBRE MOVE WX-APELLIDO TO LT-APELLIDO . * ************************************************************ * ESCRIBIR DETALLE *--|------------------+----------><----------+-------------* * ESCRIBIMOS LA LINEA DE DETALLE ************************************************************ ESCRIBIR-DETALLE. * WRITE REG-LISTADO FROM DETALLE IF NOT FS-LISTADO-OK DISPLAY 'ERROR AL ESCRIBIR DETALLE:'FS-LISTADO END-IF ADD 1 ADD 1 ADD 1 . TO WC-LINEAS TO WC-NOMBRES TO WC-TOTALES

* ************************************************************ * LEER ENTRADA *--|------------------+----------><----------+-------------* * LEEMOS DEL FICHERO DE ENTRADA ************************************************************ LEER-ENTRADA. * READ ENTRADA INTO WX-REGISTRO-ENTRADA EVALUATE TRUE WHEN FS-ENTRADA-OK CONTINUE WHEN FS-ENTRADA-EOF SET FIN-ENTRADA TO TRUE WHEN OTHER DISPLAY 'ERROR EN READ DE ENTRADA:'FS-ENTRADA

END-EVALUATE . * ************************************************************ * | 30000 - FINAL *--|------------------+----------><----------+-------------* * | FINALIZA LA EJECUCION DEL PROGRAMA ************************************************************ 30000-FINAL. * IF WC-LINEAS GREATER 60 ADD 1 TO LT-NUMPAG PERFORM PERFORM PERFORM ELSE PERFORM PERFORM END-IF ESCRIBIR-CABECERAS ESCRIBIR-SUBTOTAL ESCRIBIR-TOTALES ESCRIBIR-SUBTOTAL ESCRIBIR-TOTALES

PERFORM 31000-CERRAR-FICHEROS STOP RUN . * ************************************************************ * | ESCRIBIR TOTALES *--|------------------+----------><----------+-------------* * | ESCRIBIMOS LA LINEA DE TOTALES DEL LISTADO ************************************************************ ESCRIBIR-TOTALES. * MOVE WC-TOTALES TO LT-TOTALES WRITE REG-LISTADO FROM TOTALES . * ************************************************************ * | 31000 - CERRAR FICHEROS *--|------------------+----------><----------+-------------* * | CERRAMOS LOS FICHEROS DEL PROGRAMA ************************************************************ 31000-CERRAR-FICHEROS. * CLOSE ENTRADA LISTADO IF NOT FS-ENTRADA-OK DISPLAY 'ERROR EN CLOSE DE ENTRADA:'FS-ENTRADA END-IF IF NOT FS-LISTADO-OK DISPLAY 'ERROR EN CLOSE DE LISTADO:'FS-LISTADO END-IF . *

En el programa podemos ver las siguientes divisiones/secciones: IDENTIFICATION DIVISION: existir siempre. ENVIRONMENT DIVISION: existir siempre. CONFIGURATION SECTION: existir siempre. INPUT-OUTPUT SECTION: en este ejemplo existir porque utilizamos un fichero de entrada y uno de salida. DATA DIVISION: existir siempre. FILE SECTION: en este ejemplo existir pues utilizamos un fichero de entrada y uno de salida. WORKING-STORAGE SECTION: exisitir siempre. En este caso no exisistir la LINKAGE SECTION pues el programa no se comunica con otros programas. PROCEDURE DIVISION: exisitir siempre.

En el programa podemos ver las siguientes sentencias: PERFORM: llamada a prrafo INITIALIZE: para inicializar variable OPEN: "Abre" los ficheros del programa. Lo acompaaremos de "INPUT" para los ficheros de entrada y "OUTPUT" para los ficheros de salida. DISPLAY: escribe el contenido del campo indicado en la SYSOUT del JCL. MOVE/TO: movemos la informacin de un campo a otro. PERFORM UNTIL: bucle SET:Activa los niveles 88 de un campo tipo "switch". READ: Lee cada registro del fichero de entrada. En el "INTO" le indicamos donde debe guardar la informacin. EVALUATE TRUE: "Evala" si los niveles 88 por los que preguntamos en el "WHEN" estn activados a "TRUE". WRITE: Escribe la informacin indicada en el "FROM" en el fichero indicado. STOP RUN: sentencia de finalizacin de ejecucin. CLOSE: "Cierra" los ficheros del programa. Descripcin del programa: En el prrafo de inicio, inicializamos el registro de salida: WX-REGISTRO-SALIDA Abriremos los ficheros del programa (OPEN INPUT para la entrada, y OUTPUT para la salida) y controlaremos el file-status. Si todo va bien el cdigo del file-status valdr '00'. Podis ver lalista de los file-status ms comunes. Leemos el primer registro del fichero de entrada y controlaremos el file-status. Adems comprobamos que el fichero de entrada no venga vaco (en caso de que as sea, finalizamos la ejecucin). Si todo ha ido OK guardaremos el nombre ledo del fichero de entrada en WX-NOMBRE-ANT para controlar posteriormente el momento en que cambiemos de nombre. Informaremos la parte genrica de la cabecera e inicializamos el contador de pginas. Escribimos la cabecera por primera vez. INFORMAR-CABECERA: Recoge la fecha del sistema mediante un ACCEPT. La variable "DATE" es la fecha del sistema en formato 9(6) AAMMDD. Para informar la fecha del listado formateamos la recibida del sistema a formato DD-MM-AA. ESCRIBIR-CABECERAS: Escribe las lineas de cabecera CABECERA1, CABECERA2, CABECERA3, SUBCABECERA1 y SUBCABECERA2. En el WRITE de CABECERA1 vemos que utilizamos el "AFTER ADVANCING PAGE", esto significa que esta lnea se escribir en una pgina nueva. Lo podemos ver en el caracter ASA que aparece a la izquierda de esta linea en el fichero de salida que ser un '1'.

En el WRITE de SUBCABECERA1 vemos que utilizamos "AFTER ADVANCING 2 LINES", esto significa que se escribir una lnea en blanco y despus la lnea de SUBCABECERA1. El caracter ASA que aparecer ser un '0'. Informamos el contador de lneas a '6', pues la cabecera ocupa 6 lneas. En el prrafo de proceso, que se repetir hasta que se termine el fichero de entrada (FINENTRADA), controlaremos: Por un lado el nmero de lneas escritas, y en caso de superar un mximo (64 en nusetro caso) escribiremos otra vez las cabeceras en una pgina nueva (ver prrado ESCRIBIR-CABECERAS). Por otro lado la variable WX-NOMBRE, pues queremos escribir cada nombre en una pgina distinta. Cuando cambie el nombre escribiremos la lnea de subtotales y volveremos a escribir cabeceras (que nos har el salto de pgina). Informaremos la linea de detalle y escribiremos en el fichero del listado. Guardamos el ltimo nombre escrito en WX-NOMBRE-ANT para controlar el cambio de nombre. Leemos el siguiente registro del fichero de entrada. Llamadas a prrafos: ESCRIBIR-SUBTOTAL: Informar el campo LT-NOMTOT con el nombre que hemos estado escribiendo, y LT-NUMNOM con el contador de registros escritos para ese nombre. Escribir SUBTOTALES dejando antes una lnea en blanco (AFTER ADVANCING 2 LINES). 21000-INFORMAR-DETALLE: Informamos los campos de la lnea de detalle LT-NOMBRE y LT-APELLIDO con los campos de lfichero de entrada WX-NOMBRE y WX-APELLIDO. ESCRIBIR-DETALLE: Escribe la linea de detalle en el fichero del listado. Controlamos file-status y aadimos uno a los contadores. En el prrado de FINAL, finalizaremos el programa escribiendo la lnea de subtotales que falta, y la lnea de totales generales. Controlaremos el nmero de lneas que llevamos escritas, pues para escribir la lnea SUBTOTALES y TOTALES necesitamos 3 lneas. En el prrafo de ESCRIBIR-TOTALES informaremos el campo LT-TOTALES con el contador de registros escritos en total. Al inicio del artculo veiamos como quedara el listado una vez "impreso", ya sea por pantalla o en papel. Vamos a ver como quedara el fichero con los caracteres ASA que indican los saltos de linea. Fichero de salida: ----+----1----+----2----+----3----+----4----+ 1LISTADO DE EJEMPLO DEL CONSULTORIO COBOL DIA: 22-03-11 PAGINA: 1 -----------------------------------------0NOMBRE APELLIDO ----------------------ANA LOPEZ ANA MARTINEZ ANA PEREZ ANA RODRIGUEZ 0TOTAL ANA : 04 1LISTADO DE EJEMPLO DEL CONSULTORIO COBOL DIA: 22-03-11 PAGINA: 2

-----------------------------------------0NOMBRE APELLIDO ----------------------BEATRIZ GARCIA BEATRIZ MOREDA BEATRIZ OTERO 0TOTAL BEATRIZ : 03 TOTAL NOMBRES: 07 Donde: 1 = salto de pgina. 0 = deja una lnea en blanco justo antes. - = deja dos lneas en blanco. espacio = escribe sin dejar lineas en blanco. Y listo! Si veis que no me he parado mucho en alguna cosa y queris que explique ms en detalle, dejad un comentario y lo vemos

Ejemplo 5: programa con DB2


En este ejemplo vamos a ver un programa que accede a base de datos para recuperar informacin. Veremos un ejemplo sencillo en el que el programa recuperar de SYSIN la clave por la que acceder a la base de datos, y displayar la informacin recuperada por SYSOUT. JCL: //PASO01 EXEC PGM=IKJEFT01,DYNAMNBR=20 //SYSTSIN DD * DSN SYSTEM(DSN1) RUN PROGRAM(PRUEBA5) PLAN(PRUEBA5) LIB('LIBRERIA.DE.TU.INSTALACION') //SYSOUT DD SYSOUT=* //SYSIN DD * PEREZ /* Donde EXEC PGM=IKJEFT01 ejecutar el programa que le indiquemos en el SYSTSIN. El DSN SYSTEM depender de cada instalacin y puede variar segn el entorno (desarrollo, preproduccion, explotacin...). En PROGRAM indicaremos el programa con DB2 a ejecutar, y en PLAN el plan DB2 asociado. La librera indicada en LIB es opcional. En la SYSIN le pasaremos la clave por la que accederemos a la tabla. En este caso ser el campo APELLIDO. TABLA: Nombre CARMEN JAVIER SARA Apellido PEREZ LOPEZ GARCIA Telefono 666555444 666999888 666222111

Donde: El campo Nombre es un CHAR(10). El campo Apellido es un CHAR(10). El campo Telefono es un DECIMAL(9). PROGRAMA:

IDENTIFICATION DIVISION. PROGRAM-ID. PRUEBA5. *==========================================================* * PROGRAMA QUE ACCEDE A BASE DE DATOS CON UNA SELECT *==========================================================* * ENVIRONMENT DIVISION. * CONFIGURATION SECTION. * SPECIAL-NAMES. DECIMAL-POINT IS COMMA. * DATA DIVISION. * WORKING-STORAGE SECTION. * EXEC SQL INCLUDE SQLCA END-EXEC. EXEC SQL INCLUDE TABLA END-EXEC. 01 WX-SYSIN. 05 WX-CLAVE 05 FILLER 01 WX-TABLA. 05 WX-NOMBRE 05 WX-APELLIDO 05 WX-TELEFONO 01 WX-VARIABLES. 05 WX-TELEFONO-NUM PIC X(10). PIC X(70). PIC X(10). PIC X(10). PIC S9(9) COMP-3.

PIC 9(9). * ************************************************************ PROCEDURE DIVISION. ************************************************************ * | 00000 - PRINCIPAL *--|------------------+----------><----------+-------------* * 1| EJECUTA EL INICIO DEL PROGRAMA * 2| EJECUTA EL PROCESO DEL PROGRAMA * 3| EJECUTA EL FINAL DEL PROGRAMA ************************************************************ 00000-PRINCIPAL. * PERFORM 10000-INICIO * PERFORM 20000-PROCESO * PERFORM 30000-FINAL . ************************************************************ * | 10000 - INICIO *--|------------+----------><----------+-------------------* * | SE REALIZA EL TRATAMIENTO DE INICIO:

* 1| Inicializacin de reas de Trabajo * 2| Lectura de SYSIN ************************************************************ 10000-INICIO. * INITIALIZE WX-SYSIN WX-TABLA WX-VARIABLES ACCEPT WX-SYSIN FROM SYSIN . ************************************************************ * | 20000 - PROCESO *--|------------------+----------><------------------------* * | SE REALIZA EL TRATAMIENTO DE LOS DATOS: * 1| Realiza el acceso a base de datos ************************************************************ 20000-PROCESO. * EXEC SQL SELECT NOMBRE ,TELEFONO INTO :WX-NOMBRE ,:WX-TELEFONO FROM TABLA WHERE APELLIDO = :WX-CLAVE ORDER BY APELLIDO END-EXEC EVALUATE TRUE WHEN SQLCODE EQUAL ZEROES DISPLAY 'TODO VA BIEN' PERFORM 21000-GRABAR-SALIDA WHEN SQLCODE EQUAL +100 DISPLAY 'NO ENCONTRE NADA' WHEN OTHER DISPLAY 'ALGO HA IDO MAL. EL SQLCODE ES: 'SQLCODE PERFORM 30000-FINAL END-EVALUATE . ************************************************************* * | 21000 - GRABAR - SALIDA *--|------------------+----------><----------+--------------* * | ESCRIBE EN SYSOUT LA INFORMACIN RECUPERADA DE LA TABLA ************************************************************* 21000-GRABAR-SALIDA. * MOVE WX-TELEFONO TO WX-TELEFONO-NUM MOVE WX-CLAVE TO WX-APELLIDO DISPLAY 'NOMBRE :'WX-NOMBRE DISPLAY 'APELLIDO:'WX-APELLIDO DISPLAY 'TELEFONO:'WX-TELEFONO-NUM

. ************************************************************ * | 30000 - FINAL *--|------------------+----------><----------+-------------* * | FINALIZA LA EJECUCION DEL PROGRAMA ************************************************************ 30000-FINAL. * STOP RUN . En el programa podemos ver las siguientes divisiones/secciones: IDENTIFICATION DIVISION: existir siempre. ENVIRONMENT DIVISION: existir siempre. CONFIGURATION SECTION: existir siempre. En este caso no existir la INPUT-OUTPUT SECTION, pues nuestro programa no utiliza ficheros. DATA DIVISION: existir siempre. En este caso no existir la FILE SECTION, pues nuestro programa no utiliza ficheros. WORKING-STORAGE SECTION: exisitir siempre. En este caso no exisistir la LINKAGE SECTION pues el programa no se comunica con otros programas. PROCEDURE DIVISION: exisitir siempre. En el programa podemos ver las siguientes sentencias: PERFORM: llamada a prrafo INITIALIZE: para inicializar variable ACCEPT: esta sentencia recoge la informacin del campo indicado en el "FROM". En este caso recoge la informacin almacenada en "SYSIN"; la que nosotros hemos introducido en el JCL. EXEC SQL/END-EXEC: son las etiquetas para incluir cdigo SQL. Todas las sentencias DB2 se deben incluir entre estas etiquetas. EVALUATE TRUE: Valida que se cumplan las condiciones indicadas en cada uno de los "WHEN". MOVE/TO: movemos la informacin de un campo a otro DISPLAY: escribe el contenido del campo indicado en la SYSOUT del JCL. STOP RUN: sentencia de finalizacin de ejecucin. Descripcin del programa: En la WORKING-STORAGE hemos incluido la copy SQLCA (SQL communications area rea de comunicacin SQL), que es la que utiliza el gestor de base de datos para devolver la informacin de errores. La estructura es la siguiente: 01 SQLCA SYNC. 05 SQLCAID PIC X(8) VALUE "SQLCA ". 05 SQLCABC PIC S9(9) COMP-5 VALUE 136. 05 SQLCODE PIC S9(9) COMP-5. 05 SQLERRM. 05 SQLERRP PIC X(8). 05 SQLERRD OCCURS 6 TIMES PIC S9(9) COMP-5. 05 SQLWARN. 10 SQLWARN0 PIC X. 10 SQLWARN1 PIC X. 10 SQLWARN2 PIC X. 10 SQLWARN3 PIC X. 10 SQLWARN4 PIC X. 10 SQLWARN5 PIC X. 10 SQLWARN6 PIC X.

10 SQLWARN7 PIC X. 10 SQLWARN8 PIC X. 10 SQLWARN9 PIC X. 10 SQLWARNA PIC X. 05 SQLSTATE PIC X(5). * Como veis incluye la variable SQLCODE, donde guardar el cdigo de retorno que nos indicar si la consulta ha ido bien o no. Hemos incluido tambin la DCLGEN de la tabla "TABLA" que contendr los campos DB2 de la tabla (los que codificamos en la parte de la SELECT) y sus campos working y que tendr algo de este estilo: EXEC SQL DECLARE TABLA TABLE (NOMBRE CHAR(10) NOT NULL, APELLIDO CHAR(10) NOT NULL, RELEFONO DECIMAL(9) NOT NULL) END-EXEC. 01 DCLTABLA. 10 TAB-NOMBRE 10 TAB-APELLIDO 10 TAB-TELEFONO PIC X(10). PIC X(10). PIC S9(9) COMP-3.

En el prrafo de inicio, inicializamos todas las variables de trabajo definidas en la WORKINGSTORAGE, y realizamos un ACCEPT para recoger la informacin que hemos puesto en la SYSIN. En nuestro caso se trata del campo clave por el que accederemos a nuestra tabla. En el prrafo de proceso, hacemos una SELECT a la tabla con la condicin APELLIDO = :WXCLAVE. Donde WX-CLAVE contiene el apellido recogido por SYSIN. Comprobamos el SQLCODE que nos devuelve esta consulta: Si el SQLCODE es cero, la consulta ha ido bien y se ha encontrado el apellido contenido en WXCLAVE en nuestra tabla. En nuestro caso dar este SQLCODE, pues "PEREZ" est en la tabla. Si el SQLCODE es 100, la consulta ha ido bien pero no ha encontrado el apellido "PEREZ" en nuestra tabla. Si el SQLCODE es cualquier otro, la consulta ha ido mal y habr que comprobar en la tabla de errores DB2 cul ha sido el problema. NOTA: el tema de la puntuacin en sentencias SQL (es decir, poner o no poner un punto '.' al final de una sentencia DB2 dentro de la PROCEDURE DIVISION) depender de la versin del compilador. En el prrafo de GRABAR-SALIDA, movemos el campo WX-TELEFONO a una variable numrica sin comprimir (WX-TELEFONO-NUM), para que al hacer el DISPLAY se vea correctamente. Luego displayamos los campos recuperados de la consulta.

RESULTADO: NOMBRE : CARMEN APELLIDO: PEREZ TELEFONO: 666555444 Si queris probar este ejemplo, tendris que hacer una sentencia SELECT a una tabla que exista en vuestra base de datos

Ejemplo 6: programa que llama a otro programa

En este ejemplo vamos a ver un programa que llama a otro programa, denominado rutina, para recuperar informacin. Se trata de un programa sin DB2 que recibir un nmero de DNI por SYSIN y llamar a una rutina para calcular la letra de dicho NIF. La informacin recuperada la mostrar por SYSOUT. JCL: //PROG6 EXEC PGM=PRUEBA6 //SYSOUT DD SYSOUT=* //SYSIN DD * 32684930 /* donde EXEC PGM= indica el programa SIN DB2 que vamos a ejecutar SYSOUT DD SYSOUT=* indica que la informacin "displayada" se quedar en la cola del SYSOUT (no lo vamos a guardar en un fichero) en SYSIN DD * metemos la informacin que va a recibir el programa PROGRAMA: IDENTIFICATION DIVISION. PROGRAM-ID. PRUEBA6. *==========================================================* * PROGRAMA QUE LLAMA A OTRO PROGRAMA (RUTINA) *==========================================================* * ENVIRONMENT DIVISION. * CONFIGURATION SECTION. * SPECIAL-NAMES. DECIMAL-POINT IS COMMA. * DATA DIVISION. * WORKING-STORAGE SECTION. * 01 WX-SYSIN. 05 WX-NUMERO-NIF PIC X(8). 05 FILLER PIC X(72). 01 WX-RUTINA. 05 WX-NIF-COMPLETO. 10 WX-NUMERO-NIF PIC 9(8). 10 WX-LETRA-NIF PIC X. 05 WX-RETORNO PIC X(2). 01 RUTINA1 PIC X(7) VALUE 'RUTINA1'. * ************************************************************ PROCEDURE DIVISION. ************************************************************ * | 00000 - PRINCIPAL *--|------------------+----------><----------+-------------* * 1| EJECUTA EL INICIO DEL PROGRAMA * 2| EJECUTA EL PROCESO DEL PROGRAMA * 3| EJECUTA EL FINAL DEL PROGRAMA ************************************************************

00000-PRINCIPAL. * PERFORM 10000-INICIO * PERFORM 20000-PROCESO * PERFORM 30000-FINAL . * ************************************************************ * | 10000 - INICIO *--|------------+----------><----------+-------------------* * | SE REALIZA EL TRATAMIENTO DE INICIO: * 1| Inicializacin de reas de Trabajo * 2| Lectura de SYSIN ************************************************************ 10000-INICIO. * INITIALIZE WX-SYSIN WX-RUTINA ACCEPT WX-SYSIN FROM SYSIN . ************************************************************ * | 20000 - PROCESO *--|------------------+----------><------------------------* * | SE REALIZA EL TRATAMIENTO DE LOS DATOS: * 1| Realiza el acceso a base de datos ************************************************************ 20000-PROCESO. * MOVE WX-NUMERO-NIF OF WX-SYSIN TO WX-NUMERO-NIF OF WX-RUTINA CALL RUTINA1 USING WX-RUTINA IF WX-RETORNO EQUAL 'OK' DISPLAY 'LA LLAMADA HA IDO BIEN' PERFORM 21000-GRABAR-SALIDA ELSE DISPLAY 'LA LLAMADA HA IDO MAL' PERFORM 30000-FINAL END-IF . ************************************************************* * | 21000 - GRABAR - SALIDA *--|------------------+----------><----------+--------------* * | ESCRIBE EN SYSOUT LA INFORMACIN RECUPERADA DE LA TABLA ************************************************************* 21000-GRABAR-SALIDA. * DISPLAY 'NIF COMPLETO:'WX-NIF-COMPLETO . * ************************************************************

* | 30000 - FINAL *--|------------------+----------><----------+-------------* * | FINALIZA LA EJECUCION DEL PROGRAMA ************************************************************ 30000-FINAL. * STOP RUN . En el programa podemos ver las siguientes divisiones/secciones: IDENTIFICATION DIVISION: existir siempre. ENVIRONMENT DIVISION: existir siempre. CONFIGURATION SECTION: existir siempre. En este caso no existir la INPUT-OUTPUT SECTION, pues nuestro programa no utiliza ficheros. DATA DIVISION: existir siempre. En este caso no existir la FILE SECTION, pues nuestro programa no utiliza ficheros. WORKING-STORAGE SECTION: exisitir siempre. En este caso no exisistir la LINKAGE SECTION pues el programa no es llamado desde otros programas. PROCEDURE DIVISION: exisitir siempre.

En el programa podemos ver las siguientes sentencias: PERFORM: llamada a prrafo INITIALIZE: para inicializar variable ACCEPT: esta sentencia recoge la informacin del campo indicado en el "FROM". En este caso recoge la informacin almacenada en "SYSIN"; la que nosotros hemos introducido en el JCL. MOVE/TO: movemos la informacin de un campo a otro CALL/USING:es la sentencia que usamos para llamar a una rutina. Despus del CALL indicamos el nombre de la rutina que vamos a invocar, y despus del USING indicamos las variables de comunicacin entre ambos programas. DISPLAY: escribe el contenido del campo indicado en la SYSOUT del JCL. IF/ELSE: comprueba si se cumple una condicin. STOP RUN: sentencia de finalizacin de ejecucin.

Descripcin del programa: En el prrafo de inicio, inicializamos las variables que vamos a utilizar a lo largo del programa. Luego mediante un ACCEPT recogemos la informacin que hemos escrito en la SYSIN de nuestro JOB. En el prrafo de proceso, informamos el campo WX-NUMERO-NIF del rea WX-RUTINA con la informacin recogida de SYSIN. Como veis existen dos variables con el mismo nombre. Esto no dar problemas al compilar, mientras las variables pertenezcan a niveles superiores diferentes. En nuestro caso tenemos un WX-NUMERO-NIF que pertenece a WX-SYSIN, y otro que pertenece a WX-RUTINA. Para utilizar estas variables a lo largo del programa tendremos que indicar a cul de ellas nos referimos, por eso les hemos aadido el "OF WX-XXXXX". Una vez informada el rea de comunicacin entre dos programas, procedemos a hacer la llamada en s con la sentencia CALL/USING. Se trata de una llamada dinmica, pues el nombre de la rutina est contenido dentro de una variable, as que despus de la llamada la rutina ser descargada de la memoria. En las llamadas estticas el nombre de la rutina se indica entre comillas simpes 'RUTINA1'. En este caso, despus de la llamada el mdulo queda residente en memoria, porque se integra en el

programa objeto. Para que no haya errores comprobamos que la llamada ha ido bien validando el retorno (informado dentro de la rutina). Si todo ha ido bien grabamos la informacin recuperada (NIF con letra) en la SYSOUT mediante un DISPLAY.

RUTINA IDENTIFICATION DIVISION. PROGRAM-ID. RUTINA1. *==========================================================* * RUTINA QUE CALCULA LA LETRA DE UN NIF *==========================================================* * ENVIRONMENT DIVISION. * CONFIGURATION SECTION. * SPECIAL-NAMES. DECIMAL-POINT IS COMMA. * DATA DIVISION. * WORKING-STORAGE SECTION. * 01 WI-INDICES. 05 WI-IND PIC 9(2). * 01 WX-VARIABLES. 05 WX-NIF-DIVID PIC 9(8). 05 WX-NIF-MULTI PIC 9(8). * 01 WT-TABLAS. 05 WT-NIF-TABLA PIC X(24) VALUE "TRWAGMYFPDXBNJZSQVHLCKET". 05 WT-NIF-TABLA-R REDEFINES WT-NIF-TABLA. 10 WT-LETRA-TABLA OCCURS 24 PIC X. * LINKAGE SECTION. * 01 WX-RUTINA. 05 WX-NIF-COMPLETO. 10 WX-NUMERO-NIF PIC 9(8). 10 WX-LETRA-NIF PIC X. 05 WX-RETORNO PIC X(2). * ************************************************************ PROCEDURE DIVISION USING WX-RUTINA. ************************************************************ * | 00000 - PRINCIPAL *--|------------------+----------><----------+-------------* * 1| EJECUTA EL INICIO DEL PROGRAMA * 2| EJECUTA EL PROCESO DEL PROGRAMA * 3| EJECUTA EL FINAL DEL PROGRAMA ************************************************************

00000-PRINCIPAL. * PERFORM 10000-INICIO * PERFORM 20000-PROCESO * PERFORM 30000-FINAL . ************************************************************ * | 10000 - INICIO *--|------------+----------><----------+-------------------* * | SE REALIZA EL TRATAMIENTO DE INICIO: * 1| Inicializacin de reas de Trabajo ************************************************************ 10000-INICIO. * INITIALIZE WX-VARIABLES WI-INDICES . * ************************************************************ * | 20000 - PROCESO *--|------------------+----------><------------------------* * | SE REALIZA EL TRATAMIENTO DE LOS DATOS: * 1| Realiza el clculo de la letra del NIF ************************************************************ 20000-PROCESO. * COMPUTE WX-NIF-DIVID = WX-NUMERO-NIF / 23 COMPUTE WX-NIF-MULTI = WX-NIF-DIVID * 23 COMPUTE WI-IND = WX-NUMERO-NIF - WX-NIF-MULTI ADD 1 TO WI-IND

MOVE WT-LETRA-TABLA(WI-IND) TO WX-LETRA-NIF MOVE 'OK' . TO WX-RETORNO

* ************************************************************ * | 30000 - FINAL *--|------------------+----------><----------+-------------* * | FINALIZA LA EJECUCION DEL PROGRAMA ************************************************************ 30000-FINAL. * GOBACK .

En el programa podemos ver las siguientes divisiones/secciones: IDENTIFICATION DIVISION: existir siempre. ENVIRONMENT DIVISION: existir siempre. CONFIGURATION SECTION: existir siempre. En este caso no existir la INPUT-OUTPUT SECTION, pues nuestro programa no utiliza ficheros. DATA DIVISION: existir siempre.

En este caso no existir la FILE SECTION, pues nuestro programa no utiliza ficheros. WORKING-STORAGE SECTION: exisitir siempre. LINKAGE SECTION: en este caso s existir puesto que se trata de una rutina que es llamada por un programa principal. PROCEDURE DIVISION: exisitir siempre.

En el programa podemos ver las siguientes sentencias: PERFORM: llamada a prrafo INITIALIZE: para inicializar variable COMPUTE: realiza clculos numricos ADD: operador de adicin (suma) MOVE/TO: movemos la informacin de un campo a otro GOBACK: sentencia de finalizacin de ejecucin para rutinas. Devuelve el control al programa llamante.

Descripcin del programa: En la LINKAGE SECTION definimos el rea de comunicacin con el programa llamante (PRUEBA6), en este caso WX-RUTINA. En el prrafo de inicio inicializamos las variables que vamos a utilizar a lo largo del programa. En el prrafo de proceso hacemos los clculos necesarios para saber qu letra se corresponde al nmero de NIF que hemos introducido e informamos con un 'OK' el cdigo de retorno. En caso de que se produzca un error antes de terminar el proceso, el cdigo de retorno ir vaco, y podremos controlar esta diferencia en el programa llamante. Una vez calculada la letra del NIF devolvemos el control al programa PRUEBA6 haciendo GOBACK. RESULTADO: NIF-COMPLETO: 32684930K

Diferencias entre ambos programas: LINKAGE SECTION: slo la rutina (programa que es llamado por otro) tiene variables definidas en esta seccin. PROCEDURE DIVISION: slo la rutina lleva asociada el rea de comunicacin entre programas en la procedure, aadindole la sentencia USING. 30000-FINAL: el programa principal lleva un STOP RUN de finalizacin de ejecucin, mientras que la rutina lleva un GOBACK para devolver el control al programa llamante (programa que ha hecho el CALL).

Ejemplo 7: ficheros VB (longitud variable)


En este ejemplo vamos a crear un programa que lee de un fichero de entrada de longitud fija y escriba en un fichero de salida de longitud variable.

JCL:
//****************************************************** //******************** BORRADO ************************* //BORRADO EXEC PGM=IDCAMS //SYSPRINT DD SYSOUT=* //SYSIN DD * DEL FICHERO.DE.SALIDA SET MAXCC = 0 //****************************************************** //*********** EJECUCION DEL PROGRAMA PRUEBA3 *********** //P001 EXEC PGM=PRUEBA7 //SYSOUT DD SYSOUT=* //ENTRADA DD DSN=FICHERO.DE.ENTRADA,DISP=SHR //SALIDA DD DSN=FICHERO.DE.SALIDA, // DISP=(NEW,CATLG,DELETE),SPACE=(TRK,(50,10)), // DCB=(RECFM=VB,LRECL=107,BLKSIZE=0) /*

En este caso volvemos a utilizar el IDCAMS para borrar el fichero de salida que se genera en el segundo paso. Se trata de un programa sin DB2, as que utilizamos el EXEC PGM. Para definir el fichero de entrada "ENTRADA" indicaremos que es un fichero ya existente y compartido al indicar DISP=SHR. En la SYSOUT veremos los mensajes de error en caso de que los haya. El fichero de salida se definir como variable al indicar RECFM=VB, la longitud del fichero ser la mxima que pueda tener (pues cada registro medir diferente) indicada en LRECL=107. Si sumamos las posiciones de la variable que define el fichero de salida en el programa, REGSALIDA, veremos que suman 103. La razn de que se indique 107 en el JOB es que para los ficheros de longitud variable, el sistema reserva las 4 primeras posiciones para guardar la longitud, de ah los 107 (103+4). Veremos ms propiedades de los ficheros de longitud variable en otro artculo. Fichero de entrada: ----+----10000155501 0000155502 0000155503 0000255504 0000255505 0000355506 0000455507 Campo1: cdigo de cliente Campo2: cdigo de producto PROGRAMA: IDENTIFICATION DIVISION. PROGRAM-ID. PRUEBA7. *=======================================================* * PROGRAMA QUE LEE DE FICHERO FB Y * ESCRIBE EN FICHERO VB *=======================================================* * ENVIRONMENT DIVISION. * CONFIGURATION SECTION. * SPECIAL-NAMES.

DECIMAL-POINT IS COMMA. * INPUT-OUTPUT SECTION. * FILE-CONTROL. * SELECT ENTRADA ASSIGN TO ENTRADA STATUS IS FS-ENTRADA. SELECT SALIDA ASSIGN TO SALIDA STATUS IS FS-SALIDA. * DATA DIVISION. * FILE SECTION. * * Fichero de entrada de longitud fija (F) igual a 11. FD ENTRADA RECORDING MODE IS F BLOCK CONTAINS 0 RECORDS RECORD CONTAINS 10 CHARACTERS. 01 REG-ENTRADA PIC X(10). * * Fichero de salida de longitud variable (V). FD SALIDA RECORDING MODE IS V BLOCK CONTAINS 0 RECORDS. * Utilizando el depending on hacemos que el ltimo campo * tome diferentes longitudes dependiendo de REG-LONG 01 REG-SALIDA. 05 REG-CLIENTE PIC 9(5). 05 REG-LONG PIC 9(4) COMP-3. 05 REG-PRODUCTO. 10 PRODUCTO PIC X OCCURS 1 TO 95 TIMES DEPENDING ON REG-LONG. * WORKING-STORAGE SECTION. * FILE STATUS 01 FS-STATUS. 05 FS-ENTRADA PIC X(2). 88 FS-ENTRADA-OK VALUE '00'. 88 FS-FICHERO1-EOF VALUE '10'. 05 FS-SALIDA PIC X(2). 88 FS-SALIDA-OK VALUE '00'. * * VARIABLES 01 WB-FIN-ENTRADA PIC X(1) VALUE 'N'. 88 FIN-ENTRADA VALUE 'S'. * 01 WI-PRODUCTO 01 WX-CLIENTE-ANT * 01 WX-REGISTRO-ENTRADA. 05 WX-ENT-CLIENTE 05 WX-ENT-PRODUCTO * 01 WX-REGISTRO-SALIDA. 05 WX-SAL-PRODUCTO * PIC X(5) OCCURS 19 TIMES. PIC 9(5). PIC X(5). PIC 9(3) COMP-3. PIC 9(5).

************************************************************ PROCEDURE DIVISION. ************************************************************ * | 0000 - PRINCIPAL *--|------------------+----------><----------+-------------* * 1| EJECUTA EL INICIO DEL PROGRAMA * 2| EJECUTA EL PROCESO DEL PROGRAMA * 3| EJECUTA EL FINAL DEL PROGRAMA ************************************************************ 00000-PRINCIPAL. * PERFORM 10000-INICIO * PERFORM 20000-PROCESO UNTIL FIN-ENTRADA * PERFORM 30000-FINAL . ************************************************************ * | 10000 - INICIO *--|------------+----------><----------+-------------------* * | SE REALIZA EL TRATAMIENTO DE INICIO: * 1| Inicializacin de reas de Trabajo * 2| Primera lectura de SYSIN ************************************************************ 10000-INICIO. * INITIALIZE WX-REGISTRO-SALIDA PERFORM 11000-ABRIR-FICHERO PERFORM LEER-ENTRADA IF FIN-ENTRADA DISPLAY 'FICHERO DE ENTRADA VACIO' PERFORM 30000-FINAL END-IF MOVE WX-ENT-CLIENTE TO WX-CLIENTE-ANT MOVE ZEROES TO WI-PRODUCTO . * ************************************************************ * 11000 - ABRIR FICHEROS *--|------------------+----------><----------+-------------* * Abrimos los ficheros del programa ************************************************************ 11000-ABRIR-FICHEROS. * OPEN INPUT ENTRADA OUTPUT SALIDA * IF NOT FS-ENTRADA-OK DISPLAY 'ERROR EN OPEN DE ENTRADA:'FS-ENTRADA END-IF

IF NOT FS-SALIDA-OK DISPLAY 'ERROR EN OPEN DE SALIDA:'FS-SALIDA END-IF . * ************************************************************ * | 20000 - PROCESO *--|------------------+----------><------------------------* * | SE REALIZA EL TRATAMIENTO DE LOS DATOS: * 1| Realiza el tratamiento de cada registro recuperado de * | la ENTRADA ************************************************************ 20000-PROCESO. * IF WX-ENT-CLIENTE EQUAL WX-CLIENTE-ANT *Para un mismo cliente, guardamos sus codigos de producto PERFORM 21000-GUARDAR-PRODUCTO ELSE *Al cambiar de cliente, escribimos el registro con *los productos del cliente anterior PERFORM 22000-INFORMAR-SALIDA PERFORM ESCRIBIR-SALIDA *Inicializamos las variables de trabajo MOVE ZEROES TO WI-PRODUCTO MOVE SPACES TO WX-REGISTRO-SALIDA *Guardamos el siguiente cliente que vamos a tratar MOVE WX-ENT-CLIENTE TO WX-CLIENTE-ANT *Guardamos el codigo de producto del siguiente cliente PERFORM 21000-GUARDAR-PRODUCTO END-IF PERFORM LEER-ENTRADA . * ************************************************************ * 21000-GUARDAR-PRODUCTO *--|------------------+----------><----------+-------------* * GUARDAMOS EL CODIGO DE PRODUCTO PARA UN MISMO CLIENTE * EN LA TABLA WX-REG-SALIDA ************************************************************ 21000-GUARDAR-PRODUCTO. * ADD 1 TO WI-PRODUCTO MOVE WX-ENT-PRODUCTO TO WX-SAL-PRODUCTO(WI-PRODUCTO) . * ************************************************************ * 22000-INFORMAR-SALIDA *--|------------------+----------><----------+-------------* * INFORMAMOS LOS CAMPOS DEL FICHERO DE SALIDA * 1 * COMO HEMOS CAMBIADO DE CLIENTE, REG-CLIENTE SERA EL * ALMACENADO EN WX-CLIENTE-ANT * 2 * CALCULAMOS LA LONGITUD DE REG-PRODUCTO MULTIPLICANDO

* EL NMERO DE PRODUCTOS ALMACENADOS POR SU LONGITUD (5) * 3 * MOVEMOS LOS CODIGOS GUARDADOS EN WX-REGISTRO-SAL * A REG-PRODUCTO ************************************************************ 22000-INFORMAR-SALIDA. * *1* MOVE WX-CLIENTE-ANT TO REG-CLIENTE *2* COMPUTE REG-LONG = WI-PRODUCTO * 5 *3* MOVE WX-REGISTRO-SALIDA(1:REG-LONG) TO REG-PRODUCTO . * ************************************************************ * LEER ENTRADA *--|------------------+----------><----------+-------------* * Leemos del fichero de entrada ************************************************************ LEER-ENTRADA. * READ ENTRADA INTO WX-REGISTRO-ENTRADA EVALUATE TRUE WHEN FS-ENTRADA-OK CONTINUE WHEN FS-ENTRADA-EOF SET FIN-ENTRADA TO TRUE WHEN OTHER DISPLAY 'ERROR EN READ DE ENTRADA:'FS-ENTRADA END-EVALUATE . * ************************************************************ * - ESCRIBIR SALIDA *--|------------------+----------><----------+-------------* * ESCRIBIMOS EN EL FICHERO DE SALIDA LA INFORMACION GUARDADA * WX-REGISTRO-SALIDA ************************************************************ ESCRIBIR-SALIDA. * WRITE REG-SALIDA IF FS-SALIDA-OK INITIALIZE WX-REGISTRO-SALIDA ELSE DISPLAY 'ERROR EN WRITE DEL FICHERO:'FS-SALIDA END-IF * ************************************************************ * | 30000 - FINAL *--|------------------+----------><----------+-------------* * | FINALIZA LA EJECUCION DEL PROGRAMA

************************************************************ 30000-FINAL. * *Escribimos la informacin del ltimo cliente PERFORM 22000-INFORMAR-SALIDA PERFORM ESCRIBIR-SALIDA *Cerramos ficheros PERFORM 31000-CERRAR-FICHEROS STOP RUN . * ************************************************************ * | 31000 - CERRAR FICHEROS *--|------------------+----------><----------+-------------* * | CERRAMOS LOS FICHEROS DEL PROGRAMA ************************************************************ 31000-CERRAR-FICHEROS. * CLOSE ENTRADA SALIDA IF NOT FS-ENTRADA-OK DISPLAY 'ERROR EN CLOSE DE ENTRADA:'FS-ENTRADA END-IF IF NOT FS-SALIDA-OK DISPLAY 'ERROR EN CLOSE DE SALIDA:'FS-SALIDA END-IF Fichero de salida: ----+----1----+----2----+ 00001 555015550255503 FFFFF005FFFFFFFFFFFFFFF 0000101F555015550255503 ------------------------00002 5550455505 FFFFF000FFFFFFFFFF 0000201F5550455505 ------------------------00003 55506 FFFFF005FFFFF 0000300F55506 ------------------------00004 55507 FFFFF005FFFFF 0000400F55507

Anda mungkin juga menyukai