Дневник VBAшника
Open in Telegram
Разное о Visual Basic for Application (VBA)
Show more204
Subscribers
No data24 hours
No data7 days
No data30 days
Posts Archive
Рефакторинг. Интерфейс
Вторая часть на хабре. Разбираем проектирование интерфейса.
В два раза короче, и вроде все по делу. Велкоме!😃
Дневник VBAшника
Полезные каналы
Тут в чатике попросили подкинуть годных курсов на ютубе.
Поделюсь со всеми, думаю кому-нибудь точно будет полезно.
Итак:
➡️На русском, но для новичков с нуля. Я с этого автора начинал свой путь в vba: Билял Хасенов
➡️На английском, но уже для более продвинутого уровня. Очень многое почерпнул, начиная с форматирования, заканчивая некоторыми фишками, которые до сих пор использую: macro mastery
➡️На русском, много очень крутых и интересных фишек, но стиль кода и ведения повествования мне не особо нравится. Но у автора я тоже почерпнул несколько моментов, например программная отрисовка контролов, работа с гет/пост запросами для скачивания генерируемых файлов (не по прямой ссылке, а когда они на стороне сервера генерируются)
К сожалению автор удалил канал или сменил юзернейм. Но я нашел сайт, возможно там что-то есть: ссылка
➡️Ну и не могу не упомянуть создателя моего любимого Rubberduck. Годные статьи, большой стайлгид для vba и ожидание rd3🧘…
Mathieu Guindon
По архитектуре, увы, VBAшного ничего не находил. Можно только смотреть/читать общее и пытаться транслировать. С переменным успехом, но получается.
Всем добра, надеюсь было полезно👨💻
Дневник VBAшника
Рефакторинг
Выкатил подробную статью (целых 18 минут чтива, для меня рекорд) с кейсом рефакторинга кода. Кому интересно, велком на хабр.
🍷
Дневник VBAшника
Кто слушает музыку во время кодинга? Под что кодите?
Мне если нужна максимальная сосредоточенность - Meshuggah лучший выбор.
PStrings
Дропнул на GitHub модуль своего производства, для работы со строками.
Там немного, но это честная работа. (с)
Может кому пригодится 🙂
Дока по каждой функции в комплекте, но ее генерил GPT, поэтому могут быть бредовости.🙂
Если че, пишите, поправлю ✍️
Ссылка: https://github.com/artemdorozhkin/PStrings
Дневник VBAшника
Да, маленькая процедурка внизу скрина, у меня такие же эмоции вызывает код над тобой...😭
Дневник VBAшника
+1
Как найти значение в массиве
Хехе, простым перебором, скажите вы? Или, может быть, бинарным поиском?
А как вам вариант: используя функцию InStr?
Короче говоря...
Нужно было мне при переборе массива проверить, есть ли текущее значение в другом списке. Конкретно - является ли оно названием месяца.
Хотел сначала создать массив с названием месяцев и потом перебирать его, но в голову пришла другая идея:
Const MONTH_NAMES As String = "январь;февраль;март;апрель;май;июнь;июль;август;сентябрь;октябрь;ноябрь;декабрь"
Dim Item As Variant
For Each Item in Data
If InStr(1, MOTH_NAMES, Item, vbTextCompare) > 0 Then
' Do smth...
End If
Next
Вроде прикольно и читаемо вполне.
А потом я подумал, а что если вместо перебора массива, Join'ить его в строку и уже в ней искать значение?
Второй скрин с примером, Sub TestStringFinder.
А первый скрин с результатом времени поиска. Как видно, скорость поиска с помощью InStr даже быстрее, хотя там массив еще и Join'ится перед поиском.
Правда есть нюанс. Тестировал на массиве из 999.999 элементов и искомое значение было в самом конце. А вот если его перенести в начало, то время поиска перебором станет ~580ms.
Шустрее, но возможно не особо то и критично, зависит от конкретной задачи, наверное.
Зато в случае с InStr строк кода аж на две меньше стало💃
Ну и еще для такого способа обязательно нужен массив 1D.
Думаю, что буду периодически пользоваться, когда будет лень писать перебор.🏝
Дневник VBAшникаRepost from Denis Sexy IT 🤖
Закончу сегодняшние восторги по SORA двумя примерами img2vid из статьи выше – на входе ей подали картинки, а на выходе получили анимированные сцены ☕️
Так что скоро все наши любимые картинки и мемы оживут, не может не радовать
Не про VBA конечно, но взрыв мозга обеспечен.
OpenAI выкатили показали нейронку SORA для генерации видео.
Реалистичные примеры просто разрывают.
ipm
Короче, я пытаюсь. Правда, чесслово.
Но моих знаний явно не хватает для того результата, который я хочу получить. Напомню, у меня сейчас задача сделать надстройку для vbe, а не для Excel.
Окошко в vbe сделать удалось, но не получается растянуть текст бокс во весь экран. Не знаю пока каким образом переключать контекст между разными проектами. Не понимаю как реализовать консольный диалог, но не на уровне консоли, а на уровне окна с текстбоксом.
Короче, вопросов больше чем ответов и я пока не уверен что смогу все побороть.
Удалось пока реализовать команду
init, которая создает модуль с комментариями в формате JSON, но все данные предзаполнены (а должен быть диалог с пользователем).
Пока не сдаюсь, но стену уже потихоньку пробиваю головой в поисках ответов 🫠
Дневник VBAшникаКак добавить параметр в PowerQuery
Недавно потребовалось сделать некую доработку для макроса, который формирует отчеты в отдельных файлах, так чтобы он формировал статистику на основе этих отчетов. Сводную таблицу, с возможностью провалиться в детали.
Задумался как бы быстро и не запарно реализовать, с учетом того, что отчеты довольно большие, и после объединения их в одну большую таблицу для сводной, количество строк в скором времени перевалит за ограничение Excel.
Вспомнил про то, что раньше увлекался pq. Расчехлил.
Но был один нюанс. Папку с отчетами пользователь уже указывает в интерфейсе макроса, в юзер форме, а это значение сохраняется в реестре. И вот оттуда его нужно было бы как-то передать в pq, а он так работать не умеет. Вписывать значение в ячейку и читать ее принципиально не хотелось и тогда нашел выход:
Public Sub PutPathIntoPQ(ByVal Path As String, ByVal Name As String)
If QueryExists(Name) Then ThisWorkbook.Queries(Name).Delete
Dim Formula As String
Formula = FString("let {0} = {1} in {0}", Name, Path)
ThisWorkbook.Queries.Add Name, Formula
End Sub
Public Function QueryExists(ByVal Name As String) As Boolean
On Error Resume Next
QueryExists = Len(ThisWorkbook.Queries(Name).Name) > 0
End Function
Начнем с того, что все запросы книги хранятся в коллекции Queries. Это те самые запросы из вкладки Данные.
В самой процедуре PutPathIntoPQ:
➡️Сначала мы в этой коллекции проверяем наличие нашего запроса с именем Name с помощью вспомогательной функции QueryExists.
➡️Если такой есть, удаляем (это чтобы обновить данные).
➡️Далее формируем текст запроса с помощью FString.
➡️И наконец, добавляем запрос с именем Name и формулой (текст запроса) в запросы pq.
Таким образом мы добавляем текстовый параметр в pq, которым далее можем пользоваться в запросах. Нужно больше «запросов» в «запросах»
Пример:
PutPathIntoPQ "C:\path\to\reports", "ReportsPath"
Надеюсь будет полезно
Дневник VBAшникаError
Тут недавно смотрел несколько видосов по golang и заметил интересную особенность. В языке при возврате результата функции можно еще возвращать ошибку (ну тоже по сути как доп результат). И вот если функция может вернуть как результат так и ошибку, то эту ошибку нужно обязательно обработать.
И в голову тут же пришла идея , которую будет интересно попробовать.
Что если возвращать из функции в vba некий объект или публичный тип
Result, в котором будет два поля — собсна Value As Variant и ErrObject, ну или собственный класс Error, тут как фантазия сыграет.
То есть, когда мы вызываем какую-то функцию, если возвращается тип Result, то обязательно необходимо проверить есть ли в нем ошибка и обработать ее соответствующим образом.
Вариантов не много:
➡️проигнорировать
➡️записать в массив и далее вывести в определенный момент (например на лист Excel, или в форму в отдельный Label)
➡️вызывать ошибку с помощью Err.Raise
➡️… еще варианты?
Не знаю пока, насколько это удобно. Не удалось пока попробовать в реальном проекте, так как в последнее время ничего нового на VBA не пишу (импортозамещаемся потихоньку..).
Какие мысли?
Дневник VBAшникаЯ один такой загонный и проверяю длину строки через Immediate если она кажется длинной?🥸
Дневник VBAшника
Как сохранить изображение из фигуры (Shape) в файл
В комментах к этому посту скинул функцию, а потом решил, вдруг кому-то еще пригодится, поэтому ловите:
''' <summary>Сохраняет фигуру в виде изображения.</summary>
''' <param name="ShapePicture">Фигура.</param>
''' <param name="FolderToSave">Папка для сохранения изображения.</param>
''' <param name="Extension">Расширение сохраняемого изображения.</param>
''' <returns>Путь к сохраненному изображению.</returns>
Public Function ShapeToImage(ByVal ShapePicture As Shape, ByVal FolderToSave As String, ByVal Extension As String) As String
If Strings.Right(FolderToSave, 1) <> Application.PathSeparator Then FolderToSave = FolderToSave & Application.PathSeparator
If Strings.Left(Extension, 1) <> "." Then Extension = "." & Extension
Dim ImagePath As String: ImagePath = FolderToSave & ShapePicture.Name & Extension
ShapePicture.CopyPicture
Dim TempChart As ChartObject
Set TempChart = ShapePicture.Parent.ChartObjects.Add(0, 0, ShapePicture.Width, ShapePicture.Height)
With TempChart
.ShapeRange.Fill.Visible = msoFalse
.ShapeRange.Line.Visible = msoFalse
.Select ' Если не выбрать, будет сохраняться пустое изображение.
.Chart.Paste
.Chart.Export FileName:=ImagePath, FilterName:=Strings.Right(Extension, Strings.Len(Extension) - 1)
.Delete
End With
ShapeToImage = ImagePath
End Function
В самой функции собираем путь для сохранения изображения, копируем изображение с фигуры с помощью метода .CopyPicture, создаем временный объект Chart и вставляем в него скопированное изображение, и далее экспортируем с него изображение. Все так сложно, потому что Shape не умеет сохранять изображение в файл, в отличии от Chart, поэтому получаем такой себе костыль.
Пример использования:
Dim MyShape As Shape: Set MyShape = ActiveSheet.Shapes("MyShapeName")
Dim SaveFolder As String: SaveFolder = "C:\path\to\folder"
Dim ImagePath As String: ImagePath = ShapeToImage(Shape, SaveFolder, "jpg")
Debug.Print ImagePath
MyShape – объект фигуры. Получаем обращаясь к листу, на котором она находится и далее из коллекции Shapes извлекаем по имени.
SaveFolder – папка для сохранения изображения.
"jpg" – расширение сохраняемого изображения.
Надеюсь будет полезно🙃
Дневник VBAшникаС Наступающим!🎅🏻
Год назад я написал похожее сообщение в канал, чтобы поздравить небольшую аудиторию с грядущим праздником.
Ура! Всех 17 человек обнял!Ровно год назад вас было 17 человек (включая меня). А сейчас уже вон сколько! Немного? Возможно. Но я не рекламирую канал нигде (второй канал не в счет, наверное 😁). В общем, всех с Наступающим! Искренне поздравляю с окончанием последней рабочей недели! Спасибо, что поддержали канал подпиской, я безумно рад, что вы все здесь 🥹 Ура! Всех 68 человек обнял! Дневник VBAшника
