it-roy-ru.com

Подсчет уникальных значений в Excel

Мне нужно посчитать уникальные значения в диапазоне (C2: C2080) в Excel. Гугл формула:

=SUM(IF(FREQUENCY(MATCH(C2:C2080;C2:C2080;0);MATCH(C2:C280;C2:C2080;0))>0;1)) 

вернуть неправильное значение.

UPD: Хромое решение: 

Sub CountUnique()

Dim i, count, j As Integer

count = 1
For i = 1 To 470
    flag = False
    If count > 1 Then
        For j = 1 To count
            If Sheet1.Cells(i, 3).Value = Sheet1.Cells(j, 11).Value Then
                flag = True
            End If
        Next j
    Else
        flag = False
    End If

    If flag = False Then
        Sheet1.Cells(count, 11).Value = Sheet1.Cells(i, 3).Value
        count = count + 1
    End If

Next i

Sheet1.Cells(1, 15).Value = count

End Sub
11
dayan

=SUM(IF(FREQUENCY(IF(LEN(A2:A10)>0,MATCH(A2:A10,A2:A10,0),""), IF(LEN(A2:A10)>0,MATCH(A2:A10,A2:A10,0),""))>0,1)) 

http://office.Microsoft.com/en-us/Excel/HP030561181033.aspx

Вы также можете написать макрос VBA (но не уверен, что это то, что вам нужно.)

Что-то на эффект (учитывая электронную таблицу с заполненным A1-A11 и пустым B1-B11):

Sub CountUnique()

Dim count As Integer
Dim i, c, j As Integer

c = 0
count = 0
For i = 1 To 11
    Sheet1.Cells(i, 2).Value = Sheet1.Cells(i, 1).Value
    c = c + 1
    For j = 1 To c
        If CDbl(Sheet1.Cells(i, 1).Value) = CDbl(Sheet1.Cells(j, 2).Value) Then
            c = c - 1
            Exit For
        End If
    Next j
Next i

' c now equals the unique item count put in the 12'th row
Sheet1.Cells(12, 1).Value = c

End Sub
8
user113476

Вот функция VBA, которая работает для меня.

Вы можете использовать его как функцию рабочего листа , ссылаясь на любой диапазон, например «= CountUnique (N8: O9)»

Он обрабатывает текстовые и числовые значения и рассматривает пустые ячейки как одно значение

Не требует работы с функциями массива.

Требуется ссылка на библиотеку сценариев Microsoft, для объекта словарь .

    Public Function CountUnique(rng As Range) As Integer
        Dim dict As Dictionary
        Dim cell As Range
        Set dict = New Dictionary
        For Each cell In rng.Cells
             If Not dict.Exists(cell.Value) Then
                dict.Add cell.Value, 0
            End If
        Next
        CountUnique = dict.Count
    End Function
23
JustinG

Пытаться:

=SUM(IF(FREQUENCY(C2:C2080,C2:C2080)>0,1))

Правка: Выше будет обрабатывать пустые записи в столбце

7
Jacob

Функция JustinG работает очень хорошо (и быстро) до тех пор, пока количество уникальных предметов не превысит 32 767 из-за некоторого ограничения в Excel. 

Я нашел, если вы измените его код

Public Function CountUnique(rng As Range) As Integer

и сделать это как ...

Public Function CountUnique(rng As Range) As Long

Затем он будет обрабатывать больше уникальных предметов.

6
Jim D

Для тех, кто все еще пытается использовать метод словаря @ JustinG, вам нужно будет немного изменить код, если вы используете более новую версию VBA. 

Вам нужно будет сослаться на «Среду выполнения сценариев Microsoft» и добавить префикс Dictionary к Scripting следующим образом:

Public Function CountUnique(rng As Range) As Long
    Dim dict As Scripting.Dictionary
    Dim cell As Range
    Set dict = New Scripting.Dictionary
    For Each cell In rng.Cells
         If Not dict.Exists(cell.Value) Then
            dict.Add cell.Value, 0
        End If
    Next
    CountUnique = dict.Count
End Function
4
Jordan

Вы также можете просто использовать фильтр для временного отображения уникальных значений и считать отфильтрованные значения.

3
Mathias

Это может быть более эффективным способом работы с большим количеством строк. При этом используется встроенная команда AdvancedFilter вместо циклического перебора каждой ячейки за раз.

Public Function UniqueValues(oRange As Range) As Variant

' Uses the built-in AdvancedFilter Excel command to return the unique values onto the Worksheet
' and then populate and retuns an array of unique values

' Note:  The index:0 element in the returned array will be the header row.
'        You can ignore this element unless the first row in your oRange is a unique value
'        in which case the header will be that value.

Dim oTarget As Range
Dim r As Long, numrows As Long
Dim vs1, vs2 As Variant

