пытается проверить, существует ли значение ячейки (дублируется) в несмежной строке, где некоторые столбцы могут быть скрыты - PullRequest
0 голосов
/ 15 марта 2019

Я работаю над листом и впервые использую vba, и мне это нравится.но застрял в одном за последние несколько дней, ведь чтение и поиск не могут понять, как сделать эту часть, вот сценарий, который у меня есть:

заблокированный лист и книга, пользователь может только редактировать /значения entre (числа) в ячейках C8: G8 и I8: X8, столбец H всегда пуст и хост не имеет значения.

пользователь может скрыть столбцы в C8: G8 и I8: X8, если ему необходимо использоватьопределенное количество столбцов.

пытается установить макрос для определения, было ли введено значение более одного раза во всем диапазоне C8: X8 (исключая H, оно пустое и любые другие столбцы, если скрытые)

Я начал с countif и дал идеальные результаты, только если все столбцы видны:

Sub dup()

 Application.EnableEvents = False

  Dim x As Variant 'tried with range
  Dim n As Variant 'tried with range
  Dim rng1 As Range 'tried with variant

  Set rng1 = Range("C8:X8")

  For Each x In rng1.SpecialCells(xlCellTypeVisible)

        If Application.WorksheetFunction.CountIf(rng1, x) > 1 Then

           x.Offset(4) = "3" 'used for conditional formatting

       Else

           x.Offset(4) = "10" 'used for conditional formatting
      End If

   Next

   Application.EnableEvents = True

   End Sub

все еще работает, когда некоторые столбцы скрыты, но он проверяет скрытые столбцы, и это не то, что я хочу (я хочу, чтобы он пропускал скрытые столбцы) некоторые поиски и чтения обнаруживают, что счетчик не может получить свойство ячейки, если оно видимое или скрытое.пробовал оба варианта application.countif и application.worksheetfunction.countif

поэтому пробовал application.match, но не повезло

    For Each x In rng1

If Not IsEmpty(x) Then

    n = Application.match(x.Value, rng1.Value, 0)
    If Not IsError(n) Then

    x.Offset(4) = "3"

    Else

    x.Offset(4) = "10"
    End If
End If

Next

пробовал application.hlookup и не смог получить желаемый результат:

For Each x In rng1

If Not IsEmpty(x) Then

    n = Application.HLookup(x.Value, rng1.Value, 1, False)
    If Not IsError(n) Then

    x.Offset(4) = "3"

    Else

    x.Offset(4) = "10"
    End If
End If

Next

он будет соответствовать самой ячейке и смотреть только в первой части диапазона C8: G8.

, просто чтобы объяснить ситуацию со скрытыми столбцами, пользователь может скрыть / показать 1,2,3,4 и 5 столбцов в первом диапазоне (если пользователь выберет 2, будут видны только столбцы C8: D8) то же самое применимо к диапазону I8: X8, если пользователь выберет 5, будет виден только I8: M8), поэтому будетможет быть случай, когда скрытый столбец будет находиться между видимыми столбцами.

найдет несколько ответов о том, как использовать SumProduct (промежуточный итог, ...) только в качестве формулы, и не сможет преобразовать его в VBA.

любая рекомендация и совет будут оценены.

Ответы [ 2 ]

2 голосов
/ 15 марта 2019

Пожалуйста, попробуйте это решение.

Sub Dup()

    Const Sep As String = "|"       ' select a character that
                                    ' doesn't occur in Rng

    Dim Rng As Range
    Dim Arr As Variant
    Dim SearchString As String
    Dim n As Integer
    Dim i As Integer

    ' needed only if you have event procedures in your project:-
    Application.EnableEvents = False

    Set Rng = Range("C8:X8")
    Arr = Rng.Value
    SearchString = Sep
    For i = 1 To UBound(Arr, 2)
        If Not Columns(Rng.Cells(i).Column).Hidden Then
            SearchString = SearchString & Arr(1, i) & Sep
        End If
    Next i

    For i = 1 To UBound(Arr, 2)
        ' skip blanks, incl. column H, & hidden cells
        If (Not Columns(Rng.Cells(i).Column).Hidden) And (Len(Arr(1, i)) > 0) Then
            n = InStr(SearchString, Sep & Arr(1, i) & Sep)
            n = InStr(n + 1, SearchString, Sep & Arr(1, i) & Sep)
            With Rng.Cells(i)
                If .Column <> 8 Then    ' skip column H
                    .Offset(4).Value = IIf(n > 0, 3, 10)
                    ' Note that "3" is a string (text) whereas 3 is a number
                    ' It's unusual to enter a number as text because it's use
                    ' for calculations is greatly impaired.
                    ' However, you may modify the above line to write strings
                    ' instead of numbers.
                End If
            End With
        End If
    Next i

    Application.EnableEvents = True
End Sub

Подпрограмма присваивает все не скрытые значения в диапазоне массиву, а затем считывает их в строку (SearchString), в которой они разделяются специальным символом, который можно переопределить. Все значения существуют в этой строке хотя бы один раз. Второй цикл ищет существующее значение, за которым должен следовать и следовать, и должен предшествовать специальный символ, потому что «a» будет найдено в «ab», «a |» в "ба |" но "| a |" однозначно. Затем второй поиск (Instr), начиная с того места, где было найдено первое совпадение, определяет, существует ли дубликат. Затем функция Iif устанавливает значение в ячейке на 4 строки ниже проверяемой ячейки. Обратите внимание, что индекс массива идентичен номеру ячейки в диапазоне из-за способа создания массива.

Поскольку функция Instr "найдет" нулевую строку в позиции 1 и по умолчанию будет считать ее дубликатом, нулевые строки не обрабатываются, и не устанавливаются никакие числа для целей CF. Поэтому столбец H следует опустить. Однако, если столбец H должен иметь какое-либо значение, номер CF все равно не будет записан.

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

0 голосов
/ 17 марта 2019

@ Variatus, Извините, что возвращаюсь к этому, после дальнейших тестов, я думаю, что обнаружил проблему, если я пытаюсь скрыть любой кломун из диапазона C8: G8 (например, G8 и пусть он имеет то же значение, что и M8),Arr будет смотреть только через C8: F8, по какой-то причине он не доходит до X8 и помечает M8 как дубликат.

или даже если дублирующее значение не соответствует I8: X8не найдет его, потому что остановка Arr на первой скрытой ячейке из первого диапазона

будет признательна за любой совет

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