Может не очень хорошо искал, но примеры нашёл только в архиве и на сайте Дмитрия Щербакова Вот решил сделать и выложить на общий суд свою версию. Конструктивная критика приветствуется
2 функции
Код
Option Explicit
'===========================================================================================
Const delimNum$ = "|" ' разделитель ЧИСЕЛ
Const delimRange$ = ":" ' разделитель ДИАПАЗОНА ЧИСЕЛ
'===========================================================================================
Function PRDX_List_FromString(tmpString, Optional ByVal iStepPositive# = 1, Optional ByVal MsgIfFalse As Boolean) As Boolean
Dim dic As New Dictionary
Dim x, y, arr1x(), arrStr() As String
If TypeName(tmpString) <> "String" Then
If MsgIfFalse Then MsgBox "Тип переменной должен быть «String», а не «" & TypeName(tmpString) & "»!", vbCritical, "PRDX_List_FromString"
Exit Function
ElseIf iStepPositive <= 0 Then
If MsgIfFalse Then MsgBox "Шаг «" & iStepPositive & "» не может быть МЕНЬШЕ или РАВЕН НОЛЮ!", vbCritical, "PRDX_List_FromString"
Exit Function
End If
If InStr(tmpString, delimNum) = 0 Then
ReDim arrStr(0): arrStr(0) = tmpString
Else
arrStr = Split(tmpString, delimNum)
End If
For Each x In arrStr
If InStr(x, delimRange) Then
If Not ListFromRange(x, iStepPositive, MsgIfFalse) Then Exit Function
For Each y In x
y = dic(y)
Next y
Else
If Not IsNumeric(x) Then
If MsgIfFalse Then MsgBox "Элемент массива «" & x & "» не является ЧИСЛОМ!", vbCritical, "PRDX_List_FromString"
Exit Function
End If
x = dic(--x)
End If
Next x
Erase arrStr: x = 0: y = 0
arr1x = dic.Keys: dic.RemoveAll
If UBound(arr1x) > 0 Then PRDX_Sort_Array1x arr1x, 0, UBound(arr1x)
tmpString = arr1x: PRDX_List_FromString = True
End Function
'-------------------------------------------------------------------------------------------
Private Function ListFromRange(tmpStrRng, ByVal iStepPositive#, ByVal MsgIfFalse As Boolean) As Boolean
Dim arrStr() As String, s#, iMin#, iMax#, nStep&
arrStr = Split(tmpStrRng, delimRange)
If UBound(arrStr) > 1 Then
If MsgIfFalse Then MsgBox "Разделителей диапазона «" & delimRange & "» присутствует БОЛЕЕ ОДНОГО!", vbCritical, "ListFromRange"
Exit Function
ElseIf Not IsNumeric(arrStr(0)) Then
If MsgIfFalse Then MsgBox "1ый элемент диапазона «" & arrStr(0) & "» не является ЧИСЛОМ!", vbCritical, "ListFromRange"
Exit Function
ElseIf Not IsNumeric(arrStr(1)) Then
If MsgIfFalse Then MsgBox "2ой элемент диапазона «" & arrStr(1) & "» не является ЧИСЛОМ!", vbCritical, "ListFromRange"
Exit Function
Else
iMin = --arrStr(0)
iMax = --arrStr(1)
If iMin = iMax Then
ReDim tmpStrRng(0): tmpStrRng(0) = iMin
ListFromRange = True: Exit Function
End If
If iMin > iMax Then
s = iMin
iMin = iMax
iMax = s
End If
On Error Resume Next
s = Abs(iMax - iMin) / iStepPositive
If Err Then
If MsgIfFalse Then MsgBox "Шаг «" & iStepPositive & "» НЕ КОРРЕКТЕН!", vbCritical, "ListFromRange"
Exit Function
End If
On Error GoTo 0
If s < 1 Then
If MsgIfFalse Then MsgBox "Шаг «" & iStepPositive & "» не может быть БОЛЬШЕ РАЗНИЦЫ ЧЛЕНОВ:" & vbLf & "«" & iMax & "» – «" & iMin & "» = «" & iMax - iMin & "»!", vbCritical, "ListFromRange"
Exit Function
End If
nStep = Fix(s)
If nStep <> s Then nStep = nStep + 1
ReDim tmpStrRng(nStep)
tmpStrRng(0) = iMin
tmpStrRng(UBound(tmpStrRng)) = iMax
If nStep > 1 Then ' если количество шагов равно одному, то массив уже полностью сформирован, в противном случае дозаполняем массив (кроме первого и последнего члена)
For nStep = 1 To nStep - 1
tmpStrRng(nStep) = --Format$(tmpStrRng(nStep - 1) + iStepPositive, "0.0000000000")
Next nStep
End If
ListFromRange = True
End If
End Function
Сортер
Код
Option Explicit
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Рекурсивный сортер 1x-массива в редакции от Anchoret: https://www.planetaexcel.ru/forum/index.php?PAGE_NAME=message&FID=5&TID=114744&TITLE_SEO=114744-poluchenie-spiska-unikalnykh-znacheniy-iz-odnomernogo-massiva-vba&MID=953013&tags=%D0%9F%D0%BE%D0%BB%D1%83%D1%87%D0%B8%D1%82%D1%8C.%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5.%D1%81%D0%B2%D0%BE%D0%B4%D0%BD%D0%BE%D0%B9+%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%8B&_r=9788#message953013
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sub PRDX_Sort_Array1x(arr1x(), l&, u&)
Dim i&, j&, x, y
i = l: j = u: x = arr1x((l + u) \ 2)
Do
Do While arr1x(i) < x: i = i + 1: Loop
Do While x < arr1x(j): j = j - 1: Loop
If i <= j Then y = arr1x(i): arr1x(i) = arr1x(j): arr1x(j) = y: i = i + 1: j = j - 1
Loop Until i > j
If l < j Then PRDX_Sort_Array1x arr1x, l, j
If i < u Then PRDX_Sort_Array1x arr1x, i, u
End Sub
Пример использования
Код
Option Explicit
'===========================================================================================
Sub Test()
Dim x
x = "5|0,56|2:-20"
If PRDX_List_FromString(x, 2.3, True) Then Debug.Print Join(x, "/")
' получим: -20/-17,7/-15,4/-13,1/-10,8/-8,5/-6,2/-3,9/-1,6/0,56/0,7/2/5
End Sub
нужно вызывать только одну функцию: PRDX_List_FromString
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