Как получить значение массива, используя координаты в другом массиве? - PullRequest
0 голосов
/ 10 мая 2019

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

Dim myArray(1 To 4, 1 To 2) As String
Dim myCoord(1 To 2) As Long

myArray(1, 1) = "one_one"
myArray(1, 2) = "one_two"
...
myArray(4, 2) = "four_two"

myCoord(1) = 3
myCoord(2) = 1

MsgBox(myArray(myCoord))

Итак, я 'Я ищу что-то вроде вышеприведенного окна сообщений с возможностью отображения «three_one».Как и в Python my_multidim_list[*[i, j, ..., n]] Не знаю, возможно ли это вообще в VBA, но мне не кажется нелогичным реализовать такую ​​возможность.

Ответы [ 4 ]

1 голос
/ 10 мая 2019

Это был мой первоначальный ответ, который дает некоторые сведения о массивах VBA.Я буду расширять его, чтобы обеспечить достаточный фон для понимания моего второго ответа.

Простой ответ:

Dim myArray(1 To 4, 1 To 2) As String
Dim myCoord(1 To 2) As Long

myArray(1, 1) = "one_one"
myArray(1, 2) = "one_two"
...
myArray(4, 2) = "four_two"

myCoord(1) = 3
myCoord(2) = 1

MsgBox(myArray(myCoord(1), myCoord(2)))   ' This is the only change

Это основано на каждом элементе myCoord, определяющем номер элементасоответствующее измерение myArray.

Дополнительная информация о массивах

Когда вы пишете Dim myArray(1 To 4, 1 To 2) As String, количество измерений и количество элементов в каждом измеренииисправлено до тех пор, пока вы не перепишите этот оператор с другими номерами.

Если вы напишите Dim myArray() As String, вы объявляете массив, но число измерений и их границы будут определены во время выполнения.

В пределахВаш код вы можете написать ReDim myArray(a To b, c To d, e To f), где от a до f являются целочисленными выражениями.В большинстве языков, которые я знаю, нижняя граница определяется языком как 0 или, возможно, 1. В VBA нижняя граница может быть чем угодно, при условии, что нижняя граница не больше верхней границы.Я только однажды нашел применение для отрицательной нижней границы, но опция есть.

Позже вы можете написать ReDim myArray(g To h), но вы потеряете все данные в myArray.

В качестве альтернативы выможно написать ReDim Preserve myArray(a To b, c To d, e To g).Обратите внимание, что от а до е неизменны.С ReDim Preserve может быть изменена только верхняя граница последнего измерения.ReDim Preserve создает новый больший (или меньший) массив, копирует данные из старого массива и инициализирует новые элементы значением по умолчанию для типа данных.Чрезмерное использование ReDim Preserve может замедлить ваш макрос до сканирования, потому что интерпретатору не хватает памяти, но при осторожном использовании это может быть очень полезно.

Я бы, вероятно, определил myCoords с тем же числом измеренийкак myArray, но это зависит от вашей цели.

Я могу сказать гораздо больше о массивах VBA.Если вы расширите свои цели, я добавлю соответствующую дополнительную информацию.

0 голосов
/ 20 мая 2019

массивы VBA, варианты и массивы вариантов

Этот ответ обеспечивает основу, необходимую для понимания некоторого кода в других ответах и ​​для понимания, почему я отверг альтернативный подход.

Чтобы объявить простые переменные, я пишу:

Dim A As Long
Dim B As String
Dim C As Boolean
Dim D As Integer
Dim E As Double

В VBA есть набор встроенных типов данных, которые не сильно отличаются от доступных на других языках.

VBA имеет другой тип:

Dim F As Variant

Вариант может рассматриваться как нетипизированный или как контейнер. Если я напишу:

A = 5       ' OK because A is Long
A = "abc"   ' Will fail a n alphabetic string cannot be saved in a Long
A = "123"   ' OK because string "123" is automatically converted to integer 123

С другой стороны, я могу без ошибок написать следующее:

F = 5
F = "abc"
F = True
F = 1.23

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

F = 5
F = F + 2
F = "abc"
F = F & "def"

Все приведенные выше утверждения действительны, но

F = "abc"
F = F + 2

потерпит неудачу, потому что после установки F в «abc» его нельзя использовать в арифметическом выражении.

Variant также может содержать рабочий лист Excel, документ Word или любой объект Office. Вариант также может содержать массив. Когда Variant содержит объект или массив, синтаксис такой, как будто Variant стал этим объектом или массивом. Итак:

F = Worksheets("Data”)
F.Range("A1") = "abc"

Выше, F теперь фактически является переменной типа Worksheet, и к F можно получить доступ к любым свойствам или методам Worksheet. Это было просто для краткого ознакомления с полным объемом вариантов; остальная часть этого урока ограничена массивами.

Я могу «преобразовать» вариант в массив одним из двух способов:

1) F = VBA.Array(1, "abc", True)
2) ReDim F(0 To 2)

VBA.Array - это функция, которая возвращает одномерный массив Variant с нижней границей 0 и достаточным количеством элементов для хранения предоставленных значений. Я также могу написать F = Array(1, "abc", True). Функция Array аналогична функции VBA.Array, за исключением того, что нижняя граница зависит от текущего значения и значения команды Option Base.

Я использую функцию Array только если я собираюсь использовать функцию LBound для определения нижней границы. Я не до конца понимаю, что и на что не влияет команда Option Base, поскольку она не полностью задокументирована. Я видел различия между разными версиями разных продуктов Microsoft, которые, я уверен, случайны. Я уверен, что новый программист Microsoft предположил, что старый продукт работает разумным образом, когда это не так. Я очень стараюсь указывать как нижнюю, так и верхнюю границы, если могу. Если я не могу указать нижнюю границу, я проверяю это. Я по-прежнему использую подпрограммы, написанные в Excel 2003. Я считаю, что отсутствие проблем, с которыми я сталкиваюсь при работе со старыми подпрограммами, объясняется тем, что я избегаю предположений о том, как работает Excel, если они не полностью задокументированы.

Возвращаясь к учебнику, ReDim F(0 To 2) эффективно преобразует F в массив из трех элементов.

Все предыдущие обсуждения были об одномерных массивах. Также возможны обычные многомерные массивы:

Dim G(1 to 5) As Long
Dim H(1 to 5, 1 To 4) As String
Dim I(1 to 5, 1 To 4, 0 To 3) As Boolean

