udfItemListSortOrdinal
str udfItemListSortOrdinal (str, str, int)
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfItemListSortOrdinal (strItemList, strDelimiter, intDirection)
If intDirection != @ASCENDING && intDirection != @DESCENDING Then intDirection = @ASCENDING
If strItemList == "" Then Return ""
intCount = ItemCount (strItemList, strDelimiter)
If StrLen (strItemList) == intCount - 1 Then Return strItemList

; Get max item length, my sophisticated invention.
intItemLenMax = 0
intBBSize = 1 + intCount + StrLen (strItemList)
hdlBB = BinaryAlloc (intBBSize)
BinaryPokeStr (hdlBB, 1, StrClean (strItemList, strDelimiter, " ", @TRUE, 2))
BinaryReplace (hdlBB, strDelimiter, @CRLF, @TRUE)
BinaryPokeStr (hdlBB, intBBSize - 1, @CR)
BinaryPokeStr (hdlBB, 0, @LF)
strSearch = StrCat (@LF, @CR)
While @TRUE
   BinaryReplace (hdlBB, strSearch, "", @TRUE)
   If BinaryEodGet (hdlBB) <= intItemLenMax Then Break
   intItemLenMax = intItemLenMax + 1
   strSearch = StrCat (@LF, StrFill (" ", intItemLenMax), @CR)
EndWhile
hdlBB = BinaryFree (hdlBB)

; Ordinal sort, using BinarySort string sort with hex strings.
intHigh = intCount - 1
intRecSize = intItemLenMax * 2
hdlBBSort = BinaryAlloc (intCount * intRecSize)
For intI = 0 To intHigh
   strItem = ItemExtract (intI + 1, strItemList, strDelimiter)
   If strItem != "" Then BinaryPokeStr (hdlBBSort, intI * intRecSize, ChrStringToHex (strItem))
Next
BinarySort (hdlBBSort, intRecSize, 0, intRecSize, @STRING | intDirection)
strItemList = ""
For intI = 0 To intHigh
   strItem = BinaryPeekStr (hdlBBSort, intI * intRecSize, intRecSize)
   If strItem != "" Then strItemList = StrCat (strItemList, strDelimiter, ChrHexToString (strItem))
      Else strItemList = StrCat (strItemList, strDelimiter)
Next
hdlBBSort = BinaryFree (hdlBBSort)

Return StrSub (strItemList, 2, -1)
;..........................................................................................................................................
; This UDF "udfItemListSortOrdinal" sorts a list of alphanumerical values in ascending or descending direction
; and respects the ordinal character series.
;
; Ordinal means, that each byte of each string is binary compared "as is".
; Uppercase characters are placed before lowercase characters in standard ASCII order.
;
; Detlev Dalitz.20090513.20090515
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;Test.
strDelimiter = ","

strAlphaNumList = "9A,AAp,Bu,BU,ba7,Apm,Ba2s,Zi,Or,1A"
strResultList1 = udfItemListSortOrdinal (strAlphaNumList, strDelimiter, @ASCENDING) ; "1A,9A,AAp,Apm,BU,Ba2s,Bu,Or,Zi,ba7"

strAlphaNumList = ","
strResultList2 = udfItemListSortOrdinal (strAlphaNumList, strDelimiter, @ASCENDING) ; ","

strAlphaNumList = ",,"
strResultList3 = udfItemListSortOrdinal (strAlphaNumList, strDelimiter, @ASCENDING) ; ",,"

strAlphaNumList = ",,,Bu,BU,ba7,,Ba2s,,"
strResultList4 = udfItemListSortOrdinal (strAlphaNumList, strDelimiter, @ASCENDING) ; ",,,,,,BU,Ba2s,Bu,ba7"


strAlphaNumList = StrReplace (StrReplace (FileGet (IntControl (1004, 0, 0, 0, 0)), @CRLF, @LF), @CR, " "); We use this script as test input.
strResultList = udfItemListSortOrdinal (strAlphaNumList, @LF, @ASCENDING)
ClipPut (StrReplace (strResultList, @LF, @CRLF)) ; The result is now on the ClipBoard, you can paste it into any editor application.

Exit


