View Single Post
 
Old 07-22-2016, 12:48 AM
Guessed's Avatar
Guessed Guessed is offline Windows 10 Office 2013
Expert
 
Join Date: Mar 2010
Location: Canberra/Melbourne Australia
Posts: 4,176
Guessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant future
Default

This is my effort using a Recordset to avoid the bubblesort. It is still clunky and probably no better - just a different way of doing things with arrays, recordsets and dictionaries all called up for a showing.
Code:
Option Explicit

Sub ListExpandSortDeDupCompress()
  Dim strNumberList As String
  Dim arrMixed() As String, iNum As Integer
  Dim oRs  As New ADODB.Recordset
  Dim oDic As Object
  Dim varRawNumbers As Variant

  Set oDic = CreateObject("Scripting.Dictionary")
  
  strNumberList = fcnKillWhiteSpace(Selection.Text)
  arrMixed = Split(strNumberList, ",")
  Set oRs = ConvertToExpandedRecordset(arrMixed)
  
  'Sort the recordset into order and create a dictionary of unique values (in sorted order)
  oRs.Sort = "[FldNum]"
  With oRs
    .MoveLast
    If .RecordCount > 0 Then
      .MoveFirst
      While Not .EOF
        iNum = .Fields("FldNum").Value
        If Not oDic.Exists(iNum) Then oDic.Add iNum, iNum
        .MoveNext
      Wend
    End If
  End With
  
'  varRawNumbers = oDic.Items
'  strNumberList = Join(varRawNumbers, ",")
'  Debug.Print strNumberList
  strNumberList = ConvertDict2CompressedString(oDic)
  Selection.InsertAfter vbCr & strNumberList
End Sub

Private Function ConvertToExpandedRecordset(arrValues() As String) As Recordset
  Dim oRs  As New ADODB.Recordset, arrSpan() As String
  Dim lRec As Long, lCount As Long
  
  oRs.Fields.Append "FldName", adVariant, , adFldMayBeNull
  oRs.Fields.Append "FldNum", adInteger, , adFldMayBeNull
  
  oRs.Open
  For lRec = LBound(arrValues) To UBound(arrValues)
    If InStr(arrValues(lRec), "-") > 0 Then
      arrSpan = Split(arrValues(lRec), "-")
      For lCount = CLng(arrSpan(0)) To CLng(arrSpan(1))
        oRs.AddNew
        oRs("FldName").Value = lCount
        oRs("FldNum").Value = lCount
        oRs.Update
      Next lCount
    Else
      oRs.AddNew
      oRs("FldName").Value = arrValues(lRec)
      oRs("FldNum").Value = CLng(arrValues(lRec))
      oRs.Update
    End If
  Next lRec
  Set ConvertToExpandedRecordset = oRs
End Function

Function fcnKillWhiteSpace(strRaw As String) As String
Dim strTemp As String
  strTemp = Replace(strRaw, " ", "")
  strTemp = Replace(strTemp, Chr(160), "")
  strTemp = Replace(strTemp, Chr(13), "")
  strTemp = Replace(strTemp, Chr(11), "")
  strTemp = Replace(strTemp, Chr(9), "")
  fcnKillWhiteSpace = strTemp
lbl_Exit:
  Exit Function
End Function

Function ConvertDict2CompressedString(oDic) As String
  Dim v As Variant, bConsecutive As Boolean, sRun As String
  Dim iStartRun As Integer, iEndRun As Integer, sTemp As String
  
  For Each v In oDic.Keys
    If oDic.Exists(v + 1) Then
      If Not bConsecutive Then  'first entry in a run
        iStartRun = v
        bConsecutive = True
        'sRun = iStartRun & "," & v
      ElseIf v - iStartRun = 1 Then 'second entry in a run
        sRun = iStartRun & "," & v
      Else  'run has 3+ entries
        iEndRun = v
        sRun = iStartRun & "-" & v
      End If
    Else
      If Not bConsecutive Then
        sRun = v
        sTemp = sTemp & "," & sRun
      ElseIf v - iStartRun = 1 Then
        sRun = iStartRun & "," & v
        sTemp = sTemp & "," & sRun
      Else
        sTemp = sTemp & "," & iStartRun & "-" & v
      End If
      bConsecutive = False
    End If
  Next
  Debug.Print sTemp
  
  sTemp = Mid(sTemp, 2)
  ConvertDict2CompressedString = Replace(sTemp, ",", ", ")
End Function
__________________
Andrew Lockton
Chrysalis Design, Melbourne Australia
Reply With Quote