•  
  •  

Библиотека PHPWord: основные возможности

Библиотека PHPWord, находящаяся уже почти год в стадии бета-тестирования1), предоставляет возможность создания сложных документов формата OOXML (*.docx). Рассмотрим основные возможности этой библиотеки. Для начала работы достаточно распаковать архив с библиотекой в каталог с создаваемым вами документом PHP и подгрузить основной класс библиотеки, расположенный в файле PHPWord.php:

include_once 'PHPWord.php';

Создание документа начинается с объявления экземпляра класса PHPWord. Конструктор не требует передачи аргументов:

$word = new PHPWord();

Далее следует задать название и размер шрифта по-умолчанию:

$word->setDefaultFontName('Times New Roman');
$word->setDefaultFontSize(14);

В рассматриваемой версии до применения указанных выше функций шрифтом по-умолчанию является Arial размером 20 пунктов. Теперь можно задать время создания документа, имя автора и так далее:

$meta = $word->getProperties();
$meta->setCreator('Имя создателя документа'); 
$meta->setCompany('Организация');
$meta->setTitle('Название документа');
$meta->setDescription('Описание документа'); 
$meta->setCategory('Категория документа');
$meta->setLastModifiedBy('Имя последнего редактора');
$meta->setCreated( mktime(0, 0, 0, 5, 12, 2011) ); // Дата и время создания документа
$meta->setModified( time() ); //Дата и время последнего изменения документа
$meta->setSubject('Тема документа'); 
$meta->setKeywords('ключевые, слова, документа');

По-умолчанию в качестве даты создания и изменения документа указывается текущее время, а остальные свойства заполняются пустыми значениями. Если требуется указать конкретную дату создания или изменения, используйте функцию mktime или любую другую функцию, возвращающую время в стиле Unix.

Основным элементом документа Word является Раздел. Раздел представляет собой прямоугольную область, внутри которой помещаются остальные элементы страницы: текст, изображения, таблицы и т.д.

Раздел может иметь книжную или альбомную ориентацию, настраиваемые поля (margins), настраиваемые цвета границ раздела и их толщину (на рисунке показана пунктиром):

ПараметрОписание
orientationОриентация страницы:
null - книжная ориентация,
landscape - альбомная
marginTopРазмер верхнего поля во внутренних единицах
marginRightРазмер правого поля во внутренних единицах
marginBottomРазмер нижнего поля во внутренних единицах
marginLeftРазмер левого поля во внутренних единицах
borderTopSizeТолщина верхнего края рамки во внутренних единицах
borderRightSizeТолщина правого края рамки во внутренних единицах
borderBottomSizeТолщина нижнего края рамки во внутренних единицах
borderLeftSizeТолщина левого края рамки во внутренних единицах
borderTopColorЦвет верхнего края рамки в шестнадцатеричном формате
borderRightColorЦвет правого края рамки в шестнадцатеричном формате
borderBottomColorЦвет нижнего края рамки в шестнадцатеричном формате
borderLeftColorЦвет левого края рамки в шестнадцатеричном формате

Для создания раздела существует функция createSection. В качестве внутренних единиц используются типографские твипы. Если вам непривычно указывать размеры в твипах, можно написать простую функцию, преобразующую миллиметры в твипы:

function m2t($millimeters){
  return floor($millimeters*56.7); //1 твип равен 1/567 сантиметра
}//m2t

Указанные в таблице параметры могут быть переданы в виде массива при создании раздела...

$sectionStyle = array('orientation' => 'landscape',
               'marginLeft' => m2t(15), //Левое поле равно 15 мм
               'marginRight' => m2t(15),
               'marginTop' => m2t(15),
               'borderTopColor' => 'C0C0C0'
         );
$section = $word->createSection($sectionStyle);

... или могут быть установлены по-отдельности после создания раздела:

$section = $word->createSection();
$sectionStyle = $section->getSettings();
$sectionStyle->setLandscape(); //или setPortrait()
$sectionStyle->setMarginLeft(m2t(15));
$sectionStyle->setMarginRight(m2t(15));
$sectionStyle->setBorderBottomSize(m2t(1));
$sectionStyle->setBorderTopColor('C0C0C0');

Добавление блока текста

