提问人:Nine Crowns 提问时间:11/7/2023 最后编辑:Nine Crowns 更新时间:11/8/2023 访问量:66
如何根据工作表名称按字母顺序重新排列 Excel 工作表,但我有一个特定的规则,如果工作表名称包含“YTD”,那么它始终是 1st
how to rearrange excel sheet in alphabetical order based on sheetname,but i have one specific rule if sheet name contain "YTD" then its always 1st
问:
帮助我根据工作表名称按字母顺序重新排列 excel 工作表, 但是我有一个特定的规则,如果工作表名称包含“YTD”,那么它始终是第一位的 如果我们有数字 0,那么它将始终位于其组的末尾
谢谢
输入:
- 年初至今-AA-
- 1_AB
- 3_AB
- 2_AB
- 0_AB
- 2_NC
- 0_NC
- 1_NC
我想这样安排它:
- YTD-AA(单词中带有“YTD”的 excel 工作表将永远是第一个)
- 1_AB(按 A-Z 的顺序找到的 LEAST 数字和 FIRST 数字跟进)
- 2_AB(由与前一个(AB)相同的小组跟进)
- 3_AB
- 0_AB(在同一组 (AB) 上以数字 ZERO '0' 结尾)
- 1_NC (在 A - B - C 等之后继续下一组,但始终以最小数字重新开始,这意味着如果不存在 1,它可以从 2 开始)
- 2_NC(在同一组 (NC) 中跟进,但现在在前一个之后的下一个号码上
- 0_NC (以数字 0 结尾)
答:
1赞
FunThomas
11/7/2023
#1
您可以将您的工作分为 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
评论