Vba excel redim preserve не работает
У меня есть макрос Excel VBA, который коллеги используют без проблем уже пару лет, и внезапно с 1 декабря все получают ошибку «Ошибка выполнения '9': индекс вне допустимого диапазона». Приведенный ниже код резюмирует суть проблемы:
Даже после указания, что массив baseInd должен начинаться с индекса 1, он все равно начинается с 0 (здесь переменная после имеет значение 0, как и переменная до), что в конечном итоге приводит к сбою остальной части моего кода. Я недавно узнал об инструкции Option Base 1, но я не могу использовать ее здесь, так как это вызовет проблемы с другими массивами.
Опять же, раньше это работало отлично, и я не имею ни малейшего понятия, почему внезапно (1 декабря 2014 г.) я получаю эту ошибку. У кого-нибудь есть идея?
2 ответа
Судя по тому, что мы наблюдаем в моей компании, и после обширных исследований, кажется, что недавно выпущенное исправление безопасности MS KB3003057 нарушило функцию ReDim Preserve. См. этот форум , чтобы узнать больше о том, как другие видят ту же проблему.
Насколько мне известно, 12.01.2014 ничего не изменилось в VBA, что могло бы вызвать это. Без дополнительного кода невозможно узнать, что вызвало это в вашем коде.
Но это подчеркивает опасность полагаться на нижние границы массива по умолчанию. Вам следует вернуться и указать нижнюю границу во всех объявлениях ваших массивов.
Обратите внимание, что хотя вы можете указать нижнюю границу по умолчанию с помощью Option Base . , это применимо только к массивам, для которых вы не указываете явную нижнюю границу.
Альтернативный (и, на мой взгляд, худший) способ - опустить нижнюю границу в Redim:
Последующие действия из обновленного OP
Вы говорите Даже после указания, что массив baseInd должен начинаться с индекса 1 , но нигде в вашем коде вы не указываете нижнюю границу, равную 1. Нижняя граница фактически определяется функцией Array . За подробностями обращайтесь к интерактивной справке VBA.
ICQ: 233286456
Неработает:
 im a() As Byte
