excel 按大小对ListBox元素排序

8iwquhpp  于 2023-11-20  发布在  其他
关注(0)|答案(3)|浏览(123)

我的UserForm中有一个系统,有两个ListBoxes。一个在左边,一个在右边。我已经完成了这个函数,这样我就可以在两个ListBoxes之间来回传递任何元素。然后我想在alphabetical order AND by size中对elements (strings)进行排序。我所说的size的意思是,一个字符数为10的字符串将显示在一个字符串为9的字符串之后char.
以下是我尝试过的方法:

Public Sub Sort_Listboxes(ByVal ListBox As msforms.ListBox)
Dim i As Long
Dim j As Long
Dim Temp As Variant

For i = 0 To ListBox.ListCount - 2
    For j = i + 1 To ListBox.ListCount - 1
        If ListBox.List(i) > ListBox.List(j) Or Len(ListBox.List(i)) > Len(ListBox.List(j)) Then
            Temp = ListBox.List(j)
            ListBox.List(j) = ListBox.List(i)
            ListBox.List(i) = Temp
        End If
    Next j
Next i

End Sub

字符串
使用此函数,我得到以下结果:

Element_1
Element_10
Element_2
Element_3


如果我们只采取条件的第一部分,这似乎是正常的,但有了第二部分,它应该工作。。
注意:我在函数click_rightclick_left中为两个列表调用了Sort_ListBoxes函数

o0lyfsai

o0lyfsai1#

如果你追求的正确顺序是

Element_1
Element_2
Element_3
Element_10

字符串
然后尝试将If行替换为

If Len(ListBox.List(i)) > Len(ListBox.List(j)) Or (Len(ListBox.List(i)) = Len(ListBox.List(j)) And ListBox.List(i) > ListBox.List(j)) Then


.只是稍微修改了逻辑,以正确处理具有相同长度的字符串。

2ekbmq32

2ekbmq322#

UDF可以用于确保正确的排序。

  • 假设分隔符是_,最后一部分是数字。
Option Explicit

Public Sub Sort_Listboxes(ByVal ListBox As msforms.ListBox)
    Dim i As Long
    Dim j As Long
    Dim Temp As Variant
    For i = 0 To ListBox.ListCount - 2
        For j = i + 1 To ListBox.ListCount - 1
            If FormatStr(ListBox.List(i)) > FormatStr(ListBox.List(j)) Then
                Temp = ListBox.List(j)
                ListBox.List(j) = ListBox.List(i)
                ListBox.List(i) = Temp
            End If
        Next j
    Next i
End Sub

Function FormatStr(ByVal sInput As String) As String
    Dim aKey
    aKey = Split(sInput, "_")
    If UBound(aKey) > 0 Then
        If VBA.IsNumeric(aKey(1)) Then aKey(1) = Format(aKey(1), "0000")
    End If
    FormatStr = Join(aKey, "_")
End Function

字符串
测试:

?FormatStr("Element_10")>FormatStr("Element_9")
True
?"Element_10">"Element_9"
False

h7appiyu

h7appiyu3#

回复你的评论 * "No, I have an undefined separator which will always change." *。
这个挑战吸引了我去找到这个分隔符的位置,以便根据先前的匹配和过滤操作通过Split()对原始字符串值进行排序。即使分隔符 * 完全未知 *,数字长度范围从1到4,您仍然可以通过函数adapt()规范化原始列表框元素 (例如,从“Element_10”到“Element_0010”) 进行排序。

  • 有条不紊的暗示 *
    **ad a)**我巧妙的Match()比较了两个符号数组,第一个由原始字母+分隔符+数字组成,第二个是典型的类别,其中“0”代表数字,“A”代表任何字母。省略第三个参数,Match()函数查找给定TYPES中任何符号的基于1的类别位置。
    **ad B)**由于数字被表示为类别4,因此很容易获得分隔符的位置,因为它被放置在第一个数字之前,而第一个数字本身清楚地由类型4表示;通过4的正Filter()允许获得其余数字元素的上边界。
    **ad c)**最终,很容易计算出一个字符串连接,包括原始前缀(例如“Element”)加上“0000”格式的数字字符串。
Function adapt(ByVal s As String) As String
'Auth:  https://stackoverflow.com/users/6460297/t-m
'Date:  2023-11-18
Const TYPES = "' - . 0 A"   ' Symbol types represented by lowest element
'a) check symbol types (digits occupy 4th position in types array, letters the 5th)
    Dim chk
    chk = Application.Match(Ch2Ar(s), Split(TYPES))
'b) get position of separator placed immediately before first digit (type 4)
    Dim pos As Long
    pos = Len(s) - UBound(Filter(chk, "4")) - 1: Debug.Print "pos=" & pos
'c) return adapted sort code
    adapt = Mid$(s, 1, pos) & Format(CLng(Mid$(s, pos + 1)), "0000")
End Function

字符串
尽可能接近OP,您可能希望将排序过程更改为

Public Sub Sort_ListboxColumn(ByVal ListBox As msforms.ListBox)
    Dim i    As Long
    Dim j    As Long
    Dim Temp As Variant

    With Me.ListBox
        For i = 0 To .ListCount - 2
            For j = i + 1 To .ListCount - 1
                If adapt(.List(i)) > adapt(.List(j)) Then   ' << using function adapt()
                    Temp = .List(j)
                    .List(j) = .List(i)
                    .List(i) = Temp
                End If
            Next j
        Next i
    End With
End Sub

辅助函数ch2ar()

Function Ch2Ar(ByVal s As String)
'Purp: change a string to array elements
    Dim tmp() As String
    tmp = Split(StrConv(s, vbUnicode), vbNullChar)
    ReDim Preserve tmp(0 To UBound(tmp) - 1)
    Ch2Ar = tmp
End Function

相关问题