preserve vba что это
Оператор ReDim (Visual Basic)
Перераспределяет область хранения для переменной массива.
Синтаксис
Компоненты
Термин | Определение |
---|---|
Preserve | Необязательный элемент. Модификатор, используемый для сохранения данных в существующем массиве при изменении размера только последнего измерения. |
name | Обязательный элемент. Имя переменной массива. См. раздел Declared Element Names. |
boundlist | Обязательный элемент. Список границ для всех измерений переопределенного массива. |
Комментарии
Оператор ReDim предназначен только для массивов. Он не подходит для скалярных величин (переменных, содержащих единственное значение), коллекций или структур. Обратите внимание, что при объявлении переменной типа Array у оператора ReDim не будет достаточной информации о типе для создания нового массива.
Оператор ReDim можно использовать только на уровне процедуры. В связи с этим контекст объявления для переменной должен быть процедурой; он не может быть исходным файлом, пространством имен, интерфейсом, классом, структурой, модулем или блоком. Дополнительные сведения см. в разделе Контексты объявления и уровни доступа по умолчанию.
Правила
Множество переменных. Можно изменить размер нескольких переменных массива в одном операторе объявления и указать name boundlist части и для каждой переменной. Переменные разделяются запятыми.
Границы массива. Каждая запись в boundlist может указывать нижнюю и верхнюю границы этого измерения. Нижняя граница всегда 0 (ноль). Верхняя граница представляет собой наибольшее возможное значение индекса для этого измерения, но не длину измерения (она равна верхней границе плюс один). Индекс для каждого измерения может варьироваться от 0 до значения верхней границы.
Число измерений в boundlist должно совпадать с исходным числом измерений (рангом) массива.
Типы данных. ReDim Инструкция не может изменить тип данных переменной массива или ее элементов.
Инициализация. ReDim Инструкция не может предоставлять новые значения инициализации для элементов массива.
Рейтинг. ReDim Оператор не может изменить ранг (число измерений) массива.
Изменение размера с помощью оператора Preserve. При использовании Preserve можно изменить размер только последнего измерения массива. Для всех остальных измерений необходимо указывать привязку существующего массива.
Например, в одномерных массивах можно изменить это измерение и в то же время сохранить все содержимое массива, поскольку изменяется только одно, последнее, измерение. Если же массив имеет два или больше измерений, то с помощью оператора Preserve можно изменить только последнее измерение массива. Preserve
Свойства. Можно использовать ReDim для свойства, содержащего массив значений.
Поведение
Замена массива. ReDim Освобождает существующий массив и создает новый массив с тем же рангом. Новый массив заменяет освобожденный массив в переменной массива.
Пример
В приведенном ниже примере производится увеличение размера последнего измерения динамического массива без потери существующих данных, а затем уменьшение размера массива с частичной потерей данных. Кроме того, размер массива уменьшается до исходного значения и все элементы массива инициализируются повторно.
Оператор Dim создает новый массив с тремя измерениями. Каждое измерение объявляется с границей 10, поэтому индекс массива для каждого измерения может варьироваться в диапазоне от 0 до 10. В приведенном ниже описании эти три измерения называются слоем, строкой и столбцом.
Второй оператор ReDim создает еще один массив и копирует в него все подходящие элементы. При этом в каждой строке каждого слоя теряются пять последних столбцов. Это не проблема, если данные столбцы вам больше не нужны. Уменьшение размера большого массива позволяет освободить память, которая больше не требуется.
Дополнительные примеры см. в разделе массивы.
Оператор ReDim
Используется на уровне процедуры для перераспределения пространства хранения для динамических переменных массивов.
Синтаксис
Синтаксис оператора ReDim состоит из таких частей:
Part | Описание |
---|---|
Сохранение | Необязательное. Ключевое слово, которое используется, чтобы сохранить данные в существующем массиве при изменении размера только последнего измерения. |
varname | Обязательный. Имя переменной; соответствует стандартным соглашениям об именовании переменных. |
подскрипники | Обязательный. Измерения любой переменной массива; может быть объявлено до 60 множественных измерений. В аргументе subscripts используется следующий синтаксис: Используйте отдельный пункт Типа для каждой определяемой переменной. В случае переменной типа Variant, содержащей массив, type описывает тип каждого элемента массива, но не меняет тип Variant на другой. |
Примечания
Заявление ReDim используется для размера или размера динамического массива, который уже был официально объявлен с помощью частного, публичного или тусклого заявления с пустыми скобами (без подзаписей измерений).
С помощью оператора ReDim вы можете многократно изменять количество элементов и измерений массива. Однако вы не можете объявить массив с одним типом данных, а затем использовать ReDim, чтобы изменить тип массива, если этот массив не содержится в переменной Variant. Если массив содержится в варианте, тип элементов можно изменить с помощью элемента As type clause, если только вы не используете ключевое слово Сохранить, в этом случае изменения типа данных не допускаются.
Если вы используете ключевое слово Preserve, вы можете изменить только размер последнего измерения массива, но не количество измерений. Например, если у вашего архива всего одно измерение, вы не сможете изменить размер этого измерения, потому что оно является последним и единственным. Однако, если у вашего массива два и более измерений, вы можете изменить размер только последнего измерения и сохранить содержание архива.
В следующем примере показано, как вы можете увеличить размер последнего измерения динамического массива, не удаляя данные из массива.
Также, когда вы пользуетесь Preserve, вы можете изменить размер массива, лишь изменяя верхнюю границу; изменение нижней границы вызовет ошибку.
Если вы уменьшаете массив, данные удаленных элементов будут потеряны.
При инициализации переменных числовой переменной присваивается значение 0, строке переменной длины — строка нулевой длины («»), а строка фиксированной длины заполняется нулями. Переменные типа Variant при инициализации получают значение Empty. Каждый элемент переменной определяемого пользователем типа инициализируется как отдельная переменная.
Переменная, которая ссылается на объект, должна быть назначена существующему объекту с помощью утверждения Set, прежде чем он может быть использован. Пока объекту не назначен, объявленная переменная объекта имеет специальное значение Nothing, что указывает на то, что он не ссылается на какой-либо конкретный экземпляр объекта.
Заявление ReDim выступает в качестве декларативного заявления, если объявленная переменная не существует на уровне модуля или на уровне процедуры. Если позже создается другая переменная с тем же именем, даже расширенная, оператор ReDim будет относиться к более поздней переменной и не обязательно вызовет ошибку компиляции, даже если действует Option Explicit. Для предотвращения таких конфликтов ReDim не следует использовать как оператор объявления, а лишь для изменения измерений архивов.
Чтобы изменить размер массива, который содержится в переменной Variant, сначала нужно ее явнообъявить.
Пример
В этом примере оператор ReDim выделяет и перераспределяет место для хранения переменных динамического архива. В нем предполагается, что оператор Option Base имеет значение 1.
Следующий оператор изменяет размер массива и удаляет элементы.
Следующий оператор изменяет размер массива, но не удаляет элементы.
См. также
Поддержка и обратная связь
Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.
Preserve vba что это
Применяется на уровне процедуры для перераспределения памяти для переменных динамического массива.
Параметры
Preserve
Необязательный. Ключевое слово, используемое для сохранения данных в существующем массиве при изменении значения последней размерности.
имяПеременной
Обязательный. Имя переменной, удовлетворяющее стандартным правилам именования переменных.
индексы
Обязательный. Размерности переменной массива; допускается описание до 60 размерностей. Аргумент индексы использует следующий синтаксис:
Если нижний индекс не задан явно, нижняя граница массива определяется инструкцией Option Base. Если отсутствует инструкция Option Base, нижняя граница массива равняется нулю.
тип
Необязательный. Тип данных переменной; поддерживаются типы Byte, Boolean, Integer, Long, Currency, Single, Double, Decimal (в настоящее время не поддерживается), Date, String (для строк переменной длины), String * длина (для строк фиксированной длины), Object, Variant, определяемый пользователем тип или объектный тип. Для каждой описываемой переменной следует использовать отдельное предложение As тип. Для значения типа Variant, содержащего массив, тип описывает тип данных каждого элемента массива, но не заменяет тип Variant на какой-либо другой тип.
Замечания
Инструкция ReDim используется для задания или изменения размера динамического массива, который уже был формально описан с помощью инструкции Private, Public или Dim с пустыми скобками (без индексов размерностей).
Имеется возможность повторно использовать инструкцию ReDim для изменения числа элементов и размерностей массива. Однако не допускается описание массива с одним типом данных и использование инструкции ReDim для последующего изменения типа данных этого массива, если массив не содержится в переменной типа Variant. Тип элементов массива, содержащегося в переменной типа Variant, может быть изменен с помощью предложения As тип, если ранее не было использовано ключевое слово Preserve, запрещающее изменение типа данных.
При использовании ключевого слова Preserve имеется возможность изменить значение только последней размерности массива и не допускается изменение числа размерностей. Например, если массив имеет только одну размерность, имеется возможность изменить эту размерность, так как она является последней и единственной размерностью. Однако, если массив имеет две или более размерности, возможно изменение значения только последней размерности, сохраняя при этом содержимое массива. В следующем примере показывается, как можно увеличить значение последней размерности динамического массива без уничтожения данных, содержащихся в этом массиве.
Кроме того, при использовании ключевого слова Preserve допускается изменение размера массива только за счет изменения верхней границы индекс; попытка изменить нижнюю границу приведет к ошибке.
Если уменьшить размер массива, данные из удаленных элементов будут потеряны. При передаче массива в процедуру по ссылке нельзя изменять размеры массива в процедуре.
При инициализации переменных числовая переменная получает значение 0, строка переменной длины получает значение пустой строки («»), а строка фиксированной длины заполняется нулями. Переменные типа Variant получают при инициализации значение Empty. Каждый элемент переменной типа, определяемого пользователем, при инициализации получает значение, которые он получил бы, если бы являлся одиночной переменной. Переменной со ссылкой на объект перед ее использованием необходимо присвоить существующий объект с помощью инструкции Set. До присвоения объекта описанная объектная переменная имеет специальное значение Nothing, которое указывает, что она не содержит ссылку на какой-либо определенный экземпляр объекта.
Инструкция ReDim действует как инструкция описания, даже если описываемая в ней переменная не существует на уровне модуля или на уровне процедуры. При создании в дальнейшем переменной с тем же именем, возможно, в более широкой области определения, инструкция ReDim будет ссылаться на эту последнюю переменную и не обязательно вызовет ошибку компиляции, даже при действующей инструкции Option Explicit. Во избежание подобных конфликтов не следует использовать инструкцию ReDim как инструкцию описания. Пользуйтесь ей только для изменения размеров массивов.
Для изменения размера массива, содержащегося в переменной типа Variant, нужно явно описать переменную типа Variant перед попыткой изменения размера.
Пример
В данном примере инструкция ReDim используется для выделения и повторного выделения памяти для динамических массивов. Предполагается, что Option Base равняется 1.
Следующая инструкция изменяет размер массива и обнуляет его элементы.
Следующая инструкция изменяет размер массива, но сохраняет существующие элементы.
Preserve vba что это
Что такое массив
Типы массивов
Массивы в VBA и во многих других языках программирования делятся на 2 класса:
Объявление массивов
Объявление фиксированных массивов
Рекомендация : при объявлении массивов VBA я советую вам давать всем именам префикс » arr «. Я сторонник венгерской нотации.
Помимо вышеуказанного вы вправе использовать следующий синтаксис, который НЕ зависит от option base <0|1>:
таким образом вы в явном виде указываете и нижнюю, и верхнюю границы. Как видите, нижняя граница совершенно не обязательно должна начинаться с 0 или 1. Более того, индексы границ могут принимать и отрицательные значения, главное чтобы нижняя была меньше верхней.
Помимо одномерных массивов, можно объявлять и массивы с размерностью больше единицы.
Объявление динамических массивов
Динамические массивы объявляться так:
Однако, использовать их после такого объявления пока ещё нельзя. Необходимо выделить память под массив. Особенность работы с динамическим массивом как раз состоит в том, что программист отвечает за его своевременное расширение (усечение) в памяти. Для этого существует специальный оператор, который имеет следующий синтаксис:
ReDim [Preserve] varname(subscripts) [As Type]
После этого оператора, вы можете использовать элементы массива arrOpen с 0-го по 5-й. Всё, что мы говорили про оператор option base и нижнюю границу, верно и для динамических массивов. Предположим, что вы сохранили информацию в элементах 0-5 и у вас поспела новая порция информации для элементов 6-11. Чтобы разместить в данном массиве новые элементы и не потерять старые, вы должны сделать следующее:
Изменение элементов массива
Как и с обычными переменными запись информации в элемент массива происходит через оператор присваивания (=), но указанием индекса элемента массива.
Чтение элементов массива
Определение границ массива
LBound( array [, dimension])
UBound( array [, dimension])
Если вы ошибётесь с указанием правильного индекса массива, то возникнет ошибка периода исполнения с кодом 9. Эта же ошибка возникнет, если вы в функции LBound / UBound укажете несуществующую размерность массива (например, 3 для двумерного массива).
Перебор элементов массива
Собственно массивы нужны для того, чтобы хранить в них однотипную информацию и перебирать их в цикле. Как правило, алгоритм делает что-то полезное с одним элементом массива, а цикл повторяет эти типовые действия для всех элементов массива.
так же есть способ не заботиться об определении нижней и верхней границ, если алгоритм не требует от нас знания текущего индекса массива:
Передача массивов в подпрограммы
Массив с элементами типа массив
Продемонстрируем, как можно хранить в качестве элементов массива другие массивы.
Результат отладочной печати:
Функция Array
Array( arglist )
Функция Split
Split возвращает одномерный массив, содержащий подстроки, из строкового выражении с учётом указанного разделителя
Split(expression[, delimiter[, limit[, compare]]])
Результат выглядит так:
Нюансы работы с динамическими массивами
Неинициализированный массив
У динамического массива есть такое промежуточное состояние, когда он уже объявлен, но ещё не содержит никаких элементов.
То есть у переменной динамического массива есть такое состояние, когда мы не можем воспользоваться вспомогательными функциями LBound / UBound для определения его (массива) статуса. Это особенно надо учитывать, когда вы пишите подпрограммы, работающие с массивами. Прежде чем работать (перебирать) массив необходимо убедиться, что он проинициализирован, в противном случае программа вылетит с ошибкой 9.
Для этого я предлагаю пользоваться функцией подобной нижеописанной IsNotEmptyArray :
Расширение массива
Как правило, расширять динамический массив приходится в цикле. Возможны 2 стратегии: расширение на 1 элемент, как только в этом есть необходимость (назовём это эластичным расширением), и расширение авансом, когда вы увеличиваете верхнюю границу скачками, скажем сразу на 100 элементов. Реализовав оба варианта, я для себя сделал вывод, что авансовое расширение получилось и компактнее, и работает быстрее, так как операция расширения, вообще говоря, затратна и, чем реже вызывается, тем лучше.
Авансовый метод вышел даже компактнее
Удаление массива
Получение массива на основе диапазона Excel
Дополнительные источники
В качестве источника дополнительной информации по массивам я могу порекомендовать замечательный, исчерпывающий ресурс Чарльза Пирсона (Charles H. Pearson). Его сайт следует штудировать всем, кто серьёзно осваивает VBA. Конкретно по массивам там огромное количество готовых подпрограмм для работы с ними, исходные коды, снабженные подробнейшими комментариями, продвинутые объяснения для копающих в глубину. Без преувеличения великолепный ресурс!
VBA Excel. Массивы (одномерные, многомерные, динамические)
Массивы в VBA Excel: одномерные, многомерные и динамические. Объявление и использование массивов. Операторы Public, Dim и ReDim. Функции Array, LBound, UBound.
Одномерные массивы
Объявление одномерных (линейных) статических массивов в VBA Excel:
В первом случае публичный массив содержит 10 элементов от 0 до 9 (нижний индекс по умолчанию — 0, верхний индекс — 9), а во втором случае локальный массив содержит 9 элементов от 1 до 9.
По умолчанию VBA Excel считает в массивах нижним индексом нуль, но, при желании, можно сделать нижним индексом по умолчанию единицу, добавив в самом начале модуля объявление «Option Base 1». Вместо верхнего индекса можно использовать переменную.
Многомерные массивы
Объявление многомерных статических массивов в VBA Excel аналогично объявлению одномерных массивов, но с добавлением размерностей дополнительных измерений через запятую:
Третий массив состоит из 10000 элементов — 10×10×10×10.
Динамические массивы
Динамические массивы в VBA Excel, в отличие от статических, объявляются без указания размерности:
Такие массивы используются, когда заранее неизвестна размерность, которая определяется в процессе выполнения программы. Когда нужная размерность массива становится известна, она в VBA Excel переопределяется с помощью оператора ReDim:
Переопределять размерность динамических массивов в процессе работы программы можно неоднократно, как по количеству измерений, так и по количеству элементов в измерении.
С помощью оператора ReDim невозможно изменить обычный массив, объявленный с заранее заданной размерностью. Попытка переопределить размерность такого массива вызовет ошибку компиляции с сообщением: Array already dimensioned (Массив уже измерен).
При переопределении размерности динамических массивов в VBA Excel теряются значения их элементов. Чтобы сохранить значения, используйте оператор Preserve:
Максимальный размер
Размер массива – это произведение длин всех его измерений. Он представляет собой общее количество элементов, содержащихся в данный момент в массиве.
По информации с сайта разработчиков, максимальный размер массивов зависит от операционной системы и доступного объема памяти. Использование массивов, размер которых превышает объем доступной оперативной памяти компьютера, приводит к снижению скорости, поскольку системе необходимо выполнять запись данных и чтение с диска.
Использование массивов
Приведу два примера, где не обойтись без массивов.
1. Как известно, функция Split возвращает одномерный массив подстрок, извлеченных из первоначальной строки с разделителями. Эти данные присваиваются заранее объявленному строковому (As String) одномерному динамическому массиву. Размерность устанавливается автоматически в зависимости от количества подстрок.
2. Данные в массивах обрабатываются значительно быстрее, чем в ячейках рабочего листа. Построчную обработку информации в таблице Excel можно наблюдать визуально по мерцаниям экрана, если его обновление (Application.ScreenUpdating) не отключено. Чтобы ускорить работу кода, можно значения из диапазона ячеек предварительно загрузить в динамический массив с помощью оператора присваивания (=). Размерность массива установится автоматически. После обработки данных в массиве кодом VBA полученные результаты выгружаются обратно на рабочий лист Excel. Обратите внимание, что загрузить значения в диапазон ячеек рабочего листа через оператор присваивания (=) можно только из двумерного массива.
Функции Array, LBound, UBound
Функция Array
Функция Array возвращает массив элементов типа Variant из первоначального списка элементов, перечисленных через запятую. Нумерация элементов в массиве начинается с нуля. Обратиться к элементу массива можно, указав в скобках его номер (индекс).