I have a file with FB length=80. I want to append fixed value numeric 1 at position 81, if value at position 80='Y'
This appended value is supposed to be S9(9) BINARY when viewed from a copybook.
The appended field will be used in SUM FIELDS in a separate step.
How do I code the SORT SYSIN card ?
OPTION COPY
INREC IFTHEN=(WHEN=(80,1,CH,EQ,C'Y'),OVERLAY=(81:+1,TO=BI,LENGTH=2))
There is no need for this to be separate from you step with SUM in. Obviously you'd not use the OPTION COPY.
If you are SUMming records other than Y in Col 80, you'll need a IFTHEN=(WHEN=INIT to set everything to zero first.
Since this is a Mainframe task, you'd have got an earlier response if you'd used that Tag.
Related
I have the following control cards that I can't understand how to read. Could someone help me traduce what this part of a JOB is performing?
OUTFIL FNAMES=(XSCB),BLKCCT1,INCLUDE=(67,7,CH,EQ,
C'XSCB ',OR,69,7,CH,EQ,
C'XSCB '),
HEADER2=(22:C'XSCB MVS USERID SYSTEM USAGE REPORT',/,
01:C'GENERATED ON ',&DATE=(MD4/),70:C'PAGE',&PAGE,/,
01:C' AT ',&TIME,/,X,/,
01:C'JULIAN',/,
01:C'DATE TIME SYSTEM JOB MESSAGE',/,
01:C'-------- -------- ------ -------- ---------------->'),
TRAILER1=(X,/,01:C'RECORDS FOUND =',COUNT,/,34:C'END OF REPORT'),
OUTREC=(20,07,ZD,EDIT=(TTTT.TTT),X, * JULIAN DATE
28,08,X, * TIME
11,06,X, * SYSTEM
40,08,X, * JOB OR REF
59,07,CHANGE=(50,C'IEF125I',C'LOGGED ON ', * MESSAGE
C'IEF126I',C'LOGGED OFF'),
NOMATCH=(79,50),
132:X)
I understand that it searches the ID 'XSCB' in the position 67 or 69. But once it finds it, I cannot interpret what it does next.
Those are SORT control cards. If you look at the SYSOUT for the step, and pay attention to the messages, you will be able to tell if it is DFSORT (messages prefixed by ICE) or SyncSORT (messages prefixed by WER).
Your step may be EXEC PGM=SORT or ICEMAN or something else, depends on your site.
The control cards are producing a report. You have at least one line missing from your control cards (OPTION COPY, or SORT FIELDS=COPY or a different SORT or MERGE statement). There could be any number of missing cards, and you possibly have another output from the step. Otherwise the OUTFIL INCLUDE= could perhaps be a plain INCLUDE COND=.
What does what you have shown actually do?
OUTFIL defines final processing for a particular output data set. With no name, it would be for the SORTOUT DD in your JCL.
With FNAMES=(XSCB) it is for a DD named XSCB in your JCL. For a single name specified in FNAMES, the brackets are redundant.
BLKCTT1 says "put a blank in column one to not get a page-eject from TRAILER1 output".
The INCLUDE= is as you suspect. Testing two different starting positions for the same value. If either test is true, the current record will be included in the OUTFIL group.
HEADER2 defines what appears at the top of each page.
The 01: is a column-number, and is redundant, as each line by default starts are column one.
HEADER2 can create multiple lines (as can any HEADERn or TRAILERn and BUILD (or OUTREC, but don't use it for new) on OUTFIL), each separated by "/". &DATE, &TIME and &PAGE are special, containing the obvious. &DATE can be formatted in various ways, MD4/ is MM, DD, YYYY separated by slashes.
The X is a blank, on a line of its own. You could equally see .../,/... or n/ to create n multiple blank lines.
The constants should be obvious.
TRAILER1 defines what is printed at the end of the report.
COUNT is the number of records in the OUTFIL group, here used with no formatting, but it can be formatted.
The 34: column-number means the items following will start from column 34.
The OUTREC is better spelled as BUILD. OUTREC exists elsewhere. BUILD has been around for more than 10 years, so no need to use OUTREC on OUTFIL in new code (maybe this is old anyway).
What the BUILD would do is format the current input record into what is desired for an output line on the report.
The numbers in pairs are start-position and length of fields. Where no field-type is defined, they are (treated as) character fields.
You have one field-type, ZD, which is zoned-decimal. Its length is seven, and an EDIT mask is used, four digits, full-stop (decimal-point) and then three digits.
The Xs as previously are blanks, used as separators on the report. The content of each field is described in a comment. A comment is any text after the end of a control card. A control card ends at the blank after the statement is complete, or where a there is a blank after a possible continuation (a comma or a colon are possible continuations).
132:X puts a blank in column 132, and pads any intervening columns from the last field or constant with blanks.
That leaves the CHANGE=.
CHANGE= is a very useful test-and-replace.
79,50,CHANGE=(50,C'IEF125I',C'LOGGED ON ', * MESSAGE
C'IEF126I',C'LOGGED OFF'),
NOMATCH=(79,50)
This says "at the current column of the record being created, consider the content of the input from position 79 for a length of 50. The output length will be 50. If IEF125I, then use the constant LOGGED ON, if IEF126I use LOGGED OFF, and else (NOMATCH) use whatever is at position 79 for a length of 50 from the input.
Basically, the report is using the system log, or an extract from it, to report activity related to the Userid/Logon XSCB.
I have two string fields of unspecified length, lets call them One and Two. Now I would like to concat them, so that if One = "aaa" and Two = "bbb" the result becomes "aaabbb". Using the Concat fields step seems like a reasonable first guess for how to do this.
However, if I leave the "Length of target field" setting with the standard value of 0 I get no output. If I set it to something large, like 100, I always get extra spaces at the end. I want the resulting field to be as long as necessary to contain One + Two, not longer and not shorter. Is there anyway to do this using this step or some other one?
I have tried using the trim setting, but it trims the input and not the output. Clicking the "Minimal width" button does absolutely nothing.
This seems like it should be a pretty simple standard task. Am I missing something here?
EDIT: My input here is just a few rows from a Data grid step, without anything between the grid and the concat. I tried replacing the grid with a Generate rows step, but I get the same result (both when using fixed length for the generated fields, and when leaving the length fields blank).
My version of Kettle is 5.4.0.1-130. I am running it on a Windows 7 x64 platform.
Do the configuration as shown in the figure. It correctly gives the result as the second figure.
Result:
Used Data Grid step to get data.
The configuration suggested by Marlon Abeykoon works. It also works with type "String" instead of "None".
My problem was not in the Concat fields step, but the Text file output step I used to write the result to a file. It takes its metadata about the fields from the Concat fields step, and inherits the zero length for the field therefore printing zero characters to the text file.
The solution is to go to the "Fields" tab of the output step, and there press "Get fields". That explicitly adds all the fields and their metadata to the list, so you can change the lenght field of the output field from the concat step to be empty instead of 0.
So I have a set of data such as this:
mxyzd1 0000015000
mxyzd2 0000016000
xyzmd5823 0000017000
I need to use dfsort to get this data:
123xyzd1 0000015000
123xyzd2 0000016000
xyz123d5820000017000
So what I mean is: replace all character 'm' by '123' without overwriting the second column, so truncate data before you get to the second column (which starts at pos 11).
So far I've been able to replace the data but can't prevent all of my data of getting shifted, this is my code so far:
SYSIN DATA *
SORT FIELDS=(1,1,CH,A)
OUTREC FINDREP=(IN=C'm',OUT=C'123',STARTPOS=1,ENDPOS=10,
MAXLEN=20,OVERRUN=TRUNC,SHIFT=YES)
DATAEND
*
The problem you are facing is that all data on a record will be shifted to the right if the FINDREP change increases the length, and to the left if the FINDREP change decreases the length. Any change in the length of the changed data affects the entire record. You have discovered this yourself.
To put that another way, FINDREP does not know about fields (columns are best termed something like that) it only knows about records, even when it is looking only at a portion of the record, changes in length reflect on the rest of the record.
There is no way to write just a FINDREP to avoid this.
OPTION COPY
INREC IFTHEN=(WHEN=INIT,
OVERLAY=(21:1,10)),
IFTHEN=(WHEN=INIT,
FINDREP=(IN=C'm',
OUT=C'123',
STARTPOS=21)),
IFTHEN=(WHEN=INIT,
BUILD=(21,10,
11,10))
This will put the data from 1,10 into a temporary extension to the record. It will do the FINDREP on the temporary extension only. Then it will take the first 10 bytes of the extension and put them into position one for a length of 10.
Just make one small change in your sort card - SHIFT=NO
I have many Import files, which look like this
So there are sales values per Team Member, but NO period inside.
The period is coded in the Path like:
AllData\201501\Revenues.txt
AllData\201502\Revenues.txt
AllData\201503\Revenues.txt
I want to have the Periode from the path on each data row, so my final output table should look like this:
So I must bring the period from the path inside the file anyway.
The question how to access the path is solved in perfect example here:
How can I save a path criteria when I import from folders?
But there I have still the period on the "whole" text, not on the row.
In the linked question you can change the custom column formula from:
Text.FromBinary([Content])
to
Text.Split(Text.FromBinary([Content]), "#(000a)")
(depending on how line breaks are represented, you may need to use "#(000a)#(000d)" instead).
This will split the text at each new line, and you'll get a list of the name;value pairs. Click on the box with the two arrows next to the column name to expand the column. Each row should now have the period associated with the name;value pair. Finally, split the column by delimiter on the semicolon to separate the name from the value.
There are 2 options, both involve horrible looking equations.
First option, we assume the paths are going to have the period in the same position in the string.
for the example, we want the number between the 1st and 2nd slashes.
=TRIM(LEFT(SUBSTITUTE(MID(A1,FIND("|",SUBSTITUTE(A1,"\","|",1))+1,LEN(A1)),"\",REPT(" ",LEN(A1))),LEN(A1)))
If it's between a different set of slashes, alter the ,1 to tell the formula which slash to start from. If the number of slashes can be different, then we will have to try for the second option.
Second option, we assume that those are the only numbers in the path.
This formula will extract those numbers:
=SUMPRODUCT(MID(0&A1,LARGE(INDEX(ISNUMBER(--MID(A1,ROW($1:$25),1))* ROW($1:$25),0),ROW($1:$25))+1,1)*10^ROW($1:$25)/10)
Note that this will extract all the numbers from the string. If the path contains numbers, then these will get added to the string. e.g. C:\2014Data\201401\Revenues.txt would return 2014201401
If this doesn't take care of it, then it may be easier putting a column into the table yourself
My input data is like this:
trainnumber name station price coach seats
16001 CHN-CENTRAL PALANI 400.00 AC 02
16002 PALANI CHN-CENTRAL 410.00 ORD 76
16003 CHN-CENTRAL NAGARKOIL 425.00 AC 30
16004 NAGARKOIL CHN-CENTRAL 439.00 SLP 37
16005 THANJAVUR CHN-EGMORE 395.00 ORD 60
16006 CHN-EGMORE THANJAVUR 375.00 SLP 10
I want to add a new column before train number containing a four-digit sequence number followed by a blank and add 1 to my train number.
How to do this?
You have:
SORT FIELDS=COPY
OUTREC FIELDS=(1:SEQNUM,4,ZD,X,6:1,5,ZD,ADD,+1,EDIT=(TTTTT),
X,12:7,69)
Simplified:
OPTION COPY
INREC BUILD=(SEQNUM,4,ZD,
X,
1,5,ZD,
ADD,+1,
EDIT=(TTTTT),
X,
7,69)
OUTREC runs after a SORT/MERGE. INREC runs before a SORT/MERGE. Since you're not doing a SORT or MERGE (you're doing a COPY) it doesn't matter, but INREC is the more logical choice.
FIELDS is overloaded (consult the documentation to confirm) and since the presence of BUILD, FIELDS is not needed on INREC or OUTREC (and OUTREC is not needed on OUTFIL) because BUILD does the same job but with no possible confusion (BUILD is a synonym for FIELDS on INREC and OUTREC and OUTREC on OUTFIL - already complicated, without considering FIELDS on SUM, REFORMAT...).
Don't specify column positions (like 1:) if the positions are simply the natural arrangement. You are just building in maintenance.
The default start-point for a BUILD (or even the ugly FIELDS) is 1:. The default for the next field is immediately after the current field. You've used X for the spacing of your columns, so all data abuts the previous data. Using columns just complicates it.
Note: you have X,7,69. You could consider changing that to just 6,69, because position six is blank on your input.
Note: you are "losing" six bytes of your 80-byte record. If your input has, guaranteed, twelve trailing blanks (or other data that you do not require, ie any program using the file doesn't care about that loss) then that's OK, but we can't tell from your description.
Try to make your SORT Control Cards easier to read (try to make everything easier to read). It will save time and reduce errors. Which means cheaper. Time is money.
Assuming that you do mean with SORT, and your "column" isn't for DB2....
For fixed-length records:
OPTION COPY
INREC BUILD=(5X,1,your-lrecel)
The BUILD will cause a new current record, replacing the original, to be created. It will start with five blanks (the 5X) but you can put there whatever you like of whatever size (within the limits of the product, which are large). Change your-lrecl to the actual LRECL value.
For variable-length records:
OPTION COPY
INREC BUILD=(1,4,5X,5)
The 1,4 is the Record Descriptor Word, and it is always necessary to copy an RDW when creating a new current record. Once it is copied, SORT will ensure that the value contained in the first two bytes (the record-length) is correct. Then the new column, again five blanks in the example, then the rest of the variable-length record, which is specified simply by using a start-position (five here, to get the first byte of data) and implicitly this continues to the end of the record.
In your actual JCL (none of the above is JCL, it is SORT Control Cards), ensure that you do not specify any DCB info for SORTOUT. This means you can't use LIKE for that DD, remember that adding data makes the new LRECL different. Don't code the new LRECL in the JCL either. With it not specified, SORT will insert the correct value, and there is only one place to maintain it.
I tried like this and I did it.
SORT FIELDS=COPY
OUTREC FIELDS=(1:SEQNUM,4,ZD,X,6:1,5,ZD,ADD,+1,EDIT=(TTTTT),
X,12:7,69)
My file is 80 record length.