Extrahieren/Sortieren aus einem „variable blocked“ Dataset mit JCL

In meinem aktuellen Projekt werden die Eingangsdaten auf dem Mainframe in einem VB-Dataset (variable blocked) Dataset bereitgestellt. Das Dataset enthält Datensätze mit unterschiedlich langen Satzarten und einem einheitlichen Header. Anhand der im Headerbereich verfügbaren Information zu einer „Satzart“ kann mit der unten angeführten JCL eine (oder mehrere) bestimmte Satzarten aus diesem Dataset extrahiert/sortiert werden.

Im ersten SORT-Step werden die Satzarten BETRT2, BETRT3 und BETRT4 aus dem Dataset BAT.PO.K.KE.BEST.N0202.V0204001 in die Ergebnisdatei Y0E6844.EMKSORT.OUT geschrieben. Zu beachten ist hier, dass die Eingangs-Dataset keine FB-Datei (fixed blocked), sondern eine HOST-Datei im VB-Format (variable blocked) ist. Das führt dazu, dass in der INCLUDE-Bedingung die Stelle 72 angegeben ist (wenn man sich das Dataset im browse-mode ansieht, dann zeigt die Spaltenposition an der die Satzart im Dataset steht aber ab Position 68 – man muss bei einer VB-Datei also immer 4 Byte dazuzählen). Wäre es eine FB-Datei müsste im Job die tatsächliche Position angegeben werden – also 68.

---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
******************************** Top of Data *********************************
14002015020220150203KDINFO                                   00001DINFO     01
14002015020220150203K000000000000400020                      00001KONT01    02
14002015020220150203K000000000000400021                      00002KONT02    12
14002015020220150203K000000000001700100                      00003BETRT2    08
14002015020220150203K000000000002500200                      00004GPKT01    03
14002015020220150203K000000000000300030                      00005ANTR      04
14002015020220150203K000000000000900040                      00006BETRT4    01

Im zweiten SORT-Step (der ist optional falls man ihn braucht) werden aus den extrahierten Satzarten nur die eindeutigen Kontrakt-Nummern extrahiert und in das Dataset Y0E6844.EMKSORT.OUT2 geschrieben. Dies ist speziell für diese Satzarten gedacht, da hier in den Eingangsdaten Duplikate enthalten sind.

Quellcode:

//EMKSRT JOB (666045,BA), 
//       'MOELLER', 
//       CLASS="K",
//       NOTIFY=&SYSUID,
//       MSGCLASS=T 
//SORT EXEC PGM=SORT
//SYSPRINT DD SYSOUT=* 
//SORTIN   DD DSN=BAT.PO.K.KE.BEST.N0202.V0204001,DISP=SHR
//SORTOF01 DD DSN=Y0E6844.EMKSORT.OUT, 
//            DISP=(,CATLG,DELETE) 
//* 
//SYSIN DD * 
    SORT FIELDS=COPY 
       OUTFIL FILES=01, 
       INCLUDE=((72,6,CH,EQ,C'BETRT2'),OR, 
                (72,6,CH,EQ,C'BETRT3'),OR, 
                (72,6,CH,EQ,C'BETRT4')) 
//* 
//SORT EXEC PGM=SORT
//SYSOUT DD SYSOUT=* 
//SORTIN DD DSN=Y0E6844.EMKSORT.OUT,DISP=SHR
//SORTOUT DD DSN=Y0E6844.EMKSORT.OUT2, 
// DISP=(,CATLG,DELETE) 
//* 
//SYSIN DD * 
    SORT FIELDS=(28,18,CH,A) 
     SUM FIELDS=NONE 
//* 
.

JCL – Datensätze zählen und Record-Länge ermitteln

In meinen Projekten arbeite ich immer wieder auch auf dem IBM Mainframe unter z/OS. Dabei nutze ich die verfügbaren Bordmittel um erstellte Dateien zu überprüfen oder zu zählen. Dabei kommt das vielseitige DFSORT-Werkzeug ICETOOL zum Einsatz.

Im Folgenden beschreibe ich kurz, wie ICETOOL dazu verwendet werden kann, um eine Datei mit fester Satzlänge, deren Inhalt aber Datensätze mit variablen Längen sind, zu zählen, zu gruppieren und die Datensatzlängen in Byte zu ermitteln. Kenntnisse in der JCL werden vorausgesetzt.