или

Dim G() As Long
Dim H() As String
Dim I() As Boolean
ReDim G(1 to 5)
ReDim H(1 to 5, 1 To 4)
ReDim I(1 to 5, 1 To 4, 0 To 3)

В первом блоке количество и размер измерений фиксируются во время компиляции. Со вторым блоком число и размер измерений устанавливаются во время выполнения и могут быть изменены.

В любом случае синтаксис для доступа:

G(n) = 3
H(n, m) = "abc"
I(n, m, o) = True

Этот тип многомерного не подходит для ваших требований. Хотя границы могут быть изменены во время выполнения, количество измерений не может быть изменено в операторе ReDim, оператор Select должен быть выбран из длинного списка предварительно подготовленных операторов ReDim с одним для каждого возможного числа измерений.

Альтернатива - рваные или неровные массивы, хотя они не рваны.

Рассмотрим:

Dim F As Variant
ReDim F(0 To 2)
F(0) = VBA.Array(1, 2, 3)
F(1) = VBA.Array(4, 5, 6)
F(2) = VBA.Array(7, 8, 9)

Я превратил F в массив из трех элементов, а затем превратил каждый элемент F в массив. Чтобы получить доступ к элементам внутренних массивов, я пишу: F (n) (m), где n и m могут быть 0, 1 или 2.

Я могу продолжить:

F (0) (0) = VBA.Array (10, 11, 12)

После этого изменения элемент F (0) (0) (0) имеет значение 10, а F (0) (0) (1) - значение 11.

Я могу продолжать это до бесконечности.Я читал, что VBA имеет ограничение 60 измерений с обычными многомерными массивами.Я не пробовал, но я не понимаю, почему при использовании этого метода, кроме памяти, было бы какое-либо ограничение на число измерений.

Этот метод, по-видимому, имеет то же ограничение, что и обычные многомерные массивы.Я могу написать F (0) (0) или F (0) (0) (0), но я не могу изменить глубину простой переменной во время выполнения.

Существует также проблема, заключающаяся в том, что ReDim F (0)) (От 0 до 2) отклоняется компилятором как неверный синтаксис.Вот почему я использовал VBA.Array для преобразования F (0) в массив.

Решение - рекурсия.Рассмотрим:

Call ReDimVar(F, "1 To 2", "3 To 4", "0 To 5")

ReDimVar может:

ReDim F(1 To 2)
Call ReDimVar(F(1), "3 To 4", "0 To 5") 
Call ReDimVar(F(2), "3 To 4", "0 To 5") 

Все это может быть выполнено с помощью простых циклов.Я отказался от этого метода, потому что рекурсия медленная, а ваш вопрос подразумевает значительные объемы данных и множество измерений.Однако, чтобы продемонстрировать, что это будет работать, поиграйте со следующим:

