Дневник VBAшника
231 subscribers
109 photos
2 videos
163 links
Разное о Visual Basic for Application (VBA)
Download Telegram
Дневник VBAшника
Готовлю интересный материал (по крайней мере мне кажется, это будет интересно) Как думаете, что это и что скрыто за черными полосками?🙃
Сушайте, ну можем похоливарить на тему, если интересно

Дано
Книга на 4 столбца и на 25000 строк
Задача
Максимально быстро извлечь все данные и вывести в вбансоль количество строк

На скрине результаты решений, на момент подготовки

Regular - обычное открытие книги, без "ускорителей" в трех вариантах: просто открытие, с флагом ReadOnly и с флагами ReadONly и NoUpdateLinks.

Screen updating off
- выключенный Application.ScreenUpdating

Events off - выключен ScreenUpdating и EnableEvents

Calculation Manually - ко всему выше установлено Calculation Manual

Status bar off - ко всему выше отключен статус бар

Display Alerts off - ко всему выше отключены DisplayAlerts

ADO - чтение через ADO

Спустя некоторое время, ВНЕЗАПНО, вариант с ADO начал выдавать результаты в 2 раза хуже чем обычное открытие.

Причины? Вообще без понятия.
Просто открытие с ScreenUpdating = False выдает ~ 240ms, ADO ~430ms, при этом изначальные результаты были на скрине.

Что повлияло? Вообще без понятия.

У меня все. Спасибо за внимание🥴
👍3🔥1
Я думал, что VBA меня уже ничем не удивит😂

Итак, есть модуль TestModule, который выглядит как-то так:
Option Explicit

Private Type TType
Objects As Object ' Dictionary
End Type

Private this As TType

Public Sub Run()
CreateNewCollection
End Sub

Public Function Count() As Long
If this.Objects Is Nothing Then Exit Function
Count = this.Objects.Count
End Function

Private Sub CreateNewCollection()
If this.Objects Is Nothing Then
Set this.Objects = CreateObject("Scripting.Dictionary")
End If

Set this.Objects(Rnd) = New Collection
End Sub


И есть модуль Example:
Public Sub Test()
Debug.Print TestModule.Count
TestModule.Run
End Sub


Если с помощью F5 начать вызывать процедуру Test, то вывод в Immediate будет как на скрине 🥴
То есть, словарь this.Objects в модуле TestModule живет вечно (пока явно его не удалить или не нажать кнопку "Стоп" на панели управления).

Внимание вопрос:
WTF???

Если что, я реально не понимаю в чем прикол.
Относительный путь

Узнал в только что лет.

Попадались на таком?
Когда пытаешься сохранить книгу, используя только ее название, файл улетает, обычно, в папку Documents:

Dim Book As Workbook
Set Book = Workbooks.Add()
Book.SaveAs "Temp.xlsx"
Debug.Print Book.FullName ' C:\Users\Username\Documents\Temp.xlsx

Все дело в том, что при открытии Excel, директория «Документы» выбирается как рабочая (если я правильно понимаю).

В итоге приходится прописывать полный путь, чтобы сохранить файл в нужное место.

И я так делал, а потом вспомнил о таком модуле как FileSystem.

Все, что требуется сделать, это воспользоваться старым советским… функцией ChDir:

FileSystem.ChDir ThisWorkbook.Path ' Или другой полный путь, на свое усмотрение

Dim Book As Workbook
Set Book = Workbooks.Add()
Book.SaveAs "Temp.xlsx"
Debug.Print Book.FullName ' C:\путь\до\текущей\книги\Temp.xlsx

Что особенно круто, если вы укажете какую-то корневую директорию, а вам нужно сохранить в папку из этой директории, то можно прописать и путь к ней:

FileSystem.ChDir ThisWorkbook.Path ' Или другой полный путь, на свое усмотрение

Dim Book As Workbook
Set Book = Workbooks.Add()
Book.SaveAs "MY_FOLDER\Temp.xlsx"
Debug.Print Book.FullName ' C:\путь\до\текущей\книги\MY_FOLDER\Temp.xlsx

Причем писать можно как нравится:
- MY_FOLDER\
- ./MY_FOLDER/
и даже
- ./MY_FOLDER\

VBA слэши сам исправит ☺️

Если нужно, все таки, сохранить (зачем-то) путь к текущей рабочей директории, то можно воспользоваться функцией CurDir:
Dim WorkingDir As String
WorkingDir = FileSystem.CurDir()

Ставь😱, если было полезно
😱12👍2
PCollections

Выложил модуль с функциями для работы с коллекциями, вдруг кому надо:
https://github.com/artemdorozhkin/PCollections

Вроде неплохая дока получилась + тесты и модуль с примерами.