ReDim a(10, 20)
ReDim Preserve a(30, 30)
The ReDimstatement 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).
You can use the ReDim statement repeatedly to change the number of elements and dimensions in an array. However, you can't declare an array of one data type and later use ReDim to change the array to another data type, unless the array is contained in a Variant. If the array is contained in a Variant, the type of the elements can be changed using an As type clause, unless you’re using the Preserve keyword, in which case, no changes of data type are permitted.
If you use the Preserve keyword, you can resize only the last array dimension and you can't change the number of dimensions at all. For example, if your array has only one dimension, you can resize that dimension because it is the last and only dimension. However, if your array has two or more dimensions, you can change the size of only the last dimension and still preserve the contents of the array. The following example shows how you can increase the size of the last dimension of a dynamic array without erasing any existing data contained in the array.
ReDim X(10, 10, 10)
. . .
ReDim Preserve X(10, 10, 15)
Similarly, when you use Preserve, you can change the size of the array only by changing the upper bound; changing the lower bound causes an error.
Разработчик Offline Client
ICQ: 204447456
Скорее всего способ хранения многомерного массива не позволяет вставить дополнительный элемент внутрь.
Или вариант что переразмерность массива требует дополнительных ресурсов и усилий от создателей VB.
ICQ: 259020622
А при работе с многомерными ошибками генерируется ошибка "Нижний индекс вне диапазона"
ReDim Preserve questRan(questCount, 2) As Long
ReDim Preserve captionsRan(questCount, someVar) As Long
Хорошо что у меня четыре многомерных массива и я их разобью на одномерные, а иначе вашатся.
Не получается заставить макрос работать. Помогите пожалуйста найти ошибку. Уже второй день бьюсь и не пойму что не так.
Макрос должен скрывать столбцы при установке галочки на чекбоксе, а при снятии галочки раскрывать только те что были скрыты чекбоксом ранее (ну плюс 2 столбца заранее заданных, не знал как без них обойтись).
Не получается заставить макрос работать. Помогите пожалуйста найти ошибку. Уже второй день бьюсь и не пойму что не так.
Макрос должен скрывать столбцы при установке галочки на чекбоксе, а при снятии галочки раскрывать только те что были скрыты чекбоксом ранее (ну плюс 2 столбца заранее заданных, не знал как без них обойтись).
Или можно как у Вас оставить, только Else надо левее поместить:
не просвятите как VBA воспринимает пробелы и размещение текста команд макроса? не просвятите как VBA воспринимает пробелы и размещение текста команд макроса? У меня вываливался сейчас с ошибкой "Else without If", когда я с ним игрался, при этом ни один из If, ни Else я не трогал. Перевёл Else левее - перестал вываливаться.
Когда игрались, то нарушили синтаксис оператора If Then, местоположение в данном случае вообще не причем.
И вообще ошибка с массивами данных
Когда игрались, то нарушили синтаксис оператора If Then, местоположение в данном случае вообще не причем.
И вообще ошибка с массивами данных
Ну извините, пожалуйста.Так а первый мой вариант тоже не подойдёт?
Уважаемый Кардаган!
Форум устроен так - есть вопросы, создавай тему, может помогут бесплатно, есть раздел Фриланс - там точно помогут, но за деньги.
Нет вопросов - смотри темы, если знаешь, подскажи, не знаешь - пройди мимо.
В данной теме ошибка с массивами данных - даже в теме написано.
Я не знаю в чем здесь конкретно ошибка, никогда не работал с Redim
И прекратите, пжл, писать в личку - это было предложение для одного пользователя из личной симпатии
Перераспределяет область хранения для переменной массива.
Синтаксис
Компоненты
Термин | Определение |
---|---|
Preserve | Необязательный элемент. Модификатор, используемый для сохранения данных в существующем массиве при изменении размера только последнего измерения. |
name | Обязательный элемент. Имя переменной массива. См. раздел Declared Element Names. |
boundlist | Обязательный элемент. Список границ для всех измерений переопределенного массива. |
Комментарии
Для изменения размера одного или нескольких из уже объявленных измерений массива можно использовать оператор ReDim . Если у вас есть большой массив и некоторые из входящих в него элементов больше не требуются, ReDim позволяет освободить память, уменьшив размер массива. Если же массив требует дополнительных элементов, ReDim может их добавить.
Оператор ReDim предназначен только для массивов. Он не подходит для скалярных величин (переменных, содержащих единственное значение), коллекций или структур. Обратите внимание, что при объявлении переменной типа Array у оператора ReDim не будет достаточной информации о типе для создания нового массива.
Оператор ReDim можно использовать только на уровне процедуры. В связи с этим контекст объявления для переменной должен быть процедурой; он не может быть исходным файлом, пространством имен, интерфейсом, классом, структурой, модулем или блоком. Дополнительные сведения см. в разделе Контексты объявления и уровни доступа по умолчанию.
Правила
Множество переменных. Можно изменить размер нескольких переменных массива в одном операторе объявления и указать name boundlist части и для каждой переменной. Переменные разделяются запятыми.
Границы массива. Каждая запись в boundlist может указывать нижнюю и верхнюю границы этого измерения. Нижняя граница всегда 0 (ноль). Верхняя граница представляет собой наибольшее возможное значение индекса для этого измерения, но не длину измерения (она равна верхней границе плюс один). Индекс для каждого измерения может варьироваться от 0 до значения верхней границы.
Число измерений в boundlist должно совпадать с исходным числом измерений (рангом) массива.
Типы данных. ReDim Инструкция не может изменить тип данных переменной массива или ее элементов.
Инициализация. ReDim Инструкция не может предоставлять новые значения инициализации для элементов массива.
Рейтинг. ReDim Оператор не может изменить ранг (число измерений) массива.
Изменение размера с помощью оператора Preserve. При использовании Preserve можно изменить размер только последнего измерения массива. Для всех остальных измерений необходимо указывать привязку существующего массива.
Например, в одномерных массивах можно изменить это измерение и в то же время сохранить все содержимое массива, поскольку изменяется только одно, последнее, измерение. Если же массив имеет два или больше измерений, то с помощью оператора Preserve можно изменить только последнее измерение массива. Preserve
Свойства. Можно использовать ReDim для свойства, содержащего массив значений.
Поведение
Замена массива. ReDim Освобождает существующий массив и создает новый массив с тем же рангом. Новый массив заменяет освобожденный массив в переменной массива.
Инициализация без использования оператора Preserve. Если не указать Preserve , ReDim инициализирует элементы нового массива, используя значение по умолчанию для их типа данных.
Инициализация с использованием оператора Preserve. если указано Preserve , Visual Basic копирует элементы из существующего массива в новый массив.
Пример
В приведенном ниже примере производится увеличение размера последнего измерения динамического массива без потери существующих данных, а затем уменьшение размера массива с частичной потерей данных. Кроме того, размер массива уменьшается до исходного значения и все элементы массива инициализируются повторно.
Оператор Dim создает новый массив с тремя измерениями. Каждое измерение объявляется с границей 10, поэтому индекс массива для каждого измерения может варьироваться в диапазоне от 0 до 10. В приведенном ниже описании эти три измерения называются слоем, строкой и столбцом.
Первый оператор ReDim создает новый массив, который заменяет существующий массив в переменной intArray . Оператор ReDim копирует все элементы из существующего массива в новый массив. Кроме того, он добавляет по десять столбцов в конец каждой строки каждого слоя и инициализирует элементы в этих новых столбцах со значением 0 (значение параметра Integer , который является типом элемента массива, по умолчанию).
Второй оператор ReDim создает еще один массив и копирует в него все подходящие элементы. При этом в каждой строке каждого слоя теряются пять последних столбцов. Это не проблема, если данные столбцы вам больше не нужны. Уменьшение размера большого массива позволяет освободить память, которая больше не требуется.
Третий оператор ReDim создает еще один массив и удаляет еще пять столбцов в конце каждой строки каждого слоя. В данном случае он не копирует существующие элементы. Этот оператор возвращает массиву первоначальный размер. Поскольку оператор не включает модификатор Preserve , он приводит все элементы массива к исходным значениям по умолчанию.
Читайте также: