Vba excel добавить строку в массив

 

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

Luis Andrés García's user avatar

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

Steven's user avatar

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

genespos's user avatar

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

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Люди добрые, помогите, поискав на форуме, не нашел способа, как удалить или же добавить строку из двумерного массива. Нужно удалить строку с заданным номером.
к примеру вот массив

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
Sub www()
Dim i&, j&, m&, n&, a&()
Randomize
n = 10
m = 5
ReDim a(1 To n, 1 To m)
For i = 1 To n
    For j = 1 To m
        a(i, j) = Int(Rnd * 10000)
Next j, i
[a1].Resize(UBound(a, 1), UBound(a, 2)) = a
 
End Sub

надеюсь на помощь!



0



3217 / 966 / 223

Регистрация: 29.05.2010

Сообщений: 2,085

07.01.2013, 22:48

2

1. Удаление строки из массива — перезапись массива с пропуском номера строки.
2. Добавление: Redim preserve — потом перезапись массива начиная с номера строки на строку ниже и так далее.



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

Цитата
Сообщение от xelaalex
Посмотреть сообщение

Спасибо, я думаю что так и нужно

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



0



призрак

3261 / 889 / 119

Регистрация: 11.05.2012

Сообщений: 1,702

Записей в блоге: 2

08.01.2013, 09:34

8

Цитата
Сообщение от toiai
Посмотреть сообщение

1. Удаление строки из массива — перезапись массива с пропуском номера строки.
2. Добавление: Redim preserve — потом перезапись массива начиная с номера строки на строку ниже и так далее.

вы это попробовали и у вас получилось?



0



xelaalex

0 / 0 / 0

Регистрация: 07.01.2013

Сообщений: 5

08.01.2013, 09:41

 [ТС]

9

Скрипт, можно создать новый массив, что я только что попробовал сделать, но не могу удалить строку (не могу понять где в коде реализовать это условие), + я с »for, to, and» накосячид, но как по другому не знаю

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Sub www()
Dim i&, j&, m&, n&, a&()
Randomize
n = 10
m = 5
ReDim a(1 To n, 1 To m)
For i = 1 To n
    For j = 1 To m
        a(i, j) = Int(Rnd * 10000)
Next j, i
[a1].Resize(UBound(a, 1), UBound(a, 2)) = a
s = InputBox("Введите номер строки (от 1 до 10), которую Вы хотите удалить из массива")
t = Val(s)
Dim x&, y&, z&, k&, b&()
z = 9
k = 5
ReDim b(1 To k, 1 To z)
For x = 1 To t-1 and x = t+1 to z
For y = 1 To z
b(x, y) = a(i, j)
 Next y, x
 [b1].Resize(UBound(b, 1), UBound(b, 2)) = b
 End Sub



0



Hugo121

6875 / 2807 / 533

Регистрация: 19.10.2012

Сообщений: 8,562

08.01.2013, 10:16

10

Лучший ответ Сообщение было отмечено как решение

Решение

Как вариант:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Option Explicit
 
Sub www()
    Dim i&, j&, m&, n&, a&(), t&, ii&
    Randomize
    n = 10
    m = 5
    ReDim a(1 To n, 1 To m)
    For i = 1 To n
        For j = 1 To m
            a(i, j) = Int(Rnd * 10000)
        Next j, i
        [a1].Resize(UBound(a, 1), UBound(a, 2)) = a
        t = InputBox("Введите номер строки (от 1 до " & n & "), которую Вы хотите удалить из массива")
        ReDim b(1 To UBound(a) - 1, 1 To m)
        For i = 1 To n
            If i <> t Then
                ii = ii + 1
                For j = 1 To m
                    b(ii, j) = a(i, j)
                Next j
            End If
        Next i
        [g1].Resize(UBound(b, 1), UBound(b, 2)) = b
    End Sub



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

И еще. Нашел в сети.

Visual Basic
1
2
3
4
5
n=5' удаляемый элемент
for i=n to ubound(arr)-1
arr(i)=arr(i+1)
next
redim preserve arr(lbound(arr) to i-1)



0



6875 / 2807 / 533

Регистрация: 19.10.2012

Сообщений: 8,562

08.01.2013, 13:59

13

Preserve с двумерным работает только «вширь», что неудобно.
Но можно конечно и таким алгоритмом сделать — начиная с удаляемой позиции всё переложить вверх в этом же массиве, а в конце выгрузить на лист только верхнюю часть, без последней ненужной строки.



0



Like this post? Please share to your friends:
  • Vba excel добавить примечание к ячейке
  • Vba excel добавить несколько строк
  • Vba excel добавить лист с именем
  • Vba excel добавить лист в конце книги
  • Vba excel добавить значение в массив