![](https://habrastorage.org/getpro/habr/upload_files/001/54b/fce/00154bfce8e739705596b3154c6d7144.jpg)
Привет, Хабр! Недавно в нашем корпоративном блоге мы рассказали о выходе новой версии МойОфис 2021.02, в которой появились удобные инструменты для работы с формулами и математическими выражениями, а также со сводными таблицами.
Помимо этого, в состав релиза 2021.02 вошел программный отладчик макрокоманд. Он проверяет исполнение кода и помогает обнаружить ошибки синтаксиса. Сегодня мы продемонстрируем возможности работы с макросами в документах на примере текстового редактора «МойОфис Текст», а заодно коснемся темы создания надстроек, которые позволят расширить функциональные возможности редактора.
Для начала разберёмся, что такое макросы и надстройки, в каких продуктах они представлены, для чего используются и в чём их отличия.
При работе с текстом, таблицами или иными данными пользователь выполняет различные операции с помощью выбора пункта меню или нажатия на специальную кнопку. Однако по большей части при этом выполняется только одно действие и только над выбранным диапазоном значений. Но что делать, если нужно не просто выполнить некую последовательность действий, но ещё и повторить её несколько раз, используя при этом разные наборы данных? Или даже расширить функции обработки, добавить что-то своё, чего еще не было реализовано в редакторе? Для этого и существуют макросы и надстройки.
Макрос — это программный алгоритм, небольшой кусок кода, который позволяет пользователю автоматизировать ту или иную последовательность действий в конкретном открытом документе — например, это может быть автоматическое редактирование документа с заменой символа минус на тире, переводом кавычек в «елочки» и расстановкой символов конца абзаца до нужного значения.
Надстройка — программный модуль, который подключается в редактор и может работать не только с данными внутри конкретного документа, но и с другими документами, а также выполнять иные действия, включая операции с файлами.
МойОфис выпускает несколько продуктов для работы с документами и коммуникациями, — как для коммерческих, так и для частных пользователей. И тем и другим доступны макрокоманды, с которыми можно работать прямо в документах. Напомним, что продукт «МойОфис Стандартный. Домашняя версия» доступен для некоммерческого использования, бесплатен и не содержит рекламы. Его можно скачать с нашего сайта, а также в магазинах приложений Windows Store и Mac App Store. А вот работать с надстройками смогут только коммерческие пользователи, которые приобрели «МойОфис Стандартный».
Для написания макросов и надстроек в МойОфис используется свободный скриптовый язык программирования Lua. Этот кросс-платформенный язык легок в освоении и обладает достаточно широкими возможностями. В настоящий момент в МойОфис реализована поддержка Lua версии 5.3.2.
Отметим, что во всемирно известном офисном ПО Microsoft Office для создания макрокоманд применяется другая технология — VBA (Visual Basic for Applications), специальная версия языка Visual Basic для автоматизации действий внутри документов прикладного ПО. Но мы, как производитель программных продуктов, в силу существующих лицензионных ограничений не можем использовать проприетарные технологии Microsoft. Если вы представляете организацию, которая находится в процессе миграции на российские решения, то тоже не сможете пользоваться таким инструментом.
Кроме того, конверторов из VBA в Lua не существует в принципе. Поэтому, если вам требуется работать с документами, которые содержат макросы и были ранее созданы в Microsoft Office, то вам придется переводить код макрокоманд на язык Lua. Мы понимаем, что это может быть проблемой для тех, кто переходит на отечественное ПО, и специально для наших покупателей предлагаем такие решения:
Центр компетенций «Хаб Знаний МойОфис» разработал методологию обучения основам Lua, которая позволяет быстро научиться созданию макросов в редакторах МойОфис. Первая публичная лекция по этой методологии состоится 14 октября 2021 года.
МойОфис также предлагает полный комплекс консалтинговых услуг для покупателей наших продуктов — пользователи не останутся один на один со своими проблемами, обращайтесь в службу технической поддержки, мы поможем с решением вашей ситуации.
Для создания макросов на Lua вам точно понадобятся следующие материалы:
Книга Роберта Иерузалимски, одного из авторов языка Lua.
«Руководство программиста» — детальное описание методов и функций, которые реализованы в библиотеке MyOffice Document API и используются для работы с макросами и надстройками в редакторах.
Как писать макросы в МойОфис
Сейчас мы покажем, как происходит работа с макросами и надстройками. Для начала запускаем редактор макросов, который находится в меню «Инструменты» — «Редактирование макроса».
![](https://habrastorage.org/getpro/habr/upload_files/362/fab/441/362fab441bcba74f588debb545981e10.jpg)
Далее создаём новый скрипт: нажимаем на «плюс», после чего появляется название нового скрипта и возможность ввода кода. Для удобства работы можно задать произвольное название.
![](https://habrastorage.org/getpro/habr/upload_files/cc3/ed9/01a/cc3ed901a6bfd0317c27e80ba3fa65ec.png)
Рассмотрим простой пример
Для начала сделаем скрипт, который будет выводить в документ текстовую строку с фразой «Привет, Мир!». Для этого нам потребуется совершить несколько базовых действий. Сначала с помощью метода Document:getRange предоставим доступ ко всему документу как области данных:
local range = document:getRange()
Далее нужно определить позицию: в какую часть документа мы будем вставлять текст. В нашем случае — это конец документа. Определим значение переменной pos, которая будет отражать позицию в документе, и сделаем это с помощью метода Range:getEnd. Учтите, что этот метод возвращает позицию в конце фрагмента текстового документа, не включая последний символ paragraph mark. Если требуется определить позицию в начале документа, то пользуйтесь методом Range:getBegin.
local pos = range:getEnd()
Теперь воспользуемся методом Position:insertText и вставим строку с нужным нам текстом в определенную выше позицию в документе.
pos:insertText("Привет, Мир!")
Наш первый макрос будет выглядеть следующим образом:
![](https://habrastorage.org/getpro/habr/upload_files/5c7/c1a/eb1/5c7c1aeb1155b2c88a388193c7a58344.png)
После нажатия кнопки «Выполнить», в отладчике вы увидите сообщение «Макрос выполнен успешно», а в самом документе появится строка «Привет, Мир!»:
![](https://habrastorage.org/getpro/habr/upload_files/8a7/086/6bd/8a70866bd128d09949ba44b099c989cb.png)
Как с помощью макросов в МойОфис посчитать число символов в документе
Попробуем сделать пример посложнее. Представим типовую задачу — нужно посчитать количество символов и слов в документе. Оставим от предыдущего примера переменные range и pos, они нам еще пригодятся.
local range = document:getRange()
local pos = range:getEnd()
Теперь с помощью метода text = range:extractText() преобразуем тело документа в одну текстовую строку. При работе с этим методом находящиеся внутри области изображения, таблицы и прочие подобные элементы документа игнорируются.
Перейдем к подсчету символов. Сделать это очень просто — нам нужно лишь определить длину строки, и для этого можно было бы воспользоваться простой функцией len(). Однако, в случае с кириллическими символами в строке, Lua будет считать длину строки неправильно, т.к. на каждый такой символ будет приходиться два бита, а не один, как в случае с латиницей или цифрами. К счастью, в Lua 5.3 появилась поддержка кодировки UTF-8, которой мы и воспользуемся. Введем переменную Allsymbols, которую определим с помощью функции utf8.len():
Allsymbols = utf8.len(text)
Неотъемлемой частью любого документа являются символы конца абзаца. Их может быть произвольное количество, и для правильного подсчета числа символов их надо удалить из результата, который мы получили выше с помощью utf8.len(). Но сначала нужно посчитать, сколько символов конца абзаца попало в строку при выгрузке с помощью метода extractText(). Для этого нам понадобится несколько строк кода. В них мы сперва определим значение переменной newLine равным нулю, а затем, с помощью простого цикла подсчитаем в выгруженном объеме текста общее количество всех символов конца абзаца. Используем для этого стандартную функцию string.gmatch, в аргументах которой указываем где искать (text) и что искать ("\n").
local newLine = 0
for text in string.gmatch(text, "\n") do
newLine = newLine + 1
end
Теперь осталось лишь вычесть из общего числа символов AllSymbols число символов конца абзаца newLine. Введем новую переменную Symb:
Symb = Allsymbols – newLine
Перейдем к подсчёту слов. С этим дело обстоит несколько сложнее — для определения числа слов нам потребуется воспользоваться функцией gsub (глобальная замена) и регулярным выражением.
_,Word = text:gsub("%S+","")
Механика подсчета следующая: с помощью функции gsub мы определяем в строке слова, которые разделены пробелами. В этом нам помогает регулярное выражение %S+, с помощью которого определяются все элементы строки, не являющиеся пробелами. Так мы получаем все элементы, которые в строке отделены пробелами. И от функции gsub нам нужен не результат преобразования строки, а лишь число найденных элементов. Для этого мы определяем переменную Word как второй результат функции gsub и указываем это с помощью символа подчеркивания.
Следующая часть кода — создание таблицы, куда поместим найденные значения.
Для этого построим такую конструкцию: простую таблицу из двух строк и двух колонок (определяется переменной t_id), которая будет сопровождаться заголовком «Выводы»:
pos:insertText("Выводы")
t_id = pos:insertTable(2,2,"SomeTable")
Теперь осталось сформировать таблицу и вывести в нее результат.
local tbl= document:getBlocks():getTable(t_id)
Для этого определим переменную tbl, которая с помощью методов document:getBlocks() и getTable() формирует таблицу в документе с заданными в переменной t_id значениями: 2 строки, 2 столбца, название «Some Table».
Далее нам остается только заполнить таблицу.
tbl:getCell(DocumentAPI.CellPosition(0,0)):setText("Количество символов")
tbl:getCell(DocumentAPI.CellPosition(1,0)):setText("Количество слов")
tbl:getCell(DocumentAPI.CellPosition(0,1)):setText(tostring(Symb))
tbl:getCell(DocumentAPI.CellPosition(1,1)):setText(tostring(Word))
Для этого используем метод getCell для получения доступа к конкретной ячейке таблицы. Саму ячейку выбираем с помощью функции DocumentAPI.CellPosition, в аргументах которой начиная с нуля указываем номер строки и столбца. Затем, с помощью метода setText присваиваем ячейке текстовое значение типа «Текстовый», и выводим в нее нужную нам фразу. В случае с результатом вычислений, нам потребуется еще и преобразовать число в текст с помощью функции tostring.
В итоге получаем такой код макроса:
local range = document:getRange()
local pos = range:getEnd()
text = range:extractText()
Allsymbols = utf8.len(text)
local newLine = 0
for text in string.gmatch(text, "\n") do
newLine = newLine + 1
end
Symb = Allsymbols - newLine
_,Word = text:gsub("%S+","")
pos:insertText("Выводы")
t_id = pos:insertTable(2,2,"SomeTable")
local tbl= document:getBlocks():getTable(t_id)
tbl:getCell(DocumentAPI.CellPosition(0,0)):setText("Количество символов")
tbl:getCell(DocumentAPI.CellPosition(1,0)):setText("Количество слов")
tbl:getCell(DocumentAPI.CellPosition(0,1)):setText(tostring(Symb))
tbl:getCell(DocumentAPI.CellPosition(1,1)):setText(tostring(Word))
Вставляем код в соответствующее поле. При этом части кода маркируются разными цветами для лучшей читаемости. Назовем наш макрос «Символы».
![](https://habrastorage.org/getpro/habr/upload_files/59c/43e/f49/59c43ef49d4255bb0c6ee62f73454f3b.png)
Можно сразу запустить программу с помощью кнопки выполнить, либо использовать режим отладки (кнопка отладить). При необходимости вы можете установить контрольные точки на важных строках кода, чтобы отладчик на них останавливался. Для этого кликните по пустому серому полю между номером строки и её представлением в поле ввода кода макроса.
![](https://habrastorage.org/getpro/habr/upload_files/ffc/3a1/394/ffc3a1394daeca4bedba95722437c7d2.png)
Если в коде есть какие-то проблемы (в нашем случае была осознанно удалена буква m в слове document на 13 строке), то при отладке, в левом нижнем поле красным будет обозначена ошибка, а строка с ней помечена зелёной стрелкой.
![](https://habrastorage.org/getpro/habr/upload_files/e93/814/1db/e938141db36df747efc732fd7ff89535.png)
Если мы устраним проблему и вернем букву m в слово docuent, а затем нажмем кнопку "Выполнить", то отладчик сообщит об успешном выполнении кода макроса:
![](https://habrastorage.org/getpro/habr/upload_files/0c3/4d4/dcb/0c34d4dcbb8faba45301669de29b51e9.png)
Посмотрим, как макрос срабатывает на реальном примере. В качестве тестового материала используем пару абзацев текста-«рыбы» Lorem ipsum. Заходим в редактор макросов, выбираем скрипт и запускаем его. После запуска в поле Output появляется сообщение об успешном выполнении.
Результат работы макроса — небольшая сгенерированная табличка, расположенная ниже исходного текста.
![](https://habrastorage.org/getpro/habr/upload_files/2ee/934/fd8/2ee934fd865ce52e919dd5a06b2e8316.png)
Как запускать макросы из боковой панели редакторов МойОфис
Ещё один способ запуска скрипта в документе — это открытие панели запуска макросов. В поле под строкой «Поиск» будут перечислены все макросы данного документа.
Если навести курсор на строчку с желаемым макросом, появляются две дополнительных кнопки-символа — запуск и редактирование кода. Также запускать макрос можно двойным щелчком по названию.
![](https://habrastorage.org/getpro/habr/upload_files/616/8a3/8bd/6168a38bd088614a54c25bd5c146efaf.png)
Вы можете добавлять новые скрипты и изменять их при необходимости. Разумеется, использовать макросы можно не только в текстовым редакторе, но и в табличном — благодаря широким возможностям языка Lua.
Как писать надстройки в МойОфис
В отличие от макросов, надстройка представляет собой отдельный архивный Zip-файл с расширением .mox. Внутри архива могут содержаться различные файлы и каталоги, включая обязательные: файл регистрации надстройки, файл сценария надстройки и файл, содержащий текст лицензионного соглашения с конечным пользователем EULA.
Файл регистрации надстройки является тестовым документом и должен называться Package.lua. Внутри него содержатся ключи и их значения. Некоторые ключи являются обязательными, другие — нет. Подробный перечень ключей, их описания и другие полезные материалы для разработки собственных модулей вы можете найти в «Руководстве программиста» на сайте МойОфис.
local Package = {
vendor = "МойОфис",
description = "Это пример расширения для МойОфис",
extensionID = "com.example.entryform",
extensionName = "Тестовое Расширение",
extensionVersion = {
major = 1,
minor = 1,
patch = 0,
build = "" },
applicationId = "MyOffice Text",
apiVersion = {
major = 1,
minor = 0 },
commandsProvider = "cmd/entryform.lua",
fallbackLanguage = 'en',
onLoad = "cmd/entryform-prep.lua",
onUnload = "cmd/entryform-prep.lua"
}
return Package
Файл сценария надстройки называется так, как указано в значении ключа commandsProvider файла регистрации, и включает в себя все команды управления надстройкой и описание функций. Команды будут отображаться в виде подпунктов в меню надстроек.
Actions = {}
function Actions.getCommands()
return {
{
id = "EntryForm.addLines",
menuItem = "Добавить строку",
command = Actions.addLines
}
}
end
function Actions.addLines(context)
context.doWithDocument(function(document)
local rng = document:getRange()
local begin_pos = rng:getBegin()
begin_pos:insertText("Эта строка вставлена с помощью расширения \n")
end)
end
return Actions
local Actions = {}
function Actions.onLoadExtension()
-- Подготовка ресурсов для надстройки
end
function Actions.onUnloadExtension()
-- Освобождение ресурсов для надстройки
end
return Actions
Осталось только создать файл лицензии LICENSE и поместить его в папку META-INF.
![](https://habrastorage.org/getpro/habr/upload_files/10a/408/3f8/10a4083f8fc12ec8a9815a6a6e33e8b6.jpeg)
Теперь упаковываем всё это в Zip-архив и меняем расширение на .mox. Всё готово! Можем устанавливать.
Установка и запуск надстроек МойОфис
Процесс установки прост и понятен. Выбираем в меню «Надстройки» — «Управление надстройками». В появившемся окне нажимаем на единственную кнопку «Установить» и указываем нужный файл расширения.
![](https://habrastorage.org/getpro/habr/upload_files/a67/c2b/b4c/a67c2bb4ce823c05090e7fc8b25eb259.png)
![](https://habrastorage.org/getpro/habr/upload_files/607/b3b/5a7/607b3b5a73bffd5450aff3fd9b417a8d.png)
Читаем и принимаем лицензионное соглашение. В случае отказа установка будет прервана.
![](https://habrastorage.org/getpro/habr/upload_files/ef0/d42/41e/ef0d4241e54f0dae77e7c9aa04101d23.png)
Готово! Надстройка установлена и появилась в списке.
![](https://habrastorage.org/getpro/habr/upload_files/a52/ef8/85a/a52ef885a22d4f0fbf51ee7f0fa59db0.png)
Тут же можно посмотреть информацию о ней, отключить ее или полностью удалить из приложения.
![](https://habrastorage.org/getpro/habr/upload_files/df1/254/864/df125486419ca3096988149b18f20e81.png)
Запускается надстройка и выбираются команды также через раздел «Надстройки». После установки в нём появится название надстройки и список команд в выпадающем меню.
![](https://habrastorage.org/getpro/habr/upload_files/5a5/6ef/552/5a56ef5526b0ccecc694d8b01046c79c.png)
Нажимаем на единственную команду и видим результат — вставленную строчку.
![](https://habrastorage.org/getpro/habr/upload_files/611/7e9/da0/6117e9da036897d8a12b1964f2f7dd0f.png)
Итог
В статье мы показали разницу между макросами и надстройками и продемонстрировали на примерах лишь малую часть их возможностей. Вы легко можете разработать свою надстройку, скомпилировать внешние модули для использования в её составе и расширить функциональные возможности программ МойОфис под свои запросы.
Напомним, что на нашем сайте и в магазинах операционных систем можно бесплатно загрузить и опробовать редакторы МойОфис. Специально для наших пользователей мы также подготовили «Руководство программиста», которое содержит подробное описание функций, команд и прочую необходимую документацию для работы с макросами и надстройками.
Нам интересны ваши впечатления от реализации функциональности макрокоманд в редакторах МойОфис. Пожалуйста, расскажите в комментариях, удобно ли пользоваться таким решением, корректно ли работает отладчик макрокоманд на ваших скриптах, и каких дополнительных возможностей вам не хватает в наших редакторах. Как вы думаете, какие макросы, в том числе созданные вами, могут быть полезны для продуктов МойОфис?
Будем рады любым конструктивным откликам; возможно, именно ваши идеи окажут существенное влияние на развитие технологий автоматизации в наших продуктах. Мы внимательно изучим обратную связь и подарим памятные подарки авторам лучших на наш взгляд предложений.