Sub TryMDVA()

  ' Demonstrate how to:
  '   1) Convert a Variant into a multi-dimension array
  '   2) Store values in every element of that multi-dimension array
  '   3) Extract values from every element of that multi-dimension array

  Dim Coords() As Long
  Dim ElementValue As String
  Dim InxB As Long             ' Index for both Bounds and Coords
  Dim InxD1 As Long
  Dim InxD2 As Long
  Dim InxD3 As Long
  Dim LwrBnds As Variant
  Dim MDVA As Variant
  Dim UppBnds As Variant

  LwrBnds = Array(1, 0, -3)
  UppBnds = Array(2, 5, 4)

  ReDim Bounds(LBound(LwrBnds) To UBound(LwrBnds))
  ReDim Coords(LBound(LwrBnds) To UBound(LwrBnds))

  Call FormatMDVA(MDVA, LwrBnds, UppBnds)

  Debug.Print "Results of formatting MDVA"
  Debug.Print "Bounds of MDVA are " & LBound(MDVA) & " to " & UBound(MDVA)
  Debug.Print "Bounds of MDVA(1) are " & LBound(MDVA(1)) & " to " & UBound(MDVA(1))
  Debug.Print "Bounds of MDVA(2) are " & LBound(MDVA(2)) & " to " & UBound(MDVA(2))
  Debug.Print "Bounds or MDVA(1)(0) are " & LBound(MDVA(1)(0)) & " to " & UBound(MDVA(1)(0))
  Debug.Print "Bounds or MDVA(2)(5) are " & LBound(MDVA(2)(5)) & " to " & UBound(MDVA(2)(5))

  ' Initialise Coords to lower bound of each dimension
  For InxB = LBound(LwrBnds) To UBound(LwrBnds)
    Coords(InxB) = LwrBnds(InxB)
  Next

  Do While True
    ' Build element value from coordinates
    ElementValue = Coords(LBound(Coords))
    For InxB = LBound(LwrBnds) + 1 To UBound(LwrBnds)
      ElementValue = ElementValue & "." & Coords(InxB)
    Next
    ' Store element value in element of MDVA specified by Coords
    Call PutElement(MDVA, Coords, ElementValue)
    ' Step Coords.  Think of Coords as a speedometer with each wheel marked
    ' with the available index values for a dimension. Starting on the right,
    ' check each wheel against the relevant ubound.  If it is less than the
    ' ubound, step it by 1. If it is the upper bound, reset it to the lower
    ' bound and try the next wheel to the left.  If the leftmost wheel is
    ' to be reset, Coords has been set to all possible values.
    For InxB = UBound(LwrBnds) To LBound(LwrBnds) Step -1
      If Coords(InxB) < UppBnds(InxB) Then
        Coords(InxB) = Coords(InxB) + 1
        Exit For
      Else
        If InxB = LBound(LwrBnds) Then
          Exit Do
        End If
        Coords(InxB) = LwrBnds(InxB)
      End If
    Next
  Loop

  Debug.Print "Example values from within MDVA"
  Debug.Print "MDVA(1)(0)(-3) = " & MDVA(1)(0)(-3)
  Debug.Print "MDVA(1)(0)(-2) = " & MDVA(1)(0)(-2)
  Debug.Print "MDVA(2)(3)(0) = " & MDVA(2)(3)(0)
  Debug.Print "MDVA(2)(5)(4) = " & MDVA(2)(5)(4)

  ' Initialise Coords to upper bound of each dimension
  For InxB = LBound(UppBnds) To UBound(UppBnds)
    Coords(InxB) = UppBnds(InxB)
  Next

  Debug.Print "List of all values in MDVA"
  Do While True
    ' Output value of element of MDVA identified by Coords
    Debug.Print "MDVA(" & Coords(LBound(UppBnds));
    For InxB = LBound(UppBnds) + 1 To UBound(UppBnds)
      Debug.Print ", " & Coords(InxB);
    Next
    Debug.Print ") = """ & GetElement(MDVA, Coords) & """"

    ' Set next value of Coords.  Similar to code block in PutElement
    ' but in the opposite direction
    For InxB = UBound(LwrBnds) To LBound(LwrBnds) Step -1
      If Coords(InxB) > LwrBnds(InxB) Then
        Coords(InxB) = Coords(InxB) - 1
        Exit For
      Else
        If InxB = LBound(LwrBnds) Then
          Exit Do
        End If
        Coords(InxB) = UppBnds(InxB)
      End If
    Next
  Loop

End Sub
Sub FormatMDVA(ByRef MDVA As Variant, LwrBnds As Variant, UppBnds As Variant)

  ' Size MDVA according to the bounds in the first elements of LwrBnds and
  ' UppBnds. If there are further elements in LwrBnds and UppBnds, call
  ' FormatMDVA to format every element of MDVA according to the remaining
  ' elements.

  Dim InxB As Long
  Dim InxM As Long
  Dim LB As Long
  Dim SubLwrBnds As Variant
  Dim SubUppBnds As Variant

  LB = LBound(LwrBnds)

  ReDim MDVA(LwrBnds(LB) To UppBnds(LB))

  If LBound(LwrBnds) = UBound(LwrBnds) Then
    ' All bounds applied
  Else
    ' Another dimension to format
    ReDim SubLwrBnds(LB + 1 To UBound(LwrBnds))
    ReDim SubUppBnds(LB + 1 To UBound(UppBnds))
    ' Copy remaining bounds to new arrays
    For InxB = LB + 1 To UBound(LwrBnds)
      SubLwrBnds(InxB) = LwrBnds(InxB)
      SubUppBnds(InxB) = UppBnds(InxB)
    Next

    For InxM = LwrBnds(LB) To UppBnds(LB)
      Call FormatMDVA(MDVA(InxM), SubLwrBnds, SubUppBnds)
    Next
  End If

End Sub
Function GetElement(ByRef MDVA As Variant, ByRef Coords() As Long) As Variant

  ' Return the value of the element of MDVA identified by Coords

  Dim InxC As Long
  Dim LB As Long
  Dim SubCoords() As Long

  LB = LBound(Coords)

  If LB = UBound(Coords) Then
    ' Have reached innermost array
    GetElement = MDVA(Coords(LB))
  Else
    ' At least one more nested array
    ReDim SubCoords(LB + 1 To UBound(Coords))
    For InxC = LB + 1 To UBound(Coords)
      SubCoords(InxC) = Coords(InxC)
    Next
    GetElement = GetElement(MDVA(Coords(LB)), SubCoords)
  End If
End Function
Sub PutElement(ByRef MDVA As Variant, ByRef Coords() As Long, _
               ElementValue As Variant)

  ' Save the value of ElementValue in the element of MDVA identified by Coords

  Dim InxC As Long
  Dim LB As Long
  Dim SubCoords() As Long

  LB = LBound(Coords)

  If LB = UBound(Coords) Then
    ' Have reached innermost array
    MDVA(Coords(LB)) = ElementValue
  Else
    ' At least one more nested array
    ReDim SubCoords(LB + 1 To UBound(Coords))
    For InxC = LB + 1 To UBound(Coords)
      SubCoords(InxC) = Coords(InxC)
    Next
    Call PutElement(MDVA(Coords(LB)), SubCoords, ElementValue)
  End If
End Sub
0 голосов
/ 15 мая 2019

Мой ответ превысил ограничение Stackoverflow в 30 000 символов, поэтому я разделил его на части.Это часть 2.

Этот блок кода - мои тестовые процедуры.Я рекомендую вам попробовать их.Если ничего другого, они демонстрируют, как использовать методы класса.

Option Explicit
Sub Test1()

  Dim MyArray1 As New MultDimStrArray
  Dim MyArray2 As MultDimStrArray
  Dim MyArray3 As MultDimStrArray

  Dim Bounds1 As Variant
  Dim Bounds2() As String

  Set MyArray2 = New MultDimStrArray
  Set MyArray3 = New MultDimStrArray

  Bounds1 = Array("3 To 10", "2", 5)

  ReDim Bounds2(1 To 3)
  Bounds2(1) = "3 to 10"
  Bounds2(2) = "2"
  Bounds2(3) = "5"

  ' Error-free calls
  Call MyArray1.Initialise("3 to 10", "2")
  Call MyArray1.OutDiag
  Call MyArray2.Initialise(Bounds1)
  Call MyArray2.OutDiag
  Call MyArray3.Initialise(Bounds2)
  Call MyArray3.OutDiag
  Call MyArray1.Initialise("3 to 10", 2)
  Call MyArray1.OutDiag
  Call MyArray1.Initialise(2, "-5 to -2")
  Call MyArray1.OutDiag

  ' Calls that end in an error
  Call MyArray1.Initialise("3 to 10", "a")
  Call MyArray1.OutDiag
  Call MyArray1.Initialise("3 to 2")
  Call MyArray1.OutDiag
  Call MyArray1.Initialise("2to3")
  Call MyArray1.OutDiag
  Call MyArray1.Initialise(0)
  Call MyArray1.OutDiag
  Call MyArray1.Initialise(1.5)
  Call MyArray1.OutDiag
  Call MyArray1.Initialise("2 to ")
  Call MyArray1.OutDiag
  Call MyArray1.Initialise(" to 2")
  Call MyArray1.OutDiag

End Sub
Sub Test2()

  Dim InxD1 As Long
  Dim InxD2 As Long
  Dim InxD3 As Long
  Dim MyArray As New MultDimStrArray
  Dim Start As Variant
  Dim ValueCrnt As String
  Dim Values() As String

  Call MyArray.Initialise("3 to 5", 3)

  Call MyArray.PutElements(Array(3, 1), _
                            Array("Three-One", "Three-Two", "Three-Three", _
                                  "Four-One", "Four-Two", "Four-Three", _
                                  "Five-One", "Five-Two", "Five-Three"))

  Call MyArray.OutDiag

  ReDim Values(0 To 0)
  For InxD1 = 3 To 5
    For InxD2 = 1 To 3
      Start = Array(InxD1, InxD2)
      Values(0) = InxD1 & "." & InxD2
      Call MyArray.PutElements(Start, Values)
    Next
  Next

  Call MyArray.OutDiag

  For InxD1 = 3 To 5
    For InxD2 = 1 To 3
      Start = Array(InxD1, InxD2)
      ValueCrnt = InxD1 & "-" & InxD2
      Call MyArray.PutElements(Start, ValueCrnt)
    Next
  Next

  Call MyArray.OutDiag

  Call MyArray.Initialise("5 to 10", 3, "-3 to 4")

  Debug.Print
  ReDim Values(-3 To 4)
  For InxD1 = 10 To 5 Step -1
    For InxD2 = 1 To 3
      Start = Array(InxD1, InxD2, -3)
      For InxD3 = -3 To 4
        Values(InxD3) = InxD1 & "." & InxD2 & "." & InxD3
      Next
      Call MyArray.PutElements(Start, Values)
    Next
  Next

  Call MyArray.OutDiag

End Sub
Sub Test3()

  Dim InxD1 As Long
  Dim InxD2 As Long
  Dim InxV As Long
  Dim MyArray As New MultDimStrArray
  Dim Start As Variant
  Dim ValueCrnt As String
  Dim Values() As String

  Call MyArray.Initialise("3 to 5", 3)

  Call MyArray.PutElements(Array(3, 1), _
                            Array("Three-One", "Three-Two", "Three-Three", _
                                  "Four-One", "Four-Two", "Four-Three", _
                                  "Five-One", "Five-Two", "Five-Three"))

  Call MyArray.OutDiag

  ReDim Values(1 To 9)

  Call MyArray.GetElements(Array(3, 1), Values)

  Debug.Print
  For InxV = LBound(Values) To UBound(Values)
    Debug.Print """" & Values(InxV) & """  ";
  Next
  Debug.Print

  ReDim Values(1 To 3)

  Debug.Print
  For InxD1 = 3 To 5

    Call MyArray.GetElements(Array(InxD1, 1), Values)

    For InxV = LBound(Values) To UBound(Values)
      Debug.Print """" & Values(InxV) & """  ";
    Next
    Debug.Print

  Next

  ReDim Values(1 To 4)
  For InxV = LBound(Values) To UBound(Values)
    Values(InxV) = "Unchanged"
  Next

  Call MyArray.GetElements(Array(5, 1), Values)

  Debug.Print
  For InxV = LBound(Values) To UBound(Values)
    Debug.Print """" & Values(InxV) & """  ";
  Next
  Debug.Print

  Debug.Print
  For InxD1 = 3 To 5
    For InxD2 = 1 To 3
      Call MyArray.GetElements(Array(InxD1, InxD2), ValueCrnt)
      Debug.Print "(" & InxD1 & ", " & InxD2 & ") contains " & ValueCrnt
    Next
  Next