Если звезду ткнете, вообще буду благодарен⭐️

Stay tuned❤️
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍14
Вы себе даже не представляете, с каким трепетом я сейчас смотрел на это сообщение об авторизации на собственном публичном сервере для реестра ppm.🥲
Ну то есть любой желающий сможет выложить свой код для переиспользования участниками сообщества.
Все как во взрослом мире npm, pip и прочих пакетных менеджеров🥲

Оно работает.

Теперь буду тестить и, надеюсь, в ближайшее время будет релиз

Stay tuned❤️

Что за ppm?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥4
Это я, после того как перед грядущим релизом ppm решил переосмыслить систему работы с конфигурационными файлами 🥲
👍4🔥3😱2
Токен

Прикрутил возможность восстановить токен прямо из ppm.
Вот такое вот письмецо будет прилетать, сразу с командой, которую нужно выполнить для перезаписи токена.
За токен на скрине, кстати, можете не переживать, я его уже перевыпустил 🕺

Ах да, я же не делился еще.

Добавил команду auth, с помощью которой можно получить токен на публикацию пакетов. Устанавливать пакеты можно без регистрации и смс, а вот публикация ограничена теми, у кого есть токен. Впрочем, получить его можно тоже совершенно бесплатно.

Токен и email хранятся в конфиге на уровне user (путь: %APPDATA%/ppm/.ppmrc).

Как раз на случай утери/удаления токена из конфигурации, решил добавить возможность восстановления. Вернее это будет создание нового.

З.ы. Самые внимательные могли заменить доменное имя для удаленного реестра🤫

Stay tuned❤️

Что за ppm?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
PyPath

Выложил модуль с функциями для работы с путями, вдруг кому надо:
https://github.com/artemdorozhkin/PyPath

Этот модуль – практически полный перевод на VBA модуля os.path из python🖼️.
Соответственно, python-документация актуальна и для моего модуля 🗒

Если звезду ткнете, вообще буду благодарен⭐️

Stay tuned❤️
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9
Большое обновление ppm

Вчера загрузил большое обновление. По сути – это релиз кандидат🥳
Функционал протестил на нескольких своих проектах, вроде работает как надо.
Присоединяйтесь к тестированию 😉 Единственный момент, не рекомендовал бы пока сразу тестировать на боевых проектах.
А, ну и точно должно работать в Excel, за другие платформы, увы, не ручаюсь.
Если есть желание добавить поддержку другой платформы, welcome to contributors🍷


✒️Итак, что же изменилось:
команды install и publish теперь по умолчанию обращаются к публичному репозиторию: https://registry.ppmvba.com 😎
конфигурация собирается по восходящей:
➡️сначала читаем минус-аргументы, переданные вместе с командой (ppm "export --save-struct")
➡️затем читаем конфиг из папки проекта - project конфиг
➡️далее конфиг в %APPDATA%/ppm - user конфиг
➡️потом конфиг в %PROGRAMDATA%/ppm - global конфиг
➡️оставшиеся значения берем из установленных по умолчанию в ppm
исправлены баги


🔊А еще, много нового функционала

📌dev-зависимости
Добавил работу с dev-зависимостями. Теперь при выполнении команды ppm "install" можно добавить флаг --save-dev и пакет установится в dev часть:

'  "devDependencies": {
' "PCollections": "1.0.0"
' }


Таким образом можно разделять обязательные зависимости и те, которые нужны только для разработки.


📌Новая команда ref
ref (от references) управляет референсами проекта. То есть, теперь не нужно обращаться к Tools > References... и искать в списке Scripting, а достаточно в Immediate window выполнить команду:

ppm "ref add scripting"


и все, вы великолепны😌

ref поддерживает подкоманды/флаги:
- add – добавление
- delete – удаление
- update – обновление списков в модуле package
- list – вывод в Immediate списка подключенных референсов
- флаг --save-dev, то есть можно добавить dev-references:

'  "devReferences": {
' "Rubberduck": "2.5",
' "ppm": "1.0.0"
' }


ppm автоматически добавляется в devReferences. При удалении (ppm "ref delete ppm"), отключается от проекта.


📌Новая команда build
ppm теперь не просто пакетный менеджер, а еще и простенькая билд-система.
Помните dev-зависимости/референсы? Так вот, при выполнении:

ppm "build"


из проекта автоматически будут удалены все зависимости/референсы добавленные в dev блоки. Все остальные останутся.

Вот с референсами – это то, чего мне дико не хватало в работе. Было удобно юзать scripting при разработке, но в клиентской версии его нужно было обязательно отключать. Как и ppm, собственно. У вас такой проблемы не будет :))