;==========================================================================================================================================
; Predecessor versions of UDF "udfItemListSortOrdinal".
;==========================================================================================================================================
; _6   200900515  String to hex conversion is now be handled by the functions ChrStringToHex and ChrHexToString.
;                 This gives about 5 pct. better performance than previous version _5.
;                 (I was not aware that those functions are already there!)
;                 This UDF has the best performance against the previous versions.
;..........................................................................................................................................
; _5   200900513  "Get max item length" as "binary version" and "BinarySort".
;                 This is the current production version, same as stored in WinBatch Tech Data Base.
;..........................................................................................................................................
; _4   200900512  "Get max item length" as "string version" and "BinarySort".
;..........................................................................................................................................
; _3   200900512  "Get max item length" as "binary version" and "ItemListSort".
;..........................................................................................................................................
; _2   200900512  "Get max item length" as "string version" and "ItemListSort".
;..........................................................................................................................................
; _1   200900512  "Growing binary buffer" and "ItemListSort".
;..........................................................................................................................................
; _0   200900512  This is my modified version of an initially introduced attempt by Jim Tailor.
;                 Topic: ItemSort Case Sensitive (7 of 25), Read 95 times
;                 Conf:  WinBatch
;                 From:  JimTaylor jtaylor@jtdata.com
;                 Date:  Saturday, May 09, 2009 02:18 PM
;==========================================================================================================================================
;
;------------------------------------------------------------------------------------------------------------------------------------------
;   #DefineFunction udfItemListSortOrdinal_5 (strItemList, strDelimiter, intDirection)
;   If intDirection != @ASCENDING && intDirection != @DESCENDING Then intDirection = @ASCENDING
;   If strItemList == "" Then Return ""
;   intCount = ItemCount (strItemList, strDelimiter)
;   If StrLen (strItemList) == intCount - 1 Then Return strItemList
;
;   ; Get max item length, my sophisticated invention.
;   intItemLenMax = 0
;   intBBSize = 1 + intCount + StrLen (strItemList)
;   hdlBB = BinaryAlloc (intBBSize)
;   BinaryPokeStr (hdlBB, 1, StrClean (strItemList, strDelimiter, " ", @TRUE, 2))
;   BinaryReplace (hdlBB, strDelimiter, @CRLF, @TRUE)
;   BinaryPokeStr (hdlBB, intBBSize - 1, @CR)
;   BinaryPokeStr (hdlBB, 0, @LF)
;   strSearch = StrCat (@LF, @CR)
;   While @TRUE
;      BinaryReplace (hdlBB, strSearch, "", @TRUE)
;      If BinaryEodGet (hdlBB) <= intItemLenMax Then Break
;      intItemLenMax = intItemLenMax + 1
;      strSearch = StrCat (@LF, StrFill (" ", intItemLenMax), @CR)
;   EndWhile
;   hdlBB = BinaryFree (hdlBB)
;
;   ; Ordinal sort, using BinarySort string sort with hex strings.
;   intHigh = intCount - 1
;   intRecSize = intItemLenMax * 2
;   hdlBB = BinaryAlloc (intItemLenMax)
;   hdlBBSort = BinaryAlloc (intCount * intRecSize)
;   For intI = 0 To intHigh
;      strItem = ItemExtract (intI + 1, strItemList, strDelimiter)
;      If strItem != "" Then BinaryPokeStr (hdlBBSort, intI * intRecSize, BinaryPeekHex (hdlBB, 0, BinaryPokeStr (hdlBB, 0, strItem)))
;   Next
;   BinarySort (hdlBBSort, intRecSize, 0, intRecSize, @STRING | intDirection)
;   strItemList = ""
;   For intI = 0 To intHigh
;      strItem = BinaryPeekStr (hdlBBSort, intI * intRecSize, intRecSize)
;      If strItem != "" Then strItemList = StrCat (strItemList, strDelimiter, BinaryPeekStr (hdlBB, 0, BinaryPokeHex (hdlBB, 0, strItem)))
;         Else strItemList = StrCat (strItemList, strDelimiter)
;   Next
;   hdlBBSort = BinaryFree (hdlBBSort)
;   hdlBB = BinaryFree (hdlBB)
;
;   Return StrSub (strItemList, 2, -1)
;   ;..........................................................................................................................................
;   ; This UDF "udfItemListSortOrdinal" sorts a list of alphanumerical values in ascending or descending direction
;   ; and respects the ordinal character series.
;   ;
;   ; Ordinal means, that each byte of each string is binary compared "as is".
;   ; Uppercase characters are placed before lowercase characters in standard ASCII order.
;   ;
;   ; Detlev Dalitz.20090513.
;   ;..........................................................................................................................................
;   #EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;
;
;------------------------------------------------------------------------------------------------------------------------------------------
;   #DefineFunction udfItemListSortOrdinal_4 (strItemList, strDelimiter, intDirection)
;   If intDirection != @ASCENDING && intDirection != @DESCENDING Then intDirection = @ASCENDING
;   If strItemList == "" Then Return ""
;   intCount = ItemCount (strItemList, strDelimiter)
;   If StrLen (strItemList) == intCount - 1 Then Return strItemList
;
;   ; Get max item length, my sophisticated invention.
;   strTempList = StrCat (@LF, StrReplace (strItemList, strDelimiter, @CRLF), @CR)
;   strTempList = StrClean (strTempList, @CRLF, " ", @TRUE, 2)
;   intItemLenMax = 0
;   strSearch = StrCat (@LF, @CR)
;   While @TRUE
;      strTempList = StrReplace (strTempList, strSearch, "")
;      If strTempList == "" Then Break
;      intItemLenMax = intItemLenMax + 1
;      strSearch = StrCat (@LF, StrFill (" ", intItemLenMax), @CR)
;   EndWhile
;
;   ; Ordinal sort, using BinarySort string sort with hex strings.
;   intHigh = intCount - 1
;   intRecSize = intItemLenMax * 2
;   hdlBB = BinaryAlloc (intItemLenMax)
;   hdlBBSort = BinaryAlloc (intCount * intRecSize)
;   For intI = 0 To intHigh
;      strItem = ItemExtract (intI + 1, strItemList, strDelimiter)
;      If strItem != "" Then BinaryPokeStr (hdlBBSort, intI * intRecSize, BinaryPeekHex (hdlBB, 0, BinaryPokeStr (hdlBB, 0, strItem)))
;   Next
;   BinarySort (hdlBBSort, intRecSize, 0, intRecSize, @STRING | intDirection)
;   strItemList = ""
;   For intI = 0 To intHigh
;      strItem = BinaryPeekStr (hdlBBSort, intI * intRecSize, intRecSize)
;      If strItem != "" Then strItemList = StrCat (strItemList, strDelimiter, BinaryPeekStr (hdlBB, 0, BinaryPokeHex (hdlBB, 0, strItem)))
;         Else strItemList = StrCat (strItemList, strDelimiter)
;   Next
;   hdlBBSort = BinaryFree (hdlBBSort)
;   hdlBB = BinaryFree (hdlBB)
;   Return StrSub (strItemList, 2, -1)
;   ;..........................................................................................................................................
;   ; This UDF "ItemListSortOrdinal" sorts a list of alphanumerical values in ascending or descending direction
;   ; and respects the ordinal character series.
;   ;
;   ; Ordinal means, that each byte of each string is compared without linguistic interpretation.
;   ; Uppercase characters are placed before lowercase characters.
;   ;
;   ; Detlev Dalitz.20090512.
;   ;..........................................................................................................................................
;   #EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;
;
;------------------------------------------------------------------------------------------------------------------------------------------
;   #DefineFunction udfItemListSortOrdinal_3 (strItemList, strDelimiter)
;   If strItemList == "" Then Return ""
;   intCount = ItemCount (strItemList, strDelimiter)
;   If StrLen (strItemList) == intCount - 1 Then Return strItemList
;
;   ; Get max item length, my sophisticated invention.
;   intItemLenMax = 0
;   strTempList = StrCat (@LF, StrReplace (strItemList, strDelimiter, @CRLF), @CR)
;   intStrLen = StrLen (strTempList)
;   hdlBB = BinaryAlloc (intStrLen)
;   BinaryPokeStr (hdlBB, 0, strTempList)
;   BinaryPokeStr (hdlBB, 0, StrClean (BinaryPeekStr (hdlBB, 0, BinaryEodGet (hdlBB) - 1), @CRLF, " ", @TRUE, 2))
;   strSearch = StrCat (@LF, @CR)
;   While @TRUE
;      BinaryReplace (hdlBB, strSearch, "", @TRUE)
;      If BinaryEodGet (hdlBB) <= intItemLenMax Then Break
;      intItemLenMax = intItemLenMax + 1
;      strSearch = StrCat (@LF, StrFill (" ", intItemLenMax), @CR)
;   EndWhile
;   hdlBB = BinaryFree (hdlBB)
;   Drop (strTempList)
;
;   ; Ordinal sort.
;   hdlBB = BinaryAlloc (intItemLenMax)
;   For intI = 1 To intCount
;      strItem = ItemExtract (intI, strItemList, strDelimiter)
;      If strItem != "" Then strItemList = ItemReplace (BinaryPeekHex (hdlBB, 0, BinaryPokeStr (hdlBB, 0, strItem)), intI, strItemList, strDelimiter)
;   Next
;   strItemList = ItemSort (strItemList, strDelimiter)
;   For intI = 1 To intCount
;      strItem = ItemExtract (intI, strItemList, strDelimiter)
;      If strItem != "" Then strItemList = ItemReplace (BinaryPeekStr (hdlBB, 0, BinaryPokeHex (hdlBB, 0, strItem)), intI, strItemList, strDelimiter)
;   Next
;   hdlBB = BinaryFree (hdlBB)
;   Return strItemList
;   ;..........................................................................................................................................
;   ; This UDF "ItemListSortOrdinal" sorts a list of alphanumerical values in ascending direction
;   ; and respects the ordinal character series.
;   ;
;   ; Ordinal means, that each byte of each string is compared without linguistic interpretation.
;   ; Uppercase characters are placed before lowercase characters.
;   ;
;   ; Detlev Dalitz.20090512.
;   ;..........................................................................................................................................
;   #EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;
;
;------------------------------------------------------------------------------------------------------------------------------------------
;   #DefineFunction udfItemListSortOrdinal_2 (strItemList, strDelimiter)
;   If strItemList == "" Then Return ""
;   intCount = ItemCount (strItemList, strDelimiter)
;   If StrLen (strItemList) == intCount - 1 Then Return strItemList
;
;   ; Get max item length, my sophisticated invention.
;   strTempList = StrCat (@LF, StrReplace (strItemList, strDelimiter, @CRLF), @CR)
;   strTempList = StrClean (strTempList, @CRLF, " ", @TRUE, 2)
;   intItemLenMax = 0
;   strSearch = StrCat (@LF, @CR)
;   While @TRUE
;      strTempList = StrReplace (strTempList, strSearch, "")
;      If strTempList == "" Then Break
;      intItemLenMax = intItemLenMax + 1
;      strSearch = StrCat (@LF, StrFill (" ", intItemLenMax), @CR)
;   EndWhile
;
;   ; Ordinal sort.
;   hdlBB = BinaryAlloc (intItemLenMax)
;   For intI = 1 To intCount
;      strItem = ItemExtract (intI, strItemList, strDelimiter)
;      If strItem != "" Then strItemList = ItemReplace (BinaryPeekHex (hdlBB, 0, BinaryPokeStr (hdlBB, 0, strItem)), intI, strItemList, strDelimiter)
;   Next
;   strItemList = ItemSort (strItemList, strDelimiter)
;   For intI = 1 To intCount
;      strItem = ItemExtract (intI, strItemList, strDelimiter)
;      If strItem != "" Then strItemList = ItemReplace (BinaryPeekStr (hdlBB, 0, BinaryPokeHex (hdlBB, 0, strItem)), intI, strItemList, strDelimiter)
;   Next
;   hdlBB = BinaryFree (hdlBB)
;   Return strItemList
;   ;..........................................................................................................................................
;   ; This UDF "ItemListSortOrdinal" sorts a list of alphanumerical values in ascending direction
;   ; and respects the ordinal character series.
;   ;
;   ; Ordinal means, that each byte of each string is compared without linguistic interpretation.
;   ; Uppercase characters are placed before lowercase characters.
;   ;
;   ; Detlev Dalitz.20090512.
;   ;..........................................................................................................................................
;   #EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;
;
;------------------------------------------------------------------------------------------------------------------------------------------
;   #DefineFunction udfItemListSortOrdinal_1 (strItemList, strDelimiter)
;   If strItemList == "" Then Return ""
;   intCount = ItemCount (strItemList, strDelimiter)
;   If StrLen (strItemList) == intCount - 1 Then Return strItemList
;   intBBSizeMax = 0
;   hdlBB = 0
;   For intI = 1 To intCount
;      strItem = ItemExtract (intI, strItemList, strDelimiter)
;      If strItem != ""
;         intBBSize = StrLen (strItem)
;         If intBBSize > intBBSizeMax
;            intBBSizeMax = intBBSize
;            If hdlBB Then hdlBB = BinaryFree (hdlBB)
;         EndIf
;         If !hdlBB Then hdlBB = BinaryAlloc (intBBSizeMax)
;         strItemList = ItemReplace (BinaryPeekHex (hdlBB, 0, BinaryPokeStr (hdlBB, 0, strItem)), intI, strItemList, strDelimiter)
;      EndIf
;   Next
;   strItemList = ItemSort (strItemList, strDelimiter)
;   For intI = 1 To intCount
;      strItem = ItemExtract (intI, strItemList, strDelimiter)
;      If strItem != "" Then strItemList = ItemReplace (BinaryPeekStr (hdlBB, 0, BinaryPokeHex (hdlBB, 0, strItem)), intI, strItemList, strDelimiter)
;   Next
;   If hdlBB Then hdlBB = BinaryFree (hdlBB)
;   Return strItemList
;   ;..........................................................................................................................................
;   ; This UDF "ItemListSortOrdinal" sorts a list of alphanumerical values in ascending direction
;   ; and respects the ordinal character series.
;   ;
;   ; Ordinal means, that each byte of each string is compared without linguistic interpretation.
;   ; Uppercase characters are placed before lowercase characters.
;   ;
;   ; Detlev Dalitz.20090512.
;   ;..........................................................................................................................................
;   #EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;
;
;------------------------------------------------------------------------------------------------------------------------------------------
;   #DefineFunction udfItemListSortOrdinal_0 (strList, strDelimiter)
;   If strList == "" Then Return ""
;   intItemCount = ItemCount (strList, strDelimiter)
;   strNumDelim = "|"
;   strListNew = ""
;   intEmpty = 0
;   For intI = 1 To intItemCount
;      strItem = ItemExtract (intI, strList, strDelimiter)
;      If strItem != ""
;         intChrCount = StrLen (strItem)
;         strChars = ""
;         For intChr = 1 To intChrCount
;            strChars = strChars : StrFixLeft (Char2Num (StrSub (strItem, intChr, 1)), "0", 3) : strNumDelim
;         Next
;         strListNew = strListNew : strChars : strDelimiter
;      Else
;         intEmpty = intEmpty + 1
;      EndIf
;   Next
;   strListNew = ItemSort (strListNew, strDelimiter) ; Trailing delimiter now leading.
;   intItemCount = ItemCount (strListNew, strDelimiter) ; Just one item too much.
;   strList = ""
;   For intI = 2 To intItemCount ; Skip leading delimiter.
;      strItem = ItemExtract (intI, strListNew, strDelimiter)
;      intChrCount = ItemCount (strItem, strNumDelim) - 1
;      strChars = ""
;      For intChr = 1 To intChrCount
;         strChars = strChars : Num2Char (ItemExtract (intChr, strItem, strNumDelim))
;      Next
;      strList = strList : strChars : strDelimiter
;   Next
;   If intEmpty Then strList = StrFill (strDelimiter, intEmpty) : strList ; Insert empty items as skipped above.
;   strList = ItemRemove (-1, strList, strDelimiter)
;   Return strList
;   ;..........................................................................................................................................
;   ; This UDF "ItemListSortOrdinal" sorts a list of alphanumerical values in ascending or descending direction
;   ; and respects the ordinal character series.
;   ;
;   ; Ordinal means, that each byte of each string is compared without linguistic interpretation.
;   ; This UDF sorts uppercase characters before lowercase characters.
;   ;
;   ; Detlev Dalitz.20090512.
;   ;..........................................................................................................................................
;   #EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;
;
;------------------------------------------------------------------------------------------------------------------------------------------
;   Topic:  ItemSort Case Sensitive (7 of 25), Read 95 times
;   Conf:  WinBatch
;   From:  JimTaylor jtaylor@jtdata.com
;   Date:  Saturday, May 09, 2009 02:18 PM
;
;
;   #DefineFunction ItemSortASCII(ilist,delimiter)
;
;     If ilist == "" Then Return(ilist)
;     If StrLen(delimiter) > 1 Then
;       Message("Note","Delimiter must be one character.")
;       Return("")
;     EndIf
;
;     icnt = ItemCount(ilist,delimiter)
;     ntxt  = ""
;     nlist = ""
;     For i = 1 To icnt
;       itxt = ItemExtract(i,ilist,delimiter)
;       If itxt == "" Then Continue
;       For k = 1 To StrLen(itxt)
;         ntxt = ntxt:StrFixLeft(Char2Num(StrSub(itxt,k,1)):"|","0",4)
;       Next
;       nlist = nlist:ItemRemove(-1,ntxt,"|"):delimiter
;       ntxt  = ""
;     Next
;     nlist = ItemRemove(-1,nlist,delimiter)
;     nlist = ItemSort(nlist,delimiter)
;
;     ntxt  = ""
;     ilist = ""
;     For i = 1 To icnt
;       itxt = ItemExtract(i,nlist,delimiter)
;       kcnt = ItemCount(itxt,"|")
;       For k = 1 To kcnt
;   ;     clipput(itxt:@CRLF:k:@CRLF:ItemExtract(k,itxt,"|"))
;         ntxt = ntxt:Num2Char(ItemExtract(k,itxt,"|"))
;       Next
;       ilist = ilist:ntxt:delimiter
;       ntxt  = ""
;     Next
;     ilist = ItemRemove(-1,ilist,delimiter)
;
;     Return (ilist)
;
;   #EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;==========================================================================================================================================