Строки Fiind, которые соответствуют нескольким критериям в отдельной таблице поиска - PullRequest
0 голосов
/ 12 апреля 2019

Я на 95% закончил с небольшим скриптом, который возвращает случайную выборку записей, используя критерии поля ввода, сопоставленные с 4 или 5 столбцами. Я хотел бы включить строки, в которых значение ячейки соответствует одному из 40 или 50 различных значений в отдельном именованном диапазоне в другой электронной таблице. В настоящее время я фильтрую: между диапазоном дат (основанным на полях ввода), бизнесом (основанным на полях ввода), только записями, которые «одобрены» (нет поля ввода, просто явно указано). Я не могу понять, как сопоставлять строки, которые соответствуют десяткам критериев, которые могут со временем меняться - я бы хотел изменить таблицу поиска вместо того, чтобы вручную вводить каждую возможность поиска в моем коде.

Я уже пробовал (Data (i, 13) .Value = range ("AllBands"). Значение и множество вариаций "like", "in" и т. Д.)

Вопрос: Как дополнительно отфильтровать мой случайный выбор путем сопоставления значений ячеек в столбце 13 с теми, которые находятся в именованном диапазоне в другой рабочей книге (называемой «AllBands»), в которой перечислены 40 или 50 допустимых значений?

////

Static StartDate As String, LOBName As String, BandName As String, Status As String
  Static EndDate As String

  Dim sDate As Date
  Dim eDate As Date
  Dim Data, Possible, This
  Dim i As Long, j As Long
  Dim Ws As Worksheet
  Static Amount As Long
  Dim SheetName As String

  'Get the start date of the range you need
  Do
    StartDate = InputBox("Enter START date (Format as MM/DD/YYYY)", "Generate Random Sample", StartDate)
    If StartDate = "" Then Exit Sub
    If Not IsDate(StartDate) Then Beep
  Loop Until IsDate(StartDate)

  'Get the END date of the range you need
  Do
    EndDate = InputBox("Enter END date (Format as MM/DD/YYYY)", "Generate Random Sample", EndDate)
    If EndDate = "" Then Exit Sub
    If Not IsDate(EndDate) Then Beep
  Loop Until IsDate(EndDate)

  sDate = StartDate
  eDate = EndDate

  LOBName = InputBox("Enter LOB you want sampled (SHP, CC, Etc)", "Generate Random Sample", LOBName)
  If LOBName = "" Then Exit Sub
  If Amount = 0 Then
    Amount = 5 'Default
  Else
    Amount = Amount + 1 'Adjust from last call (see code below)
  End If
  Amount = Application.InputBox("Enter amount (Total number of rows / records you want to return - up to the total number available for date and name parameter)", "Generate Random Sample", Amount, Type:=1)
  If Amount <= 0 Then Exit Sub

  'Read in all data
  Data = Sheets("Reports").Range("A1").CurrentRegion.Value
  'Initialize
  Amount = Amount - 1
  Possible = Array()
  j = -1
  'Collect all row numbers that are possible
  For i = 2 To UBound(Data)
    'Checks in Column 9 for date, checks in column 6 for the LOB that you enter
    If (Data(i, 9) >= sDate) And (Data(i, 9) <= eDate + 1) And (Data(i, 6) = LOBName And _
    (Data(i, 8) = "Approved-PCSP") And (Data(i, 13).Value Like worksheets("LookupFile.xls").range("AllBands"))) _
    Then
      j = j + 1
      ReDim Preserve Possible(0 To j)
      Possible(j) = i
    End If
  Next
////

После этого есть еще куча, но у меня все работает - хотел, чтобы это было как можно меньше ...

1 Ответ

0 голосов
/ 13 апреля 2019

Предполагая, что я правильно понял ваш вопрос, вы ищете, существует ли элемент массива Data(i, 13) в диапазоне AllBands.

Возможно, вы могли бы изменить этот бит:

And (Data(i, 13).Value Like worksheets("LookupFile.xls").range("AllBands"))

к приведенному ниже (если AllBands - одна строка или столбец):

And IsNumber(Application.Match(Data(i, 13).Value,Worksheets("LookupFile.xls").Range("AllBands"), 0))

или ниже (если AllBands состоит из нескольких столбцов или нескольких строк):

And Not (Worksheets("LookupFile.xls").Range("AllBands").Find(Data(i, 13), , xlValues, xlWhole, xlByRows, xlNext, False) Is Nothing)

Однако VBA не предлагает оценку короткого замыкания.Таким образом, он всегда будет оценивать каждое логическое выражение в цепочке / серии.Возможно, было бы лучше разбить утверждение (так что вам не нужно проверять AllBands, например, если вы уже знаете, что дата находится за пределами диапазона дат).

Это будет означать что-то вроде:

' Some code here...
If (Data(i, 9) >= sDate) And (Data(i, 9) <= EDate + 1) Then
    If Data(i, 6) = LOBName And (Data(i, 8) = "Approved-PCSP") Then
        If IsNumber(Application.Match(Data(i, 13).Value, Worksheets("LookupFile.xls").Range("AllBands"), 0)) Then
            ' Some code here...
        End If
    End If
End If
' Some code here...

Также может быть полезно сохранить AllBands в переменной перед циклом (например, Dim cellsToSearch as range, затем Set cellsToSearch = Worksheets("LookupFile.xls").Range("AllBands"), затем обратиться к cellsToSearch внутри цикла.

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


Оба вышеуказанных подхода будут выполнять линейный поиск (с циклическим просмотром каждого значения в AllBands).Кроме того, этот линейный поиск будет выполняться для каждой строки в массиве Data.

Если выполнение кода занимает слишком много времени, возможно, вы могли бы отсортировать данные в AllBands, чтобы разрешитьдля бинарного поиска (бинарный поиск может быть выполнен через Application.Vlookup или Application.Match с правильными аргументами, если я не ошибаюсь).

Или может потребоваться использовать подход с более низкой алгоритмической сложностью, например dictionary, collection (хотя он не предлагаетcontains или exists () или любой объект, который внутренне использует хеш-таблицу.Поэтому перед циклом вы, например, добавили бы все значения в AllBands в словарь (обратите внимание на чувствительность к регистру), а затем внутри цикла вы можете проверить (гораздо быстрее), соответствует ли Data(i, 13) что-либо вAllBands.

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