2013-12-06 5 views
0

У меня SUMIF работает действительно очень медленно. Мои данные имеют 14 800 строк и 39 столбцов.Excel VBA SUMIF Супер медленный код

я сделать следующее:

 Application.ScreenUpdating = False 

Application.DisplayStatusBar = False 

Application.Calculation = xlCalculationManual 

Application.EnableEvents = False 

ActiveSheet.DisplayPageBreaks = False 

отредактирован ADD более потенциально соответствующий код, который может быть взаимодействующий с командой SumIf

Это может иметь отношение к вопросу скорости, так что я буду упоминать Это. Я хочу, чтобы пользователь открыл файл, где бы они ни хранили отчет. Затем файл остается открытым. Возможно, это проблема. Я не знаю, должно ли это быть каким-то другим способом. Например, я закрываю его, но помню адрес или что-то в этом роде?

Все работает через 8-10 секунд, пока мы не поднимемся ниже. Теперь общее время прыгает до 150 секунд.

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

Я делаю что-то неправильно? Есть ли лучший (более эффективный) способ написать общую формулу?

EDIT: Код сгенерирован Сырая формула

Некоторые функции рабочего листа первенствовать в моем коде:

 .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: Реализация решения Сэма, я получаю ошибки:

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

ли Вы [режим вычисления изменения] (http://www.cpearson.com/excel/optimize.htm) к руководству на всех в макросе? Это может помочь ускорить его. – Sam

+0

@Sam Спасибо. Да, у меня есть это в руководстве в начале кода . – Amatya

+1

Вам нужны функции CountIf на листе? или вы были бы счастливы, если бы макрос просто ввел результат функции в диапазон? – Sam

ответ

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 

Эта функция принимает в трех диапазонах:

  • Диапазон для проверки
  • диапазон, в котором критерии
  • Диапазон, в котором значения для суммы:

Диапазон проверки и диапазон сумм должны быть одинаковой длины и иметь только одну колонку.

Возвращаемый массив будет иметь тот же размер, что и массив критериев.

Вот пример использования:

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 
+0

Спасибо большое! Это интересно, что мы должны вручную перевести его в цикл. Вероятно, на данный момент я использую 6 или 7 функций Excel, поэтому мне придется воссоздать каждую из этих функций, чтобы я мог заставить их зацикливаться на диапазоне, в котором я хочу. hmm .. – Amatya

+0

Было довольно быстро, когда я его протестировал. 16000 строк в каждом диапазоне заняли менее 6 секунд. Если 'SumIf' является шеей бутылки в вашем коде, то почему вы должны воссоздать другие функции? – Sam

+0

Я последовательно тестировал свой код для узких мест, и этот SumIf появился в первых 5% кода. Я еще не добрался до остальной части кода, но я предполагаю, что во всех других случаях, когда я использую формулу, все будет замедляться аналогичным образом. Они могут быть и другими. – Amatya