Что я собираюсь рассказать в этой серии статей?

В  моих  же планах на эту серию статей   - раскрыть вам некоторые, на мой взгляд,  не самые  очевидные аспекты написания макросов для офисного пакета  «Р7-Офис» версии десктоп.  Думаю, многое из мною здесь написанного вряд ли будет вами легко найдено в открытом доступе.  Кое – что конечно  имеется в «секретных Телеграмм чатах» (в которых я  и сам много чего подчерпнул и даже считался там типа эксперта), но некоторые данные,  не найдёте наверное даже там.  Я надеюсь,  изложенные  в этих  статьях мысли, будут стоить потраченных вами  усилий на их чтение. Ну а если вам не интересны мои рассуждения на тему текущего положения дела с макросами и плагинами в редакторе «Р7» - смело пропускайте эту вводную статью и ждите следующих.

Пока мой план на статьи таков:

  1. Введение в общие проблемы написания макросов в «Р7»(эта статья)

  2. Средства взаимодействия с пользователем в макросах АПИ «Р7»

  3. Мое собственное решение для построения сложных форм в макросах

  4. Прочее (по результатам  этих статей, будет зависить от вашего мнения)

Эта часть будет короткой, и не особо полезной именно в плане конкретных решений. Но я подумал и  решил, что нужно на что то опереться, чтобы кинуться в этот омут, поэтому начну с неё.

Для чего я это пишу?

Ранее я уже обращался к проблемам автоматизации в отечественном  офисном  пакете «МойОфис», и опубликовал здесь ряд статей по отладке (и кстати, планирую ещё вернуться к нему, но позже). А теперь у меня накопился опыт по другому решению от отечественных разработчиков:  офисному пакету «Р7», который до недавнего времени являлся просто  форком опенсоурс редактора «OnlyOffice», только в «упаковке» для внутреннего рынка. Но с августа 2024 это увы, далеко не так, и их пути всё дальше расходятся. Но  относительно общая база,  всё ещё позволяет использовать исходники последнего, для понимания работы АПИ в «Р7».

За время работы, я столкнулся со многими проблемами, которые приходилось решать, и по каждой из них можно писать отдельные статьи. Но я решил для начала сосредоточится на той, которая многим покажется неочевидной и даже - неважной, а ведь по сути, она мало где освещена.

Чтобы понять, зачем вообще писать статьи на такие темы, я в этой вводной, хотел бы сперва просто сделать небольшой обзор по проблемам программирования макросов в «Р7», ибо пока не погрузишься в сам процесс, о многом просто наивно думаешь хорошо. Конечно, информация об разных аспектах автоматизации в  «Р7»(и «OnlyOffice»)  уже давно описана. Есть официальные источники по АПИ. Есть разного рода курсы по написанию макросов и плагинов (к написанию некоторых из них я причастен  непосредственно). Это все легко найти в интернете. Но но когда касаешься задачи в достаточно узком, и казалось бы - простом вопросе, как взаимодействие с пользователем в рамках макросов, то всё становится не столь уж и простым! Почему я так утверждаю, я и хотел бы изложить в этой статье, чтобы читатель мог понять, для чего ему читать следующие статьи этой серии.
Итак, моё краткое видение, что собой представляет сам «Р7» и его АПИ, с которым придется бороться.

Об мне

