【问题标题】:SUMIFS with multiple sheets/multiple criteria具有多个工作表/多个标准的 SUMIFS
【发布时间】:2018-10-25 12:10:59
【问题描述】:

我有一个 SUMIFS 函数。我想把这个函数翻译成VBA代码,但是我不能让它工作。

我的 Excel 文件的两张图片展示了一个简化的示例。

我有一个输入选项卡来提供有关在不同日期买卖的几种产品的信息。产品名称显示在 ISIN 下方。我想在特定条件下将输入表中的数量汇总到输出表中。

我有以下需要满足的论点:

Dim Arg1 As Range 'the range i want to sum : so quantity

Dim Arg2 As Range 'criteria for range : Dates
Dim Arg3 As Range 'the criteria (range)

Dim Arg4 As Range 'criteria for range : ISIN
Dim Arg5 As Range 'the criteria (range)

Dim Arg6 As Range 'criteria for range : Type
Dim Arg7 As Range 'the criteria (range)

Set Arg1 = ThisWB.Sheets("INPUT").Range("A1:A13")

Set Arg2 = ThisWB.Sheets("INPUT").Range("B1:B13")
Set Arg3 = ThisWB.Sheets("OUTPUT").Range("A4:A8")

Set Arg4 = ThisWB.Sheets("INPUT").Range("C1:C13")

'these are rows (so ISIN codes vertically)
Set Arg5 = ThisWB.Sheets("OUTPUT").Range("B2:E2")

Set Arg6 = ThisWB.Sheets("INPUT").Range("D1:D13")

'This is the criteria that only values under Buy should be summed
Set Arg7 = ThisWB.Sheets("OUTPUT").Range("B2")

我想对输出文件中每个 ISIN 代码/产品的数量求和。

结果应显示在输出表的红色轮廓框中。

如果日期和购买任务与输出文件中显示的相对应,就会发生这种情况

我不知道如何正确调暗和设置变量。我也不知道代码将如何运行输出文件中显示的所有日期和 ISIN 代码。

这是迄今为止我的真实 Excel 工作表的代码。不适用于我之前展示的简化版。

Option Explicit

Sub InsertQ()
'Sum Quantities

    'Declare variables
    Dim lastRowData, lastRowInput, I, x, pasteRow As Integer

    Dim shtInput As Worksheet
    Dim shtData As Worksheet

    Dim Arg1 As Range 'the range i want to sum : so quantity

    Dim Arg2 As Range 'criteria for range : Dates
    Dim Arg3 As Range 'the criteria (range)

    Dim Arg4 As Range 'criteria for range : ISIN
    Dim Arg5 As Range 'the criteria (range)

    Dim Arg6 As Range 'criteria for range : Type
    Dim Arg7 As Range 'the criteria (range)

    'Set variables
    Set shtData = Sheets("OUTPUT")
    Set shtInput = Sheets("INPUT")
    lastRowData = shtData.Range("B4").End(xlDown).Row
    lastRowInput = shtInput.Range("A1").End(xlDown).Row
    pasteRow = 5

    Set Arg1 = shtInput.Range("G1:G1048576")

    Set Arg2 = shtInput.Range("J1:J1048576")
    Set Arg3 = shtData.Range("A4:A20")

    Set Arg4 = shtInput.Range("AF1:AF1048576")
    Set Arg5 = shtData.Range("B2:E2")

    Set Arg6 = shtInput.Range("E1:E1048576")
    Set Arg7 = shtData.Range("A2")

    'Deactivate Screen for purpose of performance
    Application.ScreenUpdating = False

    'Code

    For I = 2 To lastRowData
        For x = 2 To lastRowInput
        shtData.Cells(x, I) = _
          Application.WorksheetFunction.SumIfs(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)
        Next x

        pasteRow = pasteRow + 1

    Next I

    'Formatting
    lastRowData = shtData.Range("B4").End(xlDown).Row
    shtData.Range("B4:XFD" & lastRowData).NumberFormat = "0.00"
    shtData.Range("E5:E" & lastRowData).NumberFormat = "0.00"

    'Confirm to user
    Application.ScreenUpdating = True

    shtData.Range("A1").Select

End Sub

