Top.Mail.Ru
15 мин

Для чего нужны макросы в МойОфис и как их писать новичку?

Автор:
Разбираем возможности макрокоманд и знакомимся с Lua.

Макросы – это небольшие программы, которые расширяют функциональность редакторов и избавляют пользователя от монотонной работы по заполнению или форматированию документов. Скажем, вам нужно удалить из длинного текста лишние пробелы, перенести данные или применить ко всем датам в таблице один и тот же формат – с такими задачками легко справится макрос.

Что еще умеют макросы?


 Искать ячейки, заполнять их, формировать и вставлять шаблоны – в настольных редакторах МойОфис вы можете создавать макрокоманды, которые будут делать именно то, что вам хочется. Вместо выполнения десятка повторяющихся манипуляций, запишите один макрос и запустите его, когда потребуется совершить эти действия снова.

Представляем 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, вам точно пригодятся следующие материалы:


Назад к публикациям
Поделиться в соц. сетях: