И вам спасибо, Бахтиёр. Ваш способ постараюсь отложить в свою копилку знаний, вдруг в следующий раз не числи в итемах лежать будут или например их выгрузить понадобится
Доброго времени суток, уважаемые форумчане. Возник небольшой вопроси, если на него есть решение, то буду очень рад его увидеть. Итак, наполняется словарь: в ключах названия, в итемах количество:
Код
Dim dicData As Object, i As Long, Data As Variant, Data2 As Variant
Set dicData = CreateObject("Scripting.Dictionary"): dicData.CompareMode = 1
For i = 1 To 5
dicData.Item(Cells(i, 1)) = Cells(i, 2)
Next i
Data = Filter(dicData.keys, "р", , vbTextCompare)
затем я отфильтровываю нужные мне значения. Все ОК, но можно ли и как, если можно, получить доступ и итемам отфильтрованных данных, чтобы иметь возможность подсчитать сумму аналогично Application.Sum(dicData.items), причем сделать это БЕЗ цикла (как в цикле я знаю). Не то чтобы мне мешал цикл или что-то другое, просто я предположил, что если VBA может отфильтровать данные словаря, то может и итемам отфильтрованных данных может получить доступ сразу, без цикла? Повторюсь, вопрос для самообразования, если такое невозможно, вопросов никаких быть не может
Ну, что касается настроек для mail.ru, то смог разобраться: в настройках на mail.ru формируется пароль для внешних приложений и, самое главное, паролем будет не та комбинация, которая будет вами придумана, а та, которая в результате будет сгенерирована сервером. После этого код выполняется правильно (по крайней мере у меня так получилось). Но вылез новый вопрос: как в коде можно указать атрибуты для письма ("важное", "с уведомлением" и т.д.) и можно ли это сделать в принципе?
Доброго времени суток, уважаемые форумчане. Вынужден вновь поднять свою же тему 2021г.: https://www.planetaexcel.ru/forum/index.php?PAGE_NAME=message&FID=1&TID=137635&a.... Тогда вопрос был частично решен советом от уважаемого Андрей VG да и, самое главное, пользователь передумал в своих желаниях. Сейчас пользователь сменился и вопрос вновь возник. Напомню, я пытаюсь отправлять почтовое сообщение, используя следующий макрос: https://www.excel-vba.ru/chto-umeet-excel/kak-otpravit-pismo-iz-excel/. В прилагаемом файле указаны логин и пароль для 2 почтовых серверов. Проблема в том (можно убедиться, указав в ячейке В2 любой существующий ящик) что для yandex.ru все работает (совет от Андрея:
Обязательно выберите опции Разрешить доступ к почтовому ящику с помощью почтовых клиентов → С сервера imap.yandex.ru по протоколу IMAP и Пароли приложений и OAuth-токены.
Сохраните изменения.
выполнен), тогда как для mail.ru код макроса сообщает об ошибке: отказ сервера SMTP. Аналогичных настроек для mail.ru я не нашел, доступ к почте по IMAP, POP и SMTP во внешних сервисах включен. В инете были советы по похожей проблеме об использовании пароля для внешних приложений, но это не помогло (в тестовом ящике такого пароля нет, так как от требует указания реального телефона, но на своем реальном адресе я проверял эту возможность). Уважаемые гуру, подскажите как все таки можно решить эту проблему хотя бы для mail.ru (рабочий ящик на нем), можно ли указать нужные настройки (как в совете от Андрея) в теле самого макроса?
Прям неудобно становится, когда для решения твоей "хотелки" отвлекаются профи . Повторю, есть ПРАВИЛЬНЫЙ код где для расчетов и используется такая конструкция (по строкам разбил для удобства):
я просто попытался сократить его. Посмотрите, при указании диапазона для Application.CountA приходится 2 раза вычислять номер строки нужного листа, а хотелось бы 1 раз, ведь формулой из файла (=СЧЁТЗ(СМЕЩ(A10;0;4;;3))) получается . Только это и нечего больше. P.S. код приведен из реального файла, так что все именные диапазоны и листы разумеется есть
Доброго времени суток, уважаемые форумчане. Пытаясь "оптимизировать" код, столкнулся с небольшой проблемкой. Скажу сразу, сейчас есть готовое решение и, если не будет другого, ничего страшного. Итак, имеется список арендаторов, среди данных которых есть и номера их телефонов. Требуется подсчитать их кол-во у каждого. Сейчас я делаю это, используя Application.CountA, при этом для указания диапазона требуется вычисление нужной строки через Application.Match, что немного громоздко и неудобно читается, т.к. вычисленное значение лишь одно из необходимых для расчета. Формулой эту задачу я смог решить более коротко: =СЧЁТЗ(СМЕЩ(A10;0;4;;3)), где А10 - нужный арендатор, но при попытке адаптировать формулу в код, увидел, что offset имеет только 2 аргумента, а аргументы высоты и ширины из формулы отсутствуют. Можно ли обойти этот момент в коде? Или еще как-нибудь указать диапазон для CountA, вычислив нужную ячейку только 1 раз? Еще раз прошу прощения, что прошу помощи, имея готовое решение, но знания других вариантов не могут быть лишними как мне кажется Заранее спасибо всем откликнувшимся.
Пусть и не совсем так как хотел, но смог сделать 2-ой отбор фильтром: сначала в словаре отбираем по "упрощенному" фильтру, т.е. включая и "головной", а затем в отфильтрованном проверяем еще 1 условие:
Код
k = 5 & "|" & 123456 & "|" & 123456
For Each kt In Filter(dicData.keys, Split(k, "|")(2) & "|" & Split(k, "|")(2), , vbTextCompare)
res = dicData.Item(kt)
Next kt
For Each kt In Filter(dicData.keys, Split(k, "|")(2), , vbTextCompare)
If Split(kt, "|")(1) <> Split(kt, "|")(2) Then sum = sum + dicData.Item(kt)
Next kt
Получается что вопрос закрыт, нет так нет. А по поводу неточного изложения задачи я рассудил так: у меня вопрос по конкретному приему работы со словарем, если бы кто-то показал как это решается (именно фильтром), то вставить код в свой файл я бы сумел. А так в реальном файле и данные берутся не напрямую с листа, а из предварительно созданного массива, да и прочих, не относящихся в вопросу, строк кода и условий расчета много. У меня вопрос получился из "середины" кода, а начало и конец кода я посчитал не относящимися к вопросу поэтому и не привел . Спасибо за отклик.
Ігор Гончаренко, здравствуйте. С одной стороны и объяснить недолго, а с другой хотелось бы именно так как в моем вопросе . Итак в таблице есть данные по показателям счётчиков электроэнергии по объектам. Данные по ним вычисляются по нескольким вариантам, одним из которых является такой: есть "головной" счетчик к которому подсоединены "подчиненные". На головном "нагорело" 100 кВт, на 4-х из 5-ти подчиненных совокупно 70 кВт. Следовательно доля оставшегося счетчика составляет 100-70 = 30 кВт. Почему есть такой вариант, я не знаю, то дело электриков с бухгалтерами . эти вычисления я пытаюсь выполнить в словаре и, повторюсь, имеется полностью рабочий вариант, но для самообразования попробовал придумать другой. проблемы вылезла именно с "маской" для фильтра. Может фильтр в словаре и не умеет использовать чуть более сложные конструкции типа * или ?. Ну чтож, останется первоначальный вариант.
Доброго времени суток, уважаемые форумчане. Подскажите, пожалуйста, как (и можно ли) решить данный вопрос. Скажу сразу, рабочее решение есть, просто пытаюсь придумать 2 вариант для (самообразования). Итак, словарь наполняется:
Код
Dim dicData As Object, key As String, i As Long, kt As Variant
Set dicData = CreateObject("Scripting.Dictionary"): dicData.CompareMode = 1
For i = 1 To Cells(Rows.Count, 1).End(xlUp).Row
key = Join(Array(i, Cells(i, 1), Cells(i, 2)), "|")
dicData.Item(key) = Cells(i, 3)
Next i
далее требуется получить данные из этого словаря (в рабочем файле это делается циклом, а сейчас пытаюсь сделать фильтром:
Код
k = 5 & "|" & 123456 & "|" & 123456
For Each kt In Filter(dicData.keys, Split(k, "|")(2) & "|" & Split(k, "|")(2), , vbTextCompare)
res = dicData.Item(kt)
Next kt
здесь все считает правильно. Чуть поясню по структуре данных, в словарь попадают: порядковый номер, номер счетчика и его индекс. Индексом является номер головного счетчика к которому присоединены прочие. Таким образом для получения значения "головного " счетчика подходит фильтр Split(k, "|")(2) & "|" & Split(k, "|")(2) и, повторюсь, здесь ошибки нет. А вот для расчета значений остальных значений счетчиков, присоединенных к головному фильтр указать не получается. Фактически нужно указать любое значениеSplit(k, "|")(1)& "|" & Split(k, "|")(2) или вообще любое значение & "|" & Split(k, "|")(2) Пытался сделать "в лоб":
Код
For Each kt In Filter(dicData.keys, "*" & "|" & Split(k, "|")(2), , vbTextCompare)
sum = sum + dicDataTemp.Item(kt)
Next kt
но не выходит. Так вот, если можно сразу 2 вопроса по теме: как это сделать и, если можно, как это сделать за 1 цикл (про цикл не так важно, просто интересно) Заранее спасибо всем откликнувшимся
Огромная благодарность всем за продолжение темы, хотя весь сыр-бор был из-за попытки чуть оптимизировать свой код по своей собственной инициативе. НО за советы еще раз спасибо!
Да счетчик у меня и так стоит ниже по коду, но и за Ваш вариант, Msi2102, спасибо. Просто интересно: ведь формулой считается правильно, dicData.keys представляет собой массив (ведь так?), а почему тогда функция не хочет работать правильно? Причем ниже по коду эта функция, правда оперирующая с данными на листе, работает правильно
Доброго времени суток, уважаемые форумчане. Давно не обращался на наш форум со своими "хотелками", как-то сам справлялся , но вот вылез маленький вопросик. Итак, имеем массив в котором ключами являются даты:
Код
Set dicData = CreateObject("Scripting.Dictionary"): dicData.CompareMode = 1
x = Range("A1:B" & Cells(Rows.Count, 2).End(xlUp).Row).Value
For i = 1 To UBound(x)
dicData.Add x(i, 1), i
Next i
Все ОК, но ХОТЕЛОСЬ бы в готовом словаре, причём обязательно БЕЗ ЦИКЛА получить кол-во ключей, удовлетворяющих условию (в примере дата должна быть сентябрьской). Пытался сделать так:
Код
ss = Application.CountIf(dicData.keys, "??.09.2022")
не выходит, ругаться на код не ругается, но значение ss становится типа массивом и значением каждого элемента Error 2015. Можно ли решить данный вопрос именно так, т.е. самое главное без цикла или нет? Если нет, ничего страшного, сейчас вопрос уже имеет решение.
Игорь, у меня получается (пробовал так: x = ActiveSheet.UsedRange) во-первых информация только о содержимом ячейки, а во-вторых эта информация находится в массиве: x(1,1) = "проба" x(1,2) = empty x(2,1) = empty x(2,2) = empty Получается, что (если решить вопрос недостатка данных придется в макросу обрабатывать массив циклом, так?
Ну коли к нашему посту присоединились еще гуру, рискну продолжить тему . Вот пример чуть обработанного макроса, созданного макрорекодером:
Код
With Range("A1")
.Font.Name = "Times New Roman"
.Font.Size = 14
.FormulaR1C1 = "ïðîáà"
End With
Columns("B:B").ColumnWidth = 2.57
Range("B2").Borders(xlEdgeBottom).LineStyle = xlContinuous
Rows("2:2").RowHeight = 9
Примерно это я и хочу увидеть и, после создания листа и его переименования, указать подобные данные по типу ВПР (для каждого листа свое описание). Я немного неточно описал свою задумку, имел ввиду конечно только рабочую (при страничном варианте отображения) часть листа. Пусть макрос (как мне кажется) в цикле переберет все ячейки рабочей области и опишет все что можно касающееся данных ячеек, а я впоследствии "причешу" код. Вот примерно так реально сделать, можно ли получить все нужные данные об ячейке макросом и, если возможно, как указать в цикле границы РАБОЧЕЙ области?
Уважаемый Игорь, так ведь я еще в первом посте указал что это чисто теоретический вопрос и то, что абсолютно ничего страшного нет, если идея не имеет приемлемо простого решения. Нет значит нет. ничего страшного. Разумеется пользователь может и описание снести, тут вы правы, этот мой аргумент слабым получился, ну тогда остается размер файла. Спасибо за отклик даже на не самую умную идею
Уважаемый Игорь, я имел ввиду другое (возможно объяснил кривовато). В принципе, то что вы описали, уже реализовано (созданы копии листов, соответствующе переименованы и скрыты, а макросом восстанавливаются). Но (чисто теоретически) ведь этот скрытый лист может быть случайно удален пользователем (разумеется можно применить защиту), да и объем книги (если таких "резервных" листов штук 10-15) увеличится, а в моем предполагаемом варианте это ведь не так? Разумеется никто не мешает мне прописать все что мне надо вручную, но ведь это долго и нудно, пропустить можно что-либо, вот я и задумал поручить описание макросу
Доброго времени суток, уважаемые форумчане. Давно не обращался за помощью на наш уважаемый форум, как-то получалось самому решать текущие вопросы, но все-таки вопрос появился. Самое главное, вопрос пока чисто теоретический. Итак, ситуация такова: пользователь теоретически может "испортить" лист документа (удалить формулы и текст, изменить высоту и ширину строк и т.д.). Для решения этой гипотетической ситуации сейчас в документе присутствуют резервные листы на основании которых макросом восстанавливаются "испорченные". А теперь наконец вопрос. Можно макросом создать лист и прописать все необходимые данные (формулы, текст в нужных ячейках со всеми параметрами шрифта, параметры строк и колонок и т.д.) А вот можно ли и как сделать это (получить необходимые данные) макросом? Т.е. оформленный лист "просканировать" и получить в итоге все данные об этом листе. А для восстановления листа использовать следующий алгоритм: создать лист и вставить данные из БД (где-то описанной) о его параметрах. Вопрос, повторюсь, чисто теоретический, нет значит нет, останется прежний вариант и все. Заранее спасибо всем откликнувшимся.
skais675, с этим как раз проще всего: просто для самообразования и освоения нового для меня элемента (словаря словарей), так то словарь использую в своих проектах
Прошу прощения не некорректное изложение вопроса. Ключом должна быть информация из столбца Е (там могут быть признаки ОК или В или не быть ничего и это тоже признак). Поскольку имеется 3 варианта, таких ключей должно быть 3. Значением для этих 3 ключей (подчеркну - в моих планах!) должны быть 3 отдельных словаря, в первом из них должно быть 5 ключей (по варианту отсутствия признака с информацией скажем из столбца В и, разумеется, 5 итемов (сумм из столбца D), во втором (по признаку ОК) должно быть соответственно 7 ключей, ну и в третьем 2 ключа (по признаку В). Уважаемый Игорь ,возможно мы не можем понять друг друга из-за того, что сам предполагаемый мною способ невозможен? Пока, как я понял из кодов (вашего и Александра) в дополнительный словарь заносится какая-либо дополнительная информация, а я предполагал наполнение внутри словаря 3-х (в данном случае) отдельных словарей.
Простите за наглость, МатросНаЗебре, не могли ли бы Вы привязать ваш код к моему файлу из поста 1? И еще,
Цитата
Словарь из трёх элементов, каждый из которых является словарём, состоящим из 7 элементов.
эта ситуация только для прилагаемого файла для второго признака, а не общее требование. Первый "внутренний" словарь должен включать 5 ключей, а третий 2
Уважаемые гуру, посмотрел сейчас предложенные вами варианты и возник вопрос. Наверное не совсем понятно объяснил, что мне хотелось бы, попробую еще. Итак, после отбора данных я бы хотел увидеть словарь внутри которого имеется 3 ключа (в прилагаемом примере) и КАЖДЫЙ ключ представляет собой отдельный словарь (например из 7 ключей для варианта с признаком ОК и соответственно из 7 итемов с данными по этому признаку. Чтобы далее, перебирая основной словарь я мог бы запустить последовательно цикл для каждого внутреннего словаря, что то вроде:
Код
for each k in dicData.keys
for each kk in dicData2.keys (цикл для первого внутреннего словаря)
... (создание массива для выгрузки и выгрузка)
next kk
next k
Возможно, то что написал выше совершенная ахинея, мне более важно понять возможен ли такой принцип, а решение, повторюсь, сейчас есть готовое, рабочее, но немного другое. Просто я предположил, что, если речь идет о словаре словарей, то "внутренние" словари могут представлять из себя полноценные словари со всеми их свойствами и выгодами использования. Если мои изначальные предположения неверны, то просто напишите об этом и вопрос будет закрыт.
Тем не менее, Игорь, Вы предложили код, который на мой первый взгляд, делает то что я хотел, спасибо большое. Буду изучать, самое главное с алгоритмом разобраться, а там и до внедрения в свои работы дойдет. Еще раз спасибо за помощь.
И Вам, Александр Моторин, спасибо большое за ваш код, тоже буду изучать. Пока, на первый взгляд, то что надо
... после завершения отбора данных мы должны получить словарь из 3 ключей в итемах которых будут находиться данные 3 субсловарей с отобранными данными.
т.е. мне хотелось бы иметь в каждом из субсловарей (с "пустым" ключом, с признаком ОК или В) полноценный словарь с отобранными данными которые потом использовать