Создание печатной формы Microsoft Word с помощью PHP

Источник: habrahabr
MrMixOFF

Предыстория

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

Мой вариант решения

И вот с этими колонтитулами и возникла проблема. Я не смог найти простого решения с использованием HTML javascript. С помощью HTML можно управлять расположением блоков при печати, переносить блок если он не входит целеком и все в таком духе. Как посчитать примерный конец страницы и уместить там блок с колонтитулом (с помощью javascript) я тоже представляю слабо, поскольку существует достаточно много нюансов на стороне пользователя. Поэтому было принято пойти немного иным путем, а именно связаться с Microsoft Word.
Слава руководству этой организации, на каждой рабочей станции установлен Microsoft Office 2007.

Итак, был собран шаблон в Word"е, который содержал полностью заполненное коммерческое предложение, с автомтически формируемыми полями и колонтитулами. Оставалось только подставить в нужные места данные клиента, таблицу со спецификацией товара и контакты менеджера. Как это сделать?

Я не стал использовать сторонние библиотеки, оказалось достаточно того, что документ Microsoft Word (речь идет про *.docx) представляет собой ничто иное, как обычный zip с кучей xml-файлов и прочих ресурсов типа картинок. Распаковав docx мы получаем следующее:
image

Собственно из всех этих файлов нам нужен только один, это document.xml. В нем содержится вся интересующая нас информация, а именно содержание нашего документа. Поскольку этот файл будет служить шаблоном, его мы аккуратно извлекаем и располагаем рядом с нашим упакованным документом. Дальше нам остается только взять его содержимое, изменить данные, упаковать его в Word в нужное место и отправить пользователю в браузер.
Для этого мы используем Zip - расширение позволяет легко читать и писать как в сами сжатые ZIP архивы, так и в файлы внутри них.

$zip = new ZipArchive; if ($zip->open('template.docx') === TRUE) { /*открываем наш шаблон для чтения (он находится вне документа) и помещаеем его содержимое в переменную $content*/ $handle = fopen("document.xml", "r"); $content = fread($handle, filesize("document.xml")); fclose($handle); /*Далее заменяем все что нам нужно например так */ $content = str_replace("{customer_r}","Иванов Иван Иванович",$content); /*Удаляем имеющийся в архиве document.xml*/ $zip->deleteName('word/document.xml'); /*Пакуем созданный нами ранее и закрываем*/ $zip->addFromString('word/document.xml',$content); $zip->close(); }
После проделанных операций отправляем полученный документ пользователю в браузер.

Если не портить xml то пользователь получит, полностью валидный документ. Если по невнимательности намудрить, то при открытии Word выругается на вас о наличии недопустимых символов, скажет где именно, и попытается исправить.
Можно добавлять любую информацию, например таблицы.
Ячейку таблицы можно легко вычислить (как и целую строку):

<w:tc><w:tcPr><w:tcW w:w="4783" w:type="dxa"/></w:tcPr><w:p w:rsidR="00BB344C" w:rsidRDefault="00BB344C"><w:r><w:t>Значение в ячейке</w:t></w:r><w:bookmarkStart w:id="0" w:name="_GoBack"/><w:bookmarkEnd w:id="0"/></w:p></w:tc></w:tr>

Ну вот собственно и все.
Если знаете другие способы как решить даную проблему, поделитесь пожалуйста.
Буду очень признателен.


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=35688