|
David, here are a few functions i wrote/plagerized. it assumes you know the field names and data type, and can load them in order. it doesn't handle date data types. if you improve upon it, send it back to me ;) in a service program: * ParseDelimAlph() * usage: returns length of delimited field found. * parms: delimeter (comma, pipe, whatever) * index (the number of the field in the string (1, 2, 3, etc) * record (pointer to the data portion of a variable length * field containing. - %addr() + 2 * length of record * pointer to allocated variable containing data. D ParseDelimAlph PR 10i 0 D peDelim 1a const D peIndx 5i 0 const D peRecord * const D peRecLen 10i 0 const D peVariable * const * ParseDelimNumb() * usage: returns a 30p 9d numeric representation of an edited * numeric, from a delimited record. * parms: delimeter (comma, pipe, whatever) * index (the number of the field in the string (1, 2, 3, etc) * record (pointer to the data portion of a variable length * field containing. - %addr() + 2 * length of record D ParseDelimNumb PR 30p 9 D peDelim 1a const D peIndx 5i 0 const D peRecord * const D peRecLen 10i 0 const P ParseDelimAlph B EXPORT D ParseDelimAlph PI 10i 0 D peDelim 1a const D peIndx 5i 0 const D peRecord * const D peRecLen 10i 0 const D peVariable * const D RecAddr S * D Rec S 32765a based(RecAddr) D VarAddr S * D Var S 512a based(VarAddr) D $beg S 3s 0 inz(0) D $len S 3s 0 inz(0) D $y S 3s 0 inz(0) D $x S 10i 0 inz(1) /FREE // position variable to allocated space reserved for // record and return variable RecAddr = peRecord; VarAddr = peVariable; // check for valid field index if peIndx < 1; return 0; endif; // if first field in record, $beg = 1 if peIndx = 1; $beg = 1; endif; // place 2 delimiters at end of record to limit scan %subst(Rec:peRecLen+1:2) = peDelim + peDelim; // do until beginning and ending commas found dou $x > peIndx; // scan for delimiter $y = %scan(peDelim:Rec:$y+1); // if past end of record + 1, not found if $y > peRecLen + 1; return 0; endif; // beginning of field found if $x = peIndx - 1; $beg = $y + 1; // else if end of record found elseif $x = peIndx; // calc length of field $len = $y - $beg; endif; $x = $x + 1; enddo; // if no beginning or length, error if $len = 0 or $beg = 0; return 0; endif; // substring out variable Var = %subst(Rec:$beg:$len); // if first char of variable is ", remove it if %subst(Var:1:1) = '"'; $len = $len-1; %subst(Var:1:$len) = %subst(Var:2:$len); endif; // if last char of variable is ", remove it if %subst(Var:$len:1) = '"'; $len = $len-1; endif; return $len; /END-FREE P E P ParseDelimNumb B EXPORT D ParseDelimNumb PI 30p 9 D peDelim 1a const D peIndx 5i 0 const D peRecord * const D peRecLen 10i 0 const D Alph S 512a varying D negative S n inz(*OFF) D string DS 30 D decnum 30s 9 inz(0) D len S 10i 0 inz(0) D i S 10i 0 inz(1) D digits S 10i 0 inz(0) D decpos S 10i 0 inz(0) D dec S 10i 0 inz(0) D ch S 1a D chtemp S 30a varying /free // Allocate all space for Alph %len(Alph) = 512; // Parse field to alpha string %len(Alph) = ParseDelimAlph(peDelim:peIndx: peRecord: peRecLen: %addr(Alph)+2); // if no data, return 0 if %Len(Alph) < 1; return 0; endif; // Skip leading blanks (if any) i = 1; dow i <= %len(Alph) and %subst(Alph:i:1) = ' '; i = i + 1; enddo; // Is string blanks or null? then return 0 if i > %len(Alph); return 0; endif; // Is first non-blank char a minus sign? if %subst(Alph:i:1) = '-'; negative = *ON; i = i + 1; endif; // Skip leading zeros (if any) dow i <= %len(Alph) and %subst(Alph:i:1) = '0'; i = i + 1; enddo; // Is string all zeros and blanks? then return 0 if i > %len(Alph); return 0; endif; // Loop through digits of string to be converted dow i <= %len(Alph); ch = %subst(Alph:i:1); if ch = '.'; // We've reached the decimal point - only // one allowed if decpos <> 0; // We've already read a decimal point leave; endif; // Indicate decimal position just after last // digit read. decpos = digits + 1; elseif ch >= '0' and ch <= '9'; // We've read a digit - save it digits = digits + 1; chtemp = chtemp + ch; // Have we read enough digits? if digits = 30; leave; endif; else; // Anything other than a digit or decimal point // ends the number leave; endif; // Advance to the next character i = i + 1; enddo; // Adjust decimal positions if decpos = 0; // If no decimal point coded, assume one after all digits decpos = %len(chtemp) + 1; else; // drop excess decimal digits dec = %len(chtemp) - decpos + 1; if dec > 9; %len(chtemp) = %len(chtemp) - (dec - 9); endif; endif; // Scale number appropriately %subst(string: 23-decpos: %len(chtemp)) = chtemp; // Set sign of result if negative; decnum = - decnum; endif; // Return pointer to answer return decnum; /end-free P E *********usage - Assumes you know the field names, type and order. * this contains your delimited string - make it as big as you want D Str S 32765A varying *return variable of a single alpha field D Alph S 512a varying * parseDelimNumb returns a 30p9d number C eval (h) CLOC = ParseDelimNumb(',':1: C %addr(Str)+2: C %len(str)) * allocate size of Alpha to max (you could set this to field length) C eval %len(Alph) = 512 * parseDelimAlph returns the new size of the field found and put in Alph C eval %len(Alph) = ParseDelimAlph(',':2: C %addr(Str)+2: C %len(str): C %addr(Alph)+2) * put Alph into alpha field. C eval CBADATE = Alph C eval %len(Alph) = 512 C eval %len(Alph) = ParseDelimAlph(',':3: C %addr(Str)+2: C %len(str): C %addr(Alph)+2) C eval CEDATE = Alph C eval (h) CITEMNUM = ParseDelimNumb(',':4: C %addr(Str)+2: C eval (h) CLOC = ParseDelimNumb(',':1: C %addr(Str)+2: C %len(str)) C eval %len(Alph) = 512 C eval %len(Alph) = ParseDelimAlph(',':2: C %addr(Str)+2: C %len(str): C %addr(Alph)+2) C eval CBDATE = Alph C eval %len(Alph) = 512 C eval %len(Alph) = ParseDelimAlph(',':3: C %addr(Str)+2: C %len(str): C %addr(Alph)+2) C eval CEDATE = Alph C eval (h) CITEMNUM = ParseDelimNumb(',':4: C %addr(Str)+2: C %len(str)) C eval (h) CQTYSOLD = ParseDelimNumb(',':5: C %addr(Str)+2: C %len(str)) C eval (h) CEXTPR = ParseDelimNumb(',':6: C %addr(Str)+2: C %len(str))
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.