Записки админа небольшого предприятия.
$name – имя placeholder’a
$img_path – путь до картинки
$width – желаемая ширина изображения в документе (если не задать – ширина оригинала)
$height – желаемая длина изображения в документе (если не задать – длина оригинала)
Сохранение документа
$odtformat->SaveToDisk(“$path_to_save”);
$path_to_save – куда будем сохранять (путь+имя файла)
Остальные методы не привожу, все можно увидеть в исходнике. Тем более, что большинство вспомогательных методов взято из публичных источников. Да и сам код прост, как две копейки. Приведу лишь некоторые настройки:
Имя папки с пользовательскими изображениями
Ну вот, можно сказать, что файл .odt, заполненный нужными нам данными, уже сформирован. Время для второго этапа.
Внимание! Чтобы placeholder’ы заменялись корректно, при добавлении их в документ используйте «Очистить формат». Класс использовал для MS World 2013. Но что-то мне подсказывает, что содержание odt одинаково и в других версиях.
ЭТАП 2. Конвертировать в pdf. Показ пользователю
Сразу скажу, что идеального решения так и не нашел. Решений, по существу, практически нет. Перерыв «интернеты», наткнулся на горстку тяжеловесов, zend примочек и просто хлама. Так что, расскажу все, как было.
Первым делом, пытался использовать онлайн-сервисы. Сначала был Google Docs. Тут все ясно. Просто показ документа на странице через iframe, избегая самого конвертирования.
Пример:
- Скорость отображения
- Кривое форматирование
- При использовании сторонних библиотек для формирования odt, появлялся странный белый лист вначале документа
- Не pdf
- Онлайн
- Простота
width="600" height="780" style="border: none;">
- Безумно долго
- Решение, само по себе, кривое
- Непредсказуемое поведение в разных браузерах
- Так и не удалось избавиться от окна печати
- Онлайн
- Качественное конвертирование
exec(“libreoffice --headless --invisible --convert-to pdf $full_path_to_file
- Нужен доступ к серверу
- Тяжелый пакет libreoffice
- exec (подобные команды в коде – дело не очень-то хорошее)
- Заметный прирост в скорости
- Качественное форматирование
- Удобство использования готовых документов
- Абсолютно локальное решение
Формирование документов на основе ODT шаблонов. ODT to PDF
Не так давно мне пришлось столкнуться с типичной задачей – формировать документы с пользовательскими данными на основе шаблонов ODT средствами PHP. Звучит весьма тривиально, но намучиться пришлось сильно. Дело в том, что ни одно из доступных средств, так или иначе, не подошло. Одни библиотеки формировали документ криво, другие не поддерживали русские шрифты, третьи – двигали картинки в стиле Harlem Shake. Вот и пришлось «велосипедить».
- Обработать ODT шаблон. Заменить placeholder’ы на пользовательские значения
- Конвертировать в pdf. Показать пользователю
ЭТАП 1. Обработать ODT шаблон. Заменить placeholder’ы
Ни для кого не секрет, что ODT — это обычный архив с xml на борту. Все картинки прячутся в папке, название которой может быть любым, лишь бы на нее ссылались в файле описаний. Не будем вдаваться в подробности: достаточно лишь сказать, что за основной контент документа отвечает content.xml, за «описательную» часть – manifest.xml. Обращаю внимание, что стили текста нас не интересуют (по крайней мере, в условиях данной задачи). Копнув чуть глубже эти xml’ки выводим алгоритм:
- Распаковать архив
- Для подмены текста: парсим content.xml, заменяем placeholder’ы на нужные значения
- Для изображений: загружаем свои изображения в папку (создаем ее внутри распакованного .odt документа), парсим content.xml, заменяем placeholder’ы на frame вида
Далее, добавляем в конец manifest.xml блок вида
Алгоритм явно упрощен, зато действенен и легок. На его основе был написан класс (на коленках) odtFormat. Небольшая справка о том, как им пользоваться:
$odtformat = new odtFormat(“$doc_path”, "$temp_dir");
$doc_path – путь до шаблона .odt
$temp_dir – папка, в которой будут храниться временные файлы.
$odtformat->SetText(“$name”, “$value”);
$name – имя placeholder’а
$value – пользовательское значение
$odtformat->SetImage(“$name”, “$img_path” ,$width, $height);
$name – имя placeholder’a
$img_path – путь до картинки
$width – желаемая ширина изображения в документе (если не задать – ширина оригинала)
$height – желаемая длина изображения в документе (если не задать – длина оригинала)
$odtformat->SaveToDisk(“$path_to_save”);
$path_to_save – куда будем сохранять (путь+имя файла)
Остальные методы не привожу, все можно увидеть в исходнике. Тем более, что большинство вспомогательных методов взято из публичных источников. Да и сам код прост, как две копейки. Приведу лишь некоторые настройки:
Отделяет placeholder от текста слева
Отделяет placeholder от текста справа
Имя папки с пользовательскими изображениями
Ну вот, можно сказать, что файл .odt, заполненный нужными нам данными, уже сформирован. Время для второго этапа.
Внимание! Чтобы placeholder'ы заменялись корректно, при добавлении их в документ используйте «Очистить формат». Класс использовал для MS World 2013. Но что-то мне подсказывает, что содержание odt одинаково и в других версиях.
ЭТАП 2. Конвертировать в pdf. Показ пользователю
Сразу скажу, что идеального решения так и не нашел. Решений, по существу, практически нет. Перерыв «интернеты», наткнулся на горстку тяжеловесов, zend примочек и просто хлама. Так что, расскажу все, как было.
Первым делом, пытался использовать онлайн-сервисы. Сначала был Google Docs. Тут все ясно. Просто показ документа на странице через iframe, избегая самого конвертирования.
Пример:
- Скорость отображения
- Кривое форматирование
- При использовании сторонних библиотек для формирования odt, появлялся странный белый лист вначале документа
- Не pdf
- Онлайн
- Простота
Очевидно, что данное решение долго не жило. Стоит глянуть в сторону Microsoft с их Office Apps. Интересным хинтом стало конвертирование pdf как версии для печати (встроенная функция онлайн сервиса). Таким образом, можно средствами Microsoft конвертировать файл и тут же его показать.
Пример:
- Безумно долго
- Решение, само по себе, кривое
- Непредсказуемое поведение в разных браузерах
- Так и не удалось избавиться от окна печати
- Онлайн
- Качественное конвертирование
Не найдя больше достойных онлайн-вариантов, решено было использовать средства сервера. С этой задачей хорошо справляется Libreoffice. У него есть встроенный конвертер документов, работающий из командной строки. Идея заключалась в том, чтобы забрасывать сформированные odt в папку, передавать ее ключом к exec, отображать уже готовые pdf, лежащие в той же папке. Положим, что apt-get install libreoffice мы уже сделали. Осталось лишь дописать одну строку кода:
exec(“libreoffice --headless --invisible --convert-to pdf $full_path_to_file --outdir $full_path_to_dir”);
$full_path_to_file – полный путь до файлов (/var/www/*.odt)
$full_path_to_dir – полный путь до папки сохранения (/var/www/result/)
Как показать pdf в iframe, я думаю, вы и сами знаете.
- Нужен доступ к серверу
- Тяжелый пакет libreoffice
- exec (подобные команды в коде – дело не очень-то хорошее)
- Заметный прирост в скорости
- Качественное форматирование
- Удобство использования готовых документов
- Абсолютно локальное решение
Заключение
При всех недостатках решения — цели выполнены. Надеюсь, что эта статья поможет избежать некоторых трудностей при выполнении подобной задачи. Всем удачного кодинга!
P.S. Прошу прощения за отвратительное форматирование.
Формирование документов на основе ODT шаблонов. ODT to PDF
Не так давно мне пришлось столкнуться с типичной задачей – формировать документы с пользовательскими данными на основе шаблонов ODT средствами PHP. Звучит весьма тривиально, но намучиться пришлось сильно. Дело в том, что ни одно из доступных средств, так или иначе, не подошло. Одни библиотеки формировали документ криво, другие не поддерживали русские шрифты, третьи – двигали картинки в стиле Harlem Shake. Вот и пришлось «велосипедить».
- Обработать ODT шаблон. Заменить placeholder’ы на пользовательские значения
- Конвертировать в pdf. Показать пользователю
ЭТАП 1. Обработать ODT шаблон. Заменить placeholder’ы
Ни для кого не секрет, что ODT — это обычный архив с xml на борту. Все картинки прячутся в папке, название которой может быть любым, лишь бы на нее ссылались в файле описаний. Не будем вдаваться в подробности: достаточно лишь сказать, что за основной контент документа отвечает content.xml, за «описательную» часть – manifest.xml. Обращаю внимание, что стили текста нас не интересуют (по крайней мере, в условиях данной задачи). Копнув чуть глубже эти xml’ки выводим алгоритм:
- Распаковать архив
- Для подмены текста: парсим content.xml, заменяем placeholder’ы на нужные значения
- Для изображений: загружаем свои изображения в папку (создаем ее внутри распакованного .odt документа), парсим content.xml, заменяем placeholder’ы на frame вида
Далее, добавляем в конец manifest.xml блок вида
Алгоритм явно упрощен, зато действенен и легок. На его основе был написан класс (на коленках) odtFormat. Небольшая справка о том, как им пользоваться:
$odtformat = new odtFormat(“$doc_path”, "$temp_dir");
$doc_path – путь до шаблона .odt
$temp_dir – папка, в которой будут храниться временные файлы.
$odtformat->SetText(“$name”, “$value”);
$name – имя placeholder’а
$value – пользовательское значение
$odtformat->SetImage(“$name”, “$img_path” ,$width, $height);
$name – имя placeholder’a
$img_path – путь до картинки
$width – желаемая ширина изображения в документе (если не задать – ширина оригинала)
$height – желаемая длина изображения в документе (если не задать – длина оригинала)
$odtformat->SaveToDisk(“$path_to_save”);
$path_to_save – куда будем сохранять (путь+имя файла)
Остальные методы не привожу, все можно увидеть в исходнике. Тем более, что большинство вспомогательных методов взято из публичных источников. Да и сам код прост, как две копейки. Приведу лишь некоторые настройки:
Отделяет placeholder от текста слева
Отделяет placeholder от текста справа
Имя папки с пользовательскими изображениями
Ну вот, можно сказать, что файл .odt, заполненный нужными нам данными, уже сформирован. Время для второго этапа.
Внимание! Чтобы placeholder'ы заменялись корректно, при добавлении их в документ используйте «Очистить формат». Класс использовал для MS World 2013. Но что-то мне подсказывает, что содержание odt одинаково и в других версиях.
ЭТАП 2. Конвертировать в pdf. Показ пользователю
Сразу скажу, что идеального решения так и не нашел. Решений, по существу, практически нет. Перерыв «интернеты», наткнулся на горстку тяжеловесов, zend примочек и просто хлама. Так что, расскажу все, как было.
Первым делом, пытался использовать онлайн-сервисы. Сначала был Google Docs. Тут все ясно. Просто показ документа на странице через iframe, избегая самого конвертирования.
Пример:
- Скорость отображения
- Кривое форматирование
- При использовании сторонних библиотек для формирования odt, появлялся странный белый лист вначале документа
- Не pdf
- Онлайн
- Простота
Очевидно, что данное решение долго не жило. Стоит глянуть в сторону Microsoft с их Office Apps. Интересным хинтом стало конвертирование pdf как версии для печати (встроенная функция онлайн сервиса). Таким образом, можно средствами Microsoft конвертировать файл и тут же его показать.
Пример:
- Безумно долго
- Решение, само по себе, кривое
- Непредсказуемое поведение в разных браузерах
- Так и не удалось избавиться от окна печати
- Онлайн
- Качественное конвертирование
Не найдя больше достойных онлайн-вариантов, решено было использовать средства сервера. С этой задачей хорошо справляется Libreoffice. У него есть встроенный конвертер документов, работающий из командной строки. Идея заключалась в том, чтобы забрасывать сформированные odt в папку, передавать ее ключом к exec, отображать уже готовые pdf, лежащие в той же папке. Положим, что apt-get install libreoffice мы уже сделали. Осталось лишь дописать одну строку кода:
exec(“libreoffice --headless --invisible --convert-to pdf $full_path_to_file --outdir $full_path_to_dir”);
$full_path_to_file – полный путь до файлов (/var/www/*.odt)
$full_path_to_dir – полный путь до папки сохранения (/var/www/result/)
Как показать pdf в iframe, я думаю, вы и сами знаете.
- Нужен доступ к серверу
- Тяжелый пакет libreoffice
- exec (подобные команды в коде – дело не очень-то хорошее)
- Заметный прирост в скорости
- Качественное форматирование
- Удобство использования готовых документов
- Абсолютно локальное решение
Заключение
При всех недостатках решения — цели выполнены. Надеюсь, что эта статья поможет избежать некоторых трудностей при выполнении подобной задачи. Всем удачного кодинга!
P.S. Прошу прощения за отвратительное форматирование.