简体   繁体   中英

CountIFs in Excel whit VBA Code is very slow

I'm try to use the VBA code for first time, I did a lot of search before to write these draft code, but one piece It isn't work well. I used the Application.WorkSheetFunction.CountIfs but the code It is very slow, I need to read a Table with 140.000 row and 31 columns, the table with criteria for countif have 6000 rows and 13 columns.

The code of Sheet2.Cells(x, 17), Sheet2.Cells(x, 14) and Sheet2.Cells(x, 17) It is wrong, but I can't found the problem

Follow the piece of code that I use to countIfs

x = 2 y = Application.CountA(Range("A:A"))

Dim Submit_Date As Range
Dim GU As Range
Dim Legal_Entity_Country As Range
Dim Media_Type As Range
Dim Doc_Status As Range
Dim Approval_Date As Range
Dim Month_Create As Range
Dim FY As Range
Dim Status As Range

Set Submit_Date = Range("Table1[[#All],[Submit_Date]]")
Set GU = Range("Table1[[#All],[GU]]")
Set Legal_Entity_Country = Range("Table1[[#All],[Legal_Entity_Country]]")
Set Media_Type = Range("Table1[[#All],[Media_Type]]")
Set Doc_Status = Range("Table1[[#All],[Doc_Status]]")
Set Approval_Date = Range("Table1[[#All],[Approval_Date]]")
Set Month_Create = Range("Table1[[#All],[Month_Create]]")
Set FY = Range("Table1[[#All],[FY]]")
Set Status = Range("Table1[[#All],[Status]]")

For x = 2 To y
    With Application.WorksheetFunction
        Sheet2.Cells(x, 10) = _
            .Sum(.CountIfs(Month_Create, Sheet2.Cells(x, 3), _
                           FY, Sheet2.Cells(x, 5), _
                           GU, Sheet2.Cells(x, 6), _
                           Legal_Entity_Country, Sheet2.Cells(x, 7), _
                           Media_Type, Sheet2.Cells(x, 8), _
                           Doc_Status, Sheet2.Cells(x, 9), _
                           Status, Sheet2.Cells(1, 10)), _
                 .CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), _
                           GU, Sheet2.Cells(x, 6), _
                           Legal_Entity_Country, Sheet2.Cells(x, 7), _
                           Media_Type, Sheet2.Cells(x, 8), _
                           Doc_Status, Sheet2.Cells(x, 9), _
                           Status, Sheet2.Cells(1, 10)), _
                 .CountIfs(Approval_Date, ">" & Sheet2.Cells(x, 2), _
                           Month_Create, Sheet2.Cells(x, 3), _
                           FY, Sheet2.Cells(x, 5), _
                           GU, Sheet2.Cells(x, 6), _
                           Legal_Entity_Country, Sheet2.Cells(x, 7), _
                           Media_Type, Sheet2.Cells(x, 8), _
                           Doc_Status, Sheet2.Cells(x, 9), _
                           Status, Sheet2.Cells(1, 13)), _
                 .CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), _
                           Approval_Date, ">=" & Sheet2.Cells(x, 1), _
                           GU, Sheet2.Cells(x, 6), _
                           Legal_Entity_Country, Sheet2.Cells(x, 7), _
                           Media_Type, Sheet2.Cells(x, 8), _
                           Doc_Status, Sheet2.Cells(x, 9), _
                           Status, Sheet2.Cells(1, 13)))
         Sheet2.Cells(x, 11) = .Sum(.CountIfs(Month_Create, Sheet2.Cells(x, 3), FY, Sheet2.Cells(x, 5), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 11)), .CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 11)))
         Sheet2.Cells(x, 12) = .Sum(.CountIfs(Month_Create, Sheet2.Cells(x, 3), FY, Sheet2.Cells(x, 5), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 12)), .CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 12)))
'         Sheet2.Cells(x, 13) = .Sum(.CountIfs(Month_Create, Sheet2.Cells(x, 3), Approval_Date, "<=" & Sheet2.Cells(x, 2), FY, Sheet2.Cells(x, 5), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 13)), .CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), Month_Approved, Sheet2.Cells(x, 3), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 13)))
'         Sheet2.Cells(x, 14) = .Sum(.CountIfs(Month_Create, Sheet2.Cells(x, 3), FY, Sheet2.Cells(x, 5), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 14)), .CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), Month_Approved, Sheet2.Cells(x, 3), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 14)))
         Sheet2.Cells(x, 15) = .Sum(Sheet2.Cells(x, 10), Sheet2.Cells(x, 11), Sheet2.Cells(x, 12), Sheet2.Cells(x, 13), Sheet2.Cells(x, 14))
         Sheet2.Cells(x, 16) = .CountIfs(Month_Create, Sheet2.Cells(x, 3), FY, Sheet2.Cells(x, 5), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9))
'         Sheet2.Cells(x, 17) = .Sum(.CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), Month_Approved, Sheet2.Cells(x, 3), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 14)), .CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 11)), .CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 12)))
         Sheet2.Cells(x, 18) = .Sum(.CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 10)), .CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), Approval_Date, ">=" & Sheet2.Cells(x, 1), GU, Sheet2.Cells(x, 6), Legal_Entity_Country, Sheet2.Cells(x, 7), Media_Type, Sheet2.Cells(x, 8), Doc_Status, Sheet2.Cells(x, 9), Status, Sheet2.Cells(1, 13)))
         Sheet2.Cells(x, 19) = .Sum(Sheet2.Cells(x, 16), Sheet2.Cells(x, 17), Sheet2.Cells(x, 18)) = Sheet2.Cells(x, 15)
    End With
Next x

Regards André

Looking at what the criteria are, I can tell you that you would see a huge increase in performance by changing them. Aside from the first or second criteria, they all are checking for equality across the same several criteria.

Add a value, in a new column that concatenates (with a delimiter) the cells to check. Then check them against the criteria similarly concatenated. An example is that they are all checking for each row's GU, Legal_Entity_Country, Media_Type, Doc_Status and Status being equal to certain values. So, join those and then check the join against the joined criteria.

So, if you want to use formulae, add a column such as "=CONCATENATE(A1,"|",B1,"|",C1,"|",D1)", where A1,B1 etc are the relevant values for the row. Then your criteria will be the relevant criteria similarly concatenated. Then, change your countifs to be eg =COUNTIFS( _ ,combinedColumn,combinedCritera).

Doing this will reduce the number of lookups significantly, and accordingly increase the speed.

To change it in the macro do something like (just an example extract from your code in the question)

Old:

.CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), _
                           GU, Sheet2.Cells(x, 6), _
                           Legal_Entity_Country, Sheet2.Cells(x, 7), _
                           Media_Type, Sheet2.Cells(x, 8), _
                           Doc_Status, Sheet2.Cells(x, 9), _
                           Status, Sheet2.Cells(1, 10)), _

New:

Dim combinedCriterion As String
combinedCriterion = Join(Array(Sheet2.Cells(x, 7),Sheet2.Cells(x, 8),Sheet2.Cells(x, 9),Sheet2.Cells(1, 10)),"|")
     .CountIfs(Submit_Date, "<" & Sheet2.Cells(x, 1), _
                               combinedColumn, combinedCriterion)
...etc

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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