KrabNaGalerah
Пользователь
Сообщений: 38
Регистрация: 02.09.2022
#1
05.09.2022 17:43:54
Здравствуйте, до этого создавал массивы с четкими размерами, сейчас понадобился табличный массив в который будет добавляться новая строка.
Проблема в том, что обычный Redim удаляет все данные, пробовал и с Preserve, но там вообще ошибку выдает, видимо работает только с однодимензиональным массивом.
В общем вопрос, как легко и без танцев с бубном добавлять новую строку в массив, при этом не терять существующие данные?
Спасибо!
In replay to @T.M. nice approach:
Try using the next function, which does not need transposing of column array:
Function AddElement(datafield, ByVal rowNum As Long, newData) As Variant
'Note: assumes 1-based 2dim input arrays with same column counts
'create zero-based combo container on the fly
With CreateObject("Forms.ComboBox.1")
.list = datafield ' assign datafield to zero-based list elems
.AddItem , rowNum - 1 ' add Null values to zero-based list index
'assign new data to each zero-based list column
Dim col As Long
For col = LBound(newData, 2) To UBound(newData, 2)
.list(rowNum - 1, col - 1) = newData(1, col)
Next col
AddElement = .list 'it returns a zero based 2D array...
End With
End Function
It can be tested in this way:
Sub testAddArrayrow()
Dim sh As Worksheet, newArr: sh = ActiveSheet 'was easier for me to check...
Dim data: data = sh.Range("A1:C4").Value
Dim newData: newData = sh.Range("A6:C6").Value
newArr = AddElement(data, 2, newData)
sh.Range("P1").Resize(UBound(newArr) + 1, UBound(newArr, 2) + 1).Value = newArr '+ 1 because of zero bazed 2D returned array
End Sub
We must make some researches in order to check the array size limitations, if any. It will be very interesting to not have such limitations, but I simply cannot hope too much from this direction…
Anyhow, the brilliant idea remains…
I´d like to add a row to a variant array:
Dim arrMod As Variant
arrMod(numberOfRow) = Array(myValue1, myValue2, myvalue3)
The execution of this code results into an exception: Error 13: type mismatch
How can I do it without iterating each column?
Thanks,
Regards
asked Apr 20, 2015 at 9:53
Your variable arrMod is not an array. You need to define it in VBA as an array using parenthesis:
Dim arrMod(0) As Variant
Obviously replace 0 with the maximum number of rows you have, or resize dynamically using redim preserve.
answered Apr 20, 2015 at 10:20
StevenSteven
6926 silver badges22 bronze badges
2
Do you need something like this:
Dim arrMod()
For i = 1 To 5
ReDim Preserve arrMod(i)
arrMod(i) = i
MsgBox Join(arrMod, vbCrLf)
Next i
answered Apr 20, 2015 at 11:59
genesposgenespos
3,1915 gold badges38 silver badges69 bronze badges
Массивы в VBA Excel: одномерные, многомерные и динамические. Объявление и использование массивов. Операторы Public, Dim и ReDim. Функции Array, LBound, UBound.
Массивы – это множества однотипных элементов, имеющих одно имя и отличающиеся друг от друга индексами. Они могут быть одномерными (линейными), многомерными и динамическими. Массивы в VBA Excel, как и другие переменные, объявляются с помощью операторов Dim и Public. Для изменения размерности динамических массивов используется оператор ReDim. Массивы с заранее объявленной размерностью называют статическими.
Одномерные массивы
Объявление одномерных (линейных) статических массивов в VBA Excel:
Public Massiv1(9) As Integer Dim Massiv2(1 To 9) As String |
В первом случае публичный массив содержит 10 элементов от 0 до 9 (нижний индекс по умолчанию — 0, верхний индекс — 9), а во втором случае локальный массив содержит 9 элементов от 1 до 9.
По умолчанию VBA Excel считает в массивах нижним индексом нуль, но, при желании, можно сделать нижним индексом по умолчанию единицу, добавив в самом начале модуля объявление «Option Base 1».
Многомерные массивы
Объявление многомерных статических массивов в VBA Excel аналогично объявлению одномерных массивов, но с добавлением размерностей дополнительных измерений через запятую:
‘Массив двухмерный Public Massiv1(3, 6) As Integer ‘Массив трехмерный Dim Massiv2(1 To 6, 1 To 8, 1 To 5) As String ‘Массив четырехмерный Dim Massiv3(9, 9, 9, 9) As Date |
Третий массив состоит из 10000 элементов — 10×10×10×10.
Динамические массивы
Динамические массивы в VBA Excel, в отличие от статических, объявляются без указания размерности:
Public Massiv1() As Integer Dim Massiv2() As String |
Такие массивы используются, когда заранее неизвестна размерность, которая определяется в процессе выполнения программы. Когда нужная размерность массива становится известна, она в VBA Excel переопределяется с помощью оператора ReDim:
Public Massiv1() As Integer Dim Massiv2() As String ReDim Massiv1(1 To 20) ReDim Massiv2(3, 5, 4) |
При переопределении размерности массива вместо верхнего индекса можно использовать переменную:
Dim Massiv1() as Variant, x As Integer x = 20 ReDim Massiv1(1 To x) |
Переопределять размерность динамических массивов в процессе работы программы можно неоднократно, как по количеству измерений, так и по количеству элементов в измерении.
С помощью оператора ReDim невозможно изменить обычный массив, объявленный с заранее заданной размерностью. Попытка переопределить размерность такого массива вызовет ошибку компиляции с сообщением: Array already dimensioned (Массив уже измерен).
При переопределении размерности динамических массивов в VBA Excel теряются значения их элементов. Чтобы сохранить значения, используйте оператор Preserve:
Dim Massiv1() As String ——— операторы ——— ReDim Massiv1(5, 2, 3) ——— операторы ——— ReDim Preserve Massiv1(5, 2, 7) |
Обратите внимание!
Переопределить с оператором Preserve можно только последнюю размерность динамического массива. Это недоработка разработчиков, которая сохранилась и в VBA Excel 2016. Без оператора Preserve можно переопределить все размерности.
Максимальный размер
Размер массива – это произведение длин всех его измерений. Он представляет собой общее количество элементов, содержащихся в данный момент в массиве.
По информации с сайта разработчиков, максимальный размер массивов зависит от операционной системы и доступного объема памяти. Использование массивов, размер которых превышает объем доступной оперативной памяти компьютера, приводит к снижению скорости, поскольку системе необходимо выполнять запись данных и чтение с диска.
Использование массивов
Приведу два примера, где не обойтись без массивов.
1. Как известно, функция Split возвращает одномерный массив подстрок, извлеченных из первоначальной строки с разделителями. Эти данные присваиваются заранее объявленному строковому (As String) одномерному динамическому массиву. Размерность устанавливается автоматически в зависимости от количества подстрок.
2. Данные в массивах обрабатываются значительно быстрее, чем в ячейках рабочего листа. Построчную обработку информации в таблице Excel можно наблюдать визуально по мерцаниям экрана, если его обновление (Application.ScreenUpdating) не отключено. Чтобы ускорить работу кода, можно значения из диапазона ячеек предварительно загрузить в динамический массив с помощью оператора присваивания (=). Размерность массива установится автоматически. После обработки данных в массиве кодом VBA полученные результаты выгружаются обратно на рабочий лист Excel. Обратите внимание, что загрузить значения в диапазон ячеек рабочего листа через оператор присваивания (=) можно только из двумерного массива.
Функции Array, LBound, UBound
Функция Array
Функция Array возвращает массив элементов типа Variant из первоначального списка элементов, перечисленных через запятую. Нумерация элементов в массиве начинается с нуля. Обратиться к элементу массива можно, указав в скобках его номер (индекс).
Sub Test1() Dim a() As Variant a = Array(«text», 25, «solo», 35.62, «stop») MsgBox a(0) & vbNewLine & a(1) & vbNewLine _ & a(2) & vbNewLine & a(3) & vbNewLine & a(4) End Sub |
Скопируйте код в модуль VBA Excel и запустите его на выполнение. Информационное сообщение MsgBox покажет значения массива, извлеченные по индексу.
Функция LBound
Функция LBound возвращает значение типа Long, равное наименьшему (нижнему) доступному индексу в указанном измерении массива.
Синтаксис:
LBound (arrayname[, dimension])
- arrayname — это имя переменной массива, является обязательным аргументом;
- dimension — это номер измерения массива, необязательный аргумент, по умолчанию принимает значение 1.
Наименьший индекс по-умолчанию может быть равен 0 или 1 в зависимости от настроек оператора Option Base. Нижняя граница архива, полученного с помощью функции Array, всегда равна 0.
При объявлении переменных массивов или переопределении их размерности наименьшие индексы могут быть любыми целыми числами, в том числе отрицательными.
Функция UBound
Функция UBound возвращает значение типа Long, равное наибольшему (верхнему) доступному индексу в указанном измерении массива.
Синтаксис:
UBound( arrayname[, dimension])
- arrayname — это имя переменной массива, является обязательным аргументом;
- dimension — это номер измерения массива, необязательный аргумент, по умолчанию принимает значение 1.
Функция UBound используется вместе с функцией LBound для определения размера массива.
Sub Test2() Dim a(—2 To 53) As String MsgBox «Наименьший индекс = « & LBound(a) & _ vbNewLine & «Наибольший индекс = « & UBound(a) End Sub |
Скопируйте код в модуль VBA Excel и запустите его на выполнение. Информационное сообщение MsgBox покажет значения наименьшего и наибольшего индекса переменной массива a.
Обход массива циклом
Обход одномерного массива циклом For… Next, в котором для определения границ массива используются функции UBound и LBound:
Sub Test3() Dim a() As Variant, i As Long a = Array(«text», 25, «solo», 35.62, «stop») For i = LBound(a) To UBound(a) Debug.Print «a(« & i & «) = « & a(i) Next End Sub |
Результат работы цикла вы увидите в окне Immediate.
Очистка (обнуление) массивов
Первый способ
Очистить любой массив, статический или динамический, без использования цикла можно с помощью оператора Erase. Термин «обнуление» можно применить только к массиву числового типа.
Dim Massiv1(4, 3) As String, Massiv2() As Variant ——— операторы ——— ‘переопределяем динамический массив ReDim Massiv2(2, 5, 3) ——— операторы ——— ‘очищаем массивы Erase Massiv1 Erase Massiv2 |
Обратите внимание, что оба массива при таком способе очистки будут возвращены в исходное состояние, которое они имели сразу после объявления:
- статический Massiv1 сохранит размерность (4, 3);
- динамический Massiv2 не сохранит размерность ().
Второй способ
Динамический массив можно очистить (обнулить) без использования цикла с помощью оператора ReDim. Просто переопределите его с той же размерностью.
Dim Massiv() As Double ——— операторы ——— ‘переопределяем массив ReDim Massiv(5, 6, 8) ——— операторы ——— ‘очищаем массив ReDim Massiv(5, 6, 8) |
xelaalex 0 / 0 / 0 Регистрация: 07.01.2013 Сообщений: 5 |
||||
1 |
||||
Удаление/добавление строки из/в двумерного массива07.01.2013, 21:59. Показов 15050. Ответов 12 Метки нет (Все метки)
Люди добрые, помогите, поискав на форуме, не нашел способа, как удалить или же добавить строку из двумерного массива. Нужно удалить строку с заданным номером.
надеюсь на помощь!
0 |
3217 / 966 / 223 Регистрация: 29.05.2010 Сообщений: 2,085 |
|
07.01.2013, 22:48 |
2 |
1. Удаление строки из массива — перезапись массива с пропуском номера строки.
1 |
5468 / 1148 / 50 Регистрация: 15.09.2012 Сообщений: 3,514 |
|
08.01.2013, 08:03 |
3 |
xelaalex, нужно в методичке посмотреть, которую вам выдали в институте, как удалять и добавлять строки в массивы, а не на форумах искать эту информацию.
0 |
0 / 0 / 0 Регистрация: 07.01.2013 Сообщений: 5 |
|
08.01.2013, 08:57 [ТС] |
4 |
Скрипт, если бы выдавали методичку, все было бы супер. Я по тому здесь и пишу, что методички в принципе нет, а задание надо сделать обязательно. Сформировать двумерный массив. Удалить из него строку с заданным номером; первую часть как я понял я выполнил, сейчас прошу вас написать вторую часть задания.
0 |
5468 / 1148 / 50 Регистрация: 15.09.2012 Сообщений: 3,514 |
|
08.01.2013, 09:00 |
5 |
xelaalex, просто в институте нужно делать по определённым правилам. Эти правила пишутся в методичках.
1 |
0 / 0 / 0 Регистрация: 07.01.2013 Сообщений: 5 |
|
08.01.2013, 09:03 [ТС] |
6 |
Скрипт, Спасибо, я думаю что так и нужно
0 |
5468 / 1148 / 50 Регистрация: 15.09.2012 Сообщений: 3,514 |
|
08.01.2013, 09:06 |
7 |
Спасибо, я думаю что так и нужно в институх дают задания, чтобы подумать, поэтому, скорее всего, нужно работать с одним и тем же массивом. Но об этом вам должны сказать в институте. Спросите у преподавателя, с одним массивом делать или можно создать новый массив.
0 |
призрак 3261 / 889 / 119 Регистрация: 11.05.2012 Сообщений: 1,702 Записей в блоге: 2 |
|
08.01.2013, 09:34 |
8 |
1. Удаление строки из массива — перезапись массива с пропуском номера строки. вы это попробовали и у вас получилось?
0 |
xelaalex 0 / 0 / 0 Регистрация: 07.01.2013 Сообщений: 5 |
||||
08.01.2013, 09:41 [ТС] |
9 |
|||
Скрипт, можно создать новый массив, что я только что попробовал сделать, но не могу удалить строку (не могу понять где в коде реализовать это условие), + я с »for, to, and» накосячид, но как по другому не знаю
0 |
Hugo121 6875 / 2807 / 533 Регистрация: 19.10.2012 Сообщений: 8,562 |
||||
08.01.2013, 10:16 |
10 |
|||
Сообщение было отмечено как решение РешениеКак вариант:
3 |
0 / 0 / 0 Регистрация: 07.01.2013 Сообщений: 5 |
|
08.01.2013, 10:21 [ТС] |
11 |
Hugo121, Спасибо огромное все работает)))
0 |
Igor_Tr 4377 / 661 / 36 Регистрация: 17.01.2010 Сообщений: 2,134 |
||||
08.01.2013, 12:14 |
12 |
|||
И еще. Нашел в сети.
0 |
6875 / 2807 / 533 Регистрация: 19.10.2012 Сообщений: 8,562 |
|
08.01.2013, 13:59 |
13 |
Preserve с двумерным работает только «вширь», что неудобно.
0 |