Я, Шумаков Виталий, программист с почти 30 летним стажем. По воле судьбы, занимаюсь последние годы различными задачами автоматизации тех или иных процессов. Кроме того, многие годы был на стороне внедрения программных продуктов, и хорошо знаю обе стороны этого процесса. Долгое время я занимался в основном VBA в CorelDraw, где стал относительно известным разработчиком, благодаря своим макросам по разработке чертежей для станков c ЧПУ. Но, потом случилось сами знаете что, и моя множественная клиентская база, была отрезана вместе с нашей банковской системой от возможностей финансовой поддержки моей работы. А внутри страны, увы, все не столь радужно ибо рынок этот достаточно специфичный. Так я и вернулся к вопросам автоматизации в сфере бизнес процессов. Так как в силу тех же обстоятельств, стало активно развиваться внедрение отечественного ПО, то решил обратить внимание именно в эту сторону. Достаточно активно поковырял «Мой офис», и написал несколько статей сюда, на Хабр, за что и получил «инвайт» прямо от администрации. Благодаря этим статьям, меня нашел один из здешних постоянных авторов, и пригласил меня поучаствовать в своем стартапе, как ведущего разработчика, но уже в другом офисном пакете отечественной разработки - в Р7. Мы сотрудничали некоторый период времени (два года), за которые я успел достаточно глубоко изучить разные аспекты работы с этим редактором (в основном табличной его части), в том числе и весьма глубоко скрытые от глаз обычного пользователя. Благо, что его исходный аналог OnlyOffice — до сих пор является open source и позволяет понять многие моменты в работе. По пути я из��чил „с нуля“ совсем не характерные для моих прежних интересов frontend разработку и язык JavaScript (но экспертом здесь я так и не стал, так что мои решения могут для опытных в этих вопросах программистов показаться дилетантскими, что так и есть!). Заодно узнал много нового для себя из мира BI, так как никогда не тяготел к этому направлению. Так же успел опробовать много разных способов решения задач связи между офисным редактором и внешним миром. Поучаствовал в проектах по переводу макросов из MS Office в Р7 для очень крупного заказчика и ощутил всю "боль" таких работ! Создал свой редактор для макросов в Р7 и разработал модульную систему для упрощения работы в его макросах. А так же, ещё много чего, о чем я рассказывать не буду из‑за контрактных обязательств. В силу определённых обстоятельств, я теперь снова „в свободном плаванье“, и бывшему работодателю желаю всяческих успехов, ибо продукты мы сделали классные! Надеюсь, у него всё получится далее и без моей помощи!
Но мой накопленный опыт и знания — они со мной, и продолжают „мучать“ мой пытливый мозг. Я продолжаю уже чисто самостоятельно свои поиски и предлагаю вам, ознакомится с некоторыми моими личными наработками!

Кратко про «Р7»

Офисный пакет «Р7», видимо исходя из реализации идей «мультиплатформенности», являет собой скомбинированное в одно целое,   клиент-серверное web приложение. "Бэкэнд" часть написана на высокоуровневых  языках  C#  и С++, с использование фреймфорка Qt (для десктоп и мобильных реш��ний)  и отвечает за внутренние механизмы по работе с  документом и рендеринг содержимого пользователю. А "фронтэнд" предоставляет собой пользовательский графический интерфейс и АПИ для автоматизации. Причем, запускается этот «комбайн» сразу как одно целое приложение, и вся «кухня» по взаимодействию этих двух  частей скрыта от глаз пользователя.
Поскольку в работу бэкэнда мы вмешиваться не можем, то нам оставляют лишь возможность работать только на уровне фронэнда.  Вот про это я и буду дальше говорить.

Что же такое « frontend» слой в «Р7»?

Наверное, для упрощения себе жизни (но не нам!), разработчики «OnlyOffice/Р7», решили построить графический интерфейс с пользователем, а заодно и АПИ любой автоматизации, на базе хорошо обкатанного и надежного web движка браузера Chromium. Думаю, особо представлять его нет смысла, ибо на его ядре крутится, наверное, где-то 80-90% всех веб-браузеров. Chromium, если верить статье на Википедии,   сам по себе давно opensource  (с 2008 года), и открыт под BCD лицензией.  На  его базе построено помимо браузеров, ещё и  огромное число так называемых WebApp  - приложений, которые чаще всего используют ядро для построения графического интерфейса, простого в разработке за счет  использования языка разметки HTML в связке с каскадными таблицами стилей CSS  и скриптовым языком JavaScript. По этому же принципу построена и видимая пользователям часть редактора «Р7».  Но конечно же, всё не так просто! Разработчиками  была проделана очень большая работа, для интеграции АПИ базового ядра редактора с кодом Chromium-а.

Написанное  АПИ для вызовов из javascript   весьма обширное и покрывает многие аспекты работы редакторов (пишу именно так, во множественном числе, потому что  в бэкэнд ядре их несколько, как минимум три – текстовый, табличный и презентаций). Но открытая и документированная для пользователя часть, представляет собой значительно урезанную версию всего АПИ, которая оставляет «за скобками» очень многие потребности в работе!  На момент написания статьи, к примеру, в табличном редакторе нет, официального АПИ доступа к сводным таблицам, к фильтрам ячеек,к некоторым аспектам форматирования и много ещё к чему. А те функции АПИ что открыты -  зачастую имеют либо довольно много багов, либо скрытых «особенностей», которые мало того что никак не документированы, но и по сути чаще всего не признаются как баги. И в итоге, это всё, для программиста отдельная головная боль!

Ну и что же делать, если официального АПИ оказалось мало для решения задач, а решать их надо?
К счастью, для пытливого ума нет преград! Если перевести редактор с помощью ключа загрузки «-ascdesktop-support-debug-info» (он кстати сам по себе наследие использования Chromium) в режим с запуска с возможностью отладки, то контекстным меню, например  на контролах или формах редактора, можно выводить привычный для  многих пользователей браузеров DevTools:

Вызов отладчика DevTools в Р7
Вызов отладчика DevTools в Р7

