Как стать автором
Обновить

Как добавить секцию с различными элементами на макрос шаблонного процессора в phpWord

Однажды, в один прекрасный солнечный день...

Мне понадобилось добавить секцию на переменную шаблонного процессора.

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

Для этого подходит метод setComplexBlock() (ссылка на док'у), но если этому методу передать объект секции, то выпадет ошибка об отсутствии данного класса в пространстве имён Writer'а для Word2007

Fatal error: Uncaught Error: 
Class 'PhpOffice\PhpWord\Writer\Word2007\Element\Section' 
not found

И там действительно отсутствует этот класс:

Можно отдельно создать экземпляр объекта таблицы, заголовка, текста (там есть много других объектов) и добавить только его, но не более.

И для того чтобы сделать то, что нам нужно. Необходимо провернуть "финт ушами".

Мы сделаем подмену и передадим вместо секции кастомный контейнер.

Для этого достаточно создать класс кастомного контейнера, который по сути своей является секцией.

namespace CustomContainer;

class Container extends \PhpOffice\PhpWord\Element\Section
{
    public function __construct($section)
    {
        parent::__construct($section->getSectionId());
        $this->elements = $section->getElements();
    }
}

Обязательно подключим этот класс и библиотеку phpWord с помощью композер. Как установить композер пояснено в других статьях. Здесь мы не будем останавливаться на этом

require_once('vendor/autoload.php');
require_once ('CustomContainer/CustomContainer.php');

Для примера создадим объект PhpWord и добавим в него секцию

$newDocumentWithSection = new \PhpOffice\PhpWord\PhpWord();
$newSection = $newDocumentWithSection->addSection();

Наполним секцию каким-нибудь сомнительным содержимым

$newTitle = $newSection->addTitle('someTitle');

$newTable = $newSection->addTable([
    'borderSize' => 12,
    'borderColor' => 'green',
    'width' => 6000,
    'unit' => PhpOffice\PhpWord\SimpleType\TblWidth::TWIP
]);

$newTable->addRow();
$newTable->addCell(150)->addText('Cell A1');
$newTable->addCell(150)->addText('Cell A2');
$newTable->addCell(150)->addText('Cell A3');
$newTable->addRow();
$newTable->addCell(150)->addText('Cell B1');
$newTable->addCell(150)->addText('Cell B2');
$newTable->addCell(150)->addText('Cell B3');

Создадим новый "контейнер" на основе нашей секции.

$newCustomContainerWithSection = new \CustomContainer\Container($newSection);

Далее создадим экземпляр шаблонного процессора и передадим в метод setComplexBlock() новый подменный "контейнер".

$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('templateWithGeneratedSection.docx');

$templateProcessor->setComplexBlock('macro', $newCustomContainerWithSection);

Напоследок сохраним данные

$templateProcessor->saveAs('DocumentWithGeneratedSection.docx');

В результате видим следующее:

Было:

Стало:

Поставленная задача выполнена.

Ссылка на код с работающим примером

Ссылка на оригинальный англоязычный issue-github.

Пока что это является временным решением данной проблемы.

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.