Alphanumeric key incrementing routine

Tagged:

Creates next string key from the passed one using specified set of characters

This is sample code. Add error handling and adjust to your requirements as necessary.

 
 
&&
&& Creates next string key from the passed one using specified set of characters
&&
&& Parameters
&&	1 - Current Key
&&	2 - Defines the list of allowed characters
&&		BASEnn - See DO CASE in the body of the program
&&		CUSTOM - the list of character as parameter 3
&&	3 - List of characters
&&
&& Returns 	Next key
&&
&&   Note 1  Routine ignores (doesn't change) positions with the characters not in the specified list
&&   Note 2  When max possible value is reached, the next return value will be the min possible value
&&
 
FUNCTION NextKey
LPARAMETERS tcOldVal, tcOpt, tcCharList
LOCAL lcNewVal, i, lcDigits, lcLetters, lnCharListLen, lcOldChar, lcNewChar, lcCharList, lnPos, lcOpt
LOCAL lnNextPos
 
lcOpt = IIF(EMPTY(tcOpt), "BASE10", UPPER(tcOpt))
&& Get the list of appropriate characters
lcCharList = NextKeyFillCharList(lcOpt, tcCharList)
lnCharListLen = LEN(lcCharList)
lcNewVal = tcOldVal
 
&& Scan string from the right to the left
FOR i = LEN(lcNewVal) TO 1 STEP -1
 
	lcOldChar = SUBSTR(tcOldVal, i, 1)
	&& Is the current charater in the list?
	lnPos = AT(lcOldChar, lcCharList)
	IF lnPos = 0
		&& Not in the list, keep it
		LOOP
	ENDIF
 
	&& Get the next character position
	lnNextPos = (lnPos % lnCharListLen) + 1
	&& Get the next character 
	lcNewChar = SUBSTR(lcCharList,lnNextPos,1)
	&& Stuff it back in the string
	lcNewVal = STUFF(lcNewVal, i, 1, lcNewChar)
	&& Check if we have to carry over to the next position
	IF lnNextPos > 1
		&& We are done
		EXIT
	ENDIF
 
ENDFOR
 
RETURN lcNewVal
&&------------------------------------------------------------
&& Fill the list of characters based on character set requested
FUNCTION NextKeyFillCharList
LPARAMETERS tcCharSet, tcCharList
LOCAL lcCharList, lcDigits, lcLetters
&& Fill string 'lcCharList' with appropriate characters
lcDigits = "0123456789"
lcLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 
DO CASE
CASE tcCharSet = "CUSTOM"  
	lcCharList = tcCharList
CASE tcCharSet == "BASE10" 
	&& Just Digits
	lcCharList = lcDigits
CASE tcCharSet == "BASE16L" 
	&& Hexadecimal in lower case
	lcCharList = lcDigits + "abcdef"
CASE tcCharSet == "BASE16" 
	&& Hexadecimal in upper case
	lcCharList = lcDigits + "ABCDEF"
CASE tcCharSet == "BASE26L" 
	&& Lower case letters
	lcCharList = LOWER(lcLetters)
CASE tcCharSet == "BASE26" 
	&& Upper case letters
	lcCharList = lcLetters
CASE tcCharSet == "BASE36L" 
	&& Digits + Lower case letters
	lcCharList = lcDigits + LOWER(lcLetters)
CASE tcCharSet == "BASE36" 
	&& Digits + Upper case letters
	lcCharList = lcDigits + lcLetters
CASE tcCharSet == "BASE52" 
	&& All letters
	lcCharList = lcLetters + LOWER(lcLetters)
CASE tcCharSet == "BASE62" 
	&& Digits + All letters
	lcCharList = lcDigits + lcLetters + LOWER(lcLetters)
OTHERWISE
	&& The same as BASE10
	lcCharList = lcDigits
ENDCASE
RETURN lcCharList

Examples

&& Rollover to min value (Base10)
? NextKey("999999")			&& 000000
 
&& Next value (Base16)
? NextKey("999999", "Base16")  && 99999A
 
&& Dash ('-') has not been changed
? NextKey("999-FFF", "Base16")  && 99A-000