Formatting breaklines using ICETOOL's DISPLAY - mainframe

I'm using DFSORT's ICETOOL DISPLAY operator to generate a list of accounts. I'm using a 'BREAK' on the branches to separate the accounts by sortcode and then sum the balance for the account. Everything works fine, but I get an additional entry(account) after summing the balance using BTOTAL. I've added my code below and the result so you better understand my question.
code
//SUR0007 JOB (5678),'ACCOUNTS'
//RUNIT EXEC PGM=ICETOOL
//TOOLMSG DD SYSOUT=*
//DFSMSG DD SYSOUT=*
//TOOLIN DD *
DISPLAY FROM(INPUT2) LIST(REPORT) -
TITLE('LIST OF BANK ACCOUNTS BY BRANCH') -
HEADER('ACCOUNT') ON(2,8,BI,E'99999999') -
HEADER('BALANCE') ON(3,6,BI,E'99999999') -
HEADER('OWNER') ON(13,30,CH) -
BTITLE('SORTCODE:') BREAK(1,4,BI,E'999999') -
BTOTAL('BRANCH TOTAL:') -
TOTAL('GRAND TOTAL:')
/*
//INPUT2 DD DSN=USER.CICS.Z022.BANK.ACCOUNTS,DISP=SHR
//REPORT DD SYSOUT=*
result
SORTCODE:000012
ACCOUNT BALANCE
-------- --------
91317760 97999587
BRANCH TOTAL :
91317760 97999587
Expected result
SORTCODE:000012
ACCOUNT BALANCE
-------- --------
91317760 97999587
BRANCH TOTAL : 97999587

DFSORT's ICETOOL DISPLAY operator has many options, which means there is extensive documentation for it.
You should consult the DFSORT Getting Started manual for introductory-level use, and DFSORT Application Programming Guide for more high-level use.
Within BCOUNT, all numeric fields will appear with totals. Your account is numeric (binary), but if you can't make it non-numeric you can use NOST (you can pretend that means NO Sub-Totals) as part of the formatting for any field that you do not want to be summed automatically.
To get your BTOTAL text to appear on the same line as the totals, use STATLEFT in the report description.
Here's an example of the use of both from the Application Programming Guide:
DISPLAY FROM(ACCTS) LIST(FANCY) -
TITLE('Accounts Report for First Quarter') -
DATE(MD4/) BLANK -
HEADER('Amount') ON(12,6,ZD,C1,N08) -
HEADER(Id') ON(NUM,N02) -
HEADER('Acct#') ON(31,3,PD,NOST,LZ) -
HEADER('Date') ON(1,4,ZD,E'99/99',NOST) -
INDENT(2) BETWEEN(5) -
STATLEFT -
TOTAL('Total for Q1') -
AVERAGE('Average for Q1')
There is coding for a plain version of the same report:
DISPLAY FROM(ACCTS) LIST(PLAIN) -
TITLE('Accounts Report for First Quarter') -
DATE(MD4/) BLANK -
HEADER('Amount') ON(12,6,ZD) -
HEADER(Id') ON(NUM) -
HEADER('Acct#') ON(31,3,PD) -
HEADER('Date') ON(1,4,ZD) -
TOTAL('Total for Q1') -
AVERAGE('Average for Q1')
The output, with explanation from the example, is:
This example shows some options you can use to improve the appearance
of a DISPLAY report. The first DISPLAY operator produces a "plain"
report, and the second DISPLAY operator uses the options shown in bold
to produce a "fancy" report.
The PLAIN output starts on a new page and looks as follows:
Accounts Report for First Quarter 05/04/2001
Amount Id Acct# Date
--------------- --------------- ------------------- --------------------
93271 1 15932 106
137622 2 187 128
83147 3 15932 212
183261 4 2158 217
76389 5 187 305
920013 6 15932 319
Total for Q1
1493703 50328 1287
Average for Q1
248950 8388 214
The FANCY output starts on a new page and looks as follows:
Accounts Report for First Quarter 05/04/2001
Amount Id Acct# Date
-------- --- ------ -----
932.71 1 15932 01/06
1,376.22 2 00187 01/28
831.47 3 15932 02/12
1,832.61 4 02158 02/17
763.89 5 00187 03/05
9,200.13 6 15932 03/19
Total for Q1 14,937.03
Average for Q1 2,489.50
Here is an explanation of the extra options used for the "fancy"
report:
First ON field: In the PLAIN report, BLANK causes ICETOOL to print
the 6-byte ZD values as unedited digits with leading zeros suppressed.
But for this example, we know the digits really represent dollars and
cents. So in the FANCY report, we use the C1 formatting item (one of
thirty-three available masks) to print the values with a comma (,) as
the thousands separator and a period (.) as the decimal point.
In the PLAIN report, TOTAL causes ICETOOL to allow 15 digits for the
values because it does not know how many digits are needed. But
for this example, we know the total amount will not exceed 8 digits.
So in the FANCY report, we use the N08 formatting item to set the
number of digits to 8. This decreases the column width for the field.
Second ON field: In the PLAIN report, NUM causes ICETOOL to allow 15
digits for the record number because it does not know how many
digits are needed. But for this example, we know the number of records
will not exceed 99. So in the FANCY report, we use the N02 formatting
item to set the number of digits to 2. This decreases the column width
for the record number.
Third ON field: In the PLAIN report, TOTAL and AVERAGE cause ICETOOL to
print the total and average for this 3-byte PD field. But
for this example, we know we do not want statistics for the field
because it is an account number. So in the FANCY report, we use the
NOST formatting item to suppress the statistics for this field.
In the PLAIN report, the default mask of A0 causes ICETOOL to suppress
leading zeros for this 3-byte PD field. But for this example,
we know that we want to show leading zeros for the field because it is
an account number. So in the FANCY report, we use the LZ formatting
item to print leading zeros for this field.
Fourth ON field: In the PLAIN report, BLANK causes ICETOOL to print the
4-byte ZD values as unedited digits with leading zeros
suppressed. But for this example, we know the digits represent a date
(month and day). So in the FANCY report, we use the E'99/99'
formatting item to print the values with leading zeros and a slash (⁄)
between the month and day.
In the PLAIN report, TOTAL and AVERAGE cause ICETOOL to print the total
and average for this 4-byte ZD field. But for this example, we
know we do not want the total or average for this field because it is
a date. So in the FANCY report, we use the NOST formatting item to
suppress the statistics for this field.
Note: In some applications, we might want the minimum and maximum for a
date displayed with E'pattern', so we would not specify NOST for
the date field.
INDENT: In the PLAIN report, ICETOOL starts the report in column 2
(after the control character), by default. But for this example, we
want to indent the report a bit. So in the FANCY report, we use the
INDENT(2) operand to indent the report by 2 blanks so it starts in
column 4.
BETWEEN: In the PLAIN report, ICETOOL uses 3 blanks between the columns
of data, by default. But for this example, we want more space
between the columns. So in the FANCY report, we use the BETWEEN(5)
operand to insert 5 blanks between the columns.
STATLEFT: In the PLAIN report, ICETOOL prints the strings for TOTAL
and AVERAGE under the first column of data, by default, and uses
two lines for each statistic to avoid having the string overlay the
value. But for this example, we would like to have the TOTAL and
AVERAGE strings stand out in the report and also have each string on
the same line as its value. So in the FANCY report, we use the
STATLEFT operand to print the TOTAL and AVERAGE strings to the left of
the first column of data.
Here's the link, which also includes a "plain" version of the report to contrast with the fancy one: http://www-01.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.icea100/ice2ca_Example_1110.htm
I located the link by search-engineing for icetool display statleft nost.

Related

Excel Formula Extract any number greater than x charters from a string

I have a file which contains a list of data. In each cell is a name and number and a date the date is either mm/yy or mm-yy or mm-yyyy etc. (never the day just month and year)
The number I need is always going to be greater than 5 characters. Is there a way that I can get just the number from the string
xx company holding - 96923432 -02-22. (number required 96923432)
yy Company (HOLDINGS) LTD - 131002204 - 02/2023 (number required 131002204)
ab HOLDINGS LIMITED / 115472907 / Feb-23 (number required 115472907)
... prior removed
=========UPDATE=========
This formula will work for you, which splits your data by space, then converts to a number and then extracts the max. Adjust as needed if you have occasions where you may not have a number greater than 5 by wrapping with an IF().
=MAX(IFERROR(NUMBERVALUE(TEXTSPLIT(A2," ")),0))
This is interesting since you use 2 different delimiters. However, no worries you can simply use the following to capture both instances. If you have more possible delimiters simply just add them between the {} in both textbefore and textafter functions. Here is an example of the equation:=TEXTBEFORE(TEXTAFTER(A2, {"-","/"}), {"-","/"})
This should work for you then if you want to return nothing if output is less than 5. =IF(LEN(TEXTBEFORE(TEXTAFTER(A1,{"-","/"}),{"-","/"}))>5,TEXTBEFORE(TEXTAFTER(A1,{"-","/"}),{"-","/"}),"")

Is there an excel formula to extract numbers from the end of a string in a cell, where the length is not always constant

I am trying to separate information copied from a PDF table - id usually use text to columns but the only delamination is spaces and this then splits the data into multiple unusable columns
The data comes like this:
Raw Data
A1 Company 0
Company2 40000
name a 1
name b 15
name c 184
Big 17 Company 1887
I need the output to be:
Company
Units
A1 Company
0
Company2
40000
name a
1
name b
15
name c
184
Big 17 Company
1887
So the company name (that might contain numbers) is separated for the unit number (that could be 1-5 digits long).
I haven't been able to figure out a way that uses =len() as the string length isn't a constant mixed with the last numbers not being a consistent number of digits.
I'm currently using:
=SUMPRODUCT(MID(0&A2, LARGE(INDEX(ISNUMBER(--MID(A2, ROW(INDIRECT("1:"&LEN(A2))), 1)) * ROW(INDIRECT("1:"&LEN(A2))), 0), ROW(INDIRECT("1:"&LEN(A2))))+1, 1) * 10^ROW(INDIRECT("1:"&LEN(A2)))/10)
This gives me all the numbers in the cell - which works for 90% of the data as most of the company's don't have numbers in their name. But for something like 'A1 Company 0' it gives 10 as the output not just the 0. I then go and manually edit the small number of companies that this happens too.
I then use a mixture of =LEN() =LEFT and =RIGHT to split the information up as required for the further automated analysis.
I'd prefer a formula over VBA/macro
I cant provide the actual data but I hope I've given enough examples in the table above to show the main problems (different company name lengths, companies with numbers in their name, different amount of digits representing the units)
Using Libre Office, but this formula checks for the last space in the cell
=RIGHT(A1,LEN(A1)-FIND("#",SUBSTITUTE(A1," ","#",LEN(A1)-LEN(SUBSTITUTE(A1," ",""))),1))
Taken from: https://trumpexcel.com/find-characters-last-position/
FILTERXML() would best choice for this case. Try-
=FILTERXML("<t><s>"&SUBSTITUTE(A1:A6," ","</s><s>")&"</s></t>","//s[last()]")
Details about FILTERXML() from JvdV here.
See if the following works for you:
Formula in B2:
=LEFT(A2,LEN(A2)-1-LEN(C2))
In C2:
=-LOOKUP(1,-RIGHT(A2,ROW($1:$5)))
For those users using ms365's newest functions:
=HSTACK(TEXTBEFORE(A2," ",-1),TEXTAFTER(A2," ",-1))

Pandas, why does division done to other rows lead to additional trailing zeroes on final row?

I have a table that shows participation in Hong Kong demonstrations by gender for different dates in 2019 (obtained from this source). The three first rows originally showed the percentage for males, females and unknown/unanswered. The final row shows the sample size. All data was initially of type string (the percentages included the % sign).
My DataFrame is titled gender_table
To be able to do some analysis, I first removed the percentage sign and changed the data to float type.
gender_table = gender_table.astype("float64")
This gives me the following:
To change the percentage values into ratios, I thought I'd just divide all the data (except the final row with sample size) by 100.
gender_table[:-1] = gender_table[:-1]/100
gender_table now looks like this:
My question is this: Why has this operation added additional trailing zeroes to the sample size row?
Pastebin with data (after removal of % signs) available here (can be saved as .csv and read into a Pandas df ("index_col=0")).
All rows of a column are formatted uniformly. The default format for a float variable x is f'{x:.6g}' (for details about format specifiers see here).
So when you divide the first rows that had 1 decimal place by 100 they get 3 decimal places and as all rows in a column share the same format 285.0 becomes 285.000.
This of course only changes the string representation of the values in the last row, the float values itself remain unchanged.

Pulling out specific characters that are combined in a single column

I have a data extract that resulted in fields being combined into column A like this:
Sales Figures Report pg 121
Walmart Inc. 001230134 99 Associates Parkway 56.12 20.00 10.00 86.12 00 1
1400.25 262.40 14.50 1677.15 02 9
50.00 100.25 10.00 160.25 00 1
1400.25 262.40 14.50 1677.15 02 9
There are over 50,000 rows in this sort of format, some are a little different as they'll start with vendor information and then have those values after (still all in col. A). In the above example 1677.15 is the combined value of the three numbers before that, i.e. the total amount due.
Originally I wanted to basically separate out each value using things like left(), mid(), right() etc. however at this point all I want is the total figure, i.e. the $1677.15 in the above example. What is the best non-vba method of doing this?
Two issues:
The problem is that the amounts are not always the same number of digits (can range from $xx.xx to $xxx,xxx.xx)
Since There are multiple "." you can't use search() to find the correct character location.
In your example, the Total figure is always the third group from the end. That being the case, you can use the following formula and defined names:
=IFERROR(--INDEX(TRIM(MID(SUBSTITUTE(A1," ",REPT(" ",99)),seq_99,99)),LEN(A1)-LEN(SUBSTITUTE(A1," ",""))-1),"")
Defined Names
seq refers to: =ROW(INDEX($1:$65535,1,1):INDEX($1:$65535,255,1))
seq_99 refers to: =IF(seq=1,1,(seq-1)*99)
In the formula,
SUBSTITUTE: Replace all spaces with a large number (99) of spaces
MID Return an array consisting of each word (space separated)
TRIM the words to remove the extra spaces
INDEX Return the item that is third from the end.
IFERROR handle lines such as your first, which does not contain the relevant pattern.
seq and seq_99 return arrays of {1,2,3,...}and{1,99,198,...}` to be used in the formulas

Generate prefix to make 4 digits

I am creating a form that will generate sequential number for report types. Each number is sequential so first report is number 1 and second report is number 2 and so on.
The thing is, the report number needs to be in 4 digits, if the report number is not enough to make 4 digits, fill it in with 0's.
For example:
Report 1 number is 0001, report 2 number is 0002, report 10 number is 0010, report 100 number is 0100
I was thinking about adding 4 0's to the report number and do a substring formula, but the problem is I do not know the starting number.
Appreciate the help
I suggest to generate the report number once this is submitted by the user, this way you can get the sharepoint list id number, and then apply a simple set of rules like this:
Condition:
If Id does not match pattern Custom Pattern: \d{4}
Run this Actions
Set reportNumber's value: result = concat (substring("0000", 1 , 4 - string-length(Id))
Check the box to prevent the next rule to run when the condition is met
Add a new rule under this one just to print the Id if the condition is met.
So this way, numbers below 4 digits will be concatenated, and ids with 4 digits will just be displayed.
I hope this help you.

Resources