【问题标题】:How to sort a list of data based on three columns in the right order?如何根据三列以正确的顺序对数据列表进行排序?
【发布时间】:2019-09-15 00:10:11
【问题描述】:

您会在下面看到一段代码,用于: 首先对数据列表进行排序,首先基于 Entity 列,第二个基于 GREN 列,第三个基于 IC 列。然后编译具有相同Entity、GREN和IC列的数据。

由于某种原因,我在运行代码时收到以下错误:

运行时错误“1004”:对象“_Global”的方法“Range”失败。

对其他列进行排序并没有失败,当我使用较少的数据时,它似乎工作得很好。有谁明白出了什么问题?更重要的是如何解决它?

Sub itest()

Dim EntityCol As Long, GRENCol As Long, ICCol As Long, ValueCol As Long, i As Long
Dim firstrow As Long, lastrow As Long, rngData As Range

Worksheets("FC_OUTPUT").Activate
Application.ScreenUpdating = False

EntityCol = 4 ' column D
GRENCol = 8
ICCol = 9
ValueCol = 12 ' column L
firstrow = 7
lastrow = Cells(Rows.Count, EntityCol).End(xlUp).Row

With ActiveSheet.Sort
     .SortFields.Add Key:=Range(Cells(firstrow, EntityCol)), Order:=xlAscending
     .SortFields.Add Key:=Range(Cells(firstrow, GRENCol)), Order:=xlAscending
     .SortFields.Add Key:=Range(Cells(firstrow, ICCol)), Order:=xlAscending
     .SetRange Range(Cells(firstrow, 1), Cells(lastrow, 96))
     .Header = xlNo
     .Apply
End With


Set rngData = Range(Cells(firstrow, 1), Cells(lastrow, 96)) ' this line should be adjusted but you'll need to also adjust firstrow and lastrow

With rngData
' Here I'll start a loop for every row going from the end to the beginning, to prevent issues when removing rows
    For i = lastrow To firstrow Step -1
    ' Here I'll use the If statement to check if the values are the same as the previous row

        If .Cells(i, EntityCol) = .Cells(i - 1, EntityCol) And _
                .Cells(i, GRENCol) = .Cells(i - 1, GRENCol) And _
                .Cells(i, ICCol) = .Cells(i - 1, ICCol) Then
            ' This is where you'll do your addition and delete
            .Cells(i - 1, ValueCol).Value2 = .Cells(i - 1, ValueCol) + .Cells(i, ValueCol)
            .Rows(i).Delete
        End If
    Next i
End With

End Sub

【问题讨论】:

    标签: excel vba sorting columnsorting


    【解决方案1】:

    我会这样做:

    Sub tgr()
    
        Const lEntityCol As Long = 4    'Column D
        Const lGRENCol As Long = 8      'Column H
        Const lICCol As Long = 9        'Column I
        Const lValueCol As Long = 12    'Column L
        Const lDataStartRow As Long = 7 'Actual data (not headers) starts on row 7
    
        Dim ws As Worksheet
        Dim rData As Range
        Dim rDel As Range
        Dim hUnq As Object
        Dim aData As Variant
        Dim sTemp As String
        Dim sDelim As String
        Dim i As Long
    
        Set ws = ActiveWorkbook.Worksheets("FC_OUTPUT")
        Set rData = ws.Range("A" & lDataStartRow & ":CR" & ws.Cells(ws.Rows.Count, lEntityCol).End(xlUp).Row)
        Set hUnq = CreateObject("Scripting.Dictionary")
        sDelim = "|"    'This is a character that will not be in your data
    
        With rData
            If .Row < lDataStartRow Then Exit Sub   'No data
            .Sort Key1:=Intersect(.Cells, ws.Columns(lEntityCol)), Order1:=xlAscending, _
                  Key2:=Intersect(.Cells, ws.Columns(lGRENCol)), Order2:=xlAscending, _
                  Key3:=Intersect(.Cells, ws.Columns(lICCol)), Order3:=xlAscending, _
                  Header:=xlNo
            aData = .Value
        End With
    
        For i = LBound(aData, 1) To UBound(aData, 1)
            If Len(Trim(aData(i, lEntityCol))) > 0 _
            And Len(Trim(aData(i, lGRENCol))) > 0 _
            And Len(Trim(aData(i, lICCol))) > 0 Then
                sTemp = LCase(Trim(aData(i, lEntityCol))) & sDelim & LCase(Trim(aData(i, lGRENCol))) & sDelim & LCase(Trim(aData(i, lICCol)))
                If Not hUnq.exists(sTemp) Then
                    'New unique combination of Entity, GREN, and IC found
                    hUnq.Add sTemp, sTemp
    
                    'Get the total sum of values for the unique combination
                    rData.Cells(i, lValueCol).Value = WorksheetFunction.SumIfs(ws.Columns(lValueCol), _
                                                                               ws.Columns(lEntityCol), aData(i, lEntityCol), _
                                                                               ws.Columns(lGRENCol), aData(i, lGRENCol), _
                                                                               ws.Columns(lICCol), aData(i, lICCol))
                Else
                    'Not a new unique combination, add it to the list of rows to be deleted
                    If rDel Is Nothing Then Set rDel = rData.Cells(i, 1) Else Set rDel = Union(rDel, rData.Cells(i, 1))
                End If
            End If
        Next i
    
        If Not rDel Is Nothing Then rDel.EntireRow.Delete
    
    End Sub
    

    【讨论】:

    • 排序部分似乎很完美(谢谢!)。然而,当我检查它是否对数据求和时,它只删除了找到匹配项的行。
    • @DutchDandy 它的总和符合我的预期。您能否提供无法求和的示例数据?
    • @DutchDandy 不求和的原因是因为定义的值列(L 列,标记为Total)中没有任何值,所以实际上没有什么可以求和。那是正确的值列吗?如果是,为什么它没有任何值?它应该是后续日期列中所有值的总和吗?
    • @DutchDandy 该工作簿中还有一堆命名范围会导致#REF! 错误。如果命名范围从不同的工作簿中提取信息,则该数据未包含在您与我共享的内容中。但是,数据中似乎没有任何公式,因此命名范围似乎并没有被使用。仍然存在为什么您的 Total col 实际上没有任何值的问题,这就是为什么没有求和的原因。
    • 我也尝试过将 lValueCol 定义为第 13 列,不幸的是没有成功。你是对的,所有后续日期列也应该相加,但我想我可能想分别解决每个问题。
    猜你喜欢
    • 1970-01-01
    • 2022-01-02
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多