LibreOffice Basic — встроенный язык, который позволяет автоматизировать рутину в Writer, Calc и Impress без установки сторонних библиотек. Макрос может собрать отчёт, разложить счета по папкам, преобразовать сотню файлов в PDF или проверить таблицу на пустые ячейки. Ниже — путь от включения IDE до запуска кода по расписанию.
Зачем Basic, если есть Python
LibreOffice поддерживает Python, Java и JavaScript, но Basic остаётся самым доступным вариантом: он встроен, не требует настройки окружения и одинаково работает в Linux и Windows. Для офисных задач его возможностей хватает с запасом, а Python выбирают, когда нужна сложная логика или внешние библиотеки.
Важно понимать модель работы. Макрос выполняется внутри процесса LibreOffice и обращается к документам через UNO-API. Объект ThisComponent указывает на активный документ, createUnoService() создаёт сервисы, а com.sun.star.frame.Desktop служит точкой входа для загрузки файлов.
Где лежат макросы и как открыть IDE
Пользовательские макросы хранятся в профиле: ~/.config/libreoffice/4/user/basic/Standard/. Там находятся модули Module1.xba и файл script.xlb, описывающий состав библиотеки. Код, привязанный к документу, путешествует вместе с ним внутри .odt. Для командной работы удобнее первый вариант: библиотеку можно положить в git.
IDE открывается через Сервис → Макросы → Изменить макросы. В левом дереве выберите Мои макросы → Standard, создайте модуль и напишите первую процедуру. Клавиша F5 запускает её, F8 включает пошаговую отладку, а точка останова ставится кликом на серую полосу слева от строки.
soffice --headless --convert-to pdf --outdir ~/out ~/docs/report.odt
soffice --headless --convert-to "pdf:writer_pdf_Export" *.odt
ls -l ~/.config/libreoffice/4/user/basic/Standard/
Эти три команды полезны и сами по себе: первая конвертирует один файл, вторая — все документы в каталоге, третья показывает, где лежит ваша библиотека перед резервным копированием.
Первый макрос: документ, текст и сохранение
Минимальный рабочий пример создаёт документ Writer, вставляет заголовок и абзац, затем сохраняет результат в формате ODT. Обратите внимание на массив PropertyValue: через него в LibreOffice передаются параметры загрузки и сохранения, включая фильтры экспорта.
Sub CreateReport
Dim oDesktop As Object, oDoc As Object, oText As Object
Dim args()
oDesktop = createUnoService("com.sun.star.frame.Desktop")
oDoc = oDesktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, args())
oText = oDoc.getText()
oText.setString("Квартальный отчёт")
oText.insertControlCharacter(oText.End, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False)
oText.insertString(oText.End, "Сформировано " & Format(Now, "YYYY-MM-DD"), False)
oDoc.storeToURL("file:///home/user/out/report.odt", args())
End Sub
Разница между методами сохранения принципиальна. storeToURL записывает копию и не меняет привязку документа к файлу, store() сохраняет по текущему пути, а storeAsURL меняет путь. Если документ создан «из фабрики», у него нет имени, поэтому store() вызовет ошибку.
Экспорт в PDF и обход каталога
Типичная задача — превратить набор ODT в PDF с понятными именами. Макрос ниже перебирает файлы через Dir(), подставляет фильтр writer_pdf_Export и складывает результат рядом с исходником. Для Calc фильтр называется calc_pdf_Export, для Impress — impress_pdf_Export.
Sub ExportAllToPdf
Dim sDir As String, sFile As String
Dim oDoc As Object
Dim aArgs(0) As New com.sun.star.beans.PropertyValue
sDir = "/home/user/docs/"
aArgs(0).Name = "FilterName"
aArgs(0).Value = "writer_pdf_Export"
sFile = Dir(sDir & "*.odt")
Do While sFile <> ""
oDoc = StarDesktop.loadComponentFromURL(ConvertToURL(sDir & sFile), "_blank", 0, Array())
oDoc.storeToURL(ConvertToURL(sDir & Replace(sFile, ".odt", ".pdf")), aArgs())
oDoc.close(False)
sFile = Dir()
Loop
End Sub
Dir() без аргументов возвращает следующее имя из ранее открытого шаблона — классика Basic, но в больших каталогах надёжнее com.sun.star.ucb.SimpleFileAccess с явным перебором содержимого. И не забывайте про oDoc.close(False): без него десятки документов останутся в памяти и приложение замедлится.
Диалоги, ввод и обработка ошибок
Макрос не должен молча падать: простейший ввод — InputBox, вывод — MsgBox. Конструкцию On Error Resume Next не используйте, она прячет причину сбоя. Проверяйте предусловия и включайте обработчик On Error Goto.
Sub AskAndSave
Dim sName As String
sName = InputBox("Имя файла без расширения:", "Сохранение")
If Len(Trim(sName)) = 0 Then
MsgBox "Пустое имя — отмена", 16, "Ошибка"
Exit Sub
End If
On Error Goto Fail
ThisComponent.storeToURL(ConvertToURL("/home/user/out/" & sName & ".odt"), Array())
MsgBox "Готово: " & sName, 64, "Экспорт"
Exit Sub
Fail:
MsgBox "Не удалось сохранить: " & Error$, 16, "Ошибка"
End Sub
Для сложных форм используйте CreateUnoDialog(DialogLibraries.Standard.Dialog1).
Запуск без графики и по расписанию
Headless-режим полезен на сервере: LibreOffice стартует без окна, выполняет макрос и завершается. Ссылка на процедуру строится по схеме macro:///Библиотека.Модуль.Процедура. Юнит systemd для ночного отчёта выглядит так:
[Unit]
Description=Nightly report
[Service]
Type=oneshot
User=docs
ExecStart=/usr/bin/soffice --headless --norestore "macro:///Standard.Module1.NightlyReport"
Сначала проверьте запуск вручную. Если процесс не завершается, добавьте в конец макроса ThisComponent.close(False) для всех открытых документов и вызовите StarDesktop.terminate(). Флаг --norestore отключает восстановление после сбоя и ускоряет старт.
Безопасность и переносимость
- Уровень макросов задаётся в
Сервис → Параметры → Безопасность → Безопасность макросов. Для рабочих машин оставляйте высокий уровень и подписывайте код сертификатом. - Доверенные расположения добавляйте точечно: папка с шаблонами, а не весь домашний каталог.
- Не запускайте макросы из чужих документов: Basic умеет вызывать
Shell()и читать файлы с правами пользователя. - Храните библиотеку в git и экспортируйте модули через IDE.
- Перед массовой обработкой прогоняйте код на копии каталога.
Чек-лист перед внедрением
- Опишите вход и выход: какие файлы, куда попадают, что считается успехом.
- Проверьте пути: используйте
file:///и абсолютные имена, избегайте пробелов в аргументах. - Добавьте обработчик ошибок и понятные сообщения на русском языке.
- Прогоните макрос на трёх копиях документов разной структуры.
- Замерьте время: обработка 500 файлов идёт минуты, поэтому увеличьте
TimeoutStartSecв юните.
Итог
LibreOffice Basic — прагматичный инструмент офисной автоматизации: он не требует отдельного рантайма, работает с теми же документами, что и пользователь, и легко запускается из командной строки. Начните с одной операции, которая отнимает время каждый день, оберните её в обработку ошибок и только потом добавляйте расписание и массовую обработку. Такой путь даёт предсказуемый результат без зависимости от внешних сервисов.