How can I "hard code" a header into my output using EASYTRIEVE as part of a JCL file? - mainframe

My goal is to have three headers appear at the top of my output. The headers will be "Title", "Genre", and "Rating". The JCL file inputs data from a dataset, a list of movies, their genres (which are numbered and later translated into words using IF logic), and the ratings (using packed data). I am not supposed to use any programs like SORT. My solution needs to be "hard coded".
I expect the results to look like this:
snapshot of the expected results
The actual results look like this:
snapshot of the actual results
The job submits successfully, without any error. However, the JCL file does not produce the desired output.
I understand that the JCL file is following a list of instructions for each record from the data set, and looping over the instructions for each record, which is why the Title, Genre, and Ratings headers repeat. I've tried using "GOTO" and labels to alter where the loop resumes from, so that the JCL file only executes the header parameters on the first execution. Unfortunately, it doesn't seem to work.
I linked screenshots of my JCL file below. As you can see, I redefined my OHEAD variable to be blank (' '), which prevents the headers from overlapping the movie data. If I could find a way to have the JCL instructions loop, and restart from AFTER the first "OHEAD" statement, then I would only need to define OHEAD once. Conceptually, that's what I'm trying to do.
I started training on JCL a few days ago, so I appreciate your patience and any input you can offer.
JCL file screenshot 1
JCL file screenshot 2
JCL file screenshot 3
JCL file screenshot 4
JCL file screenshot 5
I copied the JCL file text below.
000001 //DSINC01C JOB (0000,1178),'TRAINING',NOTIFY=DSINC01,
000002 // MSGCLASS=E
000003 //*
000004 //* DELETE STEP FOR EASIER RE-RUNS
000005 //*
000006 //S01 EXEC PGM=IDCAMS,REGION=40M
000007 //SYSPRINT DD SYSOUT=*
000008 //SYSIN DD *
000009 DELETE DSINC01.TRAINING.OUTPUT
000010 IF MAXCC=8 THEN SET MAXCC = 0
000011 /*
000012 //*
000013 //* EASYTRIEVE STEP
000014 //*
000015 //S02 EXEC PGM=EZTPA00,REGION=4M
000016 //SYSLIB DD DSN=ALCHAN.TEST.EMAC,DISP=SHR
000017 // DD DSN=SYS3.EASYPLUS.CAIMAC,DISP=SHR
000018 //FILEI DD DISP=SHR,DSN=DSINC01.TRAINING.MDATA
000019 //FILEO DD DSN=DSINC01.TRAINING.OUTPUT,
000020 // DISP=(,CATLG),
000021 // UNIT=PUBLIC,SPACE=(CYL,(500,250),RLSE),
000022 // DCB=(LRECL=80,RECFM=FB,BLKSIZE=0,DSORG=PS)
000023 //EZTVFM DD UNIT=WORK,SPACE=(CYL,(10,5))
000024 //SORTWK01 DD UNIT=WORK,SPACE=(CYL,(10,5))
000025 //SORTWK02 DD UNIT=WORK,SPACE=(CYL,(1,1))
000026 //SORTWK03 DD UNIT=WORK,SPACE=(CYL,(1,1))
000027 //SYSOUT DD SYSOUT=*
000028 //SYSPRINT DD SYSOUT=*
000029 //SYSLIZ DD SYSOUT=*
000030 //SYSLZ1 DD SYSOUT=*
000031 //SYUDUMP DD SYSOUT=*
000032 //*
000033 //SYSIN DD *
000034 FILE SYSLIZ PRINTER
000035 *
000036 * INPUT FILE LAYOUT
000037 *
000038 FILE FILEI
000039 IMNAME 1 40 A
000040 IMGENRE 41 1 N
000041 IMRATE 42 2 P
000042 * OUTPUT FILE LAYOUT
000043 *
000044 FILE FILEO
000045 OHEAD 1 80 A
000046 OMNAME 1 30 A
000047 OMGENRE 32 7 A
000048 OMRATE 40 3 N
000049 *--------------------------------------------------------------------
000050 * MAIN LINE
000051 *--------------------------------------------------------------------
000052 JOB INPUT FILEI NAME DATA
000053 OHEAD = 'TITLE GENRE RATING'
000054 PUT FILEO
000055 OHEAD = ' '
000056 OMNAME = IMNAME
000057 OMGENRE = ' '
000058 IF IMGENRE = 1
000059 OMGENRE = 'FANTASY'
000060 END-IF
000061 IF IMGENRE = 2
000062 OMGENRE = 'ACTION'
000063 END-IF
000064 IF IMGENRE = 3
000065 OMGENRE = 'COMEDY'
000066 END-IF
000067 IF IMGENRE = 4
000068 OMGENRE = 'HORROR'
000069 END-IF
000070 IF IMGENRE = 5
000071 OMGENRE = 'DRAMA'
000072 END-IF
000073 OMRATE = IMRATE
000074 PUT FILEO
000075 GO TO JOB
000076 /*

Copying just the Easytrieve code, add a label, and change the GO TO.
Edited: I modified the Easytrieve again. I don't know if this will work, as I don't have a mainframe to test with.
Get an online Easytrieve manual and learn the language.
000034 FILE SYSLIZ PRINTER
000035 *
000036 * INPUT FILE LAYOUT
000037 *
000038 FILE FILEI
000039 IMNAME 1 40 A
000040 IMGENRE 41 1 N
000041 IMRATE 42 2 P
000042 * OUTPUT FILE LAYOUT
000043 *
000044 FILE FILEO
000045 OHEAD 1 80 A
000046 OMNAME 1 30 A
000047 OMGENRE 32 7 A
000048 OMRATE 40 3 N
000049 *--------------------------------------------------------------------
000050 * MAIN LINE
000051 *--------------------------------------------------------------------
000052 JOB INPUT FILEI NAME DATA
000053 OHEAD = 'TITLE GENRE RATING'
000054 PUT FILEO
GET FILEI
DO WHILE NOT EOF FILEI
000055 OHEAD = ' '
000056 OMNAME = IMNAME
000057 OMGENRE = ' '
000058 IF IMGENRE = 1
000059 OMGENRE = 'FANTASY'
000060 END-IF
000061 IF IMGENRE = 2
000062 OMGENRE = 'ACTION'
000063 END-IF
000064 IF IMGENRE = 3
000065 OMGENRE = 'COMEDY'
000066 END-IF
000067 IF IMGENRE = 4
000068 OMGENRE = 'HORROR'
000069 END-IF
000070 IF IMGENRE = 5
000071 OMGENRE = 'DRAMA'
000072 END-IF
000073 OMRATE = IMRATE
000074 PUT FILEO
000075 GET FILEI
000076 END-DO
000077 /*

This solution also works, though the concept differs from my original thought.
000001 //DSINC01C JOB (0000,1178),'TRAINING',NOTIFY=DSINC01,
000002 // MSGCLASS=E
000003 //*
000004 //* DELETE STEP FOR EASIER RE-RUNS
000005 //*
000006 //S01 EXEC PGM=IDCAMS,REGION=40M
000007 //SYSPRINT DD SYSOUT=*
000008 //SYSIN DD *
000009 DELETE DSINC01.TRAINING.OUTPUT
000010 IF MAXCC=8 THEN SET MAXCC = 0
000011 /*
000012 //*
000013 //* EASYTRIEVE STEP
000014 //*
000015 //S02 EXEC PGM=EZTPA00,REGION=4M
000016 //SYSLIB DD DSN=ALCHAN.TEST.EMAC,DISP=SHR
000017 // DD DSN=SYS3.EASYPLUS.CAIMAC,DISP=SHR
000018 //FILEI DD DISP=SHR,DSN=DSINC01.TRAINING.MDATA
000019 //FILEO DD DSN=DSINC01.TRAINING.OUTPUT,
000020 // DISP=(,CATLG),
000021 // UNIT=PUBLIC,SPACE=(CYL,(500,250),RLSE),
000022 // DCB=(LRECL=80,RECFM=FB,BLKSIZE=0,DSORG=PS)
000023 //EZTVFM DD UNIT=WORK,SPACE=(CYL,(10,5))
000024 //SORTWK01 DD UNIT=WORK,SPACE=(CYL,(10,5))
000025 //SORTWK02 DD UNIT=WORK,SPACE=(CYL,(1,1))
000026 //SORTWK03 DD UNIT=WORK,SPACE=(CYL,(1,1))
000027 //SYSOUT DD SYSOUT=*
000028 //SYSPRINT DD SYSOUT=*
000029 //SYSLIZ DD SYSOUT=*
000030 //SYSLZ1 DD SYSOUT=*
000031 //SYUDUMP DD SYSOUT=*
000032 //*
000033 //SYSIN DD *
000034 FILE SYSLIZ PRINTER
000035 *
000036 * INPUT FILE LAYOUT
000037 *
000038 FILE FILEI
000039 IMNAME 1 40 A
000040 IMGENRE 41 1 N
000041 IMRATE 42 2 P
000042 * OUTPUT FILE LAYOUT
000043 *
000044 FILE FILEO
000045 OMNAME 1 30 A
000046 OMGENRE 32 7 A
000047 OMRATE 40 6 A
000048 *
000049 DEFINE HEADER 1 1 A
000050 *--------------------------------------------------------------------
000051 * MAIN LINE
000052 *--------------------------------------------------------------------
000053 JOB INPUT FILEI NAME DATA
000054 IF HEADER = ' '
000055 OMNAME = 'TITLE'
000056 OMGENRE = 'GENRE'
000057 OMRATE = 'RATING'
000058 PUT FILEO
000059 HEADER = 'Y'
000060 END-IF
000061 OMNAME = IMNAME
000062 OMGENRE = ' '
000063 IF IMGENRE = 1
000064 OMGENRE = 'FANTASY'
000065 END-IF
000066 IF IMGENRE = 2
000067 OMGENRE = 'ACTION'
000068 END-IF
000069 IF IMGENRE = 3
000070 OMGENRE = 'COMEDY'
000071 END-IF
000072 IF IMGENRE = 4
000073 OMGENRE = 'HORROR'
000074 END-IF
000075 IF IMGENRE = 5
000076 OMGENRE = 'DRAMA'
000077 END-IF
000078 OMRATE = IMRATE
000079 PUT FILEO
000080 GO TO JOB
000081 /*

Your header prints every time because you printed it inside of JOB INPUT FILEI. Instead, move this logic to a JOB INPUT NULL proc (or write a STARTER proc for this). Then it will only run when the program is launched.

Related

Mainframe batch job - return code RC 8 from IEBCOPY

//VENKATBK JOB (3322332),'KRISHNA',TIME=(1,0),
// CLASS=A,NOTIFY=VENKATB,MSGLEVEL=(1,1),PRTY=1
//STEP2 EXEC PGM=IEBCOPY
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSDUMP DD SYSOUT=*
//SYSUT1 DD DSN=VENKATB.KK.INPUT.COPY,DISP=SHR
//SYSUT2 DD DISP=SHR,DSN=VENKATB.KK.INPUT.COPY1
//SYSIN DD *
COPY INDD=SYSUT1,
OUTDD=SYSUT2
/*
THE MESSEGE FROM THE SPOOL IS..,
i have got return code maxcc=8.
i have wrote this program in different types by modifications still I am getting this maxcc=8 return code.
I don't know where did made a mistake. please help.
IEB1135I IEBCOPY FMID HDZ1A10 SERVICE LEVEL NONE DATED 20080414 DFP
IEB1035I VENKATBK STEP2 06:40:28 SUN 25 DEC 2022 PARM=''
COPY INDD=SYSUT1,
IEB107I INVALID CONTINUATION
IEB118I CONTROL STATEMENT ERROR
OUTDD=SYSUT2
IEB115I END OF FILE ON SYSIN
IEB151I JOB HAS TERMINATED WITH ERROR(S)
IEB147I END OF JOB - 8 WAS HIGHEST SEVERITY CODE
z/OS DFSMSdfp Utilities are a very old beast, and so is their syntax. Have a look at Continuing utility control statements in manual z/OS DFSMSdfp Utilities, chapter Introduction, topic Control:
Utility control statements are contained in columns 1 through 71. A statement that exceeds 71 characters must be continued on one or more additional records. A nonblank character must be placed in column 72 to indicate continuation.
The important part in your case is: A nonblank character must be placed in column 72 to indicate continuation.
=COLS> ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8
000011 //SYSIN DD *
000012 COPY INDD=SYSUT1, *
000013 OUTDD=SYSUT2
000014 /*

pdftotext doesn't give the same result in python3 script and shell

i try to use pdftotext and when i use it in my shell with my command:
"pdftotext pdf1" it gives me:
Révision : 0 1
Page : 1 / 1
Test Synapture
PJK
Spécification
Document n°
PJLTest 00 PJT SPC 0201 01
25 Rue Marguerite
69100 Villeurbanne
etc..
but when i use it in a simple script
with open(file, "rb") as f:
pdf = pdftotext.PDF(f)
text = "\n\n".join(pdf)
print(text)
it gives me :
PJLTest 00 PJT SPC 0201
Révision : 0 1
Test Synapture Page : 1 / 1
PJK
Spécification
Document n°
PJLTest 00 PJT SPC 0201 01
25 Rue Marguerite
69100 Villeurbanne
Tel : +33 (0)4 78.94.51.20 / Fax : +33 (0)4 78.94.51.21
01 BPE 16/09/2015 Première édition P. NOM1 P. NOM2 P. NOM3
REV. ETAT DATE OBJET DE LA REVISION REDACTION VERIFICATION APPROBATION
I searched on the documentation but i found nothing.
Thanks for you help!

How get all combinations at python with repeat

Code example
from itertools import *
from collections import Counter
from tqdm import *
#for i in tqdm(Iterable):
for i in combinations_with_replacement(['1','2','3','4','5','6','7','8'], 8):
b = (''.join(i))
if b == '72637721':
print (b)
when i try profuct i have
for i in product(['1','2','3','4','5','7','6','8'], 8):
TypeError: 'int' object is not iterable
How can i get all combinations ? ( i was belive it before not test , so now all what i was do wrong)
i was read about combinations_with_replacement return all , but how i see it's lie
i use python 3.8
Out put for ask
11111111 11111112 11111113 11111114 11111115 11111116 11111117
11111118 11111122 11111123 11111124 11111125 11111126 11111127
11111128 11111133 11111134 11111135 11111136 11111137 11111138
11111144 11111145 11111146 11111147 11111148 11111155 11111156
11111157 11111158 11111166 11111167 11111168 11111177 11111178
11111188 11111222 11111223 11111224 11111225 11111226 11111227
11111228 11111233 11111234 11111235 11111236 11111237 11111238
11111244 11111245 11111246 11111247 11111248 11111255 11111256
11111257 11111258 11111266 11111267 11111268 11111277 11111278
11111288
what it start give at end
56666888 56668888 56688888 56888888 58888888 77777777 77777776
77777778 77777766 77777768 77777788 77777666 77777668 77777688
77777888 77776666 77776668 77776688 77776888 77778888 77766666
77766668 77766688 77766888 77768888 77788888 77666666 77666668
77666688 77666888 77668888 77688888 77888888 76666666 76666668
76666688 76666888 76668888 76688888 76888888 78888888 66666666
66666668 66666688 66666888 66668888 66688888 66888888 68888888
88888888
more cleare think it how it be count from 1111 1111 to 8888 8888 ( but for characters , so this why i use try do it at permutation/combine with repitions...
it miss some possible combinations of that symbols.
as example what i try do , make all permutatuion of possible variants of hex numbers , like from 0 to F , but make it not only for them , make this possible for any charater.
this only at example ['1','2','3','4','5','6','7','8']
this can be ['a','b','x','c','d','g','r','8'] etc.
solition is use itertools.product instead combinations_with_replacement
from itertools import *
for i in product(['1','2','3','4','5','6','7','8'],repeat = 8):
b = (''.join(i))
if b == '72637721':
print (b)
:
itertools.product ('ABCD', 'ABCD') AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD # full multiplication with duplicates and mirrored pairs
itertools.permutations ('ABCD', 2) -> AB AC AD BA BC BD CA CB CD DA DB DC # full multiplication without duplicates and mirrored pairs
itertools.combinations_with_replacement ('ABCD', 2) -> AA AB AC AD BB BC BD CC CD DD # no mirror pairs with duplicates
itertools.combinations ('ABCD', 2) -> AB AC AD BC BD CD # no mirrored pairs and no duplicates
Here's the updated code that will print you all the combinations. It does not matter if your list has strings and numbers.
To ensure that you are doing a combination only for the specific number of elements, I recommend that you do:
comb_list = [1, 2, 3, 'a']
comb_len = len(comb_list)
and replace the line with:
comb = combinations_with_replacement(comb_list, comb_len)
from itertools import combinations_with_replacement
comb = combinations_with_replacement([1, 2, 3, 'a'], 4)
for i in list(comb):
print (''.join([str(j) for j in i]))
This will result as follows:
1111
1112
1113
111a
1122
1123
112a
1133
113a
11aa
1222
1223
122a
1233
123a
12aa
1333
133a
13aa
1aaa
2222
2223
222a
2233
223a
22aa
2333
233a
23aa
2aaa
3333
333a
33aa
3aaa
aaaa
I don't know what you are trying to do. Here's an attempt to start a dialogue to get to the final answer:
samples = [1,2,3,4,5,'a','b']
len_samples = len(samples)
for elem in samples:
print (str(elem)*len_samples)
The output of this will be as follows:
1111111
2222222
3333333
4444444
5555555
aaaaaaa
bbbbbbb
Is this what you want? If not, explain your question section what you expect as an output.

How to pull out a dta when it shows <-!--Content End--> after the JavaScript?

I've just started to learn python. I want to extract glass temperature data every three hours for academic purpose. The website is below:
https://www.weather.gov.hk/wxinfo/ts/display_graph_grass_e.htm?kp&
I try to use BeautifulSoup to pull out the data using the below script. Here is the result:
Before I find the wanted data, there is a < !--Content End-- > after the JavaScript and I can't scrape the script behind it. Why would that happen and if there is any solution for that?
The data is stored as Javascript Array in the HTML page. We can use re and ast.literal_eval (doc) to retrieve it:
import re
import requests
from ast import literal_eval
url = 'https://www.weather.gov.hk/wxinfo/ts/display_graph_grass_e.htm?kp&'
html_text = requests.get(url).text
station_code = literal_eval(re.findall(r'StationCode\s*=.*?(\(.*?\))', html_text)[0])
station_name = literal_eval(re.findall(r'stnname\s*=.*?(\(.*?\))', html_text)[0])
station_height = literal_eval(re.findall(r'stn_height\s*=.*?(\(.*?\))', html_text)[0])
grass_temp = literal_eval(re.findall(r'grasstemp\s*=.*?(\(.*?\))', html_text)[0])
min_since_17 = literal_eval(re.findall(r'minSince17\s*=.*?(\(.*?\))', html_text)[0])
min_hour = literal_eval(re.findall(r'minHour\s*=.*?(\(.*?\))', html_text)[0])
min_minute = literal_eval(re.findall(r'minMinute\s*=.*?(\(.*?\))', html_text)[0])
rows = [*zip(station_code, station_name, station_height, grass_temp, min_since_17, min_hour, min_minute)]
headers = ['Station Code', 'Station Name', 'Station Height', 'Grass Temp', 'Min_since_17', 'Min Hour', 'Min Minute']
print(''.join('{: <20}'.format(d) for d in headers))
for row in rows:
print(''.join('{: <20}'.format(d) for d in row))
Prints:
Station Code Station Name Station Height Grass Temp Min_since_17 Min Hour Min Minute
kp King's Park 65 25.4 25.3 23 35
tkl Ta Kwu Ling 15 25.4 24.8 17 00
tms Tai Mo Shan 955 21.3 21.3 07 19

How to join records in Easytrieve internal SORT?

I've a requirement, where I need to extract 2 types of records from a single input file & join them for EZT report processing.
Currently, I've written an ICETOOL step to perform the extraction followed by the join. The output of the ICETOOL step is fed to the Easytrieve report step.
Extraction card is as below -
SORT FIELDS=(14,07,PD,A)
OUTFILE FNAMES=FILE010,INCLUDE=(25,03,CH,EQ,C'010')
OUTFILE FNAMES=FILE011,INCLUDE=(25,04,CH,EQ,C'011')
OPTION DYNALLOC=(SYSDA,05)
Here is the join card -
SORT FIELDS=(14,07,PD,A)
JOINKEYS F1=FILE010,FIELDS=(14,07,A),SORTED,NOSEQCHK
JOINKEYS F2=FILE011,FIELDS=(14,07,A),SORTED,NOSEQCHK
REFORMAT FIELDS=(F1:14,07,
F2,25,10)
OUTREC BUILD=(1,17,80:X),VTOF
OPTION DYNALLOC=(SYSDA,05)
I'm wondering if it was possible to perform the above SORT/ICETOOL operations within EasyTrive. I've used the Easytrieve internal SORT but it was for the simple extractions. Can we perform the join operation within the Easytrieve?
Note - The idea is to have a single EZT step.
You can make use Synchronized File Processing facility (SFP) in Easytrieve to acheive the task. Read more about it here.
FILE FILE010
KEY1 14 7 N
*
FILE FILE011
KEY2 14 7 N
FIELD1 25 10 A
*
FILE OUTFILE FB(80 0)
OKEY 1 7 N
OFIELD 8 10 A
*
WS-COUNT W 5 N VALUE 0
*
JOB INPUT FILE010 KEY KEY1 FILE011 KEY KEY2 FINISH(DIS)
*
IF EOF FILE010
STOP
END-IF
*
IF MATCHED
OKEY = KEY1
OFIELD = FIELD1
WS-COUNT = WS-COUNT + 1
PUT OUTFILE
END-IF
*
DIS. PROC
DISPLAY 'RECORDS WRITTEN: ' WS-COUNT
END-PROC
Please note,
Above code isn't tested, it's just a draft showing the idea on
file matching using Easytrieve to achieve the task.
Data types to the data items are assumed. You may have to change them suitably.
You may have to define the variable input datasets in the FILE
statement.
You may add more statements within the IF MATCHED condition for the
creation of report.
Hope this helps!

Resources