2014-01-30 4 views
0

Желаемый результат: Результат будет функцией, которая строит массив значений из столбца B. Значения ограничены тем же значением в столбце A. 'Например. Значение столбца A = 1 myArray = (0,1,2) '' Столбец B Значение = 2 myArray = (4,5,6,7,8) 'Сборка массива в Excel VBA

Первый раз, когда вы пытаетесь использовать массивы в VBA и нуждаетесь в помощи , У меня есть следующие данные в столбцах A и B в Excel:

A B 
1 0 
1 1 
1 2 
2 4 
2 5 
2 6 
2 7 
2 8 
3 9 
3 10 
3 11 
4 12 
4 15 
4 18 

У меня есть следующий VBA код:

Function buildMyArray() 

    Dim ARange as Range 
    Dim B as Integer 
    Dim myArrary as Variant 

    For Each ARange In Sheets("SheetName").Range("B:B") 
     If ARange.Value = 1 Then 
      B = Application.WorksheetFunction.VLookup(ARange.Value, Sheets("SheetName").Range("A:B"), 2, False) 
      myArray = Array(B) 
     End If 
    Next ARange 

End Function 

Я пытаюсь построить функцию, которая будет искать столбец A для каждого экземпляра целое число (которое я в конечном счете динамически передаю). Затем для каждого экземпляра этого целого введите vlookup в соседний столбец (B). Затем я хочу создать массив значений из поиска (в приведенном выше случае (0,1,2)).

Приведенный выше код является самым близким, который я получил. Я получаю первое значение в B (0) как единственное значение в массиве. Я достаточно уверен в этом, потому что логика массива находится в инструкции If. Однако, если я вытащу его, я получаю ошибки компиляции.

Пожалуйста, помогите новичку учиться. Благодарю.

+1

Это очень трудно понять, что йо ты пытаешься сделать. Можете ли вы объяснить, что вы хотите, чтобы результат был простым языком, не обсуждая процесс того, как вы хотите достичь результата? – Tmdean

+0

Результатом будет функция, которая строит массив значений из столбца B. Значения ограничены тем же значением в столбце A. 'Например. Значение столбца A = 1 myArray = (0,1,2) ' ' Столбец B Значение = 2 myArray = (4,5,6,7,8) ' – augusthippo

+0

Хорошо, это имеет больший смысл.Спасибо – Tmdean

ответ

0

В VBA нет простой концепции «добавления элемента в массив». Вам всегда нужно заранее объявить, насколько большой вы хотите, чтобы массив был, тогда вы можете работать с элементами в массиве. Хотя можно написать код, который увеличивает размер массива на один элемент, обычно это не правильный подход.

В этом случае создание массива будет двухэтапным: сначала вам нужно подсчитать, сколько элементов вы будете помещать в свой массив, тогда вам нужно заполнить массив. В моем примере, x номер, который вы ищете в столбце A.

Function MakeArray(x As Integer) As Variant 
    Dim result() As Variant 
    Dim result_count As Long 
    Dim i As Long 
    Dim cursor As Range 

    result_count = WorksheetFunction.CountIf(Range("A:A"), x) 

    ' size the array to how many elements we need, minus one 
    ' because the array indexes start at zero 
    ReDim result(result_count - 1) 

    ' scan through the data and populate our array 
    Set cursor = Range("A2:B2") 
    i = 0 
    Do Until IsEmpty(cursor(1)) 
     If cursor(1) = x Then 
      result(i) = cursor(2) 
      i = i + 1 
      If i > UBound(result) Then Exit Do 
     End If 
     Set cursor = cursor.Offset(1) 
    Loop 

    MakeArray = result 
End Function 
+0

Я не согласен с вашим первым парам –

+0

, увеличивая массив на 1 каждый раз цикл работает так же приемлемо для подсчета, а затем задает размер один раз. – user1759942

+0

@ SiddharthRout Не использует 'ReDim' много (т. Е. Внутри цикла) замедляет производительность? Если нет, я был введен в заблуждение! – ARich

1

Вот пример, который я создал. Тест

Option Explicit 

