У меня проблемы с моей большой таблицей. Я ввожу много необработанных данных в таблицу данных, а затем выполняю ряд поисков по данным. Используя встроенные функции, которые я придумал
=IF(ISNA(INDEX(Data!$L$7:$L$1100,MATCH(Data!$I$2&$B$199&$B29&Data!$J$5,Data!$K$7:$K$1100&Data!$J$7:$J$1100&Data!$I$7:$I$1100&Data!$N$7:$N$1100,0))),"0",INDEX(Data!$L$7:$L$1100,MATCH(Data!$I$2&$B$199&$B29&Data!$J$5,Data!$K$7:$K$1100&Data!$J$7:$J$1100&Data!$I$7:$I$1100&Data!$N$7:$N$1100,0)))
Не очень! В основном он выполняет один и тот же поиск дважды, беря 4 переменные и сопоставляя их с 4 конкатенированными массивами, а затем использует точку в качестве индекса для значения, которое я хочу.
У меня их 8 (немного разных) в каждом ряду по 4 листа и 96 рядов на каждом листе. Редактировать их - это боль!
Из-за того, что набор данных резко вырос в этом месяце, внешние диапазоны (x1100) были превзойдены (урок усвоен, большого никогда не бывает). К сожалению, ограничения функции не позволяют мне использовать L: L или что-то подобное.
Я попытался переписать код как определяемую пользователем функцию, в которую я могу ввести 4 переменные и получить ответ, но мне не удалось объединить массивы.
Я дал диапазоны, перечисленные выше, в исходных именах функций, чтобы упростить задачу (и расширил их, чтобы использовать гораздо более широкие значения диапазона), поэтому я мог бы переписать все функции, чтобы просто использовать именованные диапазоны, но это по-прежнему оставляет меня в тупике если мне нужно изменить код.
Вот что у меня есть на данный момент:
Function Windows_Util(itma As String, env As String)
v = "Windows Server" & env & itma & ""
r = Concat(Range("Utilchassis"))
r = r & Concat(Range("Utilenv"))
r = r & Concat(Range("UtilITMA"))
r = r & Concat(Range("UtilOS"))
m = WorksheetFunction.Match(v, r, 0)
i = WorksheetFunction.Index(Range("Utilavg"), m)
If WorksheetFunction.IsNA(i) Then
Windows_Util = 0
Else
Windows_Util = i
End If
End Function
Function Concat(myRange As Range, Optional myDelimiter As String)
Dim r As Range
Application.Volatile
For Each r In myRange
If Len(r.Text) Then
Concat = Concat & IIf(Concat <> "", myDelimiter, "") & r.Text
End If
Next
End Function
Это не работает! Он не только неправильно объединяется (каждый диапазон объединяется отдельно, а не объединяется строка за строкой), но и не любит какой-либо тип в одном из запросов. (отлаживать эти вещи непросто, поскольку функция фактически завершается (в ней нет никаких синтаксических ошибок), поэтому я не могу использовать встроенные пошаговые инструкции.
Любая помощь очень ценится.
Надеюсь, я дал достаточно подробностей, чтобы понять, что я пытаюсь сделать.
Ваше здоровье,
Стив


Как насчет:
r = Range("Utilchassis,Utilenv,UtilITMA,UtilOS")
Казалось бы, достигается то же, что и ваша функция Concat
Я не совсем уверен, как вы хотите, чтобы диапазоны были объединены, но я думаю, вам стоит взглянуть на Application.Union (Range, Range, ...) метод.
В примере из статьи:
Set bigRange = Application.Union(Range("Range1"), Range("Range2"))
См. Также Статья Тушара Мехты в Daily Dose of Excel, где он описывает следующий настраиваемый метод Union (Range, Range), который может лучше обрабатывать входные данные Nothing (null):
Function Union(Rng1 As Range, Rng2 As Range) As Range
If Rng1 Is Nothing Then
Set Union = Rng2
ElseIf Rng2 Is Nothing Then
Set Union = Rng1
Else
Set Union = Application.Union(Rng1, Rng2)
End If
End Function
Если вместо этого вы собираетесь использовать конкатенацию строк адресов диапазона, вам нужно добавить запятые, как показывает Барроус в своем сообщении. Например, Range("MyRange1, MyRange2") объединит два диапазона с именами «MyRange1» и «MyRange2», тогда как разделитель пробела без запятой, такой как Range("MyRange1 MyRange2"), вернет ПЕРЕСЕЧЕНИЕ (перекрытие) этих двух диапазонов.
Однако я бы рекомендовал избегать объединения строковых адресов и вместо этого использовать метод Application.Union(Range, Range).
Надеюсь это поможет...
Функцию ПОИСКПОЗ может быть сложно использовать в VBA, когда существует более одного критерия для сопоставления. То, что делается на листе - критерии соответствия, объединенные из разных ячеек с равным количеством связанных диапазонов, в обоих случаях с использованием оператора & - недостижимо в VBA, потому что оператор "&" VBA принимает только строки в качестве аргументов и потому что другие способы объединения диапазонов в VBA, функция Union и назначение с помощью нескольких аргументов адреса для Range, похоже, не создают массив, который будет работать с функцией сопоставления VBA.
Однако можно добиться того же эффекта, создав формулу рабочего листа, объединяющую ПОИСКПОЗ и сравнения массивов, а затем выполняя формулу с помощью функции VBA Evaluate. См. Мой ответ на этот ТАК вопрос, чтобы узнать, как работает этот подход.
Следующий код по существу повторно реализует исходную формулу рабочего листа, предоставленную Стивом, вне зависимости от ранее названных диапазонов на листе или значений критериев, указанных в коде (в отличие от конкретных ячеек на листе). Он написан как подпрограмма, но может быть легко преобразован в пользовательскую функцию.
Sub x4match()
Dim adr1 As String, adr2 As String, adr3 As String, adr4 As String
Dim Rng1 As Range, Rng2 As Range, Rng3 As Range, Rng4 As Range
Dim name1 As String, name2 As String, name3 As String, name4 As String
Dim idx As Variant
Dim resultRng As Range
Dim result As Variant
With ThisWorkbook.Worksheets("Data")
adr1 = "I2"
adr2 = "B199"
adr3 = "B29"
adr4 = "J5"
Set Rng1 = .Range("K7:K1100")
Set Rng2 = .Range("J7:J1100")
Set Rng3 = .Range("I7:I1100")
Set Rng4 = .Range("N7:N1100")
Set resultRng = .Range("L7:L1100")
.Names.Add Name: = "name1", RefersTo:=Rng1
.Names.Add Name: = "name2", RefersTo:=Rng2
.Names.Add Name: = "name3", RefersTo:=Rng3
.Names.Add Name: = "name4", RefersTo:=Rng4
idx = Evaluate("IFERROR( MATCH(1, --(" & adr1 & "=name1) * --(" & _
adr2 & "=name2) * --(" & adr3 & "=name3) * --(" & _
adr4 & "=name4), 0), 0)")
If idx <> 0 Then
result = .Cells(resultRng.Row + idx - 1, resultRng.Column).Value
End If
.Names("name1").Delete
.Names("name2").Delete
.Names("name3").Delete
.Names("name4").Delete
End With
End Sub
Match приведет к ошибке при использовании в VBA, если совпадения нет. Вы можете попробовать On Error Resume Next и проверить ошибку, или вы можете использовать метод Find объекта диапазона.