Критерии WorksheetFunction.countif не работают - PullRequest
2 голосов
/ 25 мая 2019

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

Я использовал это на другом листе, где он работает хорошо, разница в том, что в этом новом приложении мне нужно скопировать данные во временное местоположение, потому что они фильтруются, а CountIf не работает на отфильтрованных строках .

Код игнорирует критерии для . Я хочу выяснить, почему это происходит.

Сначала я использую CountIf, чтобы получить список адресов электронной почты кредитного менеджера (список MLO). Это работает нормально, но тогда код для получения списка процессоров не работает должным образом. Код под списком Процессор должен игнорировать любое значение, равное , но это не так:

Sheets(2).Cells.ClearContents
  lastSrcRw = Sheets("Pipeline").Cells(Rows.Count, 2).End(xlUp).Row
     For Each cell In Sheets("Pipeline").Range("E11:E" & lastSrcRw).SpecialCells(xlCellTypeVisible)
        dstRw = dstRw + 1
        cell.Copy Sheets(2).Range("A" & dstRw)
     Next

'Loop through Sheet2 list, extract unique addresses
  lastTmpRw = Sheets(2).Cells(Rows.Count, 1).End(xlUp).Row
     For tmpRw = 1 To lastTmpRw
         If WorksheetFunction.CountIf(Sheets(2).Range("A1:A" & tmpRw), _
            Sheets(2).Range("A" & tmpRw)) < 2 Then
               addylist_tmp = addylist_tmp & Sheets(2).Range("A" & tmpRw).Value & "; "
         End If
     Next tmpRw

'Clean up temp addylist
     addylist = Left(addylist_tmp, Len(addylist_tmp) - 2)
     'MsgBox addylist

'Processor List
Sheets(2).Cells.ClearContents
  lastSrcRw = Sheets("Pipeline").Cells(Rows.Count, 4).End(xlUp).Row
     For Each cell In Sheets("Pipeline").Range("C11:C" & lastSrcRw).SpecialCells(xlCellTypeVisible)
        dstRw = dstRw + 1
        cell.Copy Sheets(2).Range("D" & dstRw)
     Next

'Loop through Sheet2 list, extract unique addresses
  lastTmpRw = Sheets(2).Cells(Rows.Count, 4).End(xlUp).Row
     For tmpRw = 1 To lastTmpRw
         If WorksheetFunction.CountIf(Sheets(2).Range("D1:D" & tmpRw), "<>" & "<UNASSIGNED>") Then
         If WorksheetFunction.CountIf(Sheets(2).Range("D1:D" & tmpRw), Sheets(2).Range("D" & tmpRw)) < 2 Then
                addylist_tmp2 = addylist_tmp2 & Sheets(2).Range("D" & tmpRw).Value & "; "
         End If
         End If
     Next tmpRw

'Clean up temp addylist
     addylist2 = Left(addylist_tmp2, Len(addylist_tmp2) - 2)


Ответы [ 3 ]

0 голосов
/ 25 мая 2019

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

Во-первых,чтобы проверить текстовую строку как проверку формата адреса электронной почты, я создал функцию, которая сначала ищет символ @, а затем проверяет, чтобы часть текста справа от разделителя имела хотя бы одну точку.

Private Function IsValidEmailFormat(ByVal thisText As String) As Boolean
    IsValidEmailFormat = False
    Dim tokens() As String
    tokens = Split(thisText, "@")
    If UBound(tokens) = 1 Then
        '--- we found the domain separator, do we have a dot?
        tokens = Split(tokens(1), ".")
        If UBound(tokens) >= 1 Then
            '--- we found the dot, looks like an email address
            IsValidEmailFormat = True
        End If
    End If
End Function

Далее, мы будем использовать эту функцию для построения нашего Dictionary из заданного диапазона.Вы увидите, что внутри этой функции мы копируем данный диапазон в массив на основе памяти (подробнее об этом здесь ).После этого, убедившись, что у нас есть строка, которая является допустимым форматом электронной почты, проверьте, что она уже есть в словаре - вот как мы можем гарантировать, что у нас есть список УНИКАЛЬНЫХ адресов электронной почты.

Private Function GetUniqueEmails(ByRef thisRange As Range) As Dictionary
    Dim theseEmails As Dictionary
    Set theseEmails = New Dictionary

    '--- copy to memory array
    Dim thisData As Variant
    thisData = thisRange

    Dim i As Long
    For i = LBound(thisData, 1) To UBound(thisData, 1)
        If IsValidEmailFormat(thisData(i, 1)) Then
            If Not theseEmails.Exists(thisData(i, 1)) Then
                theseEmails.Add thisData(i, 1), i
            End If
        End If
    Next i
    Set GetUniqueEmails = theseEmails
End Function

Наконец, как вызывается из логики основного кода, вы можете делать то, что вы хотите с результирующим списком.Я сформировал список, разделенный точкой с запятой, похожий на ваш пример.

Вот весь пример кода в одном блоке:

Option Explicit

Sub TestMe()
    Dim emails As Dictionary
    Set emails = GetUniqueEmails(Sheet3.Range("A1:A5"))

    '--- convert the emails to a semi-colon separated list for later use
    Debug.Print "there are " & emails.Count & " emails in the list"
    Dim emailList As String
    Dim email As Variant
    For Each email In emails.Keys
        emailList = emailList & email & ";"
    Next email
    emailList = Left(emailList, Len(emailList) - 1) 'remove the trailing ";"