Под блоком текста понимается отрывок текста, имеющий одинаковое форматирование (цвет, размер шрифта и т.п.). Для создания блока текста в выбранном разделе используйте функцию addText:

$section->addText( $text, [$fontStyle[, $paragraphStyle]] );

Здесь $text - добавляемый текст, необязательный параметр $fontStyle - имя определенного ранее текстового стиля, необязательный параметр $paragraphStyle - имя определенного ранее стиля абзаца.

Изменение форматирования текста

Форматирование текста, как и форматирование раздела, может осуществляться при его создании...

$fontStyle = array('color'=>'FFFF00', 'size'=>18, 'bold'=>true);
$section->addText('Привет!', $fontStyle); //Массив с параметрами форматирования передается при создании

... или устанавливается после создания предназначенными для этого методами:

$text = $section->addText('Привет!');
$style = $text->getStyle();
$style->setColor('FFFF00');
$style->setSize(18);
$style->setBold();

Ниже приведен полный список доступных параметров форматирования текста:

ПараметрОписание
sizeРазмер шрифта в типографских пунктах
nameНазвание шрифта (кегль)
boldЯвляется ли текст полужирным (true\false)
italicВыделен ли текст курсивом (true\false)
superScriptЯвляется ли текст надстрочным (true\false)
subScriptЯвляется ли текст подстрочным (true\false)
underlineВид подчеркивания2) из набора констант PHPWord_Style_Font:
UNDERLINE_NONE - нет подчеркивания,
UNDERLINE_DASHHEAVY - жирная штриховая линия,
UNDERLINE_DASHLONG - удлиненная штриховая линия,
UNDERLINE_DASHLONGHEAVY - удлиненная жирная штриховая линия,
UNDERLINE_DOUBLE - двойная линия,
UNDERLINE_DOTHASH3) - штрих-пунктир,
UNDERLINE_DOTHASHHEAVY - жирный штрих-пунктир,
UNDERLINE_DOTDOTDASH - две точки + тире,
UNDERLINE_DOTDOTDASHHEAVY - жирные две точки + тире,
UNDERLINE_DOTTED - пунктир,
UNDERLINE_DOTTEDHEAVY - жирный пунктир,
UNDERLINE_SINGLE - одинарная линия,
UNDERLINE_WAVY - волнистая линия,
UNDERLINE_WAVYDOUBLE - двойная волнистая линия,
UNDERLINE_WAVYHEAVY - тройная волнистая линия,
UNDERLINE_WORDS - подчеркивать только слова (не подчеркивать пробелы)
ColorЦвет шрифта в шестнадцатеричном формате
fgColorЦвет выделения маркером из набора констант PHPWord_Style_Font:
FGCOLOR_YELLOW - желтый,
FGCOLOR_LIGHTGREEN - ярко-зеленый,
FGCOLOR_CYAN - бирюзовый,
FGCOLOR_MAGENTA - лиловый,
FGCOLOR_BLUE - синий,
FGCOLOR_RED - красный,
FGCOLOR_DARKBLUE - темно-синий,
FGCOLOR_DARKCYAN - сине-зеленый,
FGCOLOR_DARKGREEN - темно-зеленый,
FGCOLOR_DARKMAGENTA - фиолетовый,
FGCOLOR_DARKRED - темно-красный,
FGCOLOR_DARKYELLOW - коричнево-зеленый,
FGCOLOR_DARKGRAY - серый 50%,
FGCOLOR_LIGHTGRAY - серый 25%,
FGCOLOR_BLACK - черный

Названия параметров должны употребляться с соблюдением регистра. В случае параметров underline и fgColor применение значений, не указанных в таблице, не допускается.

Cписок доступных параметров форматирования абзаца:

ПараметрОписание
alignВыравнивание текста в абзаце:
left - по левому краю,
right - по правому краю,
center - по центру,
both или justify - по ширине
spaceBeforeОтступ абзаца сверху в твипсах
spaceAfterОтступ абзаца снизу в твипсах
spacingИнтервал между строк в твипсах

Определение стилей текста и абзаца

Вместо того, чтобы каждый раз передавать в функцию createText массив с параметрами, вы можете создать именованный стиль, а затем указывать только название этого стиля:

$word->addFontStyle($styleName, $fontStyle);

