Mostrando entradas con la etiqueta SORT. Mostrar todas las entradas
Mostrando entradas con la etiqueta SORT. Mostrar todas las entradas

lunes, 28 de diciembre de 2020

SORT vol.3: OUTFIL.

ACTUALIZADO: ejemplo de STARTREC/ENDREC

La estructura general de un SORT es la siguiente:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2(opcional),DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
  …
  …

PGM=SORT --> Indica el programa a utilizar, en este caso el SORT.
PARM=('DYNALLOC=(SYSALLDA,32)') --> Cantidad de memoria que se da a la ejecución del paso. Si se queda corto, aumentarla en valores de 8,12,32,64,128, 256 (como las memorias RAM)
SORTIN --> Ficheros de entrada
SORTOUT --> Ficheros de salida
SYSIN --> Indica el tipo de sort a realizar, las opciones disponibles son muchas y muy variadas, pudiendo utilizarse varias juntas en un mismo paso. Algunas de ellas son SORT, SUM, OMIT, INCLUDE, INREC, OUTREC, OUTFIL, OPTION … .

En este documento se explica en detalle algunas de estas funciones:


OUTFIL

Esta utilidad nos permite, a partir de un fichero(o varios) de entrada, filtrar en varios ficheros de salida.
Además, permite utilizar simultáneamente, todos las utilidades del SORT(OUTREC, INCLUDE, etc.) para filtrar cada fichero independientemente del otro.

NOTA: En este documento no vamos a entrar a explicar el OUTREC, INCLUDE, etc. Existen artículos en este blog que explican en detalle estas utilidades.

La definición de un OUTFIL es la siguiente:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2,DISP=SHR
//SALIDA1  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SALIDA2  DD DSN=nombre.fichero.salida2,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SALIDA3  DD DSN=nombre.fichero.salida3,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 SORT FIELDS=COPY
 OUTFIL FNAMES=SALIDA1,INCLUDE=(…),
                        OUTREC=(…) ,
                         INREC=(…) ,
                         …
 OUTFIL FNAMES=SALIDA2,INCLUDE=(…),
                        OUTREC=(…) ,
                         INREC=(…) ,
                         …
 OUTFIL FNAMES=SALIDA3,SAVE


Primero se han de definir los ficheros de salida, asignando un nombre a cada uno (SALIDA1, SALIDA2, SALIDA3, etc..)
Luego, por cada fichero de salida se introduce un OUTFIL, y en el FNAMES se asocia con el nombre asignado antes (ejemplo FNAMES=SALIDA1).
A continuación, indicar en cada fichero, el filtro que se va a utilizar mediante INCLUDE, OUTREC, etc…
Utilizando la opción SAVE, se indica que todos los registros que no cumplan ninguna de las condiciones anteriores se escribirán en el fichero indicado. En el caso del ejemplo en la SALIDA3.

Cosas a tener en cuenta:
- Cuidado al escribir el INCLUDE, OUTREC, etc. Normalmente se escribe "INCLUDE COND=", y sin embargo, en el OUTFIL se escribe "INCLUDE=". Lo mismo pasa con el "OUTREC FIELDS=", que pasa a ser "OUTREC=". Por norma general, se ha de quitar la segunda parte. El "OMIT COND=" quedaría "OMIT=", etc.

Vamos a ver un ejemplo:

Situación 1. Vamos a dividir el siguiente fichero en 2, filtrando por la Situación Laboral. En el fichero de salida 1 meteremos los Asalariados y en el fichero de salida 2 los autónomos. Además en cada fichero, vamos a sacar únicamente el Nombre y los Apellidos:


----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO
000000006ANTONIO   VILLA     SUSO     AUTONOMO  
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO  
000000001JOSE      LOPEZ     PITA     AUTONOMO  
000000004CARLOS    POLO      DEL BARROAUTONOMO  
000000003CARLOS    PEREZ     FANO     AUTONOMO  


La fórmula sería:

//OUTREC   EXEC SORTD
//SYSOUT   DD SYSOUT=*
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//SALIDA1  DD DSN=nombre.fichero.asalariados,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SALIDA2  DD DSN=nombre.fichero.autónomos,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSIN    DD *
SORT FIELDS=COPY
OUTFIL FNAMES=SALIDA1,INCLUDE=(39,10,CH,EQ,C'ASALARIADO'),
                       OUTREC=(10,29)
OUTFIL FNAMES=SALIDA2,INCLUDE=(39,10,CH,EQ,C'AUTONOMO  '),
                       OUTREC=(10,29)

La salida quedará del siguiente modo:

SALIDA1 - ASALARIADOS:


----+----1----+----2----+----
JAVIER    MARTINEZ   CARRETERO


SALIDA2 - AUTONOMOS:


----+----1----+----2----+----
ANTONIO   VILLA     SUSO     
YOLANDA   LOPEZ     ALONSO   
JOSE      LOPEZ     PITA     
CARLOS    POLO      DEL BARRO
CARLOS    PEREZ     FANO     


STARTREC/ENDREC:
Con OUTFIL no están disponibles las opciones SKIPREC/STOPAFT, en su lugar utilizamos STARTREC y ENDREC con el mismo principio.

Retomando el fichero de entrada anterior:
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO 
000000006ANTONIO   VILLA     SUSO     AUTONOMO   
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO   
000000001JOSE      LOPEZ     PITA     AUTONOMO   
000000004CARLOS    POLO      DEL BARROAUTONOMO   
000000003CARLOS    PEREZ     FANO     AUTONOMO   

//SYSIN    DD * 
SORT FIELDS=(10,29,CH,A) 
OUTFIL FNAMES=SALIDA1,ENDREC=1 
OUTFIL FNAMES=SALIDA2,STARTREC=2,ENDREC=4 

Primero se ordenan los registros:
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000006ANTONIO   VILLA     SUSO     AUTONOMO   
000000003CARLOS    PEREZ     FANO     AUTONOMO   
000000004CARLOS    POLO      DEL BARROAUTONOMO   
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO 
000000001JOSE      LOPEZ     PITA     AUTONOMO   
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO   

Y luego genera los diferentes ficheros de salida:
SALIDA1:
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000006ANTONIO   VILLA     SUSO     AUTONOMO   


SALIDA2:
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000003CARLOS    PEREZ     FANO     AUTONOMO   
000000004CARLOS    POLO      DEL BARROAUTONOMO   
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO 
000000001JOSE      LOPEZ     PITA     AUTONOMO   

SORT vol.1: SORT, INCLUDE.

