2015-12-26 3 views
1

Я изменил код VBA, найденный по адресу checking if value present in array, по коду ниже. Пользователь выберет имя поля, и я хочу, чтобы код нашел столбец, в котором указано это поле, и создайте массив всех элементов в этом столбце, но я хочу, чтобы каждое непустое значение отображалось только один раз в массиве. Я не хочу дубликатов.Проверка наличия значения в массиве

Например, если столбец имеет значения A, B, A, C, D, я хочу код, чтобы вернуть массив как A, B, C, D.

я получаю ошибку во время выполнения 13 - несоответствие типа на этой строке кода:

If cell.Value <> "" And IsError(WorksheetFunction.Match(cell.Value, MyArray, 0)) Then 

Я запутался, потому что кажется, все мои типы данных являются правильными. Может ли кто-нибудь помочь?

Sub ChangeBlock() 

Dim MyArray() As String 
Dim cell As Range 
Dim ColNum As Integer 
Dim i As Integer 

If Not Intersect(ActiveCell, Range("Block1")) Is Nothing Then 
    If ActiveCell.Value = "" Then Exit Sub 

ColNum = WorksheetFunction.Match(ActiveCell.Value, Sheets("Budget Table").Range("A1:AG1"), 0) 

    For Each cell In Sheets("Budget Table").Columns(ColNum) 
     If cell.Value <> "" And IsError(WorksheetFunction.Match(cell.Value, MyArray, 0)) Then 
      ReDim Preserve MyArray(i) 
      MyArray(i) = cell.Value 
      i = i + 1 
     End If 
    Next 
End If 

MsgBox (MyArray) 

End Sub 

ответ

1

Ошибка 13 Несоответствие типа вызывается здесь:

cell.Value <> ""

Value здесь 2D-массив что-то вроде (1 1048576, 1 к 1), и это не представляется возможным сравнить этот массив строка, следовательно, несоответствие типа.

Изменить:


На самом деле переменная cellпредставляет собой столбец так, чтобы сравнить должным образом, необходимо сказать, что элемент массива сравнивается, например, для первого элемента:

cell.Value()(1, 1) = ""

Более правильным было бы переименовать переменную cell до, например, oneColumn, потому что переменная cell фактически содержит ссылку на столбец, например. как это:

Dim myColumns As Range 
Set myColumns = Sheets("Budget Table").Columns(ColNum) 

Dim oneColumn As Range 

For Each oneColumn In myColumns 
    ' ... 
Next oneColumn 

Примечание: Здесь for-each не имеет смысла, потому что myColumns ссылки только один столбец и myColumns.Columns.Count возвращает 1. Итак, все, что вы хотели, было на самом деле myColumns.Cells, который возвращает все ячейки столбца.

Значение oneColumn - это 2D-массив, и, честно говоря, я не знаю, почему это 2D, а не только 1D. Когда вы изучите Value, например. Range("A1:C3"), то вы видите, что он возвращает 2D-массив, который понятен. Но почему один столбец столбцов также возвращает 2D?Кажется, тоже странно для меня :). Примером 1D-массива будет Dim oneDArray: oneDArray = Array("A", "B", "C"). Насколько я знаю, 1D-массив никогда не возвращается из свойства Range.Value. Here интересная статья о размерах массива в VBA.


Но это не нужно, потому что каждый Range имеет свойство Cells. Поэтому здесь следует использовать Columns(ColNum).Cells.

Полный код может выглядеть примерно следующим образом, но он немного сложнее. Сначала в массиве много пустых элементов, потому что используется весь столбец, а во втором - решение со словарем, например @ A.S.H. HTH

Dim MyArray() As String 
Dim cell As Range 
Dim ColNum As Integer 
Dim i As Integer 

ReDim MyArray(0 To 0) 

With Sheets("Budget Table") 

    If Intersect(ActiveCell, .Range("Block1")) Is Nothing Then _ 
     Exit Sub 

    If ActiveCell.Value = "" Then _ 
     Exit Sub 

    ColNum = Application.Match(ActiveCell.Value, .Range("A1:AG1"), 0) 

    For Each cell In .Columns(ColNum).Cells 
     If cell.Value = "" Then _ 
      GoTo continue 

     If IsError(Application.Match(cell.Value, MyArray, 0)) Then 
      If i > 0 Then 
       ReDim Preserve MyArray(i) 
      End If 

      MyArray(i) = cell.Value 
      i = i + 1 

     End If 
continue: 
    Next cell 

End With 
+0

Спасибо, ди. У меня есть вопрос: почему значение представляет собой 2D-массив? На мой взгляд, один столбец данных в excel будет лучшим примером 1D-массива. Если это фактически 2D-массив, то какой пример 1D-массива? Может ли он существовать в электронной таблице Excel? Извините, если это глупый вопрос. Или вы говорите, что объект value возвращает 2D-массив, в то время как объект ячейки возвращает 1D-массив? Извините, если я что-то не понимаю. Я думаю, что меня путают, когда вы говорите: «На самом деле переменная ячейка в столбце, чтобы правильно сравнивать» @dee – christopheralan88

+0

У меня там была TYPO, '' 'Фактически переменная cell 'in'''' должна быть' ' 'Фактически переменная ячейка 'is''''. См. Отредактированный ответ HTH. – dee

2

Для использования IsError используйте Application.Match вместо WorksheetFunction.Match.

Хотя эти два метода похожи, то, как они обрабатывают ошибки, несколько отличается. Первый возвращает вариант ошибки, который вы можете проверить с помощью IsError, а последний только throws - ошибка, которую вы можете использовать только с механизмом обработки ошибок.

И, наконец, если ваши данные велики, это не оптимальный способ проверки дубликатов; вы должны подумать об использовании Dictionary.

+0

Я тоже попробовал, и у меня такая же ошибка. Я, вероятно, не пройду через более 200 000 ячеек. Это считается большим? Я изучу использование словаря. – christopheralan88

+0

Теперь, когда я думаю об этом, я также заметил, что я не могу найти ссылку на Application.Match в моем браузере объектов VBE. Я полагаю, чтобы добавить ссылку на библиотеку, чтобы использовать этот метод? – christopheralan88

+0

Извините за все комментарии, но я разместил Debug.Print MyArray перед строкой, на которой была получена ошибка, и заметила, что при выполнении кода я получаю ту же ошибку, но она будет выделять переменную MyArray. Итак, я попытался изменить тип данных MyArray на вариант, но все же получил ту же ошибку. Кто-нибудь имеет какие-либо указания относительно того, почему это все равно произойдет? Из того, что я читал в Интернете, нужно изменить этот тип данных на вариант. @ A.S.H – christopheralan88

Смежные вопросы