Здесь $styleName - заданное вами имя стиля, $fontStyle - массив, содержащий определение стиля. После создания стиля его имя можно использовать при создании блоков текста, например:

$fontStyle = array('color'=>'006699', 'size'=>18, 'italic'=>true, underline=>PHPWord_Style_Font::UNDERLINE_DOUBLE);
$word->addFontStyle('myTextStyle', $fontStyle); //myTextStyle - это имя стиля
$text = $section->addText('Привет!', 'myTextStyle');

Аналогичным образом осуществляется создание стиля абзаца:

$paragraphStyle = array('color'=>'006699', 'size'=>18, 'italic'=>true, underline=>UNDERLINE_DOUBLE);
$word->addParagraphStyle('myParagraphStyle', $paragraphStyle);
$text = $section->addText('Привет!', 'myTextStyle', 'myParagraphStyle');

Группировка блоков текста в абзац

Блоки текста с различным форматированием могут быть объединены в абзац заданного вида. Для этого применяется команда createTextRun:

$textrun = $section->createTextRun([$paragraphStyle]);
$textrun->addText('Полужирный текст', array('bold'=>true)); 
$textrun->addText('Курсив', array('italic'=>true));
$textrun->addText('Цветной текст', array('color'=>'AACC00'));

Необязательный параметр $paragraphStyle - массив со стилем абзаца или название созданного ранее именованного стиля.

Добавление заголовков

В библиотеке имеются отдельные функции для добавления заголовков (addTitle) и задания их стилей (addTitleStyle). Применение заголовков вместо форматированных блоков текста необходимо в том случае, если вы хотите добавить в документ автоматически создаваемое оглавление, поскольку в оглавление включаются только заголовки, а не обычные блоки текста. При добавлении заголовков создание стилей заголовков обязательно:

$word->addTitleStyle($titleLevel[, $fontStyle[, $paragraphStyle]]);

Здесь $titleLevel - уровень заголовка, для которого задается стиль (обычно от 1 до 6), $fontStyle - массив со стилем форматирования заголовка, $paragraphStyle - массив со стилем форматирования абзаца. Как видите, форматирование можно не трогать, но сам стиль заголовка требуемого уровня должен быть обязательно создан. Добавление заголовка делается так:

$section->addTitle( $text[, $titleLevel]);

По-умолчанию создается заголовок 1 уровня.

Добавление ссылок

Добавление ссылок мало чем отличается от добавления обычного текста. Для добавления ссылки используется команда:

$section->addLink($url, [$text[, $fontStyle[, $paragraphStyle]]]);

Здесь $url - URL ссылки. В случае, если $text не указана в качестве отображаемого текста, используется URL. Не знаю зачем, но для изменения форматирования ссылок используется отдельная функция addLinkStyle. Ее аргументы полностью совпадают с аргументами addFontStyle. Если требуется указать название стиля, но переменную $text хочется оставить пустой, передайте ей значение null:

$section->addLink('http://www.phpexport.ru/', NULL, 'myLinkStyle');

Разрыв строки и страницы

Для принудительного переноса строки используйте синтаксис:

$section->addTextBreak([$num]);

Необязательный параметр $num, по-умолчанию равный 1, указывает сколько переносов строки необходимо сделать. Для принудительной вставки разрыва страницы выполните:

$section->addPageBreak();

Добавление оглавления

Для добавления оглавления используется функция addTOC:

$section->addTOC([$fontStyle[, $tocStyle]]);

Здесь $fontStyle - форматирование текста, определенное одним из ранее указанных способов, $tocStyle - массив со стилем оформления оглавления, возможные параметры которого приведены в таблице: ^ Параметр ^ Описание ^

tabLeaderЗаполнитель между заголовком и номером страницы из набора констант PHPWord_Style_TOC:
TABLEADER_DOT - точки,
TABLEADER_UNDERSCORE - символ подчеркивания,
TABLEADER_LINE - линия,
TABLEADER_NONE - нет заполнителя
tabPosПоложение номера страницы в твипсах
IndentОтступ заголовков в твипсах

Присутствует возможность добавления нумерованных и ненумерованных списков в документ. Для добавления элемента списка используйте код:

