Выбрать дату в календареВыбрать дату в календаре

Страницы: 1
Как правильно перенести данные из массива в комментарий, оптимизация макроса
 
Цитата
написал:
А чего нужно-то? Постарайтесь объяснить. Текст комментария хранить в ячейке?

Я прикрепил файл с примерном (к первому сообщению). На листе1 есть диапазон O1:R10, которому соответствует двумерный массив arr1 (1to10, 1to4)
Мне нужно перенести данные из массива (именно из массива, т.к. диапазон O1:R10 приведен просто для наглядности) в комментарии ячеек диапазона A1:D10

Т.е. должно быть что-то на подобие:
[A1].AddComment CStr(arr1(1, 1))
[B1].AddComment CStr(arr1(1, 2))
[C1].AddComment CStr(arr1(1, 3))
[D1].AddComment CStr(arr1(1, 4))
[A2].AddComment CStr(arr1(2, 1))
и тд..

Получается, что все-равно нужен какой-то перебор по всем ячейкам + нужно каждой ячейке задавать адрес.
Или я куда-то не в ту сторону смотрю.

Цитата
написал:
И Find никто не отменял...
По Find сейчас почитаю, плохо еще знаю VBA
Изменено: Fylhtqq - 05.12.2021 19:59:50
Как правильно перенести данные из массива в комментарий, оптимизация макроса
 
Добрый вечер!

Цитата
написал:
я бы предпочел смотреть файл-пример с исходными данными и рядом что хотите получитm на выходе
Прикрепил файл к первому посту.
Для примера упростил массив с данными (задал через диапазон), в реально задаче там значительно больше данных. Из--за этого и хочется уйти от цикла по ячейкам при внесении комментариев.
Код
arr1 = Range("O1:R10")

Цитата
написал:
1. комментарии снести сразу у всего диапазона одной командой2. For Each c In r1.Specialcells(константы у вас там или формулы).Cells и тогда будет цикл строго по "правильным" ячейкам значение из каждой внести в комментарий
Не уверен, что правильно вас понял. Т.е. перенести данные из массива сразу в комментарии ячеек, а не в сами ячейки нельзя? Все-равно необходимо по ячейкам проходить?
Под занесением данных из массива "сразу в ячейку" я говорю про:
Код
r1.Resize(10, UBound(arr1, 2)) = arr1
Т.е. хотелось бы получить, что-то на подобие (понятно, что так не работает):
Код
r1.Resize(10, UBound(arr1, 2)).AddComment = arr1
Как правильно перенести данные из массива в комментарий, оптимизация макроса
 
Здравствуйте!

Подскажите, пожалуйста, можно напрямую выгружать данные из массива в комментарии диапазона ячеек? Или как-то оптимизировать мой макрос (см. последовательность работы ниже), к примеру, избавиться от пункта 2 (перебор по ячейкам).

Имеем диапазон
r1 = Range("A1:D10")
arr1 - массив с уникальными элементами (для каждой ячейки диапазона r1 будут свои данные)

Сейчас я использую следующую последовательность:
1) Данные из массива выгружаются в диапазон ячеек
Код
    r1.Resize(1, UBound(arr1, 2)) = arr1
2) Цикл по всем ячейкам диапазона -> перенос данных из непустых ячеек в комментарий этих ячеек
Код
    For Each c In r1
    On Error Resume Next
           c.Comment.Delete
           If c <> "" Then
              c.AddComment CStr(c.Value)
           End If
    Next

Прошу прощения, если описал сумбурно и не очень понятно (допишу, если будут какие-то вопросы).
Изменено: Fylhtqq - 05.12.2021 18:34:45
Объединение множества массивов в один массив
 
Цитата
Nordheim написал:
Fylhtqq , А что вы дальше собираетесь делать с массивами?
Мне необходимо получить данные со всех листов в одном массиве.
Для этого предполагалось, что с каждого листа будет "получен" отдельный массив и потом все массивы будут объединены в один. На сколько это удачный путь, не могу сказать, но выглядит логично.
Объединение множества массивов в один массив
 
Цитата
Ігор Гончаренко написал:
это решается простым циклом
Скорее всего, я не правильно выразился.
Я присваивал переменную массива каждому листу, т.е. arr1 это данные из "Лист1", arr2 - из "Лист2". И уже исходя из этих переменных формировал массив каждого листа.

Если проходить циклом по листам, как задать каждому листу свою переменную массива? и как потом такое кол-во переменных использовать при создании размерности массива массивов
Объединение множества массивов в один массив
 
Цитата
Ігор Гончаренко написал:
макросу по-барабану сколько листов использовать: 2, 3, 50 или 50 тыс. листов
Согласен с вами. Одна из моих проблем заключается в том, что я "руками" присваивал каждому листу свою переменную. если делать это для 50 листов - капец
:
Код
lrow1 = Sheets("1").Cells(Rows.Count, 1).End(xlUp).Row
lrow2 = Sheets("2").Cells(Rows.Count, 1).End(xlUp).Row
 
    arr1 = Sheets("1").Range("A1:GR" & lrow1)
    arr2 = Sheets("2").Range("A1:GR" & lrow2)
а далее уже формировал массив массивов:
Код
ReDim arr3(1 To (UBound(arr1) + UBound(arr2)), 1 To Application.Max(UBound(arr1, 2), UBound(arr2, 2)))

Предполагал, что можно сделать примерно так:
Код
For Sh = 1 To Sheets.Count
Worksheets(Sh).Activate
lrow = Cells(Rows.Count, 1).End(xlUp).Row
arr = Range("A1:GR" & lrow)
но уперся в то, что не понял, как тогда присваивать уникальное название переменной массива листа. Т.е. лист 1 - arr1, лист 2 - arr2 и тп
вероятно, что можно не формировать множество переменных массивов (для каждого листа), а просто чистить массив arr через "Erase". Но тогда опять не понятно, как формировать размерность массива массивов.

Не уверен, что вообще правильно понимаю и объясняю, но ничего лучше пока не придумал.
Изменено: Fylhtqq - 09.10.2021 19:44:07
Объединение множества массивов в один массив
 
Здравствуйте!

Сразу прошу прощения за "стену текста", познаю VBA недавно. Хочется не только получить результат, но и понять логику разработки.

Есть "х" листов с разным количеством заполненных строк и одинаковым количеством заполненных столбцов. Т.е. первая размерность разная, вторая одинаковая.
Необходимо собрать данные со всех листов в один массив

Должно получиться так (на примере двух листов):
+ : arr1 :  : Variant/Variant(1 to 26, 1 to 200) - массив с первого листа
+ : arr2 :  : Variant/Variant(1 to 29, 1 to 200) - массив со второго листа
+ : arr3 :  : Variant/Variant(1 to 55, 1 to 200) - "массив массивов"

Для решения задачи (и подтверждения того, что "массив массивов" подойдет) был использован код с перебором значений (под спойлером).
Работает, но проблема заключается в том, что нужно использовать не 2 листа, а, к примеру, 20 или 50 (количество постоянно меняется).
Скрытый текст

На данном форуме удалось найти единственный, похожий на мою ситуацию, совет-ответ, к большому сожалению, без самого кода:
Цитата
The_Prist написал:
Вообще, для сокращения кол-ва строк кода можно собирать в отдельные массивы данные с книг. Сами массивы помещать в один общий массив(в котором будут эти массивы). Иными словами создать массив массивов. А потом все это выгружать или объединить в один массив.
Как алгоритм:
1. Создаем динамический массив массивов(avMain)
2. Идем циклом по книгам и собираем данные в промежуточные массивы(avBook_1, avBook_2 ... avBook_n). Попутно в отдельную переменную плюсуем размерность каждого массива: lResCnt = lResCnt + Ubound(avBook1,1)
3. Определяем размерность результирующего массива(avRes): ReDim avRes(1 to lResCnt, 1 to lColsCnt)
4. Осталось только пройтись циклом по avMain и по очереди выгрузить циклами данные из этих массивов в avRes.
Решение вроде понятное, но как его преобразовать в макрос не могу сообразить.
1) создать динамический массив массивов - разве его можно создать первым пунктом, без понимания размерности?
2) идем циклом по листам и собираем данные в промежуточные массивы - я понимаю, как задать цикл по листам, но как автоматически задать каждому листу новый-уникальный массив?
3) ...