End Sub

За прошедшие годы я создал подпрограммы и функции, которые выполняют полезные задачи, не предусмотренные стандартными подпрограммами и функциями Excel.Я использую PERSONAL.XLSB в качестве библиотеки для хранения всех этих макросов.Это одна из тех функций, которая используется OutDiag.

Option Explicit
Public Function PadR(ByVal Str As String, ByVal PadLen As Long, _
                     Optional ByVal PadChr As String = " ") As String

  ' Pad Str with trailing PadChr to give a total length of PadLen
  ' If the length of Str exceeds PadLen, Str will not be truncated

  '   Nov15 Coded
  ' 15Sep16 Added PadChr so could pad with characters other than space

  If Len(Str) >= PadLen Then
    ' Do not truncate over length strings
    PadR = Str
  Else
    PadR = Left$(Str & String(PadLen, PadChr), PadLen)
  End If

End Function
0 голосов
/ 15 мая 2019

Мой ответ превысил ограничение Stackoverflow в 30 000 символов, поэтому я разделил его на части.Это часть 1.

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

ЕслиВы спросили меня пару месяцев назад о занятиях по VBA, я бы отказался.На мой взгляд, если ваше требование было достаточно сложным, чтобы нуждаться в классе, VBA не был подходящим языком.Я не полностью изменил свое мнение, но недавно я обнаружил класс VBA StringBuilder, который мне показался очень удобным.Опираясь на этот опыт, я решил создать класс для удовлетворения ваших требований, который показал мне, как легко класс может скрыть сложную обработку от пользователя.

Я назвал свой класс MultDimStrArray.Если вам не нравится это имя, измените его на то, что вы предпочитаете.Если вы попробуете мои тестовые макросы, вы будете менять имя во всем их модуле.

Мой класс не имеет открытых свойств.Он имеет четыре открытых метода: Initialise, PutElements, GetElements и OutDiag.

Initalise записывает число и границы измерений.Примеры вызовов:

Dim MyArray1 As New MultDimStrArray
Call MyArray1.Initialise("3 to 10", "2") 

и

