Случилось странное. На работе начал писать макрос в Excel 2007. Вечером забрал xlsb-файл домой, поработал с ним в Excel 2021, и отправил себе обратно на рабочую почту. Утром, на работе, обнаружил что файл пришел битый, не открывается (обнаружено ... содержимое... восстановить? после восстановления - полностью поломанный файл - не хватает главного листа, куча каких-то левых листов, полностью слетевшее форматирование и т.п.). Грешил на майл.ру, но не поленился - сгонял домой, и привез файл на флешке. То же самое. На соседней машине поднял офис 2021, убедился что файл там открывается нормально, пересохранил в .xlsm, перенес на рабочий комп - и всё норм, работает в 2007. Вопрос!!! Чем xlsb в 2021 офисе отличается от xlsb в 2007? Или что ещё могло стать причиной такого глюка?
написал: Вы делаете это макросом - то не обращаете внимания, какая ячейка активная. А УФ - обращает. Вот и получается такой казус.
Мда, интересный материал для размышления)) Много лет работаю с VBA, и всегда считал методы select и activate пережитками макро-рекордера. Придется пересмотреть этот момент. Ещё раз спасибо за подсказку.
Приветствую, господа. Столкнулся с непонятным поведением excel, надеюсь кто-то окажется внимательнее и поймет что происходит.
Итак. Есть макрос, выполняющий определенные вычисления в таблице. На основании полученных итогов таблица должна быть раскрашена. Чтобы точнее прицелится, ввожу в Immediate команду:
пока всё правильно, мне действительно нужно создать правило на основании клетки P6 Дописываю в конце макроса такой код:
Код
With ActiveSheet.ListObjects("реестр").DataBodyRange
.FormatConditions.Delete
.FormatConditions.Add Type:=xlExpression, Formula1:="=" & .Cells(1, 16).Address(0, 1) & ">0"
.FormatConditions(1).Interior.Color = vbGreen
End With
Выполняю макрос, замечаю что клетки раскрасились как-то неправильно, и обнаруживаю, что в созданном правиле прописалась формула "=$P8>0" Вручную исправляю эту формулу, вся таблица раскрашивается как надо. Внимание, вопрос! В какой момент выражение, вычисляющееся в "$P6" вдруг выдало "$P8" ????
Поиск текстовых данных по разным столбцам, Нужно найти определенные слова в трех столбцах и в соседнем столбце присвоить, значения, которые за этими словами закреплены
написал: Свойство Range.Value так устроено - возвращает одно скалярное значение (для ячейки) или двумерный массив (для диапазонов, состоящих более, чем из одной ячейки).
Принял к сведению, спасибо. Будут лишние запятые в макросах, ну и пусть.
Потому что регулярно натыкаюсь на ошибки "subscript out of range" в собственном коде ) потому и говорю - не путаю ли я VBA с другими языками. Вроде ведь логично: одномерный диапазон присваивается массиву. Но массив почему-то получается двумерный (x to 1), причем вторая размерность всегда 1.
В смысле .row и .column? так это свойства (properties) объекта, а не измерения (dimensions). Для получения адреса клетки это актуально, но если нужно получить массив значений из одной строки? столбца?
Коллеги, прошу подсказку. я то ли туплю, то ли путаю VBA с другим языком. Задача: загнать range в массив. Вроде бы тривиально: dim arr arr = [A1].resize(5).value но на выхлопе получается двумерный массив (5,1), то есть обращение типа msgbox(arr(3)) даст ошибку "subscript out of range", а нужно писать msgbox(arr(3,1)). А можно ли одним оператором создать из одномерного range одномерный массив? Или для этого придется обходить заданный range циклом?
написал: У меня всё работаетКодSub t() Dim dic As New Dictionary dic.add "test", Array(10, 20, 30) Debug.Print dic.Item("test")(1) ' 10 (for Option Base 1) End Sub
Да, так работает. А не получается вот так:
Код
dic.Item("test")(1) = dic.Item("test")(1) + 100 'элемент массива почему-то не изменяется.
Приходится делать через промежуточный массив:
Код
arr = dic.Item("test"): arr(1) = arr(1) + 100: dic.Item("test") = arr ' а вот так работает
Это мощно. Переписал свой макрос со словарем. Мало того что он работать стал на порядок быстрее, так ещё и код в три раза компактнее получился:
Код
Dim dic1: Set dic1 = CreateObject("Scripting.Dictionary")
With Sheets("Лист1")
For i = 2 To .UsedRange.Rows.Count
key1 = Left(CStr(.Cells(i, 3)), 10) & CStr(.Cells(i, 2))
If Not dic1.exists(key1) Then dic1.Add key1, 0
dic1.Item(key1) = dic1.Item(key1) + CDbl(.Cells(i, 4))
Next
End With
Application.ScreenUpdating = False
With Sheets("Лист2")
For i = 3 To .UsedRange.Rows.Count
key1 = Left(CStr(.Cells(i, 1)), 10) & CStr(.Cells(i, 2))
If dic1.exists(key1) Then .Cells(i, 3).Value = dic1.Item(key1)
Next
End With
Application.ScreenUpdating = True
Может и не идеально, но скорость меня уже устраивает. То что раньше работало до 10 минут, выполняется в пределах 3-5 секунд. Ура.
Привет, коллеги. Прошу помочь с алгоритмом, теоретической подготовки не хватает.
Суть в следующем. Есть книга с двумя (на самом деле гораздо больше) листами. На одном из них (назовем его Лист1) несколько десятков или даже сотен тысяч записей, которые постоянно обновляются и пополняются копированием-вставкой из внешнего источника. Данные на этом листе не упорядочены, и содержат графы "дата", "ID", некая "сумма", и много всего прочего. На другом листе (Лист2) нужно макросом сформировать типа сводного отчета, в котором данные первого листа подсуммируются по "дате" + "ID". Есть рабочее решение, но оно слишком медленно, поэтому и прошу подсказки. Суть моего макроса состоит в том, что содержимое обоих листов считывается в два массива, потом двумя вложенными FOR даные суммируются (внешний for пробегает больший массив1, а внутренний накапливает в меньшем массиве2 суммы по заданным условиям), затем меньший массив заливается обратно на Лист2 конструкцией типа cells(...).resize(...).value = arr. Этот макрос работает несколько минут, что очень долго, учитывая прочие условия задачи. Со сводными таблицами знаком, в данном случае это неприменимо, потому что Лист2 имеет фиксированную разметку - это достаточно сложный отчет, который нужно заполнить цифрами по одной кнопке, нажатой пользователем.
С функцией СУММЕСЛИМН тоже знаком, но если её использовать на этом объеме данных, перерасчет всей книги на шести ядрах core i5-8500 c 16GB памяти занимает почти 2 минуты, что также недопустимо, т.к. перерасчет будет запускаться на каждое редактирование, фильтрацию и т.п. (application.calculation =xlcalculationmanual не предлагать, противоречит прочим неозвученным условиям)
В общем, требуется именно макрос, который будет работать по кнопке, и по возможности "мгновенно". Накидайте пожалуйста идей или ссылок на описание, какой алгоритм суммирования по нескольким условиям самый быстрый. С реализацией в VBA буду разбираться сам. Спасибо.