Нужно применять показатели в VBA с учетом нескольких условий - PullRequest
0 голосов
/ 20 апреля 2020

У меня есть таблица Excel с примерами записей ниже. Существует много случайных идентификаторов отчетов, которые я напечатал для report_id = 155. Я хочу подсчитать все записи Get_Days, где get_days меньше 7. Как и в следующем примере, есть 6 таких записей. Из этих 6 2 - pending_with Lead (последние 2 строки равны 0), 4 - pending_with Owner (1,2,3,6).

Таблица ввода в Sheet1:

 Report_ID  Get_Days  Pending_With
    155        15        Owner
    155        14        Owner
    155        13        Owner
    155        10        Owner
    155        9         Owner
    155        8         Owner
    155        7         Owner
    155        6         Owner
    155        3         Owner
    155        2         Owner
    155        1         Owner
    155        21        Owner
    155        20        Owner
    155        17        Owner
    155        16        Owner
    155        0         Lead
    155        0         Lead

Печать Таблица вывода в Sheet2:

Report ID  Get_Days_LessThan7   PendingOwnerLT7  PendingLeadLT7  
155             6                    4               2        

Ответы [ 2 ]

0 голосов
/ 20 апреля 2020

Попробуйте пожалуйста следующий код. Он не использует Sumproducts. Он работает только в памяти с использованием массивов и сбрасывает результат сразу, в конце кода. Ниже Sub принимает параметры и может быть вызван для любого ID:

Private Sub FindOutputTable(sh1 As Worksheet, sh2 As Worksheet, ID As String)
   Dim lastRow As Long, lastCol As Long, lastR2 As Long
   Dim arr1 As Variant, arr2 As Variant, i As Long, j As Long


   lastRow = sh1.Range("A" & Rows.count).End(xlUp).Row
   lastCol = sh1.Cells(1, Columns.count).End(xlToLeft).Column
   lastR2 = sh2.Range("A" & Rows.count).End(xlUp).Row
   arr1 = sh1.Range(sh1.Cells(2, 1), sh1.Cells(lastRow, lastCol)).value
   If lastR2 = 1 Then 'if the sheet is blank, the array will also include the headers
        ReDim arr2(1 To 2, 1 To 4)
   Else   'the array will contain only one row, keeping the necessary values
        ReDim arr2(1 To 1, 1 To 4)
   End If
   arr2(IIf(lastR2 = 1, 2, 1), 1) = ID' the row where ID will be returned is chosen according to the lastR value
   For i = 1 To UBound(arr1, 1)
        If arr1(i, 1) = ID Then
            If arr1(i, 2) < 7 Then
                arr2(IIf(lastR2 = 1, 2, 1), 2) = arr2(IIf(lastR2 = 1, 2, 1), 2) + 1
                If arr1(i, 3) = "Owner" Then
                    arr2(IIf(lastR2 = 1, 2, 1), 3) = arr2(IIf(lastR2 = 1, 2, 1), 3) + 1
                ElseIf arr1(i, 3) = "Lead" Then
                    arr2(IIf(lastR2 = 1, 2, 1), 4) = arr2(IIf(lastR2 = 1, 2, 1), 4) + 1
                End If
            End If
        End If
   Next
   If lastR2 = 1 Then 'For a blank sheet, the headers are also added
        sh2.Range("A1").Resize(UBound(arr2, 1), UBound(arr2, 2)).value = arr2
        sh2.Range("A1").Resize(, 4).value = Split("Report ID,Get_Days_LessThan7,PendingOwnerLT7,PendingLeadLT7", ",")
   Else   'Only the collected values will be returned
        sh2.Range("A" & lastR2 + 1).Resize(UBound(arr2, 1), UBound(arr2, 2)).value = arr2
   End If
End Sub

Пожалуйста, будьте осторожны и используйте свои листы (sheet1 и sheet2). Для тестирования я использовал активный лист и последний лист для возврата результата ...

Чтобы проверить это, используйте следующий код:

Sub testFindOutputTable()
    Dim sh1 As Worksheet, sh2 As Worksheet, ID As String

    ID = "155"
    Set sh1 = ActiveSheet                  'you may use here your sheet1
    Set sh2 = Worksheets(Worksheets.count) ' you will use here your sheet2
    FindOutputTable sh1, sh2, ID
End Sub

Вы также можете выполнить итерацию, в приведенном выше тестовом сабе между всеми вашими IDs. Если вы не понимаете, как, я могу помочь вам с примером. Все Ваши IDs должны быть введены в массив и перебирать элементы массива, которые вы можете выполнить sh, запустив подпрограмму для всех ваших ID`. Код сначала заполняет заголовки столбцов, а затем только собранные значения.

Вариант, включающий итерации между существующими ID, должен выглядеть следующим образом:

Sub testFindOutputTable()
    Dim sh1 As Worksheet, sh2 As Worksheet, El As Variant, arrID As Variant

    arrID = Split("155,156", ",")
    'ID = "155"
    Set sh1 = ActiveSheet                  'you may use here your sheet1
    Set sh2 = Worksheets(Worksheets.count) ' you will use here your sheet2
    For Each El In arrID
        FindOutputTable sh1, sh2, CStr(El)
    Next
End Sub

Вы можете использовать вместо «155,156» столько идентификаторов, сколько вам нужно, но через запятую. Если у вас есть где-то в диапазоне эти идентификаторы, вы можете сразу ввести их в массив, используя что-то вроде этого: arrID = range("yourRange").value

0 голосов
/ 20 апреля 2020

Вы можете использовать функцию CountIfs для нескольких условий. Предполагая, что ваши данные в A1:C100, формулы могут выглядеть следующим образом:

=COUNTIFS(A1:A100,155,B1:B100,"<=6")
=COUNTIFS(A1:A100,155,B1:B100,"<=6",C1:C100,"Owner")
=COUNTIFS(A1:A100,155,B1:B100,"<=6",C1:C100,"Lead")

. Конечно, вы можете изменить формулу, чтобы получить критерии из других ячеек, поэтому вместо того, чтобы иметь идентификатор, жестко закодированный в 155, вы можете написать его в ячейку (скажем, D2), а затем измените 155 в формуле на D2 или запишите число дней в D3 и измените критерии на "<="&D3:

=COUNTIFS(A1:A100,D2,B1:B100,"<="&D3)

ОБНОВЛЕНИЕ С VBA:

Function CountMe(ID As Long, Optional days As Long = 6, Optional user As String = "")

    Dim data As Range
    Set data = ThisWorkbook.Sheets(1).Range("A1:C100")

    Dim idCol As Range, dayCol As Range, UserCol As Range
    Set idCol = data.Resize(, 1)
    Set dayCol = idCol.Offset(0, 1)
    Set UserCol = idCol.Offset(0, 2)

    If user = "" Then
        CountMe = Application.WorksheetFunction.CountIfs(idCol, ID, dayCol, "<=" & days)
    Else
        CountMe = Application.WorksheetFunction.CountIfs(idCol, ID, dayCol, "<=" & days, UserCol, user)
    End If

End Function
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...