en
Feedback
Дневник VBAшника

Дневник VBAшника

Open in Telegram

Разное о Visual Basic for Application (VBA)

Show more
204
Subscribers
No data24 hours
No data7 days
No data30 days
Posts Archive
Рефакторинг. Интерфейс Вторая часть на хабре. Разбираем проектирование интерфейса. В два раза короче, и вроде все по делу. Велкоме!😃 Дневник VBAшника

Полезные каналы Тут в чатике попросили подкинуть годных курсов на ютубе. Поделюсь со всеми, думаю кому-нибудь точно будет полезно. Итак: ➡️На русском, но для новичков с нуля. Я с этого автора начинал свой путь в vba: Билял Хасенов ➡️На английском, но уже для более продвинутого уровня. Очень многое почерпнул, начиная с форматирования, заканчивая некоторыми фишками, которые до сих пор использую: macro mastery ➡️На русском, много очень крутых и интересных фишек, но стиль кода и ведения повествования мне не особо нравится. Но у автора я тоже почерпнул несколько моментов, например программная отрисовка контролов, работа с гет/пост запросами для скачивания генерируемых файлов (не по прямой ссылке, а когда они на стороне сервера генерируются) К сожалению автор удалил канал или сменил юзернейм. Но я нашел сайт, возможно там что-то есть: ссылка ➡️Ну и не могу не упомянуть создателя моего любимого Rubberduck. Годные статьи, большой стайлгид для vba и ожидание rd3🧘… Mathieu Guindon По архитектуре, увы, VBAшного ничего не находил. Можно только смотреть/читать общее и пытаться транслировать. С переменным успехом, но получается. Всем добра, надеюсь было полезно👨‍💻 Дневник VBAшника

Ого, нас уже 100 человек! 🤩

Рефакторинг Выкатил подробную статью (целых 18 минут чтива, для меня рекорд) с кейсом рефакторинга кода. Кому интересно, велком на хабр. 🍷 Дневник VBAшника

Кто слушает музыку во время кодинга? Под что кодите? Мне если нужна максимальная сосредоточенность - Meshuggah лучший выбор.

Как создавали vba:
Как создавали vba:

PStrings Дропнул на GitHub модуль своего производства, для работы со строками. Там немного, но это честная работа. (с) Может кому пригодится 🙂 Дока по каждой функции в комплекте, но ее генерил GPT, поэтому могут быть бредовости.🙂 Если че, пишите, поправлю ✍️ Ссылка: https://github.com/artemdorozhkin/PStrings Дневник VBAшника

Да, маленькая процедурка внизу скрина, у меня такие же эмоции вызывает код над тобой...😭 Дневник 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 🤖
+1
Закончу сегодняшние восторги по 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шника
Я один такой загонный и проверяю длину строки через 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шника

Попался сегодня забавный легаси) Дневник VBAшника
Попался сегодня забавный легаси) Дневник VBAшника