Страницы: Пред. 1 2
RSS
Быстрое преобразование массива из одномерного в двухмерный и наоборот с сохранением всех данных (BedvitCOM v1.0.5.0 и выше)
 
Цитата
Jack Famous написал:
ты был там одним из зачинщиков
попрошу ВЫталия на ВЫ :-)

Парни, на самом деле даже диалог в теме сегодня  может оказаться полезным для расширенной аудитории завтра. Юра, чем хорош форум, что никто не затавляет читать все, если не интересует тема.


Тему чистить, а то прочел, вроде и от 12 не флуд, а спор результат которого должна быть истина.
По вопросам из тем форума, личку не читаю.
 
Друзья, добрый день!

По поводу "моя/твоя":  на форуме есть авторы тем, но нет личных тем, всё колхозное:
1. Виктор (vikttur) - На форуме нет ЛИЧНЫХ тем.
2. Юра (Юрий М) - Тема фактически становится "собственностью" форума, а не Вашей.  

Алексей, про то, как в памяти хранятся массивы, и я и Виталий пытались разъяснить обычным языком.
Напомню и дополню немного:
Массив любых размерностей всегда состоит из одного непрерывного диапазона памяти.  
В каждом элементе массива хранится значение, а для типов String/Object– адрес значения/объекта вне массива: StrPtr/ObjPtr соответственно.
У каждого массива есть своя отдельная структура вне массива  (Type SAFEARRAY), описывающая количество элементов и LBound каждой размерности и т.п., в т.ч. и адрес начального элемента массива.

Так вот, весь трюк в быстром изменении размерностей и границ Lbound/Ubound заключается в том, чтобы не трогать сам массив, а поменять значения в структуре SAFEARRAY массива.

А то, чего хотите Вы – произвольно менять размерности, нашинковать, обрубая или наращивая массив, потребует медленно делать то, что делает Redim Preserve:
- создать новый массив вместо существующего
- скопировать элементы старого массива в новый
- разрушить старый массив - освободив память, чтобы исключить утечки памяти,

Redim Preserve итак реализован на C/C+, быстрее него не получится, и я так понимаю Виталия, что ему поэтому и
не интересно повторять то же самое. Просто сделайте в VBA обертку с Redim Preserve на подобные случаи, как и советует Виталий.
Изменено: ZVI - 31.08.2022 01:28:46
 
Off
Цитата
ZVI написал:
2. Юра (Юрий М) -  Тема фактически становится "собственностью" форума, а не Вашей .  
Все верно и очень жаль, что движок позволяет редактировать сообщения независимо от срока, что позволяет не только с пользой вернутся и дополнить, но и безвозвратно удалить содержание.
По вопросам из тем форума, личку не читаю.
 
БМВ,БМВ, приветствую! Владимир, всё верно. Спасибо за подробный разбор.
БМВ, Михаил, всегда был против изменений уже выложенных сообщений. Если бы отключить это свойство в движке, было бы намного понятнее что происходит в теме, кто что и когда ответил и т.д.
Изменено: bedvit - 31.08.2022 08:29:49
«Бритва Оккама» или «Принцип Калашникова»?
 
Вот еще одно применение этой функции: сразу инициализировать ДВУХМЕРНЫЙ массив переменными:

вместо создания и потом заполнения массива значениями
Код
Dim arrP: ReDim arrP(1 To 3, 1 To 5) 'массив условий (3), входящих параметров фильтра (5 параметров для каждого условия)
arrP(1, 1) = 0: arrP(1, 2) = 1: arrP(1, 3) = 1: arrP(1, 4) = 2: arrP(1, 5) = 0
arrP(2, 1) = 0: arrP(2, 2) = 2: arrP(2, 3) = 3: arrP(2, 4) = 2: arrP(2, 5) = 0
arrP(3, 1) = 1: arrP(3, 2) = 3: arrP(3, 3) = 9: arrP(3, 4) = 2: arrP(3, 5) = 0

можно сразу инициализировать массив значениями и превратить в двухмерный  
Код
Dim p: p = Array(0, 1, 1, 2, 0, _
                 0, 2, 3, 2, 0, _
                 1, 3, 9, 2, 0)
bVBA.Array1Dto2D p, 1, 1, UBound(p) / 5: bVBA.Transpose p

А если бы порядок размерностей в COM(VBA)массивах и диапазона на листе Excel совпадал, то транспонирование не нужно было бы
Код
Dim p: p = Array(0, 1, 1, 2, 0, _
                 0, 2, 3, 2, 0, _
                 1, 3, 9, 2, 0)
bVBA.Array1Dto2D p, 1, 1, 5
Изменено: bedvit - 03.09.2022 11:28:27
«Бритва Оккама» или «Принцип Калашникова»?
 
BedvitCOM.dll_v3.9
BedvitXLL.dll_v4.10

Добавил в библу новую универсальную функцию (по аналогии с выше обсуждаемыми):
ArrayDtoD(
arrayInOut - массив для преобразования
lLboundRow - индекс начала измерения (строки)
cElementsRow - количество элементов в измерении (строки)
lLboundCol - индекс начала измерения (столбцы)
cElementsCol - количество элементов в измерении (столбцы)
lLbound3 - индекс начала измерения (3е измерение)
cElements3 - количество элементов в измерении (3е измерение)
...
всего 10 измерений
...
)
Функционал: Изменить индекс начала измерения или количество элементов в любом из 10 измерений (или во всех сразу) или количество измерений. Данные не меняются, если где-то кол-во элементов уменьшается, то где-то должно увеличится.
Так же реализовано автоматический расчет элементов первого незаполненного измерения (если указан 0), если есть строки, автоматом рассчитаются столбцы и наоборот. Общее количество элементов должно быть равно первоначальному. Если расчетное количество элементов нового измерения будет число не целое - выдаст ошибку.
Пример из выше обсуждаемого кода:

Код
bVBA.ArrayDtoDF p, 0, 1, 0, 0 (здесь автоматом рассчитается 5)
bVBA.ArrayDtoDF p, 0, 0 (здесь автоматом рассчитается 1), 0, 5
Изменено: bedvit - 21.07.2023 14:41:19
«Бритва Оккама» или «Принцип Калашникова»?
Страницы: Пред. 1 2
Наверх