ACTUALIZADO: comparando zonas de un mismo registro con INCLUDE.

La estructura general de un SORT es la siguiente:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2,DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *




PGM=SORT --> Indica el programa a utilizar, en este caso el SORT
PARM=('DYNALLOC=(SYSALLDA,32)') --> Cantidad de memoria que se da a la ejecución del paso. Si se queda corto, aumentarla en valores de 8,12,32,64,128, 256 (como las memorias RAM)
SORTIN --> Ficheros de entrada
SORTOUT --> Ficheros de salida
SYSIN --> Indica el tipo de sort a realizar, las opciones disponibles son muchas y muy variadas, pudiendo utilizarse varias juntas en un mismo paso. Algunas de ellas son SORT, SUM, OMIT, INCLUDE, INREC, OUTREC, OUTFIL, OPTION … .

En este documento se explica en detalle algunas de estas funciones:

SORT

SORT FIELDS --> Ordena los registros a partir del fichero de entrada y los guarda ordenados en el fichero de salida:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2,DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 SORT FIELDS=(I,L,T,O,I,L,T,O)

I – Inicio. Posición donde empieza el campo por el que se quiere ordenar
L – Longitud máxima del campo por el que se quiere ordenar
T – Tipo de dato del campo que se quiere ordenar:
       CH --> Alfanumérico o numérico normal(sin COMP)
       BI --> Hexadecimal (campos COMP)
       PD --> Empaquetado con o sin signo(campos COMP-3)
O – Orden. A-Ascendente, D- Descendente

Ejemplo:

Ordenar el siguiente fichero por Número y Nombre de cliente en orden ascendente:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO
000000006ANTONIO   VILLA     SUSO     AUTONOMO
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO
000000001JOSE      LOPEZ     PITA     AUTONOMO
000000004CARLOS    POLO      DEL BARROAUTONOMO
000000003CARLOS    PEREZ     FANO     AUTONOMO

Fórmula:

SORT FIELDS=(1,9,CH,A,10,10,CH,A)

Resultado:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000001JOSE      LOPEZ     PITA     AUTONOMO
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO
000000003CARLOS    PEREZ     FANO     AUTONOMO
000000004CARLOS    POLO      DEL BARROAUTONOMO
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO
000000006ANTONIO   VILLA     SUSO     AUTONOMO

Otra opción que tiene el SORT es la siguiente:

SORT FIELDS=COPY

Con ella no indicamos ningún tipo de orden, por lo cual, el fichero de entrada se grabará en salida con el mismo orden.


INCLUDE

Filtra los registros deseados por la condición que se indique:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2,DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 SORT FIELDS=COPY
 INCLUDE COND=(I,L,T,C,V)

I – Inicio. Posición donde empieza el campo por el que se quiere filtrar
L – Longitud máxima del campo por el que se quiere filtrar
T – Tipo de dato del campo que se quiere filtrar:
       CH - Carácter o numérico normal(sin COMP)
       BI - Hexadecimal (campos COMP)
C – Condición de la igualdad que se quiere realizar:
       EQ – Igual
       NE - Distinto
       GE – Mayor o igual
       GT - Mayor
       LE – Menor o igual
       LT - Menor
V – Valor del dato por el que se quiere filtrar
       X’001A‘ – Indica un valor hexadecimal o empaquetado
       C’AL12’ – Indica un valor alfanumérico

Ejemplos:

Ejemplo 1. Vamos a realizar un paso de SORT que realice un filtrado del fichero indicado, para quedarse con los clientes que cumplan lo siguiente: Sean AUTONOMOS y su número de teléfono sea un móvil (comience por 6):

Copy:

01 ENTRADA1.
   05 ENTRADA1-NUMCLI    PIC 9(9).
   05 ENTRADA1-NOMBRE    PIC X(10).
   05 ENTRADA1-APELLID1  PIC X(10).
   05 ENTRADA1-APELLID2  PIC X(10).
   05 ENTRADA1-TIPO      PIC X(11).
   05 ENTRADA1-CATEGORIA PIC 9(9) COMP-3.
   05 ENTRADA1-TLFNO     PIC 9(9).
   05 FILLER             PIC X(9) VALUE SPACES.

Fichero entrada:

=COLS>
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      983275586
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD400001FFFFFFFFF444444444
00000000211595900004193955900319953596121319914600000C983275586000000000
------------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        918514535
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD44400003FFFFFFFFF444444444
00000000615365960005933100000242600000143656460000000C918514535000000000
------------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        988453548
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD44400001FFFFFFFFF444444444
00000000586315410003675900000136526000143656460000000C988453548000000000
------------------------------------------------------------------------
000000001JOSE      LOPEZ     PITA     AUTONOMO        676757687
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001FFFFFFFFF444444444
00000000116250000003675900000793100000143656460000000C676757687000000000
------------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        666415887
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003FFFFFFFFF444444444
00000000431936200007636000000453021996143656460000000C666415887000000000
------------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        986115484
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD44400001FFFFFFFFF444444444
00000000331936200007595900000615600000143656460000000C986115484000000000
------------------------------------------------------------------------

Fórmula:

INCLUDE COND=(39,8,CH,EQ,C'AUTONOMO',AND,55,1,CH,EQ,C'6')


Fichero salida:

=COLS> ----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000001JOSE      LOPEZ     PITA     AUTONOMO        676757687
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001FFFFFFFFF444444444
00000000116250000003675900000793100000143656460000000C676757687000000000
-------------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        666415887
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003FFFFFFFFF444444444
00000000431936200007636000000453021996143656460000000C666415887000000000
-------------------------------------------------------------------------


Ejemplo 2. Vamos a realizar un paso de SORT similar al anterior, que realice un filtrado del fichero indicado, para quedarse con los clientes que cumplan lo siguiente: Sean AUTONOMOS y su número de teléfono sea un móvil (comience por 6). Pero en este caso el número de teléfono vendrá empaquetado(COMP-3):

Copy:

01 ENTRADA1.
   05 ENTRADA1-NUMCLI    PIC 9(9).
   05 ENTRADA1-NOMBRE    PIC X(10).
   05 ENTRADA1-APELLID1  PIC X(10).
   05 ENTRADA1-APELLID2  PIC X(10).
   05 ENTRADA1-TIPO      PIC X(11).
   05 ENTRADA1-CATEGORIA PIC 9(9) COMP-3.
   05 ENTRADA1-TLFNO     PIC 9(9) COMP-3.
   05 FILLER             PIC X(13) VALUE SPACES.