【问题讨论】:

  • =SUMIFS(INPUT!$A:$A;INPUT!$B:$B;OUTPUT!$A4;INPUT!$C:$C;OUTPUT!C$2;INPUT!$D: $D;输出!$B$1)
  • 在您启动宏之前,OUTPUT 表中是否已有数据?我的意思是日期和 ISIN 已经存在了吗?那么只有红色边框区域必须由程序填充?还是该程序会生成整个工作表?
  • 一年中所有日子的日期,ISIN 代码已经在输出选项卡中。所以只需要填写红色字段
  • 看我的第二个答案。我为图片中的示例添加了 VBA 解决方案。
  • 如果您的问题已解决,请将其标记为已解决:Accepting Answers: How does it work?

标签: excel vba sumifs


【解决方案1】:

这对于数据透视表来说是一项不错的任务。假设以下数据……

将导致... 请原谅德语截图

  1. 选择输入表中的所有数据。
  2. 插入数据透视表(从功能区中选择插入 › 数据透视表)
  3. 然后配置 Pivot
    • Type 添加到过滤器
    • ISIN 添加到列
    • Dates 添加到行
    • Quantity 添加到值中
  4. 在单元格 B2 中选择 Buy 并完成。

【讨论】:

  • 非常感谢您的帮助!但我有在 VBA 中执行此操作的说明。您能否为我提供此数据的 vba 代码?然后我可以自己将其更改为我的真实文件。
  • a) VBA 通常比 Pivot 慢(使用内置功能可以使用 VBA 不能使用的多线程)。 b)VBA 比这要多得多。而且您的代码与 VBA 中的结果相去甚远。因此,完成它不仅需要 2 行。 c) 如果您有更好的解决方案,“我有指示……” 并不是真正的争论。这些说明可能是不了解或不考虑数据透视表的结果。如果已经有一个完美的轮子,你就不会重新发明轮子。
  • 我明白你在说什么。但我真的必须使用VBA。你能帮我解决这个问题吗?我已经插入了我需要的参数。我只需要定义变量的代码的开头和正确公式化的 SumIfs 代码
  • 很抱歉,但基本上您要求我们为您完成(几乎)所有工作。你只有一个变量声明。我告诉过你这不是用两行代码完成的。你需要的比你想象的要多得多。 • 除此之外,您没有提出任何问题 (Why is “Can someone help me?” not an actual question?),所以这是题外话。我能给你的最好建议是:使用数据透视表
  • 我将我为原始文件制作的代码插入到问题中,也许您可​​以看到那里出了什么问题。
【解决方案2】:

这里不需要 VBA。你可以用一个简单的公式来做到这一点。

将以下内容复制到您的红色范围内:

=SUMIFS(INPUT!$A:$A,INPUT!$B:$B,OUTPUT!$A:$A,INPUT!$C:$C,OUTPUT!$2:$2,INPUT!$D:$D,OUTPUT!$B$1)

或使用 VBA 自动编写:

Option Explicit

Sub WriteFormula()
    With Worksheets("OUTPUT")
        With .Range("C4", .Cells(.Cells(.Rows.Count, "A").End(xlUp).Row, .Cells(2, .Columns.Count).End(xlToLeft).Column))
            .Formula = "=SUMIFS(INPUT!$A:$A,INPUT!$B:$B,OUTPUT!$A:$A,INPUT!$C:$C,OUTPUT!$2:$2,INPUT!$D:$D,OUTPUT!$B$1)"
            'if needed as values not forumlas uncomment the following line
            '.Value = .Value
        End With
    End With
End Sub