Hier ein Auszug (die ersten 80 Byte)aus einer beispielhaften Eingabedatei. Die Recordlänge auf Dateiebene ist fix mit 650 Bytes angegeben:

Stellen 1 bis 80:
K14002012022920150120KDINFO                                   00001DINFO     01.
K14002012022920150120K000000000000800020                      00001KONT01    02.
K14002012022920150120K000000000000800020                      00002KONT02    12.
K14002012022920150120K000000000000800020                      00003KONT04    08.
K14002012022920150120K000000000000800020                      00004GPKT01    03.
K14002012022920150120K000000000000800020                      00005ANTR      04.
K14002012022920150120K000000000000800020                      00006BETZIE    01.
K14002012022920150120K000000000000800020                      00007KONSB     01.
K14002012022920150120K000000000000800020                      00008KONSB     01.
K14002012022920150120K000000000001100020                      00001KONT01    02.

Und hier die Stellen 81 bis 160:

00;T;00400;00000;00046;                                                         
00;000000008                               ;000000008      ;0000000020;00046;004
00;X;?         ;X;X;X;X;X;H;K;?         ;?         ;?    ;?    ;?    ;N;X;?     
00;N;?;?         ;? ;?         ;?          ;?    ;?                ;?  ;?       
00;0013765367;00099;?      ;?;?    ;                                            
00;0000000;0003365367;00043;0000000008;00046;00000;EUR; 0000005000000,00;01.01.1
00;0000000010;0003365367;00043;                                                 
00;0000000004;00043;F;A;30.12.2013; 0000000000000,00;EUR;?            ; 00000000
00;0000001234;00043;K;A;30.12.2013; 0000000000000,00;EUR;?            ; 00000000
00;000000011                               ;000000011      ;0000000020;00046;004
00;X;?         ;X;X;X;X;X;H;K;?         ;?         ;?    ;?    ;?    ;N;X;?     
00;N;?;?         ;? ;?         ;?          ;?    ;?                ;?  ;?       
00;0013604472;00077;?      ;?;?    ;                                            
00;0000000;0003604472;00043;0000000171;00046;00000;USD; 0000000273541,16;01.01.1
00;0000000010;0012604492;00056;                                                 
00;0000008066;00043;K;A;30.12.2013; 0000000000000,00;EUR;?            ; 00000000

Wie man erkennen kann, ist der Feldtrenner das Semikolon. Aus Platzgründen sind die Stellen 181 bis 650 hier nicht dargestellt. Es soll lediglich veranschaulicht werden, dass es sich um Datensätze mit variabler Länge handelt und dass als Feldtrenner das Semikolon verwendet wird. Lediglich im Headerbereich (die ersten 82 Byte jeder Zeile) ist eine Struktur mit festen Positionen definiert.

Nun zur JCL. Im folgenden Code-Abschnitt ist der komplette Job dargestellt.

//EMKREC  JOB (666045,BA),                              
//        'MOELLER',                                    
//        CLASS=K,                                      
//        NOTIFY=&SYSUID,                               
//        MSGCLASS=T                                    
//ICETOOL EXEC PGM=ICETOOL                              
//TOOLMSG DD   SYSOUT=*                                 
//DFSMSG  DD   SYSOUT=*                                 
//TOOLIN  DD   *                                        
  DISPLAY FROM(CNTIN1) LIST(CNTOUT) -                   
  NOHEADER ON(72,15,CH) ON(VLEN,N01)                    