К сообщению прикрепил файл с примером. Голые данные, без макросов.
Если необходимо  
Изменено: Fylhtqq - 09.10.2021 19:03:00
Макрос поиска значения по заданным условиям и обработка результата, ускорение работы макроса
 
Цитата
vikttur написал: Если массив 50*20
Видимо, в моем примере можно немного "сжульничать", т.к. массив arr2 формируется из данных в строке (от 1 до последней заполненной ячейки).
т.е. i = 1 to

Цитата
Юрий М написал: А что Вы хотите сделать с таким массивом? Задача в чём?
Добрый вечер!
Первоначальная задача стояла в оптимизации (ускорении работы макроса). Но мне подсказали, что нужно задавать более четкий вопрос, а не спрашивать про все подряд. Т.ч. вопрос свелся к разбору формирования цикла, исходя из размерности массива, и плавно перетек в разбор того, что вообще написано в коде (и почему написано именно так).
На мой взгляд, в конкретном примере массив arr2 работает нормально.
Да и в целом, считаю задачу решенной. Найдено множество недочетов, которые стоит устранить)

Еще раз спасибо!
Макрос поиска значения по заданным условиям и обработка результата, ускорение работы макроса
 
Цитата
vikttur написал:
Возможно, для Вашего случая это не имеет смысла. Но размерность массива может начинаться  с нуля.
Действительно, где-то я уже такое слышал. У меня везде как-то само от 1 считает. Спасибо!
Цитата
vikttur написал:
Непонятно, почему для расчета последнего значения цикла берутся две размерности. Косяк какой-то...
Не уверен, что технически это правильно написано, но оно работает.
Просто начало (1) берется из первой размерности (она от 1 до 1, т.е. получается 1), а конец от второй (от 1 до 153, т.е. 153)
Опять же, в чем тут хитрость трудно понять.
Код
+ : arr2 :  : Variant/Variant(1 to 1, 1 to 153)

Спасибо за помощь и ответы! Попробую улучшить остальные строки.
Макрос поиска значения по заданным условиям и обработка результата, ускорение работы макроса
 
vikttur, первоначально был такой цикл:
Код
    For i = LBound(arr2) To UBound(arr2, 2) - LBound(arr2) + 1
Т.е. так: i = 1 to 153 - 1 + 1
Честно сказать, ерунда какая то. Надеялся, что тут есть какой то смысл или скрытая логика.

Заменил на такой цикл:
Код
    For i = 1 To UBound(arr2, 2)
i = 1 to 153

Не заметил прибавки во времени, возможно пример (кол-во обрабатываемых ячеек) слишком короткий и в реальной работе будет плюс от изменения

Это достаточно правильно или нужно по-другому как-то делать?
Макрос поиска значения по заданным условиям и обработка результата, ускорение работы макроса
 
vikttur, спасибо за отзыв!

Option Explicit добавил, лишние переменные удалил/присвоил нужные типы данных.
Перенес And mmm3 < 2000000 выше If, в отдельное условие. Заменил mmm3 с проверкой через c.Offset(, -4) на проверку через данные из массива

Цитата
vikttur написал:
Замерить время выполнения каждого "вопроса", найти проблемный и с ним выйти на форум.
Понял!, тогда, исходя из ваших замечаний, хотел бы разобраться вот с этим:

Цитата
vikttur написал:
Расчет UBound(arr2, 2) - LBound(arr2) + 1 на каждом шаге цикла.
Что это значит и как переработать в правильный вид?
Данная часть была взята из чужого макроса, проверена на работоспособность и использована тут. Но, почему это написано именно так и, что "оно" делает, не очень понятно.
Макрос поиска значения по заданным условиям и обработка результата, ускорение работы макроса
 
На правах АПа все еще не теряю надежды на то, что мой макрос можно ускорить.
Все-таки не могу понять, почему так долго идет расчет, проверка идет с использованием массивов, т.е. должно быть нормально.. Есть у кого-то идеи, в чем ошибаюсь?
Макрос поиска значения по заданным условиям и обработка результата, ускорение работы макроса
 
Цитата
Ігор Гончаренко написал: нормальное время  - это когда 60 тыс. ячеек обрабатываются за 0.01 сек
Получается, что мой макрос действительно проблемный..