' Get the first unused cell on the first row where the unique vaues will be temporarily populated
   Set oTarget = oRange.SpecialCells(xlLastCell) ' the last cell on the worksheet
   Set oTarget = oTarget.Parent.Cells(1, oTarget.Column + 1) ' the first unused cell on the first row

' Copy the unique values from your oRange to the first unused cell on row 1
   oRange.AdvancedFilter Action:=xlFilterCopy, CopyToRange:=oTarget, Unique:=True

' Get the number of rows including the first row which is the header
   numrows = WorksheetFunction.CountA(oTarget.EntireColumn)

' create an 2-dim array of the rows
   vs1 = oTarget.Resize(numrows)

' Prepare a second 1-dim array for the result
   ReDim vs2(numrows)

' Transfer the 2-dim array into the 1-dim array
   For r = 1 To UBound(vs1, 1)
      vs2(r - 1) = vs1(r, 1)
   Next

' Return the 1-dim array as the function result
   UniqueValues = vs2

' Clean up the extra column on the worksheet
   oTarget.EntireColumn.Delete

End Function
1
Neil

Посмотрите на https://excelchamps.com/blog/count-unique-values-Excel/ . Есть ваш ответ.

Формула, которую вам нужно ввести:

=SUMPRODUCT(1/COUNTIF(C2:C2080,C2:C2080))

Когда вы вводите эту формулу в виде массива, она будет выглядеть примерно так:

{=SUMPRODUCT(1/COUNTIF(C2:C2080,C2:C2080))}
1
Kleberson Felix Silva

После прочтения и дальнейшего изучения у меня есть один, который работает лучше, чем все, что я вижу здесь:

Массив введите:
(Ctrl + Shift + Enter и не включать фигурные скобки)

{=SUM(IFERROR(1/COUNTIF(C2:C2080,C2:C2080),0))}

Или в VBA:

MyResult = MyWorksheetObj.Evaluate("=SUM(IFERROR(1/COUNTIF(C2:C2080,C2:C2080),0))")

Он работает как для чисел, так и для текста, обрабатывает пустые ячейки, обрабатывает ошибки в ссылочных ячейках и работает в VBA. Это также одно из самых компактных решений, которые я видел. Используя его в VBA, он, очевидно, автоматически обрабатывает необходимость быть формулой массива.

Обратите внимание, что способ обработки ошибок заключается в простом включении их в число уникальных. Например, если у вас есть две ячейки, возвращающие # DIV/0! и три ячейки, возвращающие #VALUE !, эти 5 ячеек добавят 2 к окончательному числу уникальных значений. Если вы хотите, чтобы ошибки были полностью исключены, их нужно будет изменить для этого.

В моих тестах этот от Jacob выше работает только для чисел, а не для текста, и не обрабатывает ошибки в ссылочных ячейках (возвращает ошибку, если какая-либо из ссылочных ячеек возвращает ошибку):

=SUM(IF(FREQUENCY(G4:G29,G4:G29)>0,1))
1
Greg Lovern

Формула работает для меня. Есть несколько вещей, которые могут заставить это не работать. Во-первых, все целевые клетки должны иметь значение в них. Другой пример того, где это может не сработать, это если у вас есть одна ячейка со значением 31 и другая ячейка с текстовым значением «31». Он распознает их как разные значения.

Вы можете попробовать это:

=SUM(IF(FREQUENCY(IF(LEN(B2:B11)>0,MATCH(B2:B11,B2:B11,0),""), IF(LEN(B2:B11)>0,MATCH(B2:B11,B2:B11,0),""))>0,1))

Это формула array. Вместо того, чтобы нажать Enter, чтобы подтвердить это, вы должны нажать Ctrl + Shift + Enter.

Который из:

http://www.cpearson.com/Excel/Duplicates.aspx

1
Dan

Еще один способ сделать это:

Sub CountUnique()
    Dim Count, x, a, lastRow, Values(), StringValues
    a = ActiveCell.Column
    a = GetLetterFromNumber(a)
    lastRow = Range(a & Rows.Count).End(xlUp).row
    Count = 0
    For Each c In Range(Range(a & "1"), Range(a & Rows.Count).End(xlUp))
        If c.row = 1 Then
            ReDim Values(lastRow)
            Values(Count) = c.Value
            Count = Count + 1
        End If
        StringValues = Join(Values, "#")
        StringValues = "#" + StringValues
        If InStr(1, StringValues, c.Value) = 0 Then
            Values(Count) = c.Value
            Count = Count + 1
        End If
    Next c
    MsgBox "There are " & Count & " unique values in column " & a
End Sub

Вам просто нужно, чтобы активная ячейка находилась в строке 1 столбца, который вы считаете.

1
Mike