Возможен ли более быстрый поиск VBA с использованием подстановочных знаков? - PullRequest
1 голос
/ 29 мая 2020

Мне нужно выполнить довольно много поисков с подстановочными знаками на листе с использованием макроса (в основном поиск значения и возврат значения из другого столбца , хотя при правильной настройке он также может просто искать значение с подстановочный знак , а некоторые поиски только как проверяют, существует ли значение в наборе данных). Мои данные не могут быть отсортированы, и все поиски находятся в пределах al oop A или циклы в пределах l oop A; подстановочные знаки используются в основном для условия «строка начинается с ...». Мне часто приходится находить значение в одной строке и соответствующее значение в строке N строк ниже или выше.
У меня есть рабочий код, но мне интересно, можно ли это сделать быстрее. @response, чтобы прокомментировать публикацию в Code Review (извините, я пока не могу комментировать :)) - подготовка всего кода к публикации займет у меня слишком много времени, конфиденциальность и т. д. c, поэтому я предпочитаю рассматривать это как общий вопрос, над которым нужно работать в этом примере.

Пример данных: (я могу добавить больше столбцов, если мне нужен какой-либо вспомогательный столбец)
Пример изображения данных на Imgur

Предположим, 100 000 строк (макс. XPagesCount = 1000, обычно около 400; все значения для определенного xPage находятся в одном блоке). Из-за большого количества возможных строк с дополнительными данными я не могу просто найти одно значение и добавить числа к найденной строке, чтобы найти другие значения по их положению.

Примеры поиска для выполнения во время цикла последовательные xPages (так, для каждой данной xPage) :

  • значение в строке чуть ниже строки с текстом «RESTRICTIONS:»
  • имя поиска (которое всегда указывается с высотой (столбец C) = 35)
  • найти номер RSW (который может быть в нескольких строках в зависимости от содержимого страницы, но всегда под именем)
  • найти все строки, начинающиеся с тех же четырех цифр как RSW, в двух форматах: D DDD .LLL.DD и D DDD .DD DDD .DD (буква L, D di git) (здесь я использую внутренний l oop)
  • проверьте, есть ли текст "MASTER" (или "MASTER" et c.)
  • найдите все значения между значениями "DOCUMENTS:" и "OPTIONS:", количество которых может быть от 1 до 50 (здесь я использую внутренний l oop)

Мне было интересно, каков самый быстрый способ сделать такой поисков?
Что я пробовал:

  • с использованием словаря для всего набора данных (ключи в столбце A или C с, значения col.D), но поскольку словарь не может работать с подстановочными знаками, мне пришлось добавить ifs для того, чтобы не найти ключ для выполнения дополнительного поиска Application.Match ... а затем понял, что он в основном работает с этими поисками Match, и я не уверен, что мне даже нужен disctionary. У меня также есть повторяющиеся значения на странице, и словарь получал только первое значение, независимо от их положения (например, несколько вложений могли иметь значение 1). Основное использование осталось dict.exists («MASTER»), но когда я удалил словарь и изменил его на IsError (Application.Match (...)), код работал немного быстрее.
  • Application.Match во всем диапазоне , типичный пример: Application.Match(xPage & "4???.*", sh.Range("A1:A" & LastRow), 0)
  • в нескольких местах я использую If xValue Like "????.???.??" Then конструкцию
  • У меня есть поиск по словарю с перенаправлением ifs в Application.Match:
xValue = dict(xPage & "ATH.416")
If dict(xPage & "ATH.416") = "" Then xValue = Application.Match("ATH.*", Sheets(1).Range("D:D"), 0)

То, что я считаю, но не уверен, что оно того стоит:

  • изменение кода, в котором в начале итерации я нахожу первую и последнюю строки для xPage, и затем каждая последующая проверка выполняется в этом диапазоне
xStartPage = sh.Range("D" & Application.Match(xPage, sh.Range("A1:A" & LastRow), 0))
'or, I guess better:
xStartPage = xEndPage + 1

If xPage = xPagesCount Then
    xEndPage = LastRow
Else
    xEndPage = sh.Range("D" & Application.Match(xPage + 1, sh.Range("A1:A" & LastRow), 0) - 1)
End If

xValue = sh.Range("D" & Application.Match("4???.*", sh.Range("D" & xStartPage & ":D" & xEndPage), 0)).Value
...