PHPWord icon indicating copy to clipboard operation
PHPWord copied to clipboard

setMacroChars with [ and ]

Open sguyomard opened this issue 2 years ago • 5 comments

when using setMaroChars with [ and ] as starting and closing char, the template processor doesn't replace maros the word docx file was made with office365, not online, word installed on a laptop.

Steps to Reproduce

$templateProcessor = new TemplateProcessor($localWordFileName); $templateProcessor->setMacroChars('[', ']');

in $this->tempDocumentMainPart, I have for example : <w:rPr><w:sz w:val="16"/><w:szCs w:val="16"/></w:rPr><w:t xml:space="preserve">Nous avons bien réceptionné votre demande du </w:t></w:r><w:r w:rsidR="00790EED"><w:rPr><w:sz w:val="16"/><w:szCs w:val="16"/></w:rPr><w:t>{{</w:t></w:r><w:r w:rsidR="10F8EA5E" w:rsidRPr="22CC4AC1"><w:rPr><w:sz w:val="16"/><w:szCs w:val="16"/></w:rPr><w:t>dateSoumis</w:t></w:r><w:r w:rsidR="00790EED"><w:rPr><w:sz w:val="16"/><w:szCs w:val="16"/></w:rPr><w:t>}}</w:t></w:r><w:r w:rsidRPr="22CC4AC1"><w:rPr><w:sz w:val="16"/><w:szCs w:val="16"/></w:rPr><w:t xml:space="preserve"> et vous remercions pour la confiance que vous nous accordez : </w:t></w:r></w:p><w:p w14:paraId="0F17B8AC" w14:textId="77777777" w:rsidR="00380A60" w:rsidRDefault="033A9107" w:rsidP="002C51CC"><w:pPr><w:spacing w:after="38"/><w:ind w:left="567" w:hanging="10"/></w:pPr><w:r w:rsidRPr="22CC4AC1"><w:rPr><w:sz w:val="14"/>

can't find out how str_replace($search, $replace, $documentPartXML) could work in this ?

the same xml part without specific marcoChars :

w:rsidRDefault="033A9107" w:rsidP="002C51CC"><w:pPr><w:spacing w:after="5" w:line="265" w:lineRule="auto"/><w:ind w:left="567" w:hanging="10"/></w:pPr><w:r w:rsidRPr="22CC4AC1"><w:rPr><w:sz w:val="16"/><w:szCs w:val="16"/></w:rPr><w:t xml:space="preserve">Nous avons bien réceptionné votre demande du </w:t></w:r><w:r w:rsidR="00334903"><w:rPr><w:sz w:val="16"/><w:szCs w:val="16"/></w:rPr><w:t>${dateSoumis}</w:t></w:r><w:r w:rsidRPr="22CC4AC1"><w:rPr><w:sz w:val="16"/><w:szCs w:val="16"/></w:rPr><w:t xml:space="preserve"> et vous remercions pour la confiance que vous nous accordez : </w:t></w:r></w:p><w:p w14:paraId="0F17B8AC" w14:textId="77777777" w:rsidR="00380A60" w:rsidRDefault="033A9107" w:rsidP="002C51CC"><w:pPr><w:spacing w:after="

here the macro is clean

if I put a $ and a { , here a piece of templace.docx : image

I get this result :

image

it seems there is a glinch in the matrix with ${

Expected Behavior

example : [client_name] replaced by client name

Current Behavior

nothing replaced, we got [client_name] I tried diffrent patterns like {# and }, [#, #], etc nothing works, only ${ }

sguyomard avatar Jun 16 '23 07:06 sguyomard

Same here,

this is because, fixBrokenMacros function is called before macro changed by setMacroChar

gdevilbat avatar Jun 20 '23 04:06 gdevilbat

fixBrokenMacros is called on TemplateProcessor.php Class Instanciation (and so it's too late to change it after class instanciation)

But macroOpeningChars and macroClosingChars are static, so if you define setMacroOpeningChars, setMacroClosingChars and setMacroChars as static functions, it could work doing

TemplateProcessor::setMacroChars('[', ']'); $templateProcessor = new TemplateProcessor($localWordFileName);

(it means in TemplateProcessor.php to replace

public function setMacroOpeningChars(string $macroOpeningChars): void { self::$macroOpeningChars = $macroOpeningChars; }

public function setMacroClosingChars(string $macroClosingChars): void
{
    self::$macroClosingChars = $macroClosingChars;
}

public function setMacroChars(string $macroOpeningChars, string $macroClosingChars): void
{
    self::$macroOpeningChars = $macroOpeningChars;
    self::$macroClosingChars = $macroClosingChars;
}

by

public static function setMacroOpeningChars(string $macroOpeningChars): void { self::$macroOpeningChars = $macroOpeningChars; }

public static function setMacroClosingChars(string $macroClosingChars): void
{
    self::$macroClosingChars = $macroClosingChars;
}

public static function setMacroChars(string $macroOpeningChars, string $macroClosingChars): void
{
    self::$macroOpeningChars = $macroOpeningChars;
    self::$macroClosingChars = $macroClosingChars;
}

)

thomasb88 avatar Aug 26 '23 23:08 thomasb88

Any fix yet ?

JonnyS02 avatar Oct 23 '24 13:10 JonnyS02

I also tried changing the "Identifiers" with "setMacroChars" buts its not working. https://phpoffice.github.io/PHPWord/usage/template.html#setmacrochars


For "setValue" it is working 90% of the time (by adding spaces, changing formatting etc) with

$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor($source_file);
$templateProcessor->setMacroChars('[', ']');
$templateProcessor->setValue('tag', 'value');

For "cloneBlock" it is not working at all, no matter whatever you do.

$replacements = array(
    array('title' => 'Batman', 'price' => '10'),
    array('title' => 'Superman', 'price' => '20'),
    array('title' => 'spiderman', 'price' => '30'),
);
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor($source_file);
$templateProcessor->setMacroChars('[', ']');
$templateProcessor->cloneBlock('products', 0, true, false, $replacements);   

Issue is in identifying the pattern in xml in TemplateProcessor.php

public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVariables = false, $variableReplacements = null)
{
    $xmlBlock = null;
    $matches = [];
    $escapedMacroOpeningChars = self::$macroOpeningChars;
    $escapedMacroClosingChars = self::$macroClosingChars;
    preg_match(
        //'/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\{{' . $blockname . '}<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\{{\/' . $blockname . '}<\/w:.*?p>)/is',
        '/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\\' . $escapedMacroOpeningChars . $blockname . $escapedMacroClosingChars . '<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\\' . $escapedMacroOpeningChars . '\/' . $blockname . $escapedMacroClosingChars . '<\/w:.*?p>)/is',
        //'/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\\'. $escapedMacroOpeningChars . $blockname . '}<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\\'.$escapedMacroOpeningChars.'\/' . $blockname . '}<\/w:.*?p>)/is',
        $this->tempDocumentMainPart,
        $matches
    );

Hope, the fix will come someday. But great Library, God bless the developers. Any patreon link ?

wikkipk avatar Sep 06 '25 12:09 wikkipk

@wikkipk What is the exact issue on the XML?

xJuvi avatar Sep 07 '25 19:09 xJuvi