Permalink
Cannot retrieve contributors at this time
title | keywords | f1_keywords | ms.prod | ms.assetid | ms.date | ms.localizationpriority |
---|---|---|---|---|---|---|
Array already dimensioned |
vblr6.chm1040055 |
vblr6.chm1040055 |
office |
fcf3762f-3f3f-6182-a7c9-4f055991d2c1 |
06/08/2017 |
medium |
A static array can only be dimensioned once. This error has the following causes and solutions:
-
You attempted to change the dimensions of a static array with a ReDim statement; only dynamic arrays can be redimensioned. Either remove the redimensioning or use a dynamic array. To define a dynamic array, use a Dim, Public, Private, or Static statement with empty parentheses.
For example:
Dim MyArray()
In a procedure, you can define a dynamic array with the ReDim or Static statement using a variable for the number of elements:In a procedure, you can define a dynamic array with the ReDim or Static statement using a variable for the number of elements:
ReDim MyArray(n)
-
An Option Base statement occurs after array dimensions are set. Make sure any Option Base statement precedes all array declarations.
For additional information, select the item in question and press F1 (in Windows) or HELP (on the Macintosh).
[!includeSupport and feedback]
For certain, technical, reasons, we cannot use styles in word. In an effort to speed up applying global properties over and over, I’ve created a class that can read from a simple xml style-sheet. The sheet contains different «paragraphs.» Each paragraph simply stores the paragraph properties that we use the most.
I’m used to C++ where I can use dynamic memory and I’m trying to replicate the behavior of a dynamically allocated array. However, when I attempt to re-dim I get the error message «Array arleady dimensioned.»
My research on the MSDN suggests that in order to ReDim the array has to be Global or in the «general declaration context» This makes me think it might simply not be possible to do it in a class.
Excerpt from MSDN:
«You can use ReDim only at procedure level. Therefore, the declaration
context for the variable must be a procedure; it can’t be a source
file, a namespace, an interface, a class, a structure, a module, or a
block.»
I have attempted to search stack overflow for «Word VBA Array already dimensioned» and went through all 3 pages of results with no avail.
private type pStyle 'Definition removed because it's not needed
private Paragraphs(0) As pStyle 'Initially an empty array of paragraphs
later I have the following function
Public Function AddEmpty()
'Create space
count = count + 1
ReDim Preserve Paragraphs(count)
AddEmpty = count
End Function
Please let me know if any ideas. I would prefer to not have to «estimate» the number of paragraph styles we will need for each style sheet as every file is different.
-
#1
Dim GrpTot(1, 2)
‘Col 1 : Amt
‘Col 2 : row no for Where to put
‘col 3 : Column no for where to put
GrpTot(0, 0) = 4896.00
GrpTot(0, 1) = 5
GrpTot(0, 2) = 2
Sheets(«Summary»).Cells(GrpTot(0, 2), GrpTot(0, 1)) = GrpTot(0, 0)
ReDim Preserve GrpTot(2 To 2)
GrpTot(0, 0) = 12541.00
GrpTot(0, 1) = 5
GrpTot(0, 2) = 18
Sheets(«Summary»).Cells(GrpTot(0, 2), GrpTot(0, 1)) = GrpTot(0, 0)
Error occured at ReDim syntax
—————————
Microsoft Visual Basic for Applications
—————————
Compile error:
Array already dimensioned
—————————
OK Help
—————————
Test for Multiple Conditions in IF?
Use AND(test, test, test, test) or OR(test, test, test, …) as the logical_test argument of IF.
-
#2
To define a dynamic array, don’t Dim it with a size:
Rich (BB code):
Dim GrpTot() As Variant
ReDim GrpTot(1,2)
You can’t redim preserve the first dimension of an array, only the last
-
#3
Sorry I’m new for excel vba world.
Its solved with above code
Thanks
According to the literature it should be possible to redim the last dimension of a multidimensional array, but the code below throws up the error «Array already dimensioned», highlighting «ReDim Preserve aAnn(12».
Any advice re. what I’ve done wrong and how to fix it would be greatly appreciated.
Excel 2003
———————————-
Dim aAnn(12,1) as Integer
‘ 12 for the months Jan-Dec, unknown quantity of days for each month, so 2nd dim needs to expand as required.
‘ load other variables, etc.
If c(2, 1).Value = iM Then
i = i + 1 ‘ Dim of DAY array
If i > n Then
ReDim Preserve aAnn(12, i)
n = i
End If
End If
————————
Many thanks!
-
#1
Dim GrpTot(1, 2)
‘Col 1 : Amt
‘Col 2 : row no for Where to put
‘col 3 : Column no for where to put
GrpTot(0, 0) = 4896.00
GrpTot(0, 1) = 5
GrpTot(0, 2) = 2
Sheets(«Summary»).Cells(GrpTot(0, 2), GrpTot(0, 1)) = GrpTot(0, 0)
ReDim Preserve GrpTot(2 To 2)
GrpTot(0, 0) = 12541.00
GrpTot(0, 1) = 5
GrpTot(0, 2) = 18
Sheets(«Summary»).Cells(GrpTot(0, 2), GrpTot(0, 1)) = GrpTot(0, 0)
Error occured at ReDim syntax
—————————
Microsoft Visual Basic for Applications
—————————
Compile error:
Array already dimensioned
—————————
OK Help
—————————
__________________________________________________________________
Mod edit : post moved to appropriate forum …
-
#2
Notice : with posting in proper forum,
you must edit your post and use CODE tags ‼
Your bad : variable is first fixed declared in two dimensions
so you can’t preserve & redim it within a single dimension
as explained in VBA help !
Just use a single dimension variable, no need to redim it …
And you even do not need this variable type for this kind of stuff !
-
#3
1)
Array GrpTot is not dynamic, so you can not Re-Dimension it.
2)
ReDim Preserve GrpTot(2 To 2)
This doesn’t make sense.
What do you want to preserve and what do you want to do?
-
#5
Sorry for this question,
I’m new to VBA
after
Code:
Dim GrpTot() As Variant
ReDim GrpTot(1,2)
Problem is solved
To define a dynamic array, don’t Dim it with a size: like Dim GrpTot(1,2) only create with GrpTot() it will create Dynamic array.
> You do not need to DIM an array
That is true. Option Explicit will not catch the problem. Formally (from the VB help file), you should not use it that way:
The ReDim statement is used to size or resize a dynamic array that has already been formally declared using a Private, Public, or Dim statement with empty parentheses (without dimension subscripts).
The problem becomes apparent in the snippet. The typo isn’t identified, and the code breaks only at run-time. I don’t know why the VB compiler was made to imply Dim when reading ReDim, these are quite different operations, and no other language makes that particular confusion. Anyway, you are right:
ReDim Something(12) As String
Is interpreted as
Dim Something() As String
ReDim Something(12)
Stupid, but there you go…
(°v°)
Sub Manipulate(pvarMyArray() As Variant)
ReDim pvarMyAray(12)
pvarMyArray(12) = "something"
End Sub
Sub ShowProblem()
Dim Values() As Variant
Manipulate Values
End Sub
Open in new window
Массивы в 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) |