Dim MyArray2 As MultDimStrArray
Dim Bounds1 As Variant
Bounds1 = Array( ("3 to 10", "2") 
Call MyArray1.Initialise(Bounds1) 

То есть вы можете создать многомерный массив строк, используя:

Dim MyArray1 As New MultDimStrArray

или

Dim MyArray2 As MultDimStrArray
Set MyArray2 = New MultDimStrArray

Первый метод более популярен, но, очевидно, второй более эффективен.

Вы можете записать границы измерений в вызове Initialise или в предопределенном массиве.Я использовал функцию Array для загрузки массива.Вы можете загрузить массив обычным способом, если хотите.Все три метода демонстрируются в макросе Test1

После инициализации массива MDS вы используете PutElements для помещения значений в него.Формат вызова:

Call MyArray.PutElements(Start, Values)

Start - массив с одним элементом на измерение в MyArray;он идентифицирует элемент в MyArray.Значения могут быть одной переменной или массивом любого типа, при условии, что ее элементы могут быть преобразованы в строки.Если Values ​​представляет собой одну переменную или массив длины один, ее содержимое будет скопировано в элемент, указанный в Start.Если Values ​​является массивом длиной больше единицы, его содержимое копируется в MyArray, начиная с Start.Вызов PutElements может поместить одно значение в MyArray или может заполнить весь массив или что-нибудь между ними.Макрос Test2 показывает множество способов использования PutElements.

GetElements используется для извлечения значения или значений из MyArray.Формат вызова такой же, как для PutElement, а параметры такие же;отличается только направление копирования.

Последний метод - OutDiag, у которого нет параметров.Он выводит полную информацию о MyArray в Immediate Window.Непосредственное окно может содержать до 200 строк.Я рассмотрел вывод в текстовый файл.Если вам нужна эта процедура и у вас большие объемы данных, я могу изменить ее для вывода файла.

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

Не смотрите на класс, кроме как на взглядв документации по использованию в верхней части каждого метода.Попробуйте макросы Test1, Test2 и Test3.Адаптируйте их, чтобы они лучше соответствовали вашим требованиям.Попробуйте реальные данные.Я оставил свой первоначальный ответ в конце этого ответа, но вам понадобится больше информации о массивах VBA, чтобы понять код в классе.Я расширю свой первоначальный ответ как мое следующее задание.

Этот блок кода является классом.Он должен быть помещен в модуль класса с именем MultDimStrArray.Я оставил свой диагностический код, но закомментировал большую его часть.Если вы столкнетесь с ошибками, сообщите о них мне, так как я не думаю, что у вас есть знания, чтобы отладить класс самостоятельно.

Option Explicit
' Members
Private MDSArray() As String  ' The MD array is held as a 1D array
' Elements are held in the sequence:
'  1D  2D  3D   4D ... nD
'  lb  lb  lb  lb      lb to ub
'  lb  lb  lb  lb+1    lb to ub
'  lb  lb  lb  lb+2    lb to ub
'   :   :   :   :      :
'  lb  lb  lb  ub      lb to ub
'  lb  lb lb+1 lb      lb to ub
'   :   :   :   :      :
'  ub  ub  ub  ub      lb to ub
' Note: each dimension has its own lower and upper bound
Private DimMax As Long        ' Number of dimensions
Private DimOffs() As Long     ' Offset from element to equivalent element in next
                              ' repeat for each dimension.
                              ' For dimension 1, this is offset from (a,b,c,d) to (a+1,b,c,d).
                              ' For dimension 2, this is offset from (a,b,c,d) to (a,b+1,c,d).
                              ' And so on.
                              ' Used to convert (a,b,c,d) to index into MDSArray.
Private InxMax As Long        ' The total number of elements in the MDS array
Private LBounds() As Long     ' Lower bound of each dimension
Private UBounds() As Long     ' Upper bound of each dimension
' Methods
Public Sub Class_Initialize()
  ' Will be called by interpreter when it wishes to initialise an instance of
  ' MultDimStrArray.  Setting NumDim = 0 indicates that the instance has not
  ' be initialised by the class.
  DimMax = 0
End Sub
Public Sub GetElements(ParamArray Params() As Variant)

  ' Extracts one or more strings starting at a specified element from
  ' the multi-dimensional string array.

  ' This sub has two compulsory parameters.  The declaration uses a ParamArray
  ' to allow maximum flexibility in the type of those parameters.  Effectively,
  ' this sub has a declaration of:
  '   GetElements(ByRef Start() As xxxx, ByRef Values() as yyyy) or
  '   GetElements(ByRef Start() As xxxx, ByVal Values as yyyy) or
  '     where xxxx can be any of the integer types plus Variant or String.
  '       and yyyy can be any type that can be accept a string.

  ' Start is a one-dimensional array with DimMax, integer elements.  If the
  ' type of the array is Variant or String, the element values must be integer
  ' or an integer held as a string. The bounds of the array are not important.
  ' A lower bound of one to match dimension one may be convenient but a lower
  ' bound of zero or some other value may be used if wished.

  ' If the MDS array has N dimensions, Start must contain N values each of
  ' which must be within the bounds for the corresponding dimension.  Together,
  ' the values within Start specify an element with the MDS array.

  ' Values can be a String or Varient variable or a one-dimensional String or
  ' Varient array.  If the values within the MDS array are known to be
  ' integer, real or Boolean, then other types.  However, if a value within
  ' the MDS array is not as expected, a call of GetElements may result in a
  ' fatal, VBA error.

  ' If Values is a variable or an array with a length of one, the value of
  ' element Start of the MDS array will be copied to Values.

  ' If Values is an array with a length greater than one, values will be
  ' copied to it from the MDS array starting from element Start. If possible,
  ' array Values will be filled; however, if there are insufficient elements
  ' in the MDS array, the remaining elements of Values will be left unchanged.

  'Debug.Print "GetElements"

  If DimMax = 0 Then
    Debug.Assert False    'Not initialised
    Exit Sub
  End If

  Dim InxA As Long
  Dim InxS As Long
  Dim InxV As Long
  Dim LB As Long
  Dim Start() As Long
  Dim UB As Long

  LB = LBound(Params)
  UB = UBound(Params)

  If LB + 1 <> UB Then
    Debug.Assert False  ' There must be exactly two parameters
    Exit Sub
  End If

  If VarType(Params(LB)) < vbArray Then
    Debug.Assert False  ' First parameter (Start) must be an array
    Exit Sub
  End If

  ' Params(Params(LB)) contains values for Start.
  InxS = 1
  If UBound(Params(LB)) - LBound(Params(LB)) + 1 <> DimMax Then
    Debug.Assert False  ' Start must have one entry per dimension
    Exit Sub
  End If

  ReDim Start(1 To DimMax)

  For InxV = LBound(Params(LB)) To UBound(Params(LB))
    ' An error here indicates a value that cannot be converted to a Long
    Start(InxS) = Params(LB)(InxV)
    If Start(InxS) < LBounds(InxS) Or Start(InxS) > UBounds(InxS) Then
      Debug.Assert False  ' Index is outside range for dimension
      Exit Sub
    End If
    InxS = InxS + 1
  Next

  InxA = 1
  For InxS = 1 To DimMax
    InxA = InxA + (Start(InxS) - LBounds(InxS)) * DimOffs(InxS)
  Next

  '' Report conversion from coordinates to InxA
  'Debug.Print "(";
  'For InxS = 1 To DimMax - 1
  '  Debug.Print Start(InxS) & ", ";
  'Next
  'Debug.Print Start(DimMax) & ") -> " & InxA

  If VarType(Params(UB)) < vbArray Then
    ' Single value to be extracted from element defined by Start
    'Debug.Assert False
    ' An error here indicates Params(UB) cannot hold the value in the MDS array
    Params(UB) = MDSArray(InxA)
  Else
    ' Array of values to be extracted starting at element defined by Start
    'Debug.Assert False
    'Debug.Print "Params(UB) Bounds: " & LBound(Params(UB)) & " To " & UBound(Params(UB))
    For InxV = LBound(Params(UB)) To UBound(Params(UB))
      Params(UB)(InxV) = MDSArray(InxA)
      'Debug.Print "(" & InxA & ") contains " & Params(UB)(InxV)
      InxA = InxA + 1
      If InxA > InxMax Then
        ' Have reached end of MDSArray
        Exit For
      End If
    Next
  End If

End Sub
Public Sub Initialise(ParamArray Params() As Variant)

  ' Initalises an instance of the class by:
  '   Setting DimMax to number of dimensions
  '   Recording lower and upper bounds in LBounds and UBounds
  '   Calculating length of each dimension and recording them in DimOffs
  '   Calculating total number of entries in array and recording in InxMax
  '   ReDimming MDSarray to the required length

  ' The format of the call is: Xxxx.Initialise(parameters)

  ' Xxxx must be an object of type MultDimStrArray which must have been
  ' defined in one of these two ways:

  '   (1) Dim Xxxx As New MultDimStrArray

  '   (2) Dim Xxxx As MultDimStrArray
  '       Set Xxxx = New MultDimStrArray

  ' Most people use method 1 although method 2 results in more efficient code
  ' according to Charles H Pearson.  http://www.cpearson.com/excel/classes.aspx

  ' In all cases, the parameters are a list of bounds. Those bounds can be
  ' specified as a list in the Initialise call or can be preloaded into an
  ' array.

  ' If the bounds are specified within the call, its format will be something like:
  '   Call Xxxx.Initialise(BoundsForDim1, BoundsForDim2, BoundsForDim3, ...)

  ' If the bounds are specified in a preloaded array, its format will be something like:
  '     Bounds = Array(BoundsForDim1, BoundsForDim2, BoundsForDim3, ...)
  '     Call Xxxx.Initialise(Bounds)
  '   or
  '     Bounds(1) = BoundsForDim1
  '     Bounds(2) = BoundsForDim2
  '     Bounds(3) = BoundsForDim3
  '       :    :    :    :
  '     Call Xxxx.Initialise(Bounds)

  ' BoundsForDimN can be
  '     lb " to " ub
  '   or
  '     ub

  ' Each dimension will have its own lower bound (lb) and upper bound (ub).
  ' If the lb is not specified, it will default to 1. So 'ub' is equivalent to
  ' '1 To ub'

  'Debug.Print "Initalise"

  Dim Bounds() As String
  Dim BoundParts() As String
  Dim InxB As Long
  Dim InxP As Long
  Dim LB As Long
  Dim NumElmnts As Long

  ' Convert different formats for Params to a single format
  LB = LBound(Params)
  If LB = UBound(Params) Then
    ' Single parameter.
    'Debug.Assert False
    If VarType(Params(LB)) > vbArray Then
      ' Params(LB) is an array.  Call was of the form: .Initialise(Array)
      ' Copy contents of Array to Bounds
      'Debug.Assert False
      DimMax = UBound(Params(LB)) - LBound(Params(LB)) + 1
      ReDim Bounds(1 To DimMax)
      InxB = 1
      For InxP = LBound(Params(LB)) To UBound(Params(LB))
        ' If get error here, element InxP of Array could not be converted to a string
        Bounds(InxB) = Params(LB)(InxP)
        InxB = InxB + 1
      Next
    Else
      ' Params(LB) is not an array.  Call was of the form: .Initialise(X)
      ' where X is "N to M" or "M".  Using this class for a 1D array would
      ' be inefficient but the code would work so it is not forbidden.
      'Debug.Assert False
      DimMax = 1
      ReDim Bounds(1 To 1)
      ' If get error here,  X could not be converted to a string
      Bounds(1) = Params(LB)
    End If
  Else
    ' Multiple parameters.  Call was of the form: .Initialise(X, Y, Z ...)
      ' where X, Y, Z and so on can be "N to M" or "M".
      ' Copy X, Y, Z and so to Bounds
      'Debug.Assert False
      DimMax = UBound(Params) - LBound(Params) + 1
      ReDim Bounds(1 To DimMax)
      InxB = 1
      For InxP = LBound(Params) To UBound(Params)
        ' If get error here, one of X, Y, Z and so could not be
        ' converted to a string
        Bounds(InxB) = Params(InxP)
        InxB = InxB + 1
      Next
   End If

   'Debug.Print "Bounds in call:  ";
   'For InxB = 1 To UBound(Bounds)
   '  Debug.Print Bounds(InxB) & "  ";
   'Next
   'Debug.Print

   ' Decode values in Bounds and store in in LBounds and UBounds
   ReDim LBounds(1 To DimMax)
   ReDim UBounds(1 To DimMax)
   ReDim DimOffs(1 To DimMax)
   InxMax = 1

   For InxB = 1 To UBound(Bounds)
     ' Value can be "lb To Ub" or "Ub"
     If IsNumeric(Bounds(InxB)) Then
       ' Upper bound only
       'Debug.Assert False
       If Int(Bounds(InxB)) = Val(Bounds(InxB)) Then
         ' Integer value
         'Debug.Assert False
         LBounds(InxB) = 1
         UBounds(InxB) = Bounds(InxB)
       Else
         Debug.Print "Invalid parameter: " & Bounds(InxB)
         Debug.Assert False         ' Real ub; only integer indices allowed
         DimMax = 0                ' Not initialised
         Exit Sub
       End If
     Else
       ' lb To ub
       BoundParts = Split(LCase(Bounds(InxB)), " to ")
       LB = LBound(BoundParts)
       If LB + 1 <> UBound(BoundParts) Then
         Debug.Print "Invalid parameter: " & Bounds(InxB)
         Debug.Assert False         ' Not "ub" and not "lb to ub"
         DimMax = 0                ' Not initialised
         Exit Sub
       Else
         If IsNumeric(BoundParts(LB)) And _
            IsNumeric(BoundParts(LB + 1)) Then
           If Int(BoundParts(LB)) = Val(BoundParts(LB)) And _
              Int(BoundParts(LB + 1)) = Val(BoundParts(LB + 1)) Then
             'Debug.Assert False
             LBounds(InxB) = BoundParts(LB)
             UBounds(InxB) = BoundParts(LB + 1)
           Else
             Debug.Print "Invalid parameter: " & Bounds(InxB)
             Debug.Assert False         ' lb or ub or both are real; indices must be integer
             DimMax = 0                ' Not initialised
             Exit Sub
           End If
         Else
           Debug.Print "Invalid parameter: " & Bounds(InxB)
           Debug.Assert False         ' One or both of lb and ub are non-numeric or missing
           DimMax = 0                ' Not initialised
           Exit Sub
         End If
       End If
     End If
     If LBounds(InxB) > UBounds(InxB) Then
       Debug.Print "Invalid parameter: " & Bounds(InxB)
       Debug.Assert False         ' lb must be less than ub
       DimMax = 0                ' Not initialised
       Exit Sub
     End If
   Next InxB

   ' Calculate offset to equivalent element in next repeat for each dimension.
   DimOffs(DimMax) = 1
   NumElmnts = (UBounds(DimMax) - LBounds(DimMax) + 1)
   For InxB = DimMax - 1 To 1 Step -1
     DimOffs(InxB) = NumElmnts * DimOffs(InxB + 1)
     NumElmnts = (UBounds(InxB) - LBounds(InxB) + 1)  ' Need for next loop
   Next
   InxMax = NumElmnts * DimOffs(1)

   ReDim MDSArray(1 To InxMax)

End Sub
Public Sub OutDiag()

  Dim ColWidthCrnt As Long
  Dim ColWidthTotalLastDim As Long
  Dim ColWidthsLast() As Long
  Dim ColWidthsNotLast() As Long
  Dim Coords() As Long
  Dim InxA As Long            ' Index into MDSArray
  Dim InxC As Long            ' Index into Coords
  Dim InxD As Long            ' Index into dimensions
  'Dim InxL As Long            ' Index into Last dimension
  Dim InxWL As Long           ' Index into ColWidthsLast

  'Debug.Print "OutDiag"

  If DimMax = 0 Then
    Debug.Assert False   'Not initialised
    Exit Sub
  End If

  Debug.Print "DimMax=" & DimMax
  For InxD = 1 To DimMax
    Debug.Print "Dim" & InxD & "  Bounds=" & LBounds(InxD) & " to " & _
                UBounds(InxD) & "  Offset to next repeat=" & DimOffs(InxD)
  Next
  Debug.Print "InxMax=" & InxMax
  Debug.Print

  ReDim ColWidthsNotLast(1 To DimMax - 1)
  ReDim ColWidthsLast(LBounds(DimMax) To UBounds(DimMax))

  ' Ensure columns for all but last wide enough for headings and coordinates
  For InxD = 1 To DimMax - 1
    ColWidthsNotLast(InxD) = Len("D" & CStr(InxD))
    'Debug.Print "ColWidthsNotLast(" & InxD & ") initialsed to " & _
    '            ColWidthsNotLast(InxD) & " because of header ""D" & _
    '            CStr(InxD) & """"
    ColWidthCrnt = Len(CStr(LBounds(InxD)))
    If ColWidthsNotLast(InxD) < ColWidthCrnt Then
      Debug.Assert False
      ColWidthsNotLast(InxD) = ColWidthCrnt
      'Debug.Print "ColWidthsNotLast(" & InxD & ") increased to " & _
      '            ColWidthsNotLast(InxD) & " because of lower bound """ & _
      '            CStr(LBounds(InxD)) & """"
    End If
    ColWidthCrnt = Len(CStr(UBounds(InxD)))
    If ColWidthsNotLast(InxD) < ColWidthCrnt Then
      Debug.Assert False
      ColWidthsNotLast(InxD) = ColWidthCrnt
      'Debug.Print "ColWidthsNotLast(" & InxD & ") increased to " & _
      '            ColWidthsNotLast(InxD) & " because of upper bound """ & _
      '            CStr(UBounds(InxD)) & """"
    End If
  Next

  ' Ensure columns for last dimension wide enough for headings
  For InxWL = LBounds(DimMax) To UBounds(DimMax)
    ColWidthsLast(InxWL) = Len(CStr(InxD))
    'Debug.Print "ColWidthsLast(" & InxWL & ") initialised to " & _
    '            ColWidthsLast(InxWL) & " because of index """ & CStr(InxWL) & """"
  Next

  ' Ensure columns for last dimension wide enough for values
  ReDim Coords(1 To DimMax)
  ' Initialise Coords to indices for first entry in MDS array
  For InxC = 1 To DimMax
    Coords(InxC) = LBounds(InxC)
  Next

  '' Output co-ordinates to show which elements caused increase in width
  'Debug.Print "(";
  'For InxD = 1 To DimMax - 1
  '  Debug.Print Coords(InxD) & ", ";
  'Next
  'Debug.Print Coords(DimMax) & ") ";

  InxA = 1
  ' Check length of each value against length of each column for last dimension
  ' Increase length of column for last dimension if necessary
  Do While True
    ' Length for entry corrsponding specified by Coords
    ColWidthCrnt = Len(MDSArray(InxA))
    ' Column for current index into last dimension
    InxWL = Coords(DimMax)
    ' Increase column width if necessary
    If ColWidthsLast(InxWL) < ColWidthCrnt Then
      'Debug.Assert False
      ColWidthsLast(InxWL) = ColWidthCrnt

      '' Report reason for increased column width
      'Debug.Print "ColWidthsLast(" & InxWL & ") increased to " & _
      '            ColWidthsLast(InxWL) & " because of value """ & _
      '            MDSArray(InxA) & """"
    End If

    ' Step Coords to next entry
    For InxD = DimMax To 1 Step -1
      If Coords(InxD) < UBounds(InxD) Then
        Coords(InxD) = Coords(InxD) + 1
        Exit For
      Else
        Coords(InxD) = LBounds(InxD)
      End If
    Next
    InxA = InxA + 1   ' Step index into MDSArray to match Coords
    If InxA > InxMax Then
      Exit Do
    End If

    '' Output co-ordinates to show which elements caused increase in width
    'Debug.Print "(";
    'For InxD = 1 To DimMax - 1
    '  Debug.Print Coords(InxD) & ", ";
    'Next
    'Debug.Print Coords(DimMax) & ") ";

  Loop
  'Debug.Print

  ' Output header
  Debug.Print "Value for each element in MDSArray"
  Debug.Print "|";
  For InxD = 1 To DimMax - 1
    Debug.Print PadR("D" & CStr(InxD), ColWidthsNotLast(InxD)) & "|";
  Next
  Debug.Print "|";
  For InxWL = LBounds(DimMax) To UBounds(DimMax)
    Debug.Print PadR(CStr(InxWL), ColWidthsLast(InxWL)) & "|";
  Next
  Debug.Print

  ' Output data rows.
  ' One row for each value of each index for every dimension except last
  ' Left of row contains indices for dimensions other thsn last
  ' Right of row contains values for each index into last dimension
  ' Initialise Coords to indices for first entry in MDS array
  For InxC = 1 To DimMax
    Coords(InxC) = LBounds(InxC)
  Next
  InxA = 1
  Do While InxA <= InxMax
    Debug.Print "|";
    ' Output current index for dimensions except last
    For InxD = 1 To DimMax - 1
      Debug.Print PadR(Coords(InxD), ColWidthsNotLast(InxD)) & "|";
    Next
    Debug.Print "|";
    ' Output values for each index into last dimension
    Do While True
      Debug.Print PadR(MDSArray(InxA), ColWidthsLast(Coords(DimMax))) & "|";
      ' Step Coords to next entry
      For InxD = DimMax To 1 Step -1
        If Coords(InxD) < UBounds(InxD) Then
          Coords(InxD) = Coords(InxD) + 1
          Exit For
        Else
          Coords(InxD) = LBounds(InxD)
        End If
      Next
      InxA = InxA + 1   ' Step index into MDSArray to match Coords
      If InxA > InxMax Then
        Exit Do
      End If
      If Coords(DimMax) = LBounds(DimMax) Then
        ' Start of new row
        Debug.Print
        Exit Do
      End If
    Loop
  Loop
  Debug.Print

End Sub
Public Sub PutElements(ParamArray Params() As Variant)

  ' Saves one or more strings starting at a specified element within
  ' the multi-dimensional string array.

  ' This sub has two compulsory parameters.  The declaration uses a ParamArray
  ' to allow maximum flexibility in the type of those parameters.  Effectively,
  ' this sub has a declaration of:
  '   PutElements(ByRef Start() As xxxx, ByRef Values() as yyyy) or
  '   PutElements(ByRef Start() As xxxx, ByVal Values as yyyy) or
  '     where xxxx can be any of the integer types plus Variant or String.
  '       and yyyy can be any type that can be converted to a string plus
  '           Variant providing all the values within the Variant can be
  '           converted to strings.

  ' Start is a one-dimensional array with DimMax, integer elements.  If the
  ' type of the array is Variant or String, the element values must be integer
  ' or an integer held as a string. The bounds of the array are not important.
  ' A lower bound of one to match dimension one may be convenient but a lower
  ' bound of zero or some other value may be used if wished.

  ' If the MDS array has N dimensions, Start must contain N values each of
  ' which must be within the bounds for the corresponding dimension.  Together,
  ' the values within Start specify an element with the MDS array.

  ' Values can be a variable of any type that can be converted to a string.
  ' Alternately, Values can be a one-dimensional array containing one or more
  ' elements. If Values contains one element, the value of that element will be
  ' saved to element Start of the MDS array. If Values contains more than one
  ' element, the values of those elements will be saved to the MDS array
  ' starting at Start and continuing in the sequence defined at the top of this
  ' module until all values in Values have been saved or the last element of
  ' MDSArray has been reached.

  'Debug.Print "PutElements"

  If DimMax = 0 Then
    Debug.Assert False    'Not initialised
    Exit Sub
  End If

  Dim InxA As Long
  Dim InxS As Long
  Dim InxV As Long
  Dim LB As Long
  Dim Start() As Long
  Dim UB As Long

  LB = LBound(Params)
  UB = UBound(Params)

  If LB + 1 <> UB Then
    Debug.Assert False  ' There must be exactly two parameters
    Exit Sub
  End If

  If VarType(Params(LB)) < vbArray Then
    Debug.Assert False  ' First parameter (Start) must be an array
    Exit Sub
  End If

  ' Params(Params(LB)) contains values for Start.
  InxS = 1
  If UBound(Params(LB)) - LBound(Params(LB)) + 1 <> DimMax Then
    Debug.Assert False  ' Start must have one entry per dimension
    Exit Sub
  End If

  ReDim Start(1 To DimMax)

  For InxV = LBound(Params(LB)) To UBound(Params(LB))
    ' An error here indicates a value that cannot be converted to a Long
    Start(InxS) = Params(LB)(InxV)
    If Start(InxS) < LBounds(InxS) Or Start(InxS) > UBounds(InxS) Then
      Debug.Assert False  ' Index is outside range for dimension
      Exit Sub
    End If
    InxS = InxS + 1
  Next

  InxA = 1
  For InxS = 1 To DimMax
    InxA = InxA + (Start(InxS) - LBounds(InxS)) * DimOffs(InxS)
  Next

  '' Report conversion from coordinates to InxA
  'Debug.Print "(";
  'For InxS = 1 To DimMax - 1
  '  Debug.Print Start(InxS) & ", ";
  'Next
  'Debug.Print Start(DimMax) & ") -> " & InxA

  If VarType(Params(UB)) < vbArray Then
    ' Single value to be stored in element defined by Start
    'Debug.Assert False
    ' An error here indicates Params(UB) cannot be converted to a string
    MDSArray(InxA) = Params(UB)
  Else
    ' Array of values to be stored starting at element defined by Start
    'Debug.Assert False
    'Debug.Print "Params(UB) Bounds: " & LBound(Params(UB)) & " To " & UBound(Params(UB))
    For InxV = LBound(Params(UB)) To UBound(Params(UB))
      MDSArray(InxA) = Params(UB)(InxV)
      'Debug.Print Params(UB)(InxV) & " -> (" & InxA & ")"
      InxA = InxA + 1
      If InxA > InxMax Then
        ' Have reached end of MDSArray
        Exit For
      End If
    Next
  End If

End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...