Sub sample() 
    Dim ws As Worksheet 
    Dim rng As Range, aCell As Range, bCell As Range 
    Dim MyAr() As String 
    Dim n As Long 
    Dim SearchString 

    '~~> Set this to the relevant worksheet 
    Set ws = ThisWorkbook.Sheets("Sheet1") 

    SearchString = 2 

    With ws 
     '~~> Set this to your range 
     Set rng = .Range("A1:A14") 

     Set aCell = rng.Find(What:=SearchString, LookIn:=xlValues, _ 
        LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
        MatchCase:=False, SearchFormat:=False) 

     If Not aCell Is Nothing Then 
      Set bCell = aCell 

      '~~> Store the value from Col B in the array 
      ReDim Preserve MyAr(n) 
      MyAr(n) = aCell.Offset(, 1).Value 
      n = n + 1 

      '~~> Find Next occurance 
      Do 
       Set aCell = rng.FindNext(After:=aCell) 

       If Not aCell Is Nothing Then 
        If aCell.Address = bCell.Address Then Exit Do 

        '~~> Store the value from Col B in the array 
        ReDim Preserve MyAr(n) 
        MyAr(n) = aCell.Offset(, 1).Value 
        n = n + 1 
       Else 
        Exit Do 
       End If 
      Loop 
     End If 
    End With 

    '~~> This will give you the results 
    For n = LBound(MyAr) To UBound(MyAr) 
     Debug.Print MyAr(n) 
    Next n 
End Sub 

Скриншот:

enter image description here

Выход:

enter image description here

+0

Это отличное спасибо! – augusthippo

1

мозговым массива в качестве одной строки на листе Excel, с колоннами являясь индексами. То, что вы хотите сделать, вы сказали, это значения хранилища в указанном массиве. Таким образом, вы получаете свою ценность, b, и вы хотите поместить ее в массив.

то, что вы хотите сделать:..

при объявлении массива, объявить его как Dim myArrary() as Variant уведомления скобки (не положительный, если они необходимы, но ее лучшая практика

, объявляющий пустой массив Like Если бы вы знали, что массив имеет 5 значений, вы можете объявить:

Dim myArrary(1 to 5) as Variant, который говорит, что его массив с 5 индексами.(например, строка excel с 5 столбцами)

цифры, от 1 до 5, это начальные и конечные индексы. поэтому в этом массиве, когда вы возвращаетесь к первому месту, вы должны положить myArray(1) скобки, подобные этим, как вы ссылаетесь на конкретные индексы в массиве. вторым пятном будет myArray (2) 3rd myArray (3) 4-й myArray (4) и 5th (последнее пятно) будет myArray (5).

Вы можете объявить их как dim myarray (от 0 до 5) в качестве варианта, что означает, что первым индексом будет myArray (0) - этот массив будет иметь 6 точек - 0,1,2,3,4,5

Итак, в вашем коде вам понадобится счетчик, чтобы отслеживать, на какой итерации цикла вы были включены, и увеличивайте его, как counter = cojunter + 1 в нижней части цикла. (он будет увеличиваться при каждом запуске цикла), затем замените строку, которая говорит myArray = Array(B) с myArray(counter) = B

поэтому каждый раз, когда цикл работает, B войдет в точку в массиве.

1 еще вещь,

потому что мы не знаем, на begginning сколько пятна массив будет иметь, и мы объявим его пустым: dim myArray() as variant вы должны переопределить его после того, как иметь пробелы, прежде чем мы можем добавить что-нибудь. поэтому, в начале цикла, вы хотите поставить Redim Preserve MyArray(1 to counter), это переопределяет ваш массив как от 1 до любого вашего счетчика. так как счетчик увеличивается на 1 каждый раз, каждый раз в массив будет добавлено 1 пробел.

поэтому в основном,

заменить Dim myArrary as Variant с Dim myArrary() как вариант оных: dim counter as long в переменных (назвать его как и хотите, просто быть последовательны)

добавить counter = 1 до цикла инициализации счетчик

добавить ReDim myArray(1 to counter) в цикле, если в даного (таким образом, только при добавлении пространства, если в был найден

добавить counter = counter + 1 в конце, если if, но снова внутри, таким образом, только увеличивается, если найдено значение для B

и сменить myArray = Array(B) на MyArray(counter) = B в инструкции if.

0

вполне может не рассчитывать в ответ, но без VBA, в С2 и скопировал вниз костюм:

=IF(A3<>A2,IF(A1=A2,C1&","&B2,"("&B2)&")",IF(A1=A2,C1&","&B2,"("&B2)) 

затем скопировать ColumnC и вставить специальные значения над верхней частью, фильтр выбора не содержит ) и удалять видимый должен показать:

Columna начало диапазона
ColumnB конец диапазона
ColumnC массива

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