End Sub

Private Function GetUniqueEmails(ByRef thisRange As Range) As Dictionary
    Dim theseEmails As Dictionary
    Set theseEmails = New Dictionary

    '--- copy to memory array
    Dim thisData As Variant
    thisData = thisRange

    Dim i As Long
    For i = LBound(thisData, 1) To UBound(thisData, 1)
        If IsValidEmailFormat(thisData(i, 1)) Then
            If Not theseEmails.Exists(thisData(i, 1)) Then
                theseEmails.Add thisData(i, 1), i
            End If
        End If
    Next i
    Set GetUniqueEmails = theseEmails
End Function

Private Function IsValidEmailFormat(ByVal thisText As String) As Boolean
    IsValidEmailFormat = False
    Dim tokens() As String
    tokens = Split(thisText, "@")
    If UBound(tokens) = 1 Then
        '--- we found the domain separator, do we have a dot?
        tokens = Split(tokens(1), ".")
        If UBound(tokens) >= 1 Then
            '--- we found the dot, looks like an email address
            IsValidEmailFormat = True
        End If
    End If
End Function
0 голосов
/ 27 мая 2019

Мне удалось найти простое решение от пользователя по имени Fluff на форуме MrExcel:

Sub mecerrato()
Dim Cl As Range
Dim Mlst As String, Plst As String
Dim Mdic As Object, Pdic As Object

Set Mdic = CreateObject("scripting.dictionary")
Set Pdic = CreateObject("scripting.dictionary")
With Sheets("Pipeline")
  For Each Cl In .Range("C11", .Range("C" & 
Rows.Count).End(xlUp)).SpecialCells(xlVisible)
     If Cl.Value <> "" And Cl.Value <> "<UNASSIGNED>" Then Pdic(Cl.Value) = Empty
     If Cl.Offset(, 2).Value <> "" Then Mdic(Cl.Offset(, 2).Value) = Empty
  Next Cl
End With
Mlst = Join(Mdic.Keys, "; ")
Plst = Join(Pdic.Keys, "; ")
End Sub
0 голосов
/ 25 мая 2019

Сброс счетчика строк перед повторным использованием его в другом столбце.

Вам нужно dstRw = 0 на строке выше 'Processor List

Как это ...

'Clean up temp addylist
     addylist = Left(addylist_tmp, Len(addylist_tmp) - 2)
     'MsgBox addylist

dstRw = 0

'Processor List
Sheets(2).Cells.ClearContents

Я думаю, вы можете быть смущены тем, что происходит на Sheet(2) и каков ваш результат на самом деле.Ваш результат хранится в addylist2

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

Результат в addylist2 равен 123, все отфильтрованные и исключенные критерии игнорируются.

Sub aaa()

Dim cell As Range
Dim lastTmpRw As Long
Dim addylist_tmp As String
Dim addylist_tmp2 As String
Dim tmpRw As Long
Dim dstRw As Long
Dim lastSrcRw As Long
Dim addylist As String
Dim addylist2 As String

Sheets(2).Cells.ClearContents
  lastSrcRw = Sheets(1).Cells(Rows.Count, 2).End(xlUp).Row
     For Each cell In Sheets(1).Range("E11:E" & lastSrcRw).SpecialCells(xlCellTypeVisible)
        dstRw = dstRw + 1
        cell.Copy Sheets(2).Range("A" & dstRw)
     Next

'Loop through Sheet2 list, extract unique addresses
  lastTmpRw = Sheets(2).Cells(Rows.Count, 1).End(xlUp).Row
     For tmpRw = 1 To lastTmpRw
         If WorksheetFunction.CountIf(Sheets(2).Range("A1:A" & tmpRw), _
            Sheets(2).Range("A" & tmpRw)) < 2 Then
               addylist_tmp = addylist_tmp & Sheets(2).Range("A" & tmpRw).Value & "; "
         End If
     Next tmpRw

'Clean up temp addylist
     addylist = Left(addylist_tmp, Len(addylist_tmp) - 2)
     'MsgBox addylist

dstRw = 0

'Processor List
Sheets(2).Cells.ClearContents
  lastSrcRw = Sheets(1).Cells(Rows.Count, 4).End(xlUp).Row
     For Each cell In Sheets(1).Range("C11:C" & lastSrcRw).SpecialCells(xlCellTypeVisible)
        dstRw = dstRw + 1
        cell.Copy Sheets(2).Range("D" & dstRw)
     Next

'Loop through Sheet2 list, extract unique addresses
  lastTmpRw = Sheets(2).Cells(Rows.Count, 4).End(xlUp).Row
     For tmpRw = 1 To lastTmpRw
         If WorksheetFunction.CountIf(Sheets(2).Range("D1:D" & tmpRw), "<>" & "<UNASSIGNED>") Then
         If WorksheetFunction.CountIf(Sheets(2).Range("D1:D" & tmpRw), Sheets(2).Range("D" & tmpRw)) < 2 Then
                addylist_tmp2 = addylist_tmp2 & Sheets(2).Range("D" & tmpRw).Value & "; "
         End If
         End If
     Next tmpRw

'Clean up temp addylist
     addylist2 = Left(addylist_tmp2, Len(addylist_tmp2) - 2)
Sheet3.Cells.Clear
Sheet3.Cells(1, 1) = addylist
Sheet3.Cells(2, 1) = addylist2

End Sub

Filtered Data Set

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