Fichero entrada:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      q Íì%
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD400001937564444444444444
00000000211595900004193955900319953596121319914600000C8258C0000000000000
-----------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        q Î %
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD44400003937164444444444444
00000000615365960005933100000242600000143656460000000C8265C0000000000000
-----------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        o ÍÌ 
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD44400001937724444444444444
00000000586315410003675900000136526000143656460000000C6858C0000000000000
-----------------------------------------------------------------------
000000001JOSE      LOPEZ     PITA     AUTONOMO        #jéì%
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001695564444444444444
00000000116250000003675900000793100000143656460000000C9118C0000000000000
-----------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        ÅÂÌì%
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003667564444444444444
00000000431936200007636000000453021996143656460000000C7288C0000000000000
-----------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        m nç%
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD44400001939464444444444444
00000000331936200007595900000615600000143656460000000C4558C0000000000000
-----------------------------------------------------------------------

Fórmula:

 INCLUDE COND=(39,8,CH,EQ,C'AUTONOMO',AND,
    (55,5,BI,GE,X'600000000C',AND,55,5,BI,LT,X'700000000C'))

Resultado:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000001JOSE      LOPEZ     PITA     AUTONOMO        #jéì%
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001695564444444444444
00000000116250000003675900000793100000143656460000000C9118C0000000000000
------------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        ÅÂÌì%
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003667564444444444444
00000000431936200007636000000453021996143656460000000C7288C0000000000000
------------------------------------------------------------------------


NOTA: a la hora de comparar con valor (EQ, NE, GT...) podemos utilizar para la comparación otra zona del fichero:

Fichero entrada:
----+----1----+----2-
XXXXX111111XXXXX
YYYYY111111XXXXX
ZZZZZ111111ZZZZZ
WWWWW111111XXXXX

Fórmula:
INCLUDE COND =(1,5,CH,EQ,12,5,CH)

Resultado:
----+----1----+----2-
XXXXX111111XXXXX
ZZZZZ111111ZZZZZ

Hemos comparado las posiciones 1 a 5 con las posiciones 12 a 16 del mismo registro.

lunes, 23 de noviembre de 2020

SORT vol.4: SKIPREC, STOPAFT.

ACTUALIZADO: añadido ejemplo de OPTION SKIPREC para saltarnos registros a la hora de ordenar.

La estructura general de un SORT es la siguiente:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2(opcional),DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=CYL,500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *




PGM=SORT --> Indica el programa a utilizar, en este caso el SORT.
PARM=('DYNALLOC=(SYSALLDA,32)') --> Cantidad de memoria que se da a la ejecución del paso. Si se queda corto, aumentarla en valores de 8,12,32,64,128, 256 (como las memorias RAM)
SORTIN --> Ficheros de entrada
SORTOUT --> Ficheros de salida
SYSIN --> Indica el tipo de sort a realizar, las opciones disponibles son muchas y muy variadas, pudiendo utilizarse varias juntas en un mismo paso. Algunas de ellas son SORT, SUM, OMIT, INCLUDE, INREC, OUTREC, OUTFIL, OPTION … .

En este documento se explica en detalle algunas de estas funciones:

OPTION SKIPREC

Sirve para saltar registros a la hora de escribir/ordenar un fichero de salida. Se salta tantos registros del fichero de entrada como se indiquen y a partir de ahí escribe en la salida/ordena.

Ejemplo de copy:
//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 SORT FIELDS=COPY
 OPTION SKIPREC=número_de_registros_a_saltar

Por ejemplo, tenemos un fichero de entrada con 100 registros, si indicamos "OPTION SKIPREC=20", en el fichero de salida escribirá los registros comprendidos entre 21 y 100 ambos inclusive.

Ejemplo de sort:
//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)') 
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR 
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100)) 
//SYSOUT   DD SYSOUT=* 
//SYSPRINT DD SYSOUT=* 
//SYSIN    DD *
 SORT FIELDS=(1,10,C,A) 
 OPTION SKIPREC=número_de_registros_a_saltar

Por ejemplo, cuando tenemos un fichero que lleva una cabecera en el primer registro (el primer registro tiene un formato distinto al resto del fichero), podemos saltarnos ese primer registro en la ordenación indicando "OPTION SKIPREC=1".
Los registros saltados son eliminados y se ordenarán los registros del 2 en adelante.

NOTA: si queremos guardarnos todos los registros podemos usar OUTFIL con STARTREC y ENDREC.


OPTION STOPAFT

Sirve para dejar de escribir en salida una vez llegado al número de registros indicado.

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 SORT FIELDS=COPY
 OPTION STOPAFT=número_de_registro_que_para

Por ejemplo, tenemos un fichero de entrada con 100 registros, si indicamos "OPTION STOPAFT=30", nos escribirá en salida los registros comprendidos entre 1 y 30, ambos inclusive.

OPTION SKIPREC/STOPAFT

Se pueden combinar ambas utilidades del siguiente modo:

OPTION SKIPREC=número_de_registros_a_saltar,
       STOPAFT=número_de_registro_que_para

Por ejemplo, tenemos un fichero de 100 registros, y queremos grabar en salida los comprendidos entre el 30 y 40 ambos inclusive. El método sería el siguiente:

OPTION SKIPREC=29,STOPAFT=11

domingo, 22 de marzo de 2020

Vuelve el Consultorio Cobol

Hola amigas y amigos del Consultorio Cobol.

Son días extraños. El estado de alarma en España nos tiene a todos en casa.
Me considero afortunada porque puedo trabajar desde casa, como muchos otros compañeros coboleros.

El teletrabajo, todos soñábamos con él. Yo ya teletrabajaba un día a la semana desde hacía más de 6 meses, pero para otros es algo completamente nuevo. Y éste es un teletrabajo permanente hasta no se sabe cuándo.
Teletrabajar tiene muchas ventajas pero también hace que cosas tan sencillas como preguntar a tu compi de al lado se vuelvan más complicadas.
Es cierto que tenemos mil herramientas para comunicarnos, compartir el escritorio, compartir archivos, trabajar sobre un mismo documento de forma colaborativa... pero no siempre es lo mismo.

Es por eso que en estos días en que todo es más difícil, ponemos a vuestra disposición todo el contenido del Consultorio Cobol una vez más.

En este tiempo hemos estado trabajando para lograr una versión mejorada del blog, y no dejaremos de hacerlo. Pero mientras dure la cuarentena creemos que, ya que no tenemos al compañero experto a un giro de silla de nosotros, al menos vamos a intentar echar una mano compartiendo los artículos del blog.