А  в нём уже(ура! ),  можно получать, переведя редактор или плагин  в останов,  доступ к внутренним глобальным объектам самого редактора:

Глобальные объекты в отладчике, в том числе и для доступа к документам
Глобальные объекты в отладчике, в том числе и для доступа к документам

И это значит - есть возможность  увидеть  остальное javascript АПИ текущего редактора (хотя бОльшая часть из него обсфуркцированая и мало что даст), которое не описывается официально, и через которое можно получать доступ к управлению большинством официально скрытых объектов в модели данных документов!

Впрочем, тут  есть огромное НО! Для 99% пользователей, это скорее пагубный путь, ибо любое малейшее неверное использование этого АПИ приводит в лучшем случае к краху документа! В худшем -  к «падению» всего редактора, даже без возможности сохранить документ! Тем не менее, о  малой части  из этого скрытого АПИ, которая более-менее уже исследована и может использоваться  сравнительно безопасно, я вам поведаю, так как для многих стоявших передо мной (думаю и не только передо  мной) задач, просто не существует пока иного пути, кроме как использовать такие вот «костыли» в виде скрытых функций АПИ.

Сразу обозначу: у меня нет возможности и задачи расписывать все особенности и всё скрытое АПИ, которым можно пользоваться для целей автоматизации. Я и сам его не знаю в должной мере, ибо никогда не ставил себе такую цель  - глубоко узнать все скрытые возможности. Да и тема у меня сейчас так же очень узкая. Скрытое  же АПИ весьма обширное и в разы превосходит официальное.

Особенности объектной модели документов в «Р7»

