Я использую VBA в Excel, чтобы использовать XML-файл и выгружать определенную информацию на отдельные вкладки. Я хочу объединить 2-мерные массивы. Массивы имеют «известное» количество столбцов, но «неизвестное» количество строк. Рассмотрим следующие два массива:Объединение 2D (2-мерных) массивов
array1:
a b c
d e f
array2:
1 2 3
4 5 6
Как объединить эти массивам, если я хочу следующий результат:
array3:
a b c
d e f
1 2 3
4 5 6
И только из любопытства, как бы я код, если вместо этого я хотел бы добавить к праву, а не внизу, как это:
array4:
a b c 1 2 3
d e f 4 5 6
Я не могу найти ответ к этому где угодно.
Пожалуйста, помните, что мой пример выше довольно мал, но на самом деле я пытаюсь сделать это с примерно 100 000 строк данных одновременно. Есть только шесть столбцов данных, если это имеет значение.
Цель состоит в том, чтобы собрать большой массив, а затем записать его в лист Excel всего за один шаг, потому что, когда я делаю это по частям, производительность очень плохая.
Если возможно, я бы предпочел решение, которое не требует итерации.
Причина, по которой я спрашиваю об обоих способах, заключается в том, что на самом деле я хочу добавить последовательность последовательно. Например, предположим, у меня есть четыре массива, A, B, C, D.
Сначала добавьте массив A:
A
Затем добавьте массив B:
A B
Затем добавьте массив С:
A B
C
Затем добавьте массив D:
A B
C D
и так далее ...
Имейте в виду, что каждый из указанных массивов будет иметь такой размер, что они «подходят» правильно означая А и Б имеют одинаковое количество строк, но разное количество столбцов. С другой стороны, A и C имеют одинаковое количество столбцов, но различное количество строк. И так далее ...
Я хотел добавить демонстрацию, используя код Макро Человека снизу. Вот то, что он дал (я добавил немного, чтобы читатели могли просто скопировать/вставить):
Option Explicit
Sub Testing()
Dim Array1(0 To 1, 0 To 2) As String
Array1(0, 0) = "a"
Array1(0, 1) = "b"
Array1(0, 2) = "c"
Array1(1, 0) = "d"
Array1(1, 1) = "e"
Array1(1, 2) = "f"
Dim Array2(0 To 1, 0 To 2) As String
Array2(0, 0) = "1"
Array2(0, 1) = "2"
Array2(0, 2) = "3"
Array2(1, 0) = "4"
Array2(1, 1) = "5"
Array2(1, 2) = "6"
Dim i As Long
For i = 1 To 25000
With Range("A" & Rows.Count).End(xlUp).Offset(IIf(IsEmpty([A1]), 0, 1), 0)
.Resize(UBound(Array1, 1) - LBound(Array1, 1) + 1, _
UBound(Array1, 2) - LBound(Array1, 2) + 1).Value = Array1
End With
With Range("A" & Rows.Count).End(xlUp).Offset(IIf(IsEmpty([A1]), 0, 1), 0)
.Resize(UBound(Array2, 1) - LBound(Array2, 1) + 1, _
UBound(Array2, 2) - LBound(Array2, 2) + 1).Value = Array2
End With
Next i
End Sub
При запуске приведенного выше кода, который идет обратно в таблицу каждый раз, чтобы написать небольшое количество данных, это занимает много времени.На моей двойной машине Xeon, например, 25-30 секунд.
Однако, если вы переписываете и заполняете массив FIRST, а затем пишите в электронную таблицу ONCE, он запускается примерно через одну секунду.
Option Explicit
Sub Testing()
Dim Array1(0 To 99999, 0 To 2) As String
Array1(0, 0) = "a"
Array1(0, 1) = "b"
Array1(0, 2) = "c"
Array1(1, 0) = "d"
Array1(1, 1) = "e"
Array1(1, 2) = "f"
Dim i As Long
For i = 0 To 99999
Array1(i, 0) = "a"
Array1(i, 1) = "b"
Array1(i, 2) = "c"
Next i
With Range("A" & Rows.Count).End(xlUp).Offset(IIf(IsEmpty([A1]), 0, 1), 0)
.Resize(UBound(Array1, 1) - LBound(Array1, 1) + 1, _
UBound(Array1, 2) - LBound(Array1, 2) + 1).Value = Array1
End With
End Sub
Я хотел бы увидеть решение, которое делает то же самое, за исключением возможности добавить «куски» данных вместо отдельных элементов. Добавление массивов в большие массивы, в идеале. Еще лучше было бы, если бы «родительский» массив каким-то образом динамически менялся.
Ответ Джона Колемана ниже работал отлично.
Я на самом деле в сочетании немного Macro Человека с испытанием() подпрограммой Джона и это динамически повторно размеры диапазон:
Option Explicit
Sub test()
Dim A As Variant, B As Variant
ReDim A(0 To 1, 0 To 1)
ReDim B(0 To 1, 0 To 1)
A(0, 0) = 1
A(0, 1) = 2
A(1, 0) = 3
A(1, 1) = 4
B(0, 0) = 5
B(0, 1) = 6
B(1, 0) = 7
B(1, 1) = 8
Dim Array1 As Variant
Array1 = Combine(A, B)
With Range("A" & Rows.Count).End(xlUp).Offset(IIf(IsEmpty([A1]), 0, 1), 0)
.Resize(UBound(Array1, 1) - LBound(Array1, 1) + 1, _
UBound(Array1, 2) - LBound(Array1, 2) + 1).Value = Array1
End With
End Sub
Я думаю, что я недопонимаю «массив». Вы можете сохранить все эти значения в массив, а затем отобразить их в Excel, но вы хотите ... вы можете пройти три столбца, затем вниз по строке, повторить. Или вы можете пройти шесть столбцов и вниз. Я хочу сказать, что массив Excel (AFAIK) не хранится каким-то физическим способом ... это всего лишь список элементов. Как вы показываете их в Excel, вы до 100%. Имеет ли это смысл? – BruceWayne
Я немного уточнил свой вопрос. это связано с VBA, который в конечном итоге записывается на лист excel. если я ударил лист, чтобы обновлять каждое значение или даже в больших кусках значений за раз, он берет навсегда. когда я перешел от хранения каждого значения отдельно, чтобы разместить их на листе в блоках, производительность значительно увеличилась. Я надеюсь найти способ сделать то же самое, но объединить массивы еще больше в VBA. – gotmike
Команда «Redim PRESERVE» может только расширить последний ранг *. Вероятно, вам лучше создать новый массив, который затемняется с добавлением UBounds и заполняется тогда оттуда. Держитесь подальше от '.Transpose', чтобы выполнить команду redim. Ваши 100K «ряды» данных превышают его ограничения. – Jeeped