Excel VBA SUMIF超级慢速代码

时间:2013-12-06 21:49:01

标签: excel-vba vba excel

我的SUMIF运行真的很慢。我的数据有14,800行和39列。

我执行以下操作:

      Application.ScreenUpdating = False

Application.DisplayStatusBar = False

Application.Calculation = xlCalculationManual

Application.EnableEvents = False

ActiveSheet.DisplayPageBreaks = False

编辑添加可能与SUMIF命令交互的更多可能相关的代码

这可能与速度问题有关,所以我会提到它。我让用户从存储报告的任何地方打开文件。然后该文件保持打开状态。也许这是一个问题。我不知道它是否应该采用其他方式..比如我关闭它但是记住地址还是什么?

    FilterType = "Text Files (*.txt),*.txt," & "Comma Separated Files (*.csv),*.csv," & "ASCII Files (*.asc),*.asc," & "All Files (*.*),*.*"

        FilterIndex = 4

        Title = "File to be Selected"

        File_path = Application.GetOpenFilename(FileFilter:=FilterType, FilterIndex:=FilterIndex, Title:=Title)

            If File_path = "" Then

                MsgBox "No file was selected."

            Exit Sub

            End If



        Set wbSource = Workbooks.Open(File_path)
        Original_Name = ActiveWorkbook.Name
        If ActiveSheet.AutoFilterMode Then
            ActiveSheet.AutoFilterMode = False
        End If



     Set wb1 = ActiveWorkbook
    Set ws1 = wb1.Worksheets("Sheet1")

    With ws1

    FinalColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
    FinalRow = .Range("B" & .Rows.Count).End(xlUp).Row



    For j = 1 To FinalColumn
                        If .Cells(1, j).Value = "Effec.Date" Then
                                Effective_Date_Column = j
                        ElseIf .Cells(1, j).Value = "FolderId" Then
                                FolderId_column = j
                        ElseIf .Cells(1, j).Value = "FolderNotional" Then
                                 FolderNotional_column = j

                        End If
         Next j 




    'range_Total_Folder_Fixed = .Cells(2, Total_Folder_Column).Address & ":" & .Cells(FinalRow, Total_Folder_Column).Address

    range_FolderId_Fixed = .Cells(2, FolderId_column).Address & ":" & .Cells(FinalRow, FolderId_column).Address
     range_FolderId_Cell = .Cells(2, FolderId_column).Address(RowAbsolute:=False, ColumnAbsolute:=False)

    range_FolderNotional_Fixed = .Cells(2, FolderNotional_column).Address & ":" & .Cells(FinalRow, FolderNotional_column).Address

一切都在8-10秒内完成,直到我们来到下面的谎言。现在总时间跳到150秒。

  .Range(range_Total_Folder_Fixed).Formula = "=SUMIF(" & range_FolderId_Fixed & "," & range_FolderId_Cell & "," & range_FolderNotional_Fixed & ")"

我做错了吗?是否有更好(更有效)的方式来编写通用公式?

编辑:代码生成原始公式

我的代码中的一些excel工作表函数:

     .Range(range_Isnumber).Formula = "=(RIGHT(" & range_TradeId_cell & ",2)<> ""IB"")*1"
     .Range(range_Is_IB).Formula = "=(RIGHT(" & range_TradeId_cell & ",2)= ""IB"")*1"

     .Range(range_Exceptions).Formula = "=(SUMIF(" & range_FolderId_Fixed & "," & range_FolderId_Cell & "," & range_Isnumber_fixed & ")= COUNTIF(" & range_FolderId_Fixed & "," & range_FolderId_Cell & "))*1+(SUMIF(" & range_FolderId_Fixed & "," & range_FolderId_Cell & "," & range_Is_IB_fixed & ")= COUNTIF(" & range_FolderId_Fixed & "," & range_FolderId_Cell & "))*1  "
  .Range("C13").FormulaR1C1 = "=SUM(IF(FREQUENCY(MATCH([SCL_FL_2013_11_30.xlsx]Rest!R2C2:R2321C2,[SCL_FL_2013_11_30.xlsx]Rest!R2C2:R2321C2,0),MATCH([SCL_FL_2013_11_30.xlsx]Rest!R2C2:R2321C2,[SCL_FL_2013_11_30.xlsx]Rest!R2C2:R2321C2,0))>0,1))"

好像

 Range("I2")=SUMIF($H$2:$H$5,H2,$G$2:$G$5)

数据可能就像

RowG   RowH   RowI

Alice   1      4

Alice    3     4 

Bob      9     17

Bob     8      17

Dan      2      2

EDIT2:实施Sam的解决方案,我收到了错误:

   Set range_FolderId_Fixed = .Range(.Cells(2, FolderId_column), .Cells(FinalRow, FolderId_column))
   Set range_FolderId_Cell = .Range(.Cells(2, FolderId_column),.Cells(FinalRow, FolderId_column))
   Set range_FolderNotional_Fixed = .Range(.Cells(2, FolderNotional_column), .Cells(FinalRow, FolderNotional_column))
   Set range_Total_Folder_Fixed = .Range(.Cells(2, Total_Folder_Column), .Cells(FinalRow, Total_Folder_Column))

   .Range(range_Total_Folder_Fixed).Value = SumIf_func(range_FolderId_Fixed, range_FolderId_Cell, range_FolderNotional_Fixed)

我在下面的行中获得了一个类型应用程序定义或对象定义错误。

   .Range(range_Total_Folder_Fixed).Value = SumIf_func(range_FolderId_Fixed, range_FolderId_Cell, range_FolderNotional_Fixed)

我不知道下一步该做什么。

1 个答案:

答案 0 :(得分:1)

好的,这就是我想出来的

 Public Function SumIf_func(rng As Range, _
                            criteria As Range, _
                            sumRange As Range) As Variant()

Dim rngArr() As Variant
Dim sumArr() As Variant
Dim criteriaArr() As Variant
Dim returnArr() As Variant

Dim temp As Double

rngArr = rng.Value2
sumArr = sumRange.Value2
criteriaArr = criteria.Value2

If UBound(sumArr) <> UBound(rngArr) Then _
Err.Raise 12345, "SumIf_func", "Sum range and check range should be the same size"

If UBound(sumArr, 2) <> 1 Or UBound(rngArr, 2) <> 1 Then _
Err.Raise 12346, "SumIf_func", "Sum range and check range should be a single column"

ReDim returnArr(1 To UBound(criteriaArr), 1 To 1)

    For c = LBound(criteriaArr) To UBound(criteriaArr)

            returnArr(c, 1) = Application.WorksheetFunction.SumIf(rng, criteriaArr(c, 1), sumRange)                
    Next c

SumIf_func = returnArr

End Function

此功能有三个范围:

  • 要检查的范围
  • 标准的范围
  • 要求和的值
  • 的范围

要检查的范围和总和范围应该是相同的长度,并且只有1列。

返回的数组与条件数组的大小相同..

以下是一个使用示例:

Public Sub test_SumIf()

Dim ws As Worksheet

Set ws = Sheet1

Dim rng As Range, sumRng As Range, criteria As Range

Set rng = ws.Range("A1:A100")
Set sumRng = ws.Range("B1:B100")
Set criteria = ws.Range("C1:C10")

ws.Range("D1:D10").Value = SumIf_func(rng, criteria, sumRng)

End Sub