Alphanumeric key incrementing routine

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
No votes yet