Поддерживает флаги:
- -o|--output имя файла для билда. По умолчанию берется name@version из модуля package.
- --file-format формат/расширение файла билда. По умолчанию xlsb. Если в output передано имя файла с расширением, в конце будет добавлено расширение переданное с флагом --file-format:

ppm "build -o main.xlsb --file-format xlsm" ' сохранит билд в файл main.xslb.xslm



Поддерживаются форматы xlsb, xlsm, xls, xla, xlam.


📌Новая команда auth
Для публикации пакетов (ppm "publish") в публичный репозиторий, потребуется api-token.
Чтобы его получить, необходимо выполнить команду:

ppm "auth <email>


Где email – ваш email-адрес.
На самом деле, на данный момент, это может быть любая строка без пробелов, но лучше всего указать, все-таки, действительный email, т.к. в случае утери токена, восстановить его не удастся.

После выполнения команды будет выведено сообщение с токеном для указанного email-адреса.
Токен и email автоматически записываются в user конфиг и при публикации пакетов считываются оттуда.

В случае утери токена, можно выполнить команду:

ppm "auth --recreate-token"


после чего, на указанный email будет выслано письмо с новым токеном и инструкцией по его установке.


Уф... вроде все на сегодня :)
Код уже на GitHub🖥

Stay tuned❤️

Что за ppm?
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍2
Я тут подумал, и решил в несколько постов сделать туториал по ppm: как им пользоваться, как его установить и тд
Типа документации в постах.
Что думаете, нужно?👇
Нужны туториалы по ppm?
Anonymous Poll
63%
Да 👍
3%
Нет 👎
34%
Что за ppm?🙂
👍1
PPrint

Наконец-то дошли руки до проекта, о котором я мечтал уже давно.

Представляю простой, но мощный модуль, состоящий из одной функции — pprint. Можно забыть о надоедливых джойнах массивов перед выводом в окно Immediate и нудном просмотре словарей через Watch window.

Теперь всё стало проще:

➡️Вывод словарей:

Dim d As Object
Set d = CreateObject("Scripting.Dictionary")
d("Hello") = "World"

pprint d
' Результат: {"Hello": "World"}


➡️Красивый вывод коллекций:

Dim c As Collection
Set c = New Collection

c.Add "Hello"
c.Add "World"

pprint c
' Результат: ("Hello", "World")


➡️Удобный вывод массивов:

Dim a As Variant
a = Array(1, "Hello, World!", CreateObject("Scripting.Dictionary"))

pprint a
' Результат: [1, "Hello, World!", {}]


А еще:

Поддержка вывода объектов Range.
Любой другой объект выводится как <object 'ObjectName'>, включая пользовательские классы.
Хотите более информативный вывод ваших пользовательских объектов? Просто добавьте метод Repr__ в свой класс, и pprint отобразит его так, как вам нужно.

Подробности и примеры на GitHub.📖

В ppm уже добавил. Установить очень легко:

ppm "install pprint"


Stay tuned❤️

Дневник VBAшника
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12
xlcat

Решил тут параллельно с другими проектами немного поэкспериментировать с Go, и вместе с GPT родили идею написать небольшую удобную утилиту: xlcat.

Это что-то вроде привычного cat, но только для Excel-файлов — теперь можно быстро просматривать их содержимое прямо в терминале, без лишних движений и интерфейсов.

Максимально простая и легкая утилита, без перегруженного функционала и лишних деталей.

Делюсь своим маленьким творением — возможно, кто-то давно искал именно такую штуку 🙂

В релизах есть exe под win x64. Не забудьте добавить в переменную PATH.

Это первый мой проект на go, поэтому гоферов прошу тапками не кидаться)

Stay tuned❤️

Дневник VBAшника
Please open Telegram to view this post
VIEW IN TELEGRAM
Зачем нужен Open Statement, когда есть FSO?

Думаю, как многие из вас, я мало задумывался над тем каким способом читать текстовые файлы. FileSystemObject (FSO) — удобно, просто, работает.

И вот наступил момент, когда любопытство взяло верх: решил проверить на практике, насколько велика разница.


🖥 Тест: три способа чтения, один большой файл

Для теста я взял обычный текстовый файл объемом около 200 Мб (для наглядности) и выбрал три разных подхода для чтения данных:
▶️FSO — привычный способ через OpenTextFile().ReadAll()
▶️Open For Input — построчное чтение
▶️Open For Binary Access Read — побайтовое чтение всего файла за раз

Результаты оказались весьма показательными (скрин ниже).
Binary Access просто разорвал конкурентов на больших объемах.
Там, где FSO и Input начинают тупить, Binary метод справляется моментально.