Так как я не знаю уровень подготовки читающих этот текст, я так же опишу свой взгляд (в малом объеме из того, что мог бы расписать) на некоторые  особенности открытой части АПИ в «Р7», из-за которых приходится городить весь  этот «огород» в дальнейшем.

  1. У вас нет возможности записать свои ручные действия и далее воспроизвести их, чтобы автоматизировать таким способом какие-то свои  рутинные ручные действия. Даже в «МойОфис» такая функция есть, а вот в «Р7» – извините! Только хардкор! Только ручное набивание кода с полным предварительным пониманием, что вы хотите добиться, а как это можно сделать.

  2. Забудьте о самом верхнем уровне абстракции модели классов в «MS Office» – Application! В модели «Р7» просто нет некой главенствующей части, которая бы собой символизировала сам редактор, и предоставляла бы сервисные функции предназначенные для координации работы пользователя в целом. Вы НЕ СМОЖЕТЕ, к примеру, получить список открытых в редакторах  документов. И доступа к другим открытым документам получить не сможете! В API  «Р7» вы можете получить доступ ТОЛЬКО  к текущему документу в котором вы вызываете макрос или плагин!

  3. Так же вам не удастся, к примеру, штатно в фоновом режим подгружать документы в редактор, для считывания из них каких-либо данных. С недавних пор можно  использовать внешние ��сылки на такие документы. Тогда связанные по ссылке данные будут считываться при открытии основного документа или при его  принудительном обновлении. Но через АПИ этот процесс просто недоступен! Да и сам линки  все равно остаются пока ненадёжным и часто глючат.  Поэтому, для гарантированной надежности получения данных, в итоге приходится городить загрузку документов в память плагина или макроса сторонними js библиотеками (если такие  есть для нужного формата документов). Или же использовать внешние средства в виде запущенных во вне редактора  вэб прокси серверов, и получать доступ к файлам с их помощью (на чем сейчас строится уже целая своя, небольшая индустрия, но сейчас не про неё).

  4. Объектная модель документов, лишь внешне напоминает ту, что имеется в «MS Office». В целом применяются похожие структуры данных и их иерархии. Названия объектов, атрибутов и методов почти одинаковые везде, для схожих  по своей сути частей документа. Но особенности языка плюс видимо какие - то свои мысли разработчиков, иногда дают другое наименование функций и некоторых объектов. И если копать глубже, то приходишь к выводу: эти  аналогии зачастую - довольно поверхностные и поэтому чаще всего не выйдет напрямую транслировать синтаксические названия при переводе макроса из «МС Офиса» на  VBA  в макросы «Р7» на javascript.  Кстати, именно поэтому, обычно не получается у Искусственного Интеллекта писать  даже сравнительно простые макросы сразу работающими, так как ИИ быстро начинает галлюцинировать несуществующими в АПИ «Р7(OnlyOffice)» объектами,  функциями и атрибутами, придумывая их на ходу,  по аналогии с известными ему АПИ объектной модели  из микрософтовского офиса,  референсным для подобных задач.

  5. Как следствие из предыдущего пункта, и из-за разности базовых особенностей языков, которые используются для автоматизации, не всегда аналогичны и аргументы и их последовательность при вызовах методов классов. Поэтому, у вас всегда должна быть под рукой шпаргалка по фукнциям АПИ, или же настроено автодополнение, чтобы не ошибиться, что и в какой последовательности вы передаёте при вызовах функций. Поскольку javascript типо-независимый язык, то очень легко передать внутрь не ту последовательность данных, и потом очень долго вылавливать ошибки, которая появляются из-за этого, но о которых чаще всего, консоль отладчика пользователя  просто не оповещает!

  6. Однопоточная модель работы javascript.При больших объемах расчётных данных, которые нужно прогнать через макрос или плагин,  это просто огромная «боль» из-за медлительности всех действий. Ещё и  вся «красота» для сложных алгоритмов требующих последовательно-параллельных ветвлений в рабочих алгоритмах. Кое-что для выполнения подобных алгоритмов конечно можно реализовывать через Promise, но это все равно приводит к сильному  ухудшению понимания js кода. Не говоря уже про то, что  вся внутренняя работа с данными в общем то идет в асинхронном режиме, что может приводить к неопределённости конечных результатов, так как не всегда понятно, какие действия пользователя внутри документа окончатся первыми, и что выводится в итоге как результат для вызов через callCommand() в плагинах. А в макросах что либо серьезное писать по обработке данных даже не стоит и пробовать! В общем, не предназначен javascript изначально для таких задач, и поэтому и написание сложных алгоритмов обработки данных, это задача не для слабаков.

  7. Странные методологические просчеты разработчиков. Некоторые,  в общем  очевидные  за долгие годы работы миллионов пользователей методы, просто не предусмотрены изначально. Вот, например, не отключается расчет формул и перерисовка экрана при изменении данных в таблицах. Если в листах  есть формулы в больших количествах, то любые действия в документах по изменению данных  приводят к запуску циклов расчетов по всей книге сразу! И это никак не отменить, даже пользователем через меню самого редактора! Не предусмотрено, и всё!

  8. Песочница в макросах. Макросы по сути – это вызов функции eval(), в которую передается записанный как строка код макроса. Процедура опасная и при любых неверных действиях – приводящая к серьезным проблемам. Поэтому написать нормально работающий макрос, который чуть сложнее, чем раскрашивание ячеек по цветам – это целое искусство, требующее терпения и хороших навыков по отладке в javascript.  Я бы вообще рекомендовал: сперва написать код для макроса и отладить его в куда более безопасных плагинах, и лишь потом сразу «оптом» переносить его в документы как макрос (сам  часто так и делаю).  Сам круг задач для макросов из-за использования для их выполнения eval(), сильно ограничен простыми задачами. Большой  код для макросов лучше не писать!

  9. Есть также проблемы с использованием в макросах внешних библиотек  задач отсутствующих в  функционале редакторов. Это сложно, но можно конечно, и я знаю, как минимум два способа как это сделать. Но они коммерческая тайна.

  10.  Все действия кода внутри eval() только в ‘strict mode’ (строгий режим), а значит - любая ошибка с объявлениями переменных приводит к остановкам выполнения, которые начинающим трудно понять и устранить. Отладить код макроса можно, по сути, только расставив ‘debugger’ в коде макроса и только потом при остановке в DevTools искать причины ошибок. Но если вы уже крутой программист на js, то все эти проблемы можно обойти или хотя бы - приглушить, и писать довольно серьезные макросы, «с подкидным и девушками пониженной социальной ответственности», как говорится. Часть решений я уже придумал за вас, и покажу вам возможные пути.

Думаю, дальше продолжать смысла нет, ибо проблем увы хватает и на их описание с разбором, можно потратить не одну статью (но я буду о них писать в других своих источниках, так что, как модно сейчас у блоггеров : «лайк и подписка» на них!). Моя же цель сейчас не ввести вас в депрессию, а напротив показать что и в «Р7» можно решать многие сложные задачи, только надо знать – как?!
В следующих статьях я опишу пка лишь одну из проблем, которую трудно решить штатными методами, и о которой я не писал в списке проблем: способы взаимодействия с пользователем из макросов.Сперва, я напишу про методы, которыми можно это сделать.  И делать нам это придется сразу в нештатным АПИ.

В  третьей статье я опишу свое бесплатное и платное решения, в которых будут решены многие проблемы с нудным действиями, возникающие при программировании вручную через  АПИ. Сами же мои решение, надеюсь, к тому времени станут доступны через официальный магазин плагинов «Р7».
Спасибо тем кто дочитал до конца, и жду вас в следующей статье этого цикла!