$section->addListItem( $text[, $depth[, $textStyle[, $listStyle[, $paragraphStyle]]]]);

Здесь $text - текст добавляемого элемента списка, $depth - глубина вложенности элемента в списке (от 1 до 9, по-умолчанию равна 1), $textStyle - форматирование текста списка одним из предложенных ранее способов, $listStyle - форматирование самого списка при помощи массива параметров, $paragraphStyle - форматирование абзаца. На данный момент не существует функции addListStyle, поскольку у списков пока может изменяться только один параметр:

ПараметрОписание
listTypeВид списка из набора констант PHPWord_Style_ListItem:
TYPE_NUMBER - одноуровневый нумерованный список,
TYPE_NUMBER_NESTED - многоуровневый нумерованный список,
TYPE_BULLET_FILLED - ненумерованный список с маркерами в виде закрашенных кругов,
TYPE_BULLET_EMPTY - ненумерованный список с маркерами в виде незакрашенных кругов,
TYPE_SQUARE_FILLED - ненумерованный список с маркерами в виде закрашенных квадратов

Важной частью документа Word являются таблицы. Для создания таблицы в PHPWord выполните:

$table = $section->addTable([$tableStyle]);

Необязательный аргумент $tableStyle - массив с описанием стиля таблицы или название такового, определенного методом addTableStyle:

$word->addTableStyle($styleName,  $tableStyle[, $firstRowStyle]);

Аргументы: $styleName - название стиля, $tableStyle - массив с определением стиля, $firstRowStyle - массив с определением стиля ячеек 1 строки (шапки) таблицы. Ниже приведена таблица возможных стилевых параметров таблицы в целом: ^ Параметр ^ Описание ^

cellMarginTopОтступ от ячейки сверху в твипсах
cellMarginRightОтступ от ячейки справа в твипсах
cellMarginBottomОтступ от ячейки снизу в твипсах
cellMarginLeftОтступ от ячейки слева в твипсах

Теперь в созданную таблицу можно добавить ячейки. Как и в XHTML, вначале нужно создать строку...

$table->addRow([$rowHeight]);

... затем добавить ячейки и заполнить их форматированным текстом...

$cell = $table->addCell([$cellWidth[, $cellStyle]]);
$cell->addText('Текст ячейки');

... или сделать то же самое одной командой...

$table->addCell([$cellWidth[, $cellStyle]])->addText('Текст ячейки');

... или вместо простого текста добавить изображения, списки ссылки одной из следующих команд:

КомандаДействие
addTextДобавить форматированный текст
addTextBreakДобавить перенос строки
addLinkДобавить ссылку
addListItemДобавить элемент списка
addImageДобавить изображение из файла
addMemoryImageДобавить динамически сгенерированное изображение
addObjectДобавить объект OLE
addPreserveTextДобавить поле (например, нумерацию страниц)

Как вы уже, наверное, догадались, параметр $rowHeight - позволяет задать высоту в твипсах создаваемой строки, $cellWidth - ширину ячейки (столбца), а $cellStyle - изменить форматирование ячейки. При форматировании ячейки поддерживаются следующие параметры:

ПараметрОписание
valignВыравнивание в ячейке по-вертикали: both - по-вертикали по ширине,
top - по верхнему краю,
bottom - по нижнему краю,
center - по-центру
textDirectionНаправление текста из набора констант PHPWord_Style_Cell:
TEXT_DIR_BTLR - развернут на 90 градусов против часовой стрелки,
TEXT_DIR_TBRL - развернут на 90 градусов по часовой стрелке
bgColorЦвет фона ячейки в шестнадцатеричном формате
borderTopSizeТолщина верхней границы ячейки в твипсах
borderRightSizeТолщина правой границы ячейки в твипсах
borderBottomSizeТолщина нижней границы ячейки в твипсах
borderLeftSizeТолщина левой границы ячейки в твипсах
borderTopColorЦвет верхней границы ячейки в шестнадцатеричном формате
borderRightColorЦвет правой границы ячейки в шестнадцатеричном формате
borderBottomColorЦвет нижней границы ячейки в шестнадцатеричном формате
borderLeftColorЦвет левой границы ячейки в шестнадцатеричном формате