ℹ️ Сразу оговорюсь:
на маленьких файлах разница практически незаметна, но когда дело доходит до больших объемов, Binary Access просто творит чудеса! 👏



🧑‍💻 Код для теста

Можно потестить у себя.
Просто вставьте код ниже в любой модуль, сохраните файл в удобном месте, разместите рядом текстовый файл test.txt для теста или укажите свое имя в константе FILE_PATH.
'@Folder("VBAProject")
Option Explicit

Const FILE_PATH As String = "test.txt"

Public Sub Run()
Const LINE_SEP As String = "------------"

FileSystem.ChDir ThisWorkbook.Path

FSORead
Debug.Print LINE_SEP
RegularRead
Debug.Print LINE_SEP
BinaryRead
Debug.Print LINE_SEP
End Sub

Public Sub RegularRead()
Dim t As Single
t = DateTime.Timer

Dim n As Integer
n = FileSystem.FreeFile()

Dim Buffer() As String
ReDim Buffer(255)

Dim i As Long
Open FILE_PATH For Input As #n
While Not FileSystem.EOF(n)
If i > UBound(Buffer) Then
ReDim Preserve Buffer(Conversion.CLng(UBound(Buffer) * 1.5))
End If
Line Input #n, Buffer(i)
i = i + 1
Wend
Close #n

ReDim Preserve Buffer(i - 1)

Dim Data As String
Data = Strings.Join(Buffer, vbNewLine)

Debug.Print "RegularRead:", "Reading time: "; (DateTime.Timer - t) * 1000 & "ms"
Debug.Print "RegularRead:", "Data len: "; Strings.Len(Data)
End Sub

Public Sub BinaryRead()
Dim t As Single
t = DateTime.Timer

Dim n As Integer
n = FileSystem.FreeFile()

Dim i As Long
Open FILE_PATH For Binary Access Read As #n
Dim Buffer() As Byte
ReDim Buffer(FileSystem.LOF(n) - 1)
Get #n, , Buffer
Close #n

Dim Data As String
Data = Strings.StrConv(Buffer, vbUnicode)

Debug.Print "BinaryRead:", "Reading time: "; (DateTime.Timer - t) * 1000 & "ms"
Debug.Print "BinaryRead:", "Data len: "; Strings.Len(Data)
End Sub

Public Sub FSORead()
Dim t As Single
t = DateTime.Timer

Dim FSO As FileSystemObject
Set FSO = New FileSystemObject

Dim Data As String
Data = FSO.OpenTextFile(FILE_PATH, ForReading).ReadAll()

Debug.Print "FSORead:", "Reading time: "; (DateTime.Timer - t) * 1000 & "ms"
Debug.Print "FSORead:", "Data len: "; Strings.Len(Data)
End Sub


Stay tuned❤️

Дневник VBAшника
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥85👍3
А у вас вчера спина белая была!🫵
👍3😱1
Внезапные вести с полей VBA 🤓

Да, это я таким способом решил напомнить о себе всем, кто успел забыть, что я вообще существую.

На днях я вернулся к своей старой статье о рефакторинге и понял, что с тех пор кое-что изменилось. В частности, моя архитектурная парадигма. Спасибо коллеге Максу, его взгляд помог мне иначе осмыслить многие вещи.
Теперь вот подумываю о продолжении статьи… Хотя, честно говоря, не знаю, когда у меня на это найдется время.

Сейчас на работе у нас миграция макросов — задач море. Заодно я пытаюсь внедрить хоть какие-то стандарты по ведению проектов. Потому что в нашем VBA принято просто «делать прямо сейчас». А то, что это 2500 строк копипасты с глубиной вложенности на 10 уровней и без намека на читаемость, как бы никого не волнует. (И нет, это не гипербола, я такое реально видел — и, к сожалению, не один раз.)

И вот, эта культура, а вернее, ее отсутствие, перетекла и в Python-код. Такого Python-кода я ещё не встречал 😄

В общем, все это жутко пожирает время, а у меня ведь еще и семья есть (люблю вас ❤️). Поэтому пока что мои проекты вроде ppm и все, что связано с VBA, находятся на паузе.

Но очень хочется вернуться (и ворваться, конечно 😀).

А пока, предлагаю вам такой интерактивчик:
напишите в комментариях, о чем вам было бы интересно почитать здесь. Необязательно про VBA. Если тема мне знакома, постараюсь в ней разобраться глубже и рассказать, как умею 🙈
Please open Telegram to view this post
VIEW IN TELEGRAM
😱32🤯2
Кстати ppm

Пока я тут думаю, что вам рассказать про WinAPI и про классы, вспомнил, что отделил ppm и некоторые библиотеки в отдельный проект, поэтому велкоме:

https://github.com/Pear-VBA
6