Цитата
Ігор Гончаренко написал: нужно не описание макроса, а описание вашей задачи
Согласен, не описал задачу полностью.

В книге Итог нужно занести результаты во все ячейки диапазона, начиная от ячейки EA2 до последней ячейки*
Последняя ячейка* зависит от количества строк (проверка идет по столбцу i) и количества столбцов (проверка по строке 1)
(В моем примере диапазон EA2:JW18, т.к. в столбце i последняя заполненная строка 18, а в строке 1 столбец JW)

1) Если цифра в текущей строке столбца А меньше, чем 2000000 переходим к пункту 2 (если цифра больше, то пропускаем строку)
2) Определяется значение ячейки текущей строки в столбце i (с ячейки i2 по последнюю заполненную). Значение может быть "П" или "В", в зависимости от результата выбираем какие данные сравнивать:

Если значение = "П":
1) Дату из строки 1 текущего столбца (книга Итог) сравниваем с датами из столбца АН (книга Свод)
2) Определяем, что дата из строки 1 текущего столбца (книга Итог) находится в диапазоне между датами (или равна им) из столбцов E и F текущей строки (книга Итог)
3) Цифру из ячейки J2 (книга Итог) сравниваем с цифрами из столбца АТ (книга Свод)
4) Цифру из ячейки L2 (книга Итог) сравниваем с цифрами из столбца C (книга Свод)
5) Суммируем значения всех ячеек из столбца СС (книга Свод), которые попадают под условия (пункт 1, 3, 4) - (в примере, в столбце СС, везде стоят 1, но фактически там может быть пусто или стоять 0, т.ч. просто сложить количество подходящих дат из столбца АН нельзя, будет считать с ошибкой)
6) Умножаем цифру из текущей строки столбца G (книга Итог) на сумму значений из пункта 5
7) Записываем результат в текущую ячейку (книга Итог)
8 ) Переходим к следующей ячейке

Если значение = "В":
1) Дату из строки 1 текущего столбца (книга Итог) сравниваем с датами из столбца ВЕ (книга Свод)
2) не меняется
3) не меняется
4) не меняется
5) не меняется
6) не меняется
7) не меняется
8 ) не меняется
Изменено: vikttur - 18.09.2021 12:11:56
Макрос поиска значения по заданным условиям и обработка результата, ускорение работы макроса
 
Здравствуйте, уважаемые!

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

У меня есть два файла (прикрепил их к сообщению).
Из файла Свод в файл Итог макросом переносятся данные. Макрос найден на просторах интернета и немного переработан под мою задачу, есть вероятность, что он не совсем правильно работает. Проблема заключается в том, что для получения результата необходимо ждать очень много времени.

Как работает макрос и что нужно получить:
Скрытый текст

Ранее не сталкивался с формированием таких больших отчетов, не уверен, что правильно понимаю принцип работы экселя/макросов.
В примере 17 строк по 153 ячейки в каждой, т.е. 2601 ячейка.
Если я задаю проверку через строку (ниже), макрос завершает свою работу через 20 секунд
Код
If arr2(1, i) = arr(n, 57) And arr(n, 46) = m And arr(n, 3) = gg Then
Если я задаю проверку через строку (ниже), макрос завершает свою работу через 40 секунд
Код
If arr2(1, i) = arr(n, 57) And arr2(1, i) >= c1 And arr2(1, i) <= c2 And arr(n, 46) = m And arr(n, 3) = gg Then
Т.е. из-за дополнительной проверки двух переменных макрос начинает работать в 2 раза дольше
Код
arr2(1, i) >= c1 And arr2(1, i) <= c2
Рабочий файл должен содержать более 60 тыс обрабатываемых ячеек (30 листов с результатами). Грубый математический расчет дает понять, что 60 тыс ячеек будут обрабатываться: 1 вариант - 7,5 минут, 2 вариант - 15 минут
Первый вариант близок к нормальному времени, но не выполняет свою задачу на 100%. Второй вариант занимает слишком много времени.

Вопросы:
1) Мой макрос написан плохо или это нормально, что на обработку 2600 ячеек уходит 20 секунд?
2) Как можно улучшить текущий макрос (или как должен выглядеть новый) для более быстрой обработки результатов?
Изменено: vikttur - 05.10.2021 21:42:13
Страницы: 1
Наверх