Muchos junior han empezado en pleno confinamiento y para ellos seguro que se hace aún más difícil.
Esperamos ayudar un poquito reabriendo el blog.
No puedo aseguraros que vayamos a contestar dudas, porque ya ninguno estamos en el día a día de un programador.


Esto sólo es un granito de arena en medio de la que está cayendo, pero menos es nada :-)

Espero de verdad que estéis todos bien y que salgamos de ésta fortalecidos.


Un abrazo muy fuerte a todos,

Talli.


lunes, 23 de octubre de 2017

REPLACE / REEMPLAZAR con FINDREP en JCL

Hola a todos.
Hace unos días un amigo me contaba que tenía un fichero que generaba desde Java, y que le llegaba a host con espacios al final.
Él necesitaba cambiar esos espacios a low-values y me preguntaba cómo hacerlo por JCL.

Así que aprovecho y os enseño este job facilito para reemplazar algunos valores de tu fichero usando OUTREC FINDREP, como complemento al artículo SORT vol.2: OUTREC donde explicábamos el uso de CHANGE.

Imaginad que tenemos un fichero de longitud variable que viene relleno con espacios al final de los datos:

                                                           Columns 00001 00072
Command ===>                                                  Scroll ===> CSR 
****** ***************************** Top of Data ******************************
000001 ENTRADA1                                                               
       CDEDCCCF4444444444444444444444444444444444444444444444444444444444444444
       553914110000000000000000000000000000000000000000000000000000000000000000
------------------------------------------------------------------------------
000002 ENTRADA1MASCOSAS                                                       
       CDEDCCCFDCECDECE44444444444444444444444444444444444444444444444444444444
       553914114123621200000000000000000000000000000000000000000000000000000000
------------------------------------------------------------------------------
****** **************************** Bottom of Data ****************************


Y que queremos reemplazar esos espacios por low-values.



JCL:
//******************************************* 
//* SORT REPLACE DE ESPACIOS POR LOW-VALUES   
//******************************************* 
//REPLACE EXEC PGM=SORT                       
//SORTIN   DD DSN=ENTRADA.OUTRECVB,DISP=SHR
//SORTOUT  DD DSN=ENTRADA.OUTRECVB.SAL,   
//            DISP=(,CATLG,DELETE),           
//            SPACE=(CYL,(200,50),RLSE)       
//SYSOUT   DD SYSOUT=*                        
//SYSIN    DD *                               
    SORT FIELDS=COPY                          
    OUTREC FINDREP=(IN=(X'40'),OUT=(X'00')) 
  
