繁体   English   中英

Excel数组公式对条件求和然后排序

[英]Excel array formula to sum for criteria then sort

寻找一个excel数组公式来对每个“代码”的“权重”求和,并按权重对“代码”进行排序。

    |   A   |    B   |   C   |   D   |    E    |
 |1 |  Code | Weight |       |  Code |TotWeight|
 |2 |  444  |   30   |       |  444  |   50    |
 |3 |  333  |   10   |       |  222  |   40    |    
 |4 |  222  |   10   |       |  333  |   40    |
 |5 |  444  |   10   |       |  555  |   20    |        
 |6 |  444  |   10   |
 |7 |  222  |   30   |
 |8 |  333  |   20   |
 |9 |  555  |   20   |
 |10|  333  |   10   |

Cols A 和 B 是输入,D 和 E 是输出。

虽然这可能最终可以通过复杂且计算密集型的数组公式实现,但出于所有意图和目的,您实际上是在尝试使用聚合 SUM、GROUP BY 和 ORDER BY 子句来完成数据库 SELECT 语句。 就像是,

SELECT code, weight FROM
 (SELECT cw.code, Sum(cw.weight) AS weight
  FROM tblCodeWeights AS cw
  GROUP BY cw.code)
ORDER BY weight DESC, code;

我建议使用 ADODB.Connection 到工作表的 VBA 子程序,它可以产生您想要实现的结果。 下面的代码很冗长,可能会被删减一点,但操作的每个方面都得到处理,应该是不言自明或易于研究的。

Option Explicit

Sub sortedFilteredSums()
    Dim cnx As Object, rs As Object
    Dim sWS1 As String, sWB As String, sCNX As String, sSQL As String
    Dim ws1TBLaddr As String

    With Worksheets("Sheet8")
        ws1TBLaddr = .Cells(1, 1).CurrentRegion.Address(0, 0)
        sWS1 = Worksheets("Sheet8").Name
    End With

    sWB = ThisWorkbook.FullName
    sCNX = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sWB _
        & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
    Debug.Print sCNX

    Set cnx = CreateObject("ADODB.Connection")
    Set rs = CreateObject("ADODB.Recordset")

    cnx.Open sCNX

    sSQL = "SELECT [code], [weight] FROM ("
    sSQL = sSQL & " SELECT cw.[code], SUM(cw.[weight]) AS [weight]"
    sSQL = sSQL & " FROM [" & sWS1 & "$" & ws1TBLaddr & "] cw"
    sSQL = sSQL & " GROUP BY cw.code"
    sSQL = sSQL & ") ORDER BY [weight] DESC, [code]"

    Debug.Print sSQL
    'SELECT code, weight FROM
    ' (SELECT cw.code, Sum(cw.weight) AS weight
    '  FROM tblCodeWeights AS cw
    '  GROUP BY cw.code)
    'ORDER BY weight DESC, code;

    rs.Open sSQL, cnx

    With Worksheets("Sheet8")
        .Range("D1").Resize(1, 2) = Array("code", "totweight")
        .Range("D2").CopyFromRecordset rs
    End With

    rs.Close: Set rs = Nothing
    cnx.Close: Set cnx = Nothing

End Sub

请注意,这不能在尚未保存的工作簿上执行; 例如,不在新的无标题工作簿上。 您的结果应该类似于以下内容。

sum_group_order

用于此示例的测试工作簿暂时可从以下位置获得:

ADO Select Sum Group By.xlsb

正如@Jeeped 所解释的,这个请求非常复杂。 然而,它可以在工作列的帮助下通过公式来实现。

假设您的数据位于A1:B11

标题列CTotal.Weight并在C2:C11输入此公式:

=IF(COUNTIF($A$1:$A2,$A2)>1,"", SUMIF($A$1:$A$11,$A2,$B$1:$B$11))

然后使用位于F2:G11的预期结果输入以下公式:

F2:F11=IF(EXACT($G2,""),"",INDEX($A$1:$A$11,MATCH($G2,$C$1:$C$11,0)))

G2:G11=IFERROR(LARGE($C$1:$C$11,COUNTA($F$1:$F1)),"")

图。1 图。1

上述公式适用于问题中提供的数据。

但是,如果代码具有相同的总重量,则需要额外的工作栏。

标题列D作为Rank并输入此公式以对总重量进行排名(见图 2):

D2:D11

=IFERROR(RANK.EQ($C2,$C$2:$C$11, 0) +COUNTIF($D$1:$D1,RANK.EQ($C2,$C$2:$C$11, 0)),"")

F2:G11处的公式应该是这些:

F2:F11=IFERROR(INDEX($A$1:$A$11,MATCH(COUNTA($F$1:$F1),$D$1:$D$11,0)),"")

G2:G11=IF(EXACT($F2,""),"",SUMIF($A$1:$A$11,$F2,$B$1:$B$11))

在此处输入图片说明 图2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM