многомерный массив с разными элементами; VBA Excel - PullRequest
0 голосов
/ 20 февраля 2020

Можно ли создать многомерный массив с различными типами элементов (строки и целые числа)? Я пытался так, но не получилось

BT = Range("A12")
ReDim IT(BT) As String
ReDim RBT(BT) As Integer
ReDim IT_RBT(IT, RBT) as ???? how to create multi dim array with different variables type

Range("B2").Select
i = 0
Do
    i = i + 1
    IT(i) = ActiveCell
    RBT(i) = i
    IT_RBT(i, i) = ????  how to enter values in such array ????
    ActiveCell.Offset(1, 0).Select
Loop While ActiveCell <> ""

Спасибо

Ответы [ 3 ]

2 голосов
/ 20 февраля 2020

Используйте массив Variant.

Dim values() As Variant

Теперь ваш код делает предположения, которые следует удалить.

BT = Range("A12") '<~ implicit: ActiveSheet.Range("A12").Value

Если вы хотите получить значение A12 из определенного указанного c листа, тогда вы должны квалифицировать этот Range вызов участника с правильным Worksheet объектом. См. CodeName: Sheet1 для получения дополнительной информации, но если коротко, если этот лист находится в ThisWorkbook, вы можете сделать это:

BT = Sheet1.Range("A12").Value

И теперь предположения пропали. Правильно? Неправильно. BT не объявлено (по крайней мере, не здесь). Если он объявлен и не является Variant, то при таком назначении существует потенциальная ошибка несоответствие типов . Фактически, единственный тип данных, который может принимать любое значение ячейки, это Variant:

Dim BT As Variant
BT = Sheet1.Range("A12").Value

Здесь мы предполагаем, что BT является числовым значением c :

ReDim IT(BT) As String

Это еще одно предположение. Мы не знаем , что BT это число c. Мы даже не знаем, что это значение, которое может быть приведено к типу цифр c: мы должны выручить, если это не так:

If Not IsNumeric(BT) Then
    MsgBox "Cell A12 contains a non-numeric value; please fix & try again."
    Exit Sub
End If

ReDim IT(BT) As String

Теперь, когда будет работать ... но тогда, только верхняя граница является явной; это массив на основе 0 или 1? Если модуль говорит Option Base 1, то он основан на 1. В противном случае это основано на 0 - неявные нижние границы массива являются простым источником ошибок "off-by-one" (например, как вы заполняете массивы, начиная с индекса 1, оставляя индекс 0 пустым). Всегда делайте границы массива явными:

ReDim IT(1 To BT) As String

Непонятно, зачем вам вообще нужно 3 массива, и почему вы только заполняете (i,i) в третьем - вы не можете заполнить 2D-массив Do...Loop структура; вам нужно каждое значение y для каждого значения x, и если вы не жестко закодируете ширину массива, это будет вложенное l oop.

Более того, цикл на ActiveCell и Select из-за Offset делает код 1) очень трудным для понимания и 2) невероятно неэффективным.

Рассмотрим:

Dim lastRow As Long
lastRow = Sheet1.Range("B" & Sheet1.Rows).End(xlUp).Row

ReDim values(1 To lastRow, 1 To 2) As Variant

Dim currentRow As Long
For currentRow = 2 To lastRow
    Dim currentColumn As Long
    For currentColumn = 1 To 2
        values(currentRow, currentColumn) = Sheet1.Cells(currentRow, currentColumn).Value
    Next
Next

Теперь, если мы этого не сделаем нам нужен любой вид логики c в этом l oop, и все, что нам нужно, это получить массив 2D-вариантов, который содержит каждую ячейку в B2:B???, тогда нам не нужны никакие циклы:

Dim values As Variant
values = Sheet1.Range("A2:B" & lastRow).Value

И готово: values - это двумерный вариантный массив на основе 1 (потому что он взят из Range), который содержит значения каждой ячейки в A2:B{lastRow}.

Примечание. Код, который потребляет этот массив должен избегать предположений о типах данных в нем.

1 голос
/ 20 февраля 2020

Как сказал @SJR, вариант позволит это сделать. Приведенный ниже пример является простым примером того, как добавлять различные типы в массив. Вместо x или y вы можете иметь ячейку на листе.

Dim array1() As Variant, i As Long
Dim x As String, y As Long

    x = "5"
    y = 1

    For i = 1 To 10

        ReDim Preserve array1(1 To 2, 1 To i)
        array1(1, i) = x
        array1(2, i) = y
        y = y + 1
        Debug.Print array1(1, i) & "," & array1(2, i) ' This is where you insert output

    Next
0 голосов
/ 20 февраля 2020

Вы можете сделать это:

BT = Range("A12")
ReDim IT(BT) As String
ReDim RBT(BT) As Integer

Dim IT_RBT(1 to 2) 'variant
IT_RBT(1) = IT   'add String array
IT_RBT(2) = RBT  'add Integer array

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

IT_RBT(1)(1)  'String type
IT_RBT(2)(1)  'Integer type
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...