Макросы – это небольшие программы, которые расширяют функциональность редакторов и избавляют пользователя от монотонной работы по заполнению или форматированию документов. Скажем, вам нужно удалить из длинного текста лишние пробелы, перенести данные или применить ко всем датам в таблице один и тот же формат – с такими задачками легко справится макрос.
Что еще умеют макросы?
Искать ячейки, заполнять их, формировать и вставлять шаблоны – в настольных редакторах МойОфис вы можете создавать макрокоманды, которые будут делать именно то, что вам хочется. Вместо выполнения десятка повторяющихся манипуляций, запишите один макрос и запустите его, когда потребуется совершить эти действия снова.
Представляем Lua
Хотя макросы и считаются инструментом для продвинутых пользователей, освоить их в МойОфис не так сложно – в наших редакторах они записываются в виде кода на Lua, скриптовом языке с понятным и изящным синтаксисом. Изначально разработанный для интеграции со сторонним программным обеспечением, Lua включает лишь малое число понятий.
Вместе с тем Lua отличается быстродействием, гибкостью и низким потреблением ресурсов, благодаря чему он получил признание и популярность среди разработчиков. Например, на нем написан графический интерфейс пакета Adobe Lightroom, многочисленные игры – World of Warcraft, Angry Birds и другие.
От теории к практике
Для начала запустим редактор макросов, который находится в меню «Инструменты».
Кликнем в редакторе на «плюс» и зададим новому скрипту название.
Пусть наш первый макрос будет выводить традиционное ''Hello, World!'' в первую строку исходного документа. Для этого предоставим доступ ко всему документу как области данных.
local range = document:getRange()
Вторым шагом установим курсор в начало документа.
local startPos = range:getBegin()
Напечатаем текст.
startPos:insertText("Hello World!")
После нажатия кнопки «Выполнить», в отладчике вы увидите сообщение «Макрокоманда успешно выполнена», а в самом документе появится строка ''Hello World!''.
Попробуем рассмотреть задачу посложнее. Как мы уже говорили, если пользователю понадобятся дополнительные функции, которых нет в МойОфис, он может записать их самостоятельно. Так, мы создадим макрос, который подсчитает слова, символы, пробелы и выводит результаты в таблицу.
Определяем границы документа и устанавливаем позицию курсора в конец, чтобы разместить таблицу с результатами под текстом.
local range = document:getRange()
local pos = range:getEnd()
Определяем начало строки.
local newLine = 0
Введем две переменные: text, куда перенесем все содержимое документа, и paragraphcount, в которую будем «складывать» число абзацев.
Затем мы запускаем цикл подсчета абзацев внутри документа, который разделяет текст на блоки, содержащие абзацные отступы, и увеличиваем значение переменной paragraphCount.
local text = ""
local paragraphCount = 0
for para in document:getBlocks():enumerateParagraphs() do
text = text..para:getRange():extractText()
paragraphCount = paragraphCount + 1
end
Для корректного подсчета символов в документе, нужно учитывать кодировку таблицы символов. Сегодня наиболее универсальной кодировкой с поддержкой кириллицы является кодировка UTF. В Lua предусмотрена работа с кодировкой UTF8, достаточно лишь использовать нужную функцию.
Считаем количество символов в кодировке UTF8.
allSymbols = utf8.len(text)
Подсчитываем количество переходов на новую строку при помощи функции string.gmatch и символа перевода каретки ''n''.
for text in string.gmatch(text, "\n") do
newLine = newLine + 1
end
Подсчитываем количество символов без символов новой строки.
symbolCount = allSymbols - newLine
Перейдем к подсчету слов. В этом нам поможет функция gsub, определяющая в строке слова, разделенные пробелами, и регулярное выражения %S+ – оно определяет все элементы, не являющиеся пробелами. За счет этого мы получаем все элементы, которые в строке отделены пробелами. И от функции gsub нам нужен не результат преобразования строки, а лишь число найденных элементов. Мы определяем переменную wordCount в качестве второго результата функции gsub запятой и символом подчеркивания.
_,wordCount = text:gsub("%S+","")
По тому же принципу найдем символы пунктуации (переменная punctCount и регулярное выражение в скобках).
_,punctCount = text:gsub("[\"(),:;<>@[\\%]!?.-]","")
После этого, мы начнем считать пробелы: укажем " " и получившееся значение определим в переменную spaceCount.
_,spaceCount = text:gsub(" ","")
Добавляем таблицу, пусть она называется Result1.
local tableName = "Result1"
Важно, чтобы при изменении исходных данных, наша таблица обновлялась автоматически. Для этого мы должны найти такую таблицу в документе (переменная tableName), и если она уже есть, удалить ее, и вывести заново.
local tbl = document:getBlocks():getTable(tableName)
--если нашли, то удаляем ее
if tbl then
document:getBlocks():getTable(tableName):remove()
end
Вставляем таблицу выводов и заполняем ее данными. Нам требуется 6 строк и два столбца.
pos:insertTable(6,2,"Result1")
Обратите внимание, что при создании таблицы к ее имени будет добавлен индекс. Мы создаем таблицу с именем "Result", а обращаемся к ней будем по имени "Result1".
tbl = document:getBlocks():getTable(tableName)
Выведем заголовое «Итоги», воспользовавшись функцией setText.
tbl:getCell(DocumentAPI.CellPosition(0,0)):setText("Итоги")
Для каждой ячейки можно задать свойства форматирования. Давайте выделим строку «Итоги». Для этого используем функцию DocumentAPI.CellProperties() и переменную props. Определим в нее диапазон ячеек, которые будем форматировать.
local rng = tbl:getCellRange("A1:B1")
local props = DocumentAPI.CellProperties()
Зададим цвет ячейки за счет функции DocumentAPI.ColorRGBA. В скобках указано значение цвета в цветовом пространстве RGBA (RGB + альфа-канал).
props.backgroundColor = DocumentAPI.ColorRGBA(55, 146, 179, 200)
Установим выравнивание по вертикали в значение «По центру», а следующим шагом применим выбранные нами параметры ячейки к переменной rng.
props.verticalAlignment = DocumentAPI.VerticalAlignment_Center
rng:setCellProperties(props)
Поскольку мы применяли форматирование к двум ячейкам (A1 и B1), то нам нужно их объединить. Сделаем это с помощью функции merge().
rng:merge()
Ну и напоследок заполним столбцы: функция setText выведет нужные нам фразы и значения переменных в соответствующие ячейки.
-- первый столбец
tbl:getCell(DocumentAPI.CellPosition(1,0)):setText("Количество абзацев")
tbl:getCell(DocumentAPI.CellPosition(2,0)):setText("Количество слов")
tbl:getCell(DocumentAPI.CellPosition(3,0)):setText("Количество символов")
tbl:getCell(DocumentAPI.CellPosition(4,0)):setText("Количество символов пунктуации")
tbl:getCell(DocumentAPI.CellPosition(5,0)):setText("Количество пробелов")
-- второй столбец
tbl:getCell(DocumentAPI.CellPosition(1,1)):setText(tostring(paragraphCount))
tbl:getCell(DocumentAPI.CellPosition(2,1)):setText(tostring(wordCount))
tbl:getCell(DocumentAPI.CellPosition(3,1)):setText(tostring(symbolCount))
tbl:getCell(DocumentAPI.CellPosition(4,1)):setText(tostring(punctCount))
tbl:getCell(DocumentAPI.CellPosition(5,1)):setText(tostring(spaceCount))
Посмотрим, что получилось. Заходим в редактор макросов, выбираем скрипт и запускаем его. Итог нашей работы — новая таблица в документе, которая находится снизу от исходного текста.
Для вашего удобства скопируем сюда весь код с комментариями. Пользуйтесь и дополняйте!
-- определяем границы документа
local range = document:getRange()
-- устанавливаем позицию курсора в конец
local pos = range:getEnd()
-- определяем начало строки
local newLine = 0
-- извлекаем текст для подсчета (только абзацы, без учета таблицы)
local text = ""
local paragraphCount = 0
for para in document:getBlocks():enumerateParagraphs() do
text = text..para:getRange():extractText()
paragraphCount = paragraphCount + 1
end
-- считаем количество символов в кодировке utf-8
allSymbolsCount = utf8.len(text)
-- подсчитываем количество переходов на новую строку
for text in string.gmatch(text, "\n") do
newLineCount = newLine + 1
end
-- подсчитываем количество символов без символов новой строки
symbolCount = allSymbolsCount - newLine
-- подсчитываем количество слов
_,wordCount = text:gsub("%S+","")
-- подсчитываем количество символов пунктуации
_,punctCount = text:gsub("[\"(),:;<>@[\\%]!?.-]","")
-- подсчитываем количество пробелов
_,spaceCount = text:gsub(" ","")
-- добавляем таблицу
local tableName = "Result1"
-- ищем в документе таблицу со значением переменной tableName
local tbl = document:getBlocks():getTable(tableName)
--если нашли, то удаляем ее
if tbl then
document:getBlocks():getTable(tableName):remove()
end
-- создаем таблицу выводов
pos:insertTable(6,2,"Result")
-- заполняем ее данными
tbl = document:getBlocks():getTable(tableName)
-- заголовок
tbl:getCell(DocumentAPI.CellPosition(0,0)):setText("Итоги")
local rng = tbl:getCellRange("A1:B1")
local props = DocumentAPI.CellProperties()
props.backgroundColor = DocumentAPI.ColorRGBA(55, 146, 179, 200)
props.verticalAlignment = DocumentAPI.VerticalAlignment_Center
rng:setCellProperties(props)
rng:merge()
-- первый столбец
tbl:getCell(DocumentAPI.CellPosition(1,0)):setText("Количество абзацев")
tbl:getCell(DocumentAPI.CellPosition(2,0)):setText("Количество слов")
tbl:getCell(DocumentAPI.CellPosition(3,0)):setText("Количество символов")
tbl:getCell(DocumentAPI.CellPosition(4,0)):setText("Количество символов пунктуации")
tbl:getCell(DocumentAPI.CellPosition(5,0)):setText("Количество пробелов")
-- второй столбец
tbl:getCell(DocumentAPI.CellPosition(1,1)):setText(tostring(paragraphCount))
tbl:getCell(DocumentAPI.CellPosition(2,1)):setText(tostring(wordCount))
tbl:getCell(DocumentAPI.CellPosition(3,1)):setText(tostring(symbolCount))
tbl:getCell(DocumentAPI.CellPosition(4,1)):setText(tostring(punctCount))
tbl:getCell(DocumentAPI.CellPosition(5,1)):setText(tostring(spaceCount))
Полезные материалы
Для лучшего погружения в тему и более глубокого изучения макросов на Lua, вам точно пригодятся следующие материалы:
- Книга Роберта Иерузалимски, одного из авторов языка Lua.
- Русскоязычное руководство по Lua версии 5.3.
- «Руководство программиста» — детальное описание методов и функций, которые реализованы в библиотеке MyOffice Document API и используются для работы с макросами и надстройками в редакторах.
- Вебинар «Автоматизация в документах: введение в разработку макросов в МойОфис» от специалистов «Хаб Знаний МойОфис».