【讨论】:

    【解决方案3】:

    因此,通过在构建函数Application.WorksheetFunction.SumIfs() 中使用 VBA 可以实现您想要的。我想这不是执行 SUMIFS 的最快方法,但它是 excel 函数“=SUMIFS()”的复制。

    通知,根据我的理解,标准值在每个标准位置只能是一个值(而不是范围)......因此我们需要根据需要循环遍历每个标准值(标准 1 和标准 2)在SUMIFS application 中只有一个值)。这是在 VBA 中通过“For each .. In ...”循环完成的。

    Application.WorksheetFunction.SumIfs(Sum_range, Criteria_range1, Criteria1, Criteria_range2, criteria2, etc..)
    

    工作表“输入”:

    工作表“输出”:

    代码复制了上图中“输出”工作表中的右表。我们正在使用另一个工作表“输入”中的一些范围,以及我们想要结果的这个工作表“输出”中的一些范围。 (注意在 excel 中您可以使用范围作为条件 1,在 VBA 中这是不可能的。)

    颜色是我们在工作表中使用的 =sumifs 范围。这些在代码中被复制。

    VBA 代码:

    Option Explicit
    Sub Sumifs()
    
    Dim InputSheet As Worksheet
    Dim OutputSheet As Worksheet
    
    Set InputSheet = ActiveWorkbook.Worksheets("Input")
    Set OutputSheet = ActiveWorkbook.Worksheets("Output")
    
    Dim Arg1 As Range 'the range i want to sum : so quantity
    
    Dim Arg2 As Range 'criteria for range : Dates
    Dim Arg3 As Variant 'the criteria (range)
    
    Dim Arg4 As Range 'criteria for range : ISIN
    Dim Arg5 As Variant 'the criteria (range)
    
    Dim Arg6 As Range 'criteria for range : Type
    Dim Arg7 As Variant 'the criteria (range)
    
    Set Arg1 = InputSheet.Range("A2:A14") 'Sum_range
    
    Set Arg2 = InputSheet.Range("B2:B14") 'Criteria_range1
    Set Arg3 = OutputSheet.Range("A3:A7") 'Criteria1
    
    Set Arg4 = InputSheet.Range("C2:C14") 'Criteria_range2
    Set Arg5 = OutputSheet.Range("C2:F2") 'Criteria2 - these are rows (so ISIN codes vertically)
    
    Set Arg6 = InputSheet.Range("D2:D14") 'Criteria_range3
    Set Arg7 = OutputSheet.Range("B1")    'Criteria3 - This is the criteria that only values under Buy should be summed
    
    
    Dim cell_date As Variant
    Dim cell_ISIN As Variant
    Dim cell_Type As Variant
    Dim cell_ISIN_column As Long
    Dim cell_date_row As Long
    
    For Each cell_ISIN In Arg5 'Loop through all ISIN codes in range setin Arg 5
        cell_ISIN_column = cell_ISIN.Column 'Get current column for ISIN
        For Each cell_date In Arg3 'Loop through all Dates in range set in Arg3
            cell_date_row = cell_date.Row 'Get current row for date
                    'My understanding is that the criteria values can only be only one single value at each criteria... therefore we need to loop through each criteria value (Arg3 and Arg5 needs to have only one value in SUMIFS application).
                    OutputSheet.Cells(cell_date_row, cell_ISIN_column) = Application.WorksheetFunction.Sumifs(Arg1, Arg2, cell_date, Arg4, cell_ISIN, Arg6, Arg7)
        Next cell_date 'go to next date
    Next cell_ISIN 'go to next ISIN
    
    End Sub
    

    Credit to D_Bester at SO and more inspiration/explantions can be found here in his thread :)

    【讨论】:

    • 自从 OP 声明 “我在多年期间有 800 个 ISIN 代码/产品。” 他担心速度,你必须注意每个 向单元格写入 操作需要很多时间。这意味着至少 584000 次写入操作(为期 2 年)。虽然该答案是正确的并且会起作用,但它比编写公式(一次写入操作)并在必要时将其转换为值(一次写入操作)要慢得多。
    • 我同意你的观点,即迭代次数 + VBA sumif,对于更大的数据,本质上会变慢,你的评论是相关的。我可以看到一些好处,由于有一组范围,修改起来相对容易,如果你想添加到这些计算中,你可以稍后使用相同的变量,这一切都在 VBA [并不意味着它总是好的或程序的最佳使用:),但可能在某种程度上满足 OP 的意图]。除此之外,我环顾四周,看到公式如何工作的例子很少,所以我认为这是一个巨大的挑战和展示的好机会:)。
    • 谢谢你,这行得通!如果我想更改将值传输到的单元格,我该怎么做?例如,现在输入和输出表中的数量值都从第 2 行开始。但是现在我希望输出表中的结果在从 B4 开始的范围内
    • 请将此标记为已接受/已解决。 Accepting Answers: How does it work? 所以其他人可以看到问题已解决。投票按钮下方的灰色标记/代码。谢谢:)
    • 如果您只想调整输出范围,您可以使用类似:OutputSheet.Cells(cell_date_row, cell_ISIN_column).Offset(1, -1) = Application.WorksheetFunction.Sumifs(Arg1, .....),在这种情况下,输出数字将从单元格 B4 开始。所以我们在输出中添加.Offset(row, column)
    猜你喜欢
    • 2023-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多