PHPOffice / PHPWord

A pure PHP library for reading and writing word processing documents
https://phpoffice.github.io/PHPWord/
Other
7.2k stars 2.69k forks source link

setComplexBlock or setComplexValue remove placeholder other than the searched one #2300

Open rizpras opened 1 year ago

rizpras commented 1 year ago

Describe the Bug

Using setComplexBlock or setComplexValue remove all other placeholder than the one being searched

Steps to Reproduce

This code is used to add html string from WYSIWYG editor to template. First html is added to section and then making placeholder with the same number as elements in the section and saving it to a file. Afterwards, the file is loaded using second template processor and setComplexBlock is used to add the elements.


$phpWord = new PhpWord();
$section = $phpWord->addSection();

//$data is array of data fetched from database
Html::addHtml($section, $data['provision_current']);
$elements = $section->getElements();

$placeArray = [];
for($i = 0; $i<count($elements); $i++)
{
    $placeArray[$i] = '${place'.$i.'}';
}
$placeholder = implode("<w:br/>", $placeArray);

$templateProc = new TemplateProcessor(storage_path('Template.docx'));

$templateProc->setValue('here', $placeholder);

$templateProc->saveAs($file);
$templateSecond = new TemplateProcessor($file);
for($j = 0; $j<count($elements); $j++)
{
    $templateSecond->setComplexBlock($placeArray[$j], $elements[$j]);
}

$templateSecond->saveAs($file);

Expected Behavior

All elements of section replace all placeholder

Current Behavior

Only first element is replacing the placeholder. All other placeholders are somehow removed afterwards.

Context

Please fill in your environment information:

jorge-koki commented 12 months ago

Hi, did you find a solution to that problem? I'm trying to make several tables that way as well

rizpras commented 12 months ago

Hi, did you find a solution to that problem? I'm trying to make several tables that way as well

Unfortunately no. For the time being, I decide to just use HTML instead

thomasb88 commented 12 months ago

First, setComplexBlock replace 1 block at a time, taking everything that is inside the paragraph that is surrounding the block macro. So, if your macros '${place'.$i.'}' are in the same paragraph, then replacing 1 will replace them all.

And as you set '${place'.$i.'}' using setValue, you try to put them all in a text run, that is to say they are all in the same paragraph....

thomasb88 commented 12 months ago

I succeed adding HTML content using TemplateProcessor, like this

$section = (new PhpWord())->addSection(); Html::addHtml($section, $html_content, false, false); $this->setComplexBlock($search, $section, 'Variable', 1, false);

And add a trick in complex Block, replacing

$elementName = substr(get_class($complexType), strrpos(get_class($complexType), '\') + 1); $objectClass = 'PhpOffice\PhpWord\Writer\Word2007\Element\' . $elementName;

    $xmlWriter = new XMLWriter();
    /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $elementWriter */
    $elementWriter = new $objectClass($xmlWriter, $complexType, false);
    $elementWriter->write();

By a function that allow to use the section as a container only (Section exist for PHPWord Element, but not for word2007 writer). But the Container object do the job, and even better that what i can do using $section->getElements(); (i tried it also), as every kind of object declare how they should word (included in a paragraph or not for example)