This morning my nerdish IBM-i Chum Toby, pinged me a whatsapp challenge to write a little RPG code snippet to “extract invoice numbers” from a random string of data.
So…. if you had a string ‘INV#10563592 DATED 12/17/19 SO#286045 NOT GOING’ and you knew that this is a shitty text file way of referencing an invoice to a sales order. What %BIF would you to extrapolate ‘10563592’. Invoices are all numeric, 8 digits and it’s a good bet will be preceded by by ‘INV#’Toby. He swears a lot. This was particularly mild.
%SCAN returns the first position of the search argument in the source string, or 0 if it was not found. If the start position is specified, the search begins at the starting position. The result is always the position in the source string even if the starting position is specified.
%CHECK returns the first position of the string containing a character. The check begins at the starting position and continues to the right until a character that is not contained in the search string is found.
%SUBST returns a portion of argument string. It may also be used as the result of an assignment with the EVAL operation code. The start parameter represents the starting position of the substring. The length parameter represents the length of the substring.
So taking the premise that we can check for a number like this:
You can use this to test numeric w/o indicators.
dcl-s Numbers char(10) Inz('0123456789') If %check(Numbers:My_Field) > 0; Error = *On; // it has non-numerics in it else; Error = *off; // everything is numeric #huzzah! EndIf;
Let’s knock out a little code snippet to try to do this:
// + ------------------------------------------------------- + // + Extract Invoice Number from string + // + ------------------------------------------------------- + dcl-proc get_invoice_from_string; dcl-pi get_invoice_from_string char(8); p_string char(100) const; end-pi; dcl-s success ind; dcl-s invoice char(8); dcl-s numbers char(10) Inz('0123456789'); dcl-s posn zoned(5); // Look for an invoice number starting with INV# first posn = %scan('INV#':p_string); // if this scan worked then 'posn' holds the starting character of 'INV#' if posn > 0; // now lets check if the next 8 chars are numeric If %check(numbers:%subst(p_string:posn+4:8)) > 0; success = *off; // it has non-numerics in it else; success = *on; // everything is numeric #huzzah! invoice = %subst(p_string:posn+4:8); EndIf; endIf; return invoice; end-proc;
and to call the procedure we would have something like this:
invoice_number = get_invoice_from_string( $stringtobescanned );
Got any better code snippets to do this?
IBM i Software Developer, Digital Dad, AS400 Anarchist, RPG Modernizer, Alpha Nerd and Passionate Eater of Cheese and Biscuits. Nick Litten Dot Com is a mixture of blog posts that can be sometimes serious, frequently playful and probably down-right pointless all in the space of a day. Enjoy your stay, feel free to comment and in the words of the most interesting man in the world: Stay thirsty my friend.
New Developerworks RDi website is ‘IBM Rational Developer for i Hub’
IFS File system error occurred. Error number 3021?
How to rename IFS Files
How to copy IBM i IFS folder
How to rename Fresche (BCD) Presto Library – XL_PRESTO
Using TURNOVER in an IBM i iASP Environment
Preparing to implement IBM i iASP (Independent Auxiliary Storage Pool)
How to move IFS from *SYSBAS into iASP (Independent ASP)
Update IBM i IFS Objects Data Change Timestamp