如何根据工作表名称按字母顺序重新排列 Excel 工作表,但我有一个特定规则,如果工作表名称包含“YTD”,那么它始终是第一个

问题描述 投票:0回答:1

帮助我根据工作表名称按字母顺序重新排列 Excel 工作表, 但我有一个特定的规则,如果工作表名称包含“YTD”,那么它始终是第一个 如果我们有数字 0 那么它将始终位于其组的末尾

谢谢你

输入:

  • YTD-WTRA-实际-Dts
  • 1_AB
  • 3_AB
  • 2_AB
  • 0_AB
  • 2_NC
  • 0_NC
  • 1_NC

我想这样安排:

  • YTD-WTRA-Actual-Dts(带有“YTD”字样的 Excel 工作表始终是第一个)
  • 1_AB(按照 A-Z 顺序找到的最小数字和第一个数字进行跟踪)
  • 2_AB(与前一组(AB)同一组跟进
  • 3_AB
  • 0_AB(在同一组(AB)上以数字零“0”结束
  • 1_NC(在 A - B - C 等之后继续下一组,但始终以最小的数字重新开始,意味着如果 1 不存在,它可以从 2 开始)
  • 2_NC(在同一组 (NC) 中跟进,但现在在上一个号码之后的下一个号码上
  • 0_NC(以数字0结尾)
excel vba sorting excel-2010 uipath
1个回答
0
投票

您可以将您的工作分为 2 个任务:a) 如何排序 b) 如何说出确切的顺序。

任何库排序例程都会实现或多或少复杂的排序算法(冒泡排序、快速排序、堆排序等)。在排序过程中,对两个对象进行比较,以回答这两个对象中哪一个“先出现”的问题。对于字符串,您通常使用字母顺序(这已经引起了几个问题,例如区分大小写、非 7 位 Ascii 字符等),对于数字,您比较值。当您想要对文件进行排序时,您可以有不同的标准:名称、大小、日期...

现在的重点是,无论您如何比较对象,排序算法本身都保持不变。因此,最常见的实现是排序例程调用一个函数来回答两个对象中哪一个较小(= 首先)的问题。通常,如果第一个对象较小,则该函数返回负数;如果第二个对象较小,则该函数返回正数;如果两者相同,则返回 0。

由于工作簿中只有几张工作表(是的,对于排序而言,即使 100 张工作表也是一个很小的数字),因此简单的冒泡排序就可以了。在评论中链接的问题中(Excel VBA:按字母数字顺序对工作表进行排序),使用了以下代码(我稍作修改)

Sub SortWorksheets()
    Dim i As Long, j As Long
    For i = 1 To Worksheets.Count - 1
        For j = i + 1 To Worksheets.Count 
            If Worksheets(j).Name < Worksheets(i).Name Then
                Worksheets(j).Move before:=Worksheets(i)
            End If    
        Next j
    Next i
End Sub

现在例程本身就回答了哪个工作表“较小”的问题:它直接比较工作表名称。现在让我们将此比较转移到一个函数中:

            If compare(Worksheets(j).Name, Worksheets(i).Name) < 0 Then
                Worksheets(j).Move before:=Worksheets(i)
            End If    

并且有一个功能

Function compare(name1 As String, name2 As String) as Long
    compare = Iif(name1 < name2, -1, 1)
End Function

功能完全相同,但比较是“外包”的。如果您现在想要有不同的顺序逻辑,您所要做的就是更改该比较函数。在你的情况下,可能是这样的:

Function compare(name1 As String, name2 As String) As Long

    ' (1) Handle the YTD-Case:
    If Left(name1, 3) = "YTD" And Left(name2, 3) <> "YTD" Then
        compare = -1
    ElseIf Left(name1, 3) <> "YTD" And Left(name2, 3) = "YTD" Then
        compare = 1
    Else
        ' Compare the names without the leading number
        Dim pieces1() As String, pieces2() As String
        pieces1 = Split(name1, "_")
        pieces2 = Split(name2, "_")
    
        If UBound(pieces1) > 0 And UBound(pieces2) > 0 Then
            If pieces1(1) <> pieces2(1) Then
                ' different groups
                compare = IIf(pieces1(1) < pieces2(1), -1, 1)
            Else
                ' Same group, compare numbers
                If pieces1(0) = "0" Then
                    compare = 1
                    Exit Function
                ElseIf pieces2(0) = "0" Then
                    compare = -1
                    Exit Function
                Else
                    compare = Val(pieces1(0)) - Val(pieces2(0))
                End If
            End If
        Else
            ' Whatever that is: Compare names directly
            compare = IIf(name1 < name2, -1, 1)
        End If
    End If
End Function
© www.soinside.com 2019 - 2024. All rights reserved.