/*                                                      
//CNTIN1 DD DSN=BAT.PO.K.KE.BEST.N0229.V0121001,DISP=SHR
//CNTOUT DD DSN=Y0E6844.CNTOUT.N0229.TEMP,              
//          DISP=(NEW,CATLG,DELETE),                    
//          RECFM=FB                                    
//ICETOOL EXEC PGM=ICETOOL                               
//TOOLMSG DD   SYSOUT=*                                  
//DFSMSG  DD   SYSOUT=*                                  
//TOOLIN  DD   *                                         
  OCCUR FROM(CNTIN2) LIST(CNTOU2) -                      
  TITLE('ZAEHLER REPORT') DATE TIME -                
  HEADER('SATZART - VERSION -  RECL') ON(1,25,CH) BLANK -
  HEADER('ANZAHL') ON(VALCNT)                            
/*                                                       
//CNTIN2 DD DSN=Y0E6844.CNTOUT.N0229.TEMP,DISP=SHR       
//CNTOU2 DD DSN=Y0E6844.CNTOUT.N0229.COUNT,              
//          DISP=(NEW,CATLG,DELETE),                     
//          RECFM=FB                                     
//DELEMKCT EXEC PGM=IEFBR14                              
//SYSPRINT DD  SYSOUT=*                                  
//DELDATA  DD  DSN=Y0E6844.CNTOUT.N0229.TEMP,            
//     DISP=(OLD,DELETE,DELETE) 
/*

In diesem Job wird das ICETOOL zwei mal aufgerufen. Im ersten Aufruf wird die Eingabedatei mit dem Operator DISPLAY aufgerufen. Hierbei wird die Eingabedatei nach dem Gruppierungsmerkmal ab Stelle 72 für 15 Stellen gruppiert.

NOHEADER ON(72,15,CH)

Der Parameter NOHEADER im Operator DISPLAY sorgt dafür, dass keine Überschriften in die Ausgabedatei geschrieben werden. Im zweiten Parameter

ON(VLEN,N01)

wird die Recordlänge ermittelt. Als Ergebnis wird eine Datei erstellt, in der für jede Zeile der Eingabedatei, die Satzart und die Recordlänge ermittelt wird.

Mit dem zweiten Aufruf des ICETOOL wird die soeben erstellte Datei nach Satzarten gruppiert. Hierfür wird der Operator

OCCUR FROM(CNTIN2) LIST(CNTOU2) -

verwendet.  Zusätzlich wird noch eine Berichtsüberschrift hinzugefügt und die Anzahl der Satzarten mit dem Parameter

HEADER('ANZAHL') ON(VALCNT)

ermittelt. Die Ergebnisdatei sieht wie folgt aus:

ZAEHLER REPORT        02/04/15        08:55:28
                                                  
SATZART - VERSION -  RECL            ANZAHL       
-------------------------   ---------------       
 ANTR      04.00      312             37244       
 BETRM1    04.00      220             52460       
 BETRM2    02.00      231              3674       
 BETRT1    04.00      236             53975       
 BETRT2    02.00      303               788       
 BETRT3    02.00      303               759       
 BETRT4    02.00      519               231       
 BETRT5    02.00      189            116482       
 BETRT7    02.00      175              8424       
 BETZIE    01.00      115             78338       
 BEW       01.00      154                 8       
 BEWEG     02.00      195                97       
.....

Zu guter letzt wird im Job die temporär erstellte Datei mit dem Programm IEFBR14 gelöscht.

BlueZone – Datei vom HOST an PC übertragen

Mit der HOST Emulation BlueZone-D besteht die Möglichkeit eine Datei vom HOST zu empfangen, bzw. vom PC an den HOST zu übertragen. Auf dieser Seite wird beschrieben, wie man eine Datei vom HOST herunterladen kann. Bitte beachten, dass dies nur mit kleinen Datenmengen sinnvoll ist!

Voraussetzung: Leserechte auf die zu übertragende HOST-Datei

1. Um eine Datei vom HOST zum PC zu übertragen, muss man sich am HOST anmelden und in den COMMAND-Modus begeben. Dazu ist im ISPF Primary Option Menu die 6 auszuwählen

bluezone_datei_uebertragen_1

2. Im anschließend erscheinenden Dialog kann dann aus dem BlueZone Menü „Übertragung“ der Menüpunkt „Senden“ ausgewählt werden.

 

bluezone_datei_uebertragen_2
3. Das folgende Bild zeigt das Fenster in dem der Name der Zieldatei (1.), der Name der HOST-Quelldatei (2.) und der „Senden“-Button (3.) anzugeben und auszuwählen sind

bluezone_datei_uebertragen_3

Danach startet der Download und die übertagene Datei steht im Zielverzeichnis zur Verfügung

bluezone_datei_uebertragen_4