PHPWord позволяет добавлять в создаваемый документ изображения 2 типов: из файла (метод addImage) и динамически сгенерированное сценарием изображение (метод addMemoryImage). Поддерживаются файлы форматов jpg, png, gif, tiff, bmp. Примеры применения методов:

$section->addImage($src[, $imageStyle]);
$section->addMemoryImage($url[, $imageStyle]);

Здесь $src и $url - соответственно путь к файлу и абсолютный путь к сценарию (с адресом сайта и промежуточных каталогов), $imageStyle - массив с форматированием изображения. Поддерживаемые параметры форматирования:

ПараметрОписание
widthТребуемая ширина изображения в пикселях
heightТребуемая высота изображения в пикселях
alignГоризонтальное выравнивание изображения:
left - по левому краю,
right - по правому краю,
center - по центру

Если требуемые размеры изображения не указаны - библиотека пытается определить фактические размеры изображения при помощи функции [php>getimagesize|getimagesize]].

С помощью метода addObject вы можете внедрить в создаваемый документ фрагмент другого документа (*.docx, *.xlsx, *.pptx) при помощи технологии OLE:

$section->addObject($src[, $objectStyle]);

Массив $objectStyle может содержать только один параметр:

ПараметрОписание
alignВыравнивание объекта по-горизонтали:
left - по левому краю,
right - по правому краю,
center - по центру

Каждый раздел документа может иметь свой верхний (header) и нижний (footer) колонтитул, отображаемый на всех принадлежащих ему страницах. С точки зрения Word колонтитул является особым видом раздела, поэтому к колонтитулу применимо большинство описанных выше методов: addText, createTextRun, addTextBreak, addImage, addMemoryImage, addListItem, addTable. Кроме этого колонтитул имеет собственный метод addPreserveText, позволяющий создавать нумерацию страниц. Пример создания верхнего (createHeader) и нижнего (createFooter) колонтитула:

//Верхний колонтитул со статическим текстом
$header = $section->createHeader();
$header->addText('Этот документ создан Vania-pooh при помощи PHPWord!');
//Нижний колонтитул с нумерацией страниц посередине
$footer = $section->createFooter();
$footer->addPreserveText('Страница {PAGE} из {NUMPAGES}.', array('bold'=>true),array('align'=>'center'));

Как и всегда форматирование текста колонтитула и абзаца являются необязательными параметрами.

Библиотека PHPWord поддерживает еще один интересный метод создания документов Word - использование шаблонов. Подробный принцип работы при генерировании документов из шаблонов описан в статье docx-templates. В качестве метки в PHPWord используется комбинация ${NAME}, где NAME - имя метки. Пример генерирования с использованием меток:

$template = $word->loadTemplate('template.docx'); //Загружаем шаблон
$template->setValue('Name', 'Иванов'); //Производим замену метки на значение
$template->setValue('Surname', 'Иван'); //И еще одну метку
$template->save('document.docx'); //Сохраняем результат в файл

Для сохранения файла на жесткий диск или вывода его для скачивания пользователю используется метод save класса PHPWord_Writer_Word2007. В качестве единственного аргумента метода указывается строка 'php://output', если требуется вывести документ для скачивания пользователем или имя файла, если документ нужно сохранить на жесткий диск. При выводе файла для скачивания не забудьте отправить браузеру пользователя соответствующие заголовки:

header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
header('Content-Disposition: attachment;filename="document.docx"');
header('Cache-Control: max-age=0');
$writer = PHPWord_IOFactory::createWriter($word, 'Word2007');
$writer->save('php://output');

Сохранение файла на жесткий диск:

$writer = PHPWord_IOFactory::createWriter($word, 'Word2007');
$writer->save('filename.docx');

Подытоживая все вышесказанное хочется привести пример, в котором проиллюстрировано применение большинства возможностей библиотеки PHPWord:

Текст примера появится несколько позже, когда автор сможет сгенерировать документ с кириллицей (на английском работает). Проблема связана с функцией utf8_encode, используемой в PHPWord. Если у вас есть решение этой проблемы, просьба отписаться.
Update! Проблема с функцией utf8_encode и кириллической кодировкой решается если заменить функцию на iconv и указать входящую кодировку CP1251 и выходе UTF8. Сделать это надо во всех местах библиотеки где используется функция utf8_encode.