/*     
                                     

Podéis poner varios valores en IN, y pueden ser caracteres alfanuméricos (un guión, una letra, un número....), parejas de reemplazo...
Tenéis un montón de ejemplos de FINDREP en este enlace de IBM.

NOTA: Tened en cuenta que si reemplazáis una cadena (por ejemplo 'HOLA') por otra con diferente longitud (por ejemplo 'HI'), se eliminarán las posiciones sobrantes, es decir, si en mi fichero de entrada tenía:
HOLATALLIAN
En el de salida tendré
HITALLIAN
:-)

Saludos!

miércoles, 22 de junio de 2016

Sort vol.2.3: OUTREC. Ficheros VB

Para aquellos que trabajéis con ficheros de longitud variable VB os traigo un ejemplo de como hacer un OUTREC.

Hay que tener en cuenta que en los ficheros de longitud variable las 4 primeras posiciones contienen la longitud de cada registro.
Así como a la hora de contar posiciones para posicionarnos en un campo empezamos por la 5, al hacer el outrec la información de las 4 primeras posiciones también hay que llevársela al fichero de salida.

Por otro lado, en un fichero VB habrá registros que no lleguen a ocupar la longitud máxima, por lo que si no indicamos qué hacer, el SORT dará error al no saber cómo rellenar o ignorar esas posiciones.

En el manual de DFSORT de IBM nos indican como solucionar los casos en que tenemos registros con diferentes longitudes (es decir, no todos los registros del fichero tienen la longitud máxima):
"If a variable-length record was too short to contain all INREC, OUTREC, or OUTFIL fields, use an INREC or OUTREC statement with operands OVERLAY or IFTHEN as appropriate, or an OUTFIL statement with operands OVERLAY, IFTHEN, or BUILD and VLFILL=C 'x' or VLFILL=X 'yy' as appropriate, to prevent DFSORT from terminating"

En nuestro ejemplo vamos a usar un OUTREC con OVERLAY.

FICHERO DE ENTRADA, LONGITUD MÁXIMA 55 (4+51):

----+----1----+----2----+----3----+----4----+----5-
***************************** Top of Data *********

2015-01-01DATOS VARIABLES   
FFFF6FF6FFCCEDE4ECDCCCDCE44444444444444444444444444
201500100141362051991235200000000000000000000000000
---------------------------------------------------

2015-01-01DATOS VARIABLES LARGO   40 FFFF6FF6FFCCEDE4ECDCCCDCE4DCDCD444FF444444444444444
201500100141362051991235203197600040000000000000000
---------------------------------------------------

2015-01-01DATOS VARIABLES MAS LARGO    45              
FFFF6FF6FFCCEDE4ECDCCCDCE4DCE4DCDCD4444FF4444444444
201500100141362051991235204120319760000450000000000
---------------------------------------------------

2015-01-01DATOS VARIABLES LARGO MAXIMO           51
FFFF6FF6FFCCEDE4ECDCCCDCE4DCDCD4DCECDD44444444444FF
201500100141362051991235203197604179460000000000051
---------------------------------------------------
 
 


Supongamos que queremos cambiar todas las fechas a 9999-12-31, manteniendo idéntico el resto del fichero.
En un OUTREC de un fichero FB pondríamos:

//PASO040 EXEC PGM=SORT
//SYSOUT  DD SYSOUT=*
//SORTIN  DD DSN=fichero_de_entradaFB,DISP=SHR
//SORTOUT DD DSN=fichero_de_salidaFB,
//           DISP=(,CATLG),
//           SPACE=(CYL,(150,75),RLSE)
//SYSIN DD *
     SORT FIELDS=COPY
     OUTREC FIELDS=(C'9999-12-31',11,41) 



Si intentásemos usarlo para ficheros VB:
//PASO040 EXEC PGM=SORT
//SYSOUT  DD SYSOUT=*
//SORTIN  DD DSN=fichero_de_entradaVB,DISP=SHR
//SORTOUT DD DSN=fichero_de_salidaVB,
//           DISP=(,CATLG),
//           SPACE=(CYL,(150,75),RLSE)
//SYSIN DD *
     SORT FIELDS=COPY
    
OUTREC FIELDS=(C'9999-12-31',15,41)

Obtendremos un error SORT01 - ABEND=S000 U0251:







Pues nos hemos dejado por el camino las posiciones que llevan la información de la longitud.

Si sobre el mismo outrec añadimos las 4 primeras posiciones:
//PASO040 EXEC PGM=SORT
//SYSOUT  DD SYSOUT=*
//SORTIN  DD DSN=fichero_de_entradaVB,DISP=SHR
//SORTOUT DD DSN=fichero_de_salidaVB,
//           DISP=(,CATLG),
//           SPACE=(CYL,(150,75),RLSE)
//SYSIN DD *
     SORT FIELDS=COPY
    
OUTREC FIELDS=(1,4,C'9999-12-31',15,41)

Obtendremos el error SORT01 - ABEND=S000 U0218:





Que nos dice que hay registros con longitud menor al máximo del fichero.


La solución para un OUTREC de un fichero VB sería:

//PASO040 EXEC PGM=SORT
//SYSOUT  DD SYSOUT=*
//SORTIN  DD DSN=fichero_de_entradaVB,DISP=SHR
//SORTOUT DD DSN=fichero_de_salidaVB,
//           DISP=(,CATLG),
//           SPACE=(CYL,(150,75),RLSE)
//SYSIN DD *
     SORT FIELDS=COPY
     OUTREC OVERLAY=(5:C'9999-12-31')


De esta forma indicamos el cambio que queremos hacer y que el resto de posiciones de cada registro se copien tal cual estén en el fichero de entarda.

OJO! En el fichero de salida no se está indicando la longitud porque es la misma que la del fichero de entrada. Si en un outrec el fichero de salida tiene diferente longitud que el fichero de entrada, hay que indicarlo en el DCB:
DCB=(RECFM=VB,LRECL=55,BLKSIZE=0)

Y de regalo os dejo como pasar de FB a VB y viceversa:

//**********************************************
//*         FICHERO FB A VB
//* LA SALIDA MEDIRÁ 4 POSICIONES MÁS
//**********************************************
//SORT01   EXEC PGM=SORT                      
//SORTIN   DD DSN=fichero_de_entradaFB,DISP=SHR
//VBOUT    DD DSN=fichero_de_salidaVB,       
//            DISP=(,CATLG,DELETE),           
//            SPACE=(CYL,(200,50),RLSE)       
//SYSOUT   DD SYSOUT=*                        
//SYSIN    DD *                               
    OPTION COPY                               
    OUTFIL FNAMES=VBOUT,FTOV                  
/* 

//***********************************************
//*         FICHERO VB A FB
//* INDICAMOS LAS POSICIONES A COPIAR
//* PODEMOS COPIAR LAS POSICIONES QUE LLEVAN LA
//* INFORMACION DE LA LONGITUD DEL REGISTRO, O NO
//*********************************************** 
//SORT01   EXEC PGM=SORT                      
//SORTIN   DD DSN=fichero_de_entradaVB,DISP=SHR
//FBOUT    DD DSN=fichero_de_salidaFB,       
//            DISP=(,CATLG,DELETE),           
//            SPACE=(CYL,(200,50),RLSE)       
//SYSOUT   DD SYSOUT=*                        
//SYSIN    DD *                               
    OPTION COPY                               
    OUTFIL FNAMES=FBOUT,VTOF,OUTREC(5,51)
/*

martes, 27 de septiembre de 2011

Publicado "PGM=SORT: utilidades."

Buenos días a todos.
Como se indica en el título, ya está publicado el segundo libro del Consultorio Cobol, "PGM=SORT: utilidades", donde se recogen todos los artículos relacionados con el uso del programa SORT en JCL.

Está a la venta en la web de Lulu.com con el título "PGM=SORT: utilidades", y podéis adquirirlo por tan sólo 1,50€.

Una vez más se trata de un formato pdf para facilitar la búsqueda dentro de un mismo tema como es el SORT.




















Esperamos que os guste y, sobre todo, que os sea útil.

lunes, 19 de septiembre de 2011

Sort vol.7: OMIT.

La estructura general de un SORT es la siguiente:

//SORT001 EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN DD DSN=nombre.fichero.entrada1,DISP=SHR
// DD DSN=nombre.fichero.entrada2,DISP=SHR
//SORTOUT DD DSN=nombre.fichero.salida1,
// DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN DD *




PGM=SORT --> Indica el programa a utilizar, en este caso el SORT
PARM=('DYNALLOC=(SYSALLDA,32)') --> Cantidad de memoria que se da a la ejecución del paso. Si se queda corto, aumentarla en valores de 8,12,32,64,128, 256 (como las memorias RAM)
SORTIN --> Ficheros de entrada
SORTOUT --> Ficheros de salida
SYSIN --> Indica el tipo de sort a realizar, las opciones disponibles son muchas y muy variadas, pudiendo utilizarse varias juntas en un mismo paso. Algunas de ellas son SORT, SUM, OMIT, INCLUDE, INREC, OUTREC, OUTFIL, OPTION … .

En este documento se explica en detalle algunas de estas funciones:

OMIT

Excluye los registros deseados por la condición que se indique:

//SORT001 EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN DD DSN=nombre.fichero.entrada1,DISP=SHR
// DD DSN=nombre.fichero.entrada2,DISP=SHR
//SORTOUT DD DSN=nombre.fichero.salida1,
// DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
SORT FIELDS=COPY
OMIT COND=(I,L,T,C,V)

I – Inicio. Posición donde empieza el campo por el que se quiere filtrar
L – Longitud máxima del campo por el que se quiere filtrar
T – Tipo de dato del campo que se quiere filtrar:
CH - Carácter o numérico normal(sin COMP)
BI - Hexadecimal (campos COMP)
C – Condición de la igualdad que se quiere realizar:
EQ – Igual
NE - Distinto
GE – Mayor o igual
GT - Mayor
LE – Menor o igual
LT - Menor
V – Valor del dato por el que se quiere filtrar
X’001A‘ – Indica un valor hexadecimal o empaquetado
C’AL12’ – Indica un valor alfanumérico

Ejemplos:

Ejemplo 1. Vamos a realizar un paso de SORT que realice un filtrado del fichero indicado, para quedarse con los clientes que NO cumplan lo siguiente: Sean AUTONOMOS y su número de teléfono sea un móvil (comience por 6), es decir, se excluirán del fichero de salida aquellos registros que SI cumplan esa condición:

Copy:

01 ENTRADA1.
05 ENTRADA1-NUMCLI PIC 9(9).
05 ENTRADA1-NOMBRE PIC X(10).
05 ENTRADA1-APELLID1 PIC X(10).
05 ENTRADA1-APELLID2 PIC X(10).
05 ENTRADA1-TIPO PIC X(11).
05 ENTRADA1-CATEGORIA PIC 9(9) COMP-3.
05 ENTRADA1-TLFNO PIC 9(9).
05 FILLER PIC X(9) VALUE SPACES.


Fichero entrada:

=COLS>
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      983275586
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD400001FFFFFFFFF444444444
00000000211595900004193955900319953596121319914600000C983275586000000000
------------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        918514535
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD44400003FFFFFFFFF444444444
00000000615365960005933100000242600000143656460000000C918514535000000000
------------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        988453548
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD44400001FFFFFFFFF444444444
00000000586315410003675900000136526000143656460000000C988453548000000000
------------------------------------------------------------------------
000000001JOSE      LOPEZ     PITA     AUTONOMO        676757687
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001FFFFFFFFF444444444
00000000116250000003675900000793100000143656460000000C676757687000000000
------------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        666415887
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003FFFFFFFFF444444444
00000000431936200007636000000453021996143656460000000C666415887000000000
------------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        986115484
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD44400001FFFFFFFFF444444444
00000000331936200007595900000615600000143656460000000C986115484000000000
------------------------------------------------------------------------


Fórmula:

OMIT COND=(39,8,CH,EQ,C'AUTONOMO',AND,55,1,CH,EQ,C'6')


Fichero salida:

-----------------------------------------------------------------------
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      983275586
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD400001FFFFFFFFF44444444
00000000211595900004193955900319953596121319914600000C98327558600000000
-----------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        918514535
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD44400003FFFFFFFFF44444444
00000000615365960005933100000242600000143656460000000C91851453500000000
-----------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        988453548
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD44400001FFFFFFFFF44444444
00000000586315410003675900000136526000143656460000000C98845354800000000
-----------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        986115484
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD44400001FFFFFFFFF44444444
00000000331936200007595900000615600000143656460000000C98611548400000000



Ejemplo 2. Vamos a realizar un paso de SORT similar al anterior, que realice un filtrado del fichero indicado, para quedarse con los clientes que NO cumplan lo siguiente: Sean AUTONOMOS y su número de teléfono sea un móvil (comience por 6) , es decir, se excluirán del fichero de salida aquellos registros que SI cumplan esa condición. Pero en este caso el número de teléfono vendrá empaquetado(COMP-3):

Copy:

01 ENTRADA1.
05 ENTRADA1-NUMCLI PIC 9(9).
05 ENTRADA1-NOMBRE PIC X(10).
05 ENTRADA1-APELLID1 PIC X(10).
05 ENTRADA1-APELLID2 PIC X(10).
05 ENTRADA1-TIPO PIC X(11).
05 ENTRADA1-CATEGORIA PIC 9(9) COMP-3.
05 ENTRADA1-TLFNO PIC 9(9) COMP-3.
05 FILLER PIC X(13) VALUE SPACES.


Fichero entrada:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      q Íì%
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD400001937564444444444444
00000000211595900004193955900319953596121319914600000C8258C0000000000000
-----------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        q Î %
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD44400003937164444444444444
00000000615365960005933100000242600000143656460000000C8265C0000000000000
-----------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        o ÍÌ
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD44400001937724444444444444
00000000586315410003675900000136526000143656460000000C6858C0000000000000
-----------------------------------------------------------------------
000000001JOSE      LOPEZ     PITA     AUTONOMO        #jéì%
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001695564444444444444
00000000116250000003675900000793100000143656460000000C9118C0000000000000
-----------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        ÅÂÌì%
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003667564444444444444
00000000431936200007636000000453021996143656460000000C7288C0000000000000
-----------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        m nç%
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD44400001939464444444444444
00000000331936200007595900000615600000143656460000000C4558C0000000000000
-----------------------------------------------------------------------


Fórmula:

OMIT COND=(39,8,CH,EQ,C'AUTONOMO',AND,
(55,5,BI,GE,X'600000000C',AND,55,5,BI,LT,X'700000000C'))


Resultado:

-----------------------------------------------------------------------
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      q Íì%
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD40000193756444444444444
00000000211595900004193955900319953596121319914600000C8258C000000000000
-----------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        q Î %
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD4440000393716444444444444
00000000615365960005933100000242600000143656460000000C8265C000000000000
-----------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        o ÍÌ
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD4440000193772444444444444
00000000586315410003675900000136526000143656460000000C6858C000000000000
-----------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        o ÍÌ
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD4440000193772444444444444
00000000586315410003675900000136526000143656460000000C6858C000000000000
-----------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        m nç%
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD4440000193946444444444444
00000000331936200007595900000615600000143656460000000C4558C000000000000


Como veis hemos utilizado los mismos ficheros de entrada que para el caso del INCLUDE. El resultado es que ahora obtenemos en el fichero de salida los registros que con el INCLUDE no se mostraban, es decir, justo lo contrario.

lunes, 5 de septiembre de 2011

Sort vol.2.2: OUTREC. Máscaras de edición

FICHERO DE ENTRADA

Supongamos que tenemos este fichero, en el que tenemos los siguientes campos sin formatear:

- una fecha (posiciones del 5 al 10)
- una hora (del 20 al 25)
- importe 1 comprimido (del 26 al 31)
- importe 2 (del 32 al 35)
- importe 3 (del 36 al 45)
- importe 4 (del 46 al final)


----+----1----+----2----+----3----+----4----+----5----+
***************************** Top of Data *************
0001100811MARIA    143010      011100001111110000111111
FFFFFFFFFFDCDCC4444FFFFFF000001FFFFFFFFFFFFFFFFFFFFFFFF
000110081141991000014301000000C011100001111110000111111
-------------------------------------------------------
0002230411VICTOR   153523      022200002222220000222222
FFFFFFFFFFECCEDD444FFFFFF000002FFFFFFFFFFFFFFFFFFFFFFFF
000223041159336900015352300000C022200002222220000222222
-------------------------------------------------------
0003150811MARIANO  164022      033300003333330000333333
FFFFFFFFFFDCDCCDD44FFFFFF000003FFFFFFFFFFFFFFFFFFFFFFFF
000315081141991560016402200000C033300003333330000333333
-------------------------------------------------------
0004251211LUCIA    174515     <044400004444440000444444
FFFFFFFFFFDECCC4444FFFFFF000004FFFFFFFFFFFFFFFFFFFFFFFF
000425121134391000017451500000C044400004444440000444444



Con este ejemplo vamos a aprender a dar el formato que queramos a cada uno de estos campos. Para ello utilizaremos un OUTREC, en donde vamos a tener este fichero de entrada y otro de salida donde saldrán los campos formateados. En este OUTREC vamos a aplicar las MASCARAS. Las máscaras simplemente son herramientas que nos van a permitir modificar el formato de los campos seleccionados con el OUTREC:


//PASO040 EXEC SORTD,OUT=*
//SYSOUT  DD SYSOUT=*
//SORTIN  DD DSN=fichero_de_entrada,DISP=SHR
//SORTOUT DD DSN=fichero_de_salida,
//           DISP=(,CATLG),
//           SPACE=(CYL,(150,75),RLSE)
//SYSIN DD *
SORT FIELDS=COPY
OUTREC FIELDS=(01,04,
               05,06,ZD,M9,LENGTH=8,
               11,09,
               20,06,ZD,M8,LENGTH=8,
               26,06,PD,
               32,04,ZD,M18,LENGTH=4,
               36,10,ZD,M4,LENGTH=11,
               46,10,ZD,M26,LENGTH=11)



En el fichero_de_salida obtendremos como RESULTADO:

----+----1----+----2----+----3----+----4----+----5----+----6----+--
***************************** Top of Data *************************
000110/08/11MARIA    14:30:10     11.11  +1,111.11+0000111111
000223/04/11VICTOR   15:35:23     22.22  +2,222.22+0000222222
000315/08/11MARIANO  16:40:22     33.33  +3,333.33+0000333333
000425/12/11LUCIA    17:45:15     44.44  +4,444.44+0000444444


Por ejemplo, en el primer caso (01,04), simplemente hemos seleccionado el campo pero no hemos aplicado ninguna máscara.
Sin embargo, en el segundo (05,06,ZD,M9,LENGTH=8), hemos seleccionado el campo 'fecha' que ocupa 6 posiciones(DDMMAA) y la hemos aplicado el código de máscara M9 que lo que hace es meter una '/' entre medias formateando el campo a DD/MM/AA.

Para el campo 'hora' hemos hecho lo mismo pero aplicando el código M8, que convierte un formato HHMMSS en HH:MM:SS.
Para los importes también hemos aplicado otros códigos, por ejemplo el M4 que pone a una cantidad un signo(+ o -), una coma para separar los miles y un punto para separar los decimales.

Existe una tabla donde están reflajados los códigos de conversión de las máscaras. Os dejo la que tengo para descargar, si encontráis más códigos de conversión por favor indicarlos.

Lista de códigos de conversión de las máscaras

Tengo entendido que puedes formar tus propias máscaras a partir de estos valores, y así no utilizar los códigos de conversión. De ese modo es más libre y cada uno puede formatear según le interese. Cuando sepa como se hace lo indico, estoy en ello...


MÁS UTILIDADES DE LAS MÁSCARAS.

El ejemplo anterior nos permite dar un formato más leíble a nuestros ficheros, pero además si tu host lo permite, podemos exportar este fichero fuera del host, y visualizarlo en una hoja de cálculo. Para ello, podemos preparar el fichero para abrirlo por ejemplo con el Excel. Solo tenemos que poner un ';' entre cada campo del siguiente modo:

//PASO040 EXEC SORTD,OUT=*
//SYSOUT DD SYSOUT=*
//SORTIN DD DSN=LAET.LAEHISTA.CCOBOL,DISP=SHR
//SORTOUT DD DSN=LAET.MASCARA.SALIDA,
// DISP=(,CATLG),
// SPACE=(CYL,(150,75),RLSE)
//SYSIN DD * 

SORT FIELDS=COPY
OUTREC FIELDS=(01,04,C';',
               05,06,ZD,M9,LENGTH=8,C';',
               11,09,C';',
               20,06,ZD,M8,LENGTH=8,C';',
               26,06,PD,C';',
               32,04,ZD,M18,LENGTH=4,C';',
               36,10,ZD,M4,LENGTH=11,C';',
               46,10,ZD,M26,LENGTH=11)



RESULTADO:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7----
***************************** Top of Data ********************************
0001;10/08/11;MARIA    ;14:30:10;    1;1.11;  +1,111.11;+0000111111
0002;23/04/11;VICTOR   ;15:35:23;    2;2.22;  +2,222.22;+0000222222
0003;15/08/11;MARIANO  ;16:40:22;    3;3.33;  +3,333.33;+0000333333
0004;25/12/11;LUCIA    ;17:45:15;    4;4.44;  +4,444.44;+0000444444


Ahora solo hay que exportar el fichero host a un archivo excel poniendo al archivo la extensión .CSV (por ejemplo: "ejemplo_mascaras.csv").
De este modo el excel utiliza los ';' para separar los campos en celdas y que cada campo quede organizado en su correspondiente columna. Si has seguido el ejemplo te ha de quedar de este modo:


lunes, 14 de febrero de 2011

Sentencia SORT en un programa COBOL

Hemos visto en otros artículos como hacer un SORT en un JCL. En este artículo veremos como hacerlo en un programa cobol.
¿Utilidad? Depende. Lo cierto es que pudiendo hacerlo por JCL, no tiene caso hacerlo en un programa. Pero quién sabe! Tal vez alguno de los lectores puedan darnos una idea de su uso práctico : D

SORT:

La sentencia SORT en cobol sirve para ordenar registros por un campo clave que le indiquemos. Podremos elegir varias claves y definir si el orden será ascendente o descendente.
Para el ejemplo, hemos creado un fichero temporal en nuestro programa que utilizaremos para generar en él la información ordenada. Como registros a ordenar, utilizaremos una tabla interna, de tal forma que no necesitaremos utilizar ficheros en ningún momento.
La información ordenada se cargará desde el fichero temporal al registro de salida, que podría utilizarse a lo largo de la ejecución.
Nosotros nos pararemos cuando tengamos nuestra información ordenada, y la "displayaremos" mostrándola por SYSOUT.

 IDENTIFICATION DIVISION.
 PROGRAM-ID. PRGSORT.
*
 ENVIRONMENT DIVISION.
 CONFIGURATION SECTION.
 SPECIAL-NAMES.
 DECIMAL-POINT IS COMMA.
*
 INPUT-OUTPUT SECTION.
 FILE-CONTROL.
* Fichero temporal donde guardaremos la información ordenada
 SELECT TABLA-SORT ASSIGN TO DISK "SORTWORK".
*
 DATA DIVISION.
 FILE SECTION.
* Definición del fichero temporal
 SD TABLA-SORT
 DATA RECORD IS ELEMENTO-SORT.
 01 ELEMENTO-SORT.
    05 SORT-CLAVE1 PIC X.
    05 SORT-CLAVE2 PIC X(3).
    05 SORT-CAMPO PIC X(10).
    05 SORT-INDICADOR PIC X.
*
 WORKING-STORAGE SECTION.
* Formato del registro de salida
 01 VARIABLES.
    05 WA-REGISTRO.
       10 WA-SORT-CLAVE1 PIC X.
       10 WA-SORT-CLAVE2 PIC X(3).
       10 WA-SORT-CAMPO PIC X(10).
       10 WA-SORT-INDICADOR PIC X.
* Switches que utilizaremos en los bucles
 01 SWITCHES.
    05 SW-FIN-TABLA-SORT PIC X(1).
       88 SI-FIN-TABLA-SORT VALUE 'S'.
       88 NO-FIN-TABLA-SORT VALUE 'N'.
* Tabla interna con los datos a ordenar
 01 TABLA.
    05 WT-TBL-LISTA.
       10 PIC X(15) VALUE 'F216CAMPO02802S'.
       10 PIC X(15) VALUE 'M144CAMPO17114N'.
       10 PIC X(15) VALUE 'Q651CAMPO24536S'.
       10 PIC X(15) VALUE 'F217CAMPO03312N'.
       10 PIC X(15) VALUE 'T487CAMPO44914S'.
       10 PIC X(15) VALUE 'O372CAMPO52113N'.
       10 PIC X(15) VALUE 'F457CAMPO61224N'.
       10 PIC X(15) VALUE 'L547CAMPO73985N'.
       10 PIC X(15) VALUE 'L354CAMPO89173N'.
       10 PIC X(15) VALUE 'W516CAMPO92815N'.
    05 REDEFINES WT-TBL-LISTA.
       10 WT-TBL-ELEMENTO OCCURS 15
                           INDEXED BY WI-ELEM.
          15 WT-TBL-CLAVE1 PIC X.
          15 WT-TBL-CLAVE2 PIC X(3).
          15 WT-TBL-CAMPO PIC X(10).
          15 WT-TBL-INDICADOR PIC X.
* Formato del registro a ordenar
 01 WR-ELEMENTO-SORT.
   05 WR-SORT-CLAVE1 PIC X.
   05 WR-SORT-CLAVE2 PIC X(3).
   05 WR-SORT-CAMPO PIC X(10).
   05 WR-SORT-INDICADOR PIC X.
*
 PROCEDURE DIVISION.
*
    PERFORM 1000-INICIO
    PERFORM 2000-PROCESO
    PERFORM 9000-FINAL
    .
*
 1000-INICIO.
*
    INITIALIZE VARIABLES
    .
*
 2000-PROCESO.
* Proceso de SORT
* Indicamos las claves por las que ordenaremos ON ASCENDING ó 

* ON DESCENDING

    SORT TABLA-SORT
     ON ASCENDING KEY SORT-CLAVE1
     ON DESCENDING KEY SORT-CLAVE2
     INPUT PROCEDURE 2100-PROCESO-ENTRADA
     OUTPUT PROCEDURE 2200-PROCESO-SALIDA
* En la INPUT PROCEDURE cargamos los datos a ordenar
* En la OUTPUT PROCEDURE guardamos la información ordenada 

* en variables del programa

* Controlamos el retorno del SORT con SORT-RETURN
    IF SORT-RETURN NOT = ZEROS
       DISPLAY 'ERROR EN EL SORT:' SORT-RETURN
    END-IF
    .
*
 2100-PROCESO-ENTRADA.
* Cargamos los datos a ordenar(los de la tabla interna) en el

* fichero temporal donde se realizará la ordenación
* (ELEMENTO-SORT) con la sentencia RELEASE.
    PERFORM VARYING WI-ELEM
       FROM 1 BY 1
      UNTIL WT-TBL-CLAVE1(WI-ELEM) = LOW-VALUES
            OR WI-ELEM = 16
*
        MOVE WT-TBL-CLAVE1(WI-ELEM) TO WR-SORT-CLAVE1
        MOVE WT-TBL-CLAVE2(WI-ELEM) TO WR-SORT-CLAVE2
        MOVE WT-TBL-CAMPO(WI-ELEM) TO WR-SORT-CAMPO
        MOVE WT-TBL-INDICADOR(WI-ELEM) TO WR-SORT-INDICADOR
*
        RELEASE ELEMENTO-SORT FROM WR-ELEMENTO-SORT
        DISPLAY 'ELEMENTO-SORT:'WR-ELEMENTO-SORT
    END-PERFORM
    .
*
 2200-PROCESO-SALIDA.
* Recuperamos los datos ordenados del fichero temporal con la

* sentencia RETURN y los displayamos
    SET NO-FIN-TABLA-SORT TO TRUE
*
    PERFORM UNTIL SI-FIN-TABLA-SORT

     RETURN TABLA-SORT INTO WR-ELEMENTO-SORT
     AT END
            SET SI-FIN-TABLA-SORT TO TRUE
     NOT AT END
            MOVE WR-SORT-CLAVE1 TO WA-SORT-CLAVE1
            MOVE WR-SORT-CLAVE2 TO WA-SORT-CLAVE2
            MOVE WR-SORT-CAMPO TO WA-SORT-CAMPO
            MOVE WR-SORT-INDICADOR TO WA-SORT-INDICADOR
*
            DISPLAY 'REGISTRO->' WA-REGISTRO
*
     END-RETURN
    END-PERFORM
    .
*
 9000-FINAL.
*
    STOP RUN
    .
*


RESULTADO:

REGISTRO->F457CAMPO61224N
REGISTRO->F217CAMPO03312N
REGISTRO->F216CAMPO02802S
REGISTRO->L547CAMPO73985N
REGISTRO->L354CAMPO89173N
REGISTRO->M144CAMPO17114N
REGISTRO->O372CAMPO52113N
REGISTRO->Q651CAMPO24536S
REGISTRO->T487CAMPO44914S
REGISTRO->W516CAMPO92815N