.st0{fill:#FFFFFF;}

Using RPGLE to extract invoice numbers from an alpha string 

 February 26, 2020

By  NickLitten

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.

To look for invoice numbers – we can use the %SCAN %BIF

%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.

To test the suspected invoice numbers – we can use %CHECK

%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.

To extract invoice numbers – we can use %SUBST

%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.

Sample RPGLE sub-procedure

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 );  

How does that work Tobers?

Got any better code snippets to do this?

NickLitten


IBM i Software Developer, Digital Dad, AS400 Anarchist, RPG Modernizer, Shameless Trekkie, Belligerent Nerd, Englishman Abroad 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 remember: If at first you don't succeed then skydiving probably isn't a hobby you should look into.

Nick Litten

related posts:

  • Hi.

    Maybe its more simple to use sql (in a rpg program) šŸ™‚

    regexp_substr extracts hits šŸ™‚

    select regexp_substr(regexp_substr(textfelt,’INV#.*[0-9]{8} ‘,1,1,’i’) , ‘[0-9]{8} ‘,1,1,’i’)
    from (select ‘INV#05635902 DATED 12/17/19 SO#286045 NOT GOING’ as textfelt
    from sysibm.sysdummy1);

    Which would give a rpg program like this :

    exec sql Value(regexp_substr(regexp_substr(:stringtobescanned,’INV#.*[0-9]{8} ‘,1,1,’i’) , ‘[0-9]{8} ‘,1,1,’i’) into :result;

    Iam not a regex expert, but iam sure that a regex could be written that would match all combinations.

    Best regards Jan

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
    __CONFIG_colors_palette__{"active_palette":0,"config":{"colors":{"cff50":{"name":"Main Accent","parent":-1},"a344d":{"name":"Accent Transparent","parent":"cff50"}},"gradients":[]},"palettes":[{"name":"Default","value":{"colors":{"cff50":{"val":"var(--tcb-skin-color-0)"},"a344d":{"val":"rgba(46, 138, 229, 0.85)","hsl_parent_dependency":{"h":210,"l":0.54,"s":0.78}}},"gradients":[]},"original":{"colors":{"cff50":{"val":"rgb(0, 178, 255)","hsl":{"h":198,"s":1,"l":0.5}},"a344d":{"val":"rgba(0, 178, 255, 0.85)","hsl_parent_dependency":{"h":198,"s":1,"l":0.5}}},"gradients":[]}}]}__CONFIG_colors_palette__

    Get In Touch

    Iā€™m always looking for awesome input, feedback and critique!

    >