
Я буду не многословен и сразу скажу, что речь идет о конвертере, встроенном в пакет LibreOffice. Вы можете запустить конвертацию из консоли, чтобы увидеть как это работает:
libreoffice --headless --writer --convert-to pdf html.html
Эта команда конвертирует файл html.html в pdf файл. Количество поддерживаемых форматов впечатляет.
Выгода от использования такого инструмента очевидна. Вместо того, чтобы писать код для генерации документов в каждом из нужных форматов, просто создаем обычное html-представление. Далее сгенерированную страницу прогоняем через конвертер.
Запуск конвертации из PHP
Для установки конвертера на сервере придется установить пакет libreoffice-core:
sudo apt-get install libreoffice-core --no-install-recommendsЧтобы было удобно работать с утилитой из PHP, я написал обертку.
Обертка позволяет вам не думать о работе с временными файлами, подставляет в команду некоторые параметры по умолчанию, содержит константы с описанием доступных форматов, а также дает возможность задать таймаут на выполнение конвертации.
Для работы с оберткой подключаем ее к своему проекту через composer:
composer require mnvx/lowrapperИспользовать ее можно так:
use Mnvx\Lowrapper\Converter;
use Mnvx\Lowrapper\LowrapperParameters;
use Mnvx\Lowrapper\Format;
// Создаем объект конвертера
$converter = new Converter();
// Описываем параметры для конвертера
$parameters = (new LowrapperParameters())
    // На вход подаем строку с HTML
    ->setInputData('<html>My html file</html>')
    // В каком формате нужен результат
    ->setOutputFormat(Format::TEXT_DOCX)
    // Файл для сохранения результата
    ->setOutputFile('path-to-result-docx.docx');
// Запускаем конвертацию
$converter->convert($parameters);
В результате будет сформирован docx файл. Больше примеров можно найти на гитхабе.
Разумеется, в качестве бонуса можно запускать конвертацию в другую сторону — из doc в html и отображать содержимое офисных документов в браузере. Качество конвертации будет не всегда на высоте, но для каких-то случаев вполне подойдет.
Несколько граблей
Будет полезно рассказать про несколько особенностей, с которыми я столкнулся при работе с этой утилитой.
1. Применение CSS стилей. При преобразовании html в нужный формат имейте ввиду, что такая запись воспринимается корректно:
<p class=”someclass”></p>А такие записи будут обработаны точно так же, как если бы class мы совсем не указали:
<p class=”some_class”>Some text</p>
<p class=”class1 class2”>Some text</p>2. При преобразовании html в нужный формат не всегда срабатывают описания стилей и иногда приходится экспериментировать, чтобы заработало. Например, так не работает:
td, th {
    border: 1px solid black;
}
Но так работает:
.td {
    border: 1px solid black;
}
...
<td class=”td”>...</td>
3. Одно и то же преобразование можно выполнять с помощью разных конвертеров. При этом результат будет существенно отличаться. Если у вас на выходе получится не очень красивый документ, попробуйте принудительно задать используемый модуль, например:
$parameters = (new LowrapperParameters())
    ->setDocumentType(DocumentType::WRITER);
4. Можно ли настроить ширину строк в таблице — для меня пока загадка. И в целом со стилизацией таблицы при преобразовании html в docx или pdf у меня возникли затруднения. Поэтому на мой взгляд подход трудно будет применять для генерации сложных печатных форм, таких как счет-фактура.
Вывод
Инструмент универсален и очень хорош, если на входе у вас не очень сложные по верстке документы. Тогда на выходе вы получаете документы в нужных форматах написав всего несколько строк кода.
Комментарии (14)
 - caballero24.01.2017 14:52+3- что касается doc И excel — майкрософтовский офис сам их конвертит — достаточно сохранить HTML файлы с расширением docx или, соответственно, xslx 
 
 Что касается граблей — нужно делать inline стили и верстать HTML одной таблицей иначе части документа формируются отдельно и расползаются - mnv24.01.2017 18:49- Раньше тоже так делал. Но при редактировании и последующем сохранении такого документа возникало сообщение, мол, переконвертировать ли документ в формат ворда (не помню точно формулировку). Свежий LibreOffice тоже спрашивает. А вот офис от Microsoft давно не использовал. Новые версии MS Office задают такой вопрос?  - caballero24.01.2017 19:08+1- последние не пробовал думаю да — обычный вопрос любой проги если она собирается пересохранить файл с другой структурой 
 А вот либреофис как то некоректно открывал
 Точнее майкрософт сразу конвертил и открывал уже как родной а либре по моему открывал как HTML
 но в целом проблем не было даже с бухгалтерсикими отчетомаи типа главной книги и налоговыми накладными
 главное верстать внутри одного table
 
 
 - Misanthropist24.01.2017 21:42+1- Внедряли на проекте конвертертацию на основе LibreOffice. Нужно было сконвертить около 200000 doc-файлов в html. Процесс периодически зависал, приходилось ручками конвертор перезапускать.  - mnv24.01.2017 21:46- На такой случай в обертке можно задать таймаут. По умолчанию конвертеру дается 60 секунд, после чего будет выброшено исключение. 
 
 - KonstantinS25.01.2017 10:06- Как на счет формирования документов в формате openoffice(odt, ods). Сами эти файлы представляют zip архив, в котором находятся xml файлы. Правите content.xml, запаковываете обратно в zip, переименовывываете архив обратно в odt или ods. После этого можно конвертировать в любой формат. Это сложнее, т.к. надо разбираться с xml. Зато все возможности, которых нет в html. А разметка в xml очень похожа на html 
 - Express77725.01.2017 11:34- У меня была задача конвертировать html в PDF. К сожалению, так и не смог найти подходящий инструмент. Пытался использовать DomPDF, HTML2PDF. У них у всех одна болезнь не понимают даже среднюю верстку. А документ был как раз счет фактурой со сложными таблицами. Пришлось верстать с нуля с помощью fPDF(tPDF). 
 Libre office не использовал.
 
 Вот вопрос. Как хром быстро конвертирует в PDF при печати? Нужно всего лишь выбрать PDF принтер и все, PDF готов, каким бы сложным не был документ. - mnv25.01.2017 11:38- По моей практике наиболее быстрым и при этом наиболее качественным оказался конвертер wkhtmltopdf. Я работал с ним через https://github.com/barryvdh/laravel-snappy 
 
 
           
 

hudson
Тоже недавно писал конвертацию DOCX в PDF, ни один вариант с использованием PHPOffice и PHP-конвертеров не дал приемлемого результата, кроме Libre Office. Причём я сначала хотел использовать unoconv, но он уверенно конвертировал файлы только из консоли (и у него под капотом тоже libreoffice), а из кода ни в какую.
mnv
Да, unoconv по сути аналогичная обертка, но на питоне. Я сперва начал использовать ее, даже написал модуль на php под нее, не найдя подходящего. И для laravel в том числе. Но потом понял, что в unoconv есть свои проблемы и автор его не очень активно поддерживает. Поэтому решил, что лучше сделать обертку поверх libreofffice. Если будут возникать какие-то трудности, то мне их легче будет быстренько пофиксить.
Ordinatus
Unoconv — это небольшая python обертка над unoAPI LibreOffice(OpenOffice). По сути один файл, который можно расковырять и привести к приемлемому функционалу, заменив прием аргументов из нужного источника.
Так же писал подобный микросервис для себя (из unoconv) и с лета собираюсь написать об этом :)