PHPWord icon indicating copy to clipboard operation
PHPWord copied to clipboard

New line with templateProcessor

Open R-Benjamin opened this issue 6 years ago • 23 comments

This is:

  • [x] a bug report
  • [ ] a feature request
  • [ ] not a usage question (ask them on https://stackoverflow.com/questions/tagged/phpword)

Expected Behavior

$myString = "Test-X \n Test-Y" `Test-X' 'Test-Y'

Current Behavior

$myString = "Test-X \n Test-Y" `Test-XTest-Y'

#838 <w:br/>\n and </w:t><w:br/><w:t> don't work. the problem is the same.

Failure Information

When I use the template processor, I can't insert a new line with a string.

How to Reproduce.

<?php
$templateProcessor->setValue('txt_agent_detail_evalB#'.$i.'', "test1 \n test2");
?>

Context

  • PHP version: 7
  • PHPWord version: 0.14

R-Benjamin avatar Mar 23 '18 17:03 R-Benjamin

+1

lon9man avatar Apr 20 '18 14:04 lon9man

Hi,

Any news about it ?

Thanks

R-Benjamin avatar Jun 01 '18 08:06 R-Benjamin

+1 Also the </w:t><w:br/><w:t> solution doesn't seem to work with \PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true); since the tags are escaped then.

maba4891 avatar Aug 31 '18 09:08 maba4891

+1

ozilion avatar Sep 12 '18 06:09 ozilion

+1, any news ?

Hydro8 avatar Sep 17 '18 07:09 Hydro8

Did anyone came up with a fix or workaround for this already?

maba4891 avatar Oct 15 '18 15:10 maba4891

Since I need this urgently I came up with a dirty workaround for this problem.

As I see it the exact problem is the following:

  1. I want to add newlines to stuff I add via TemplateProcessor (which works by adding </w:t><w:br/><w:t>).
  2. But I also want to use outputEscapingEnabled = true in phpword.ini so a simple & sign in the input doesn't break my word file.

Yet, output escaping uses htmlspecialchars and therefore also escapes and breaks the newlines.

I tried to fix this problem in Phpword/Escaper/Xml.php:

There I changed the function escapeSingleValue FROM:

    protected function escapeSingleValue($input)
    {
        // todo: omit encoding parameter after migration onto PHP 5.4
        return htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
    }

TO:

    protected function escapeSingleValue($input)
    {
        $escaped = htmlspecialchars($input, ENT_QUOTES, 'UTF-8');

        // we don't want to escape the newline code, so we replace it with html tag again
        $escaped_but_newlines_allowed = str_replace('&lt;/w:t&gt;&lt;w:br/&gt;&lt;w:t&gt;', '</w:t><w:br/><w:t>', $escaped);
        return $escaped_but_newlines_allowed;
    }

So after the input is escaped with htmlspecialchars I simply revert these changes for the newlines. Not very elegant but does the job for now.

maba4891 avatar Oct 26 '18 12:10 maba4891

Any news on this issue?

ghost avatar Mar 04 '19 15:03 ghost

I'm also interested by having a cleaner solution ! Some news ?

simogeo avatar Jun 12 '19 09:06 simogeo

Same issue Any news?

+1 Also the </w:t><w:br/><w:t> solution doesn't seem to work with \PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true); since the tags are escaped then.

xavenix avatar Jun 26 '19 13:06 xavenix

+1

victor-ponamariov avatar Dec 19 '19 12:12 victor-ponamariov

help please, +1

gautiermichelin avatar Apr 03 '20 09:04 gautiermichelin

+1

lyt8384 avatar Apr 17 '20 03:04 lyt8384

+1

ozilion avatar Apr 17 '20 07:04 ozilion

Here is my solution:

$templateProcessor->setValue('foo', 'Lorem.${newline}Ipsum....');

$new_line = new \PhpOffice\PhpWord\Element\PreserveText('</w:t><w:br/><w:t>');

$templateProcessor->setComplexValue('newline', $new_line);

I hope it helps.

damienlaguerre avatar Apr 29 '20 15:04 damienlaguerre

I added </w:t><w:p/><w:t> for a new paragraph and it is working well.

Here is the templatewords and printscreen of the word document:

${alternatif_block} Alternatif-${altId} ${alternatif} ${/alternatif_block}

image

Here is the codes:

		$replacements = array(
		    array('altId' => '1', 'alternatif' => 'Lorem </w:t><w:p/><w:t> ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
'),			   
		);		

		$templateProcessor->cloneBlock('alternatif_block', 0, true, false, $replacements);

And here is the printscreen of output:

image

mukiraz avatar Oct 17 '20 15:10 mukiraz

I added </w:t><w:p/><w:t> for a new paragraph and it is working well.

Here is the templatewords and printscreen of the word document:

${alternatif_block} Alternatif-${altId} ${alternatif} ${/alternatif_block}

image

Here is the codes:

		$replacements = array(
		    array('altId' => '1', 'alternatif' => 'Lorem </w:t><w:p/><w:t> ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
'),			   
		);		

		$templateProcessor->cloneBlock('alternatif_block', 0, true, false, $replacements);

And here is the printscreen of output:

image

But it works for only at first paragraph...

mukiraz avatar Oct 17 '20 16:10 mukiraz

Here is my solution:

$templateProcessor->setValue('foo', 'Lorem.${newline}Ipsum....');

$new_line = new \PhpOffice\PhpWord\Element\PreserveText('</w:t><w:br/><w:t>');

$templateProcessor->setComplexValue('newline', $new_line);

I hope it helps.

For you this code works in all breaks or for just the first?

Gadeoli avatar Feb 22 '21 17:02 Gadeoli

It replaces all ${newline} not only the first one.

damienlaguerre avatar Feb 22 '21 17:02 damienlaguerre

@damienlaguerre tks for the quickly reply. I'll look why for me replace just the first.

Gadeoli avatar Feb 22 '21 17:02 Gadeoli

Unless I'm missing something, it seems that TemplateProcessor::setComplexValue() (cf. https://github.com/PHPOffice/PHPWord/blob/0.18.2/src/PhpWord/TemplateProcessor.php#L267-L293) only replaces one (the first) occurrence whereas TemplateProcessor::setValue() replaces all occurrences.

However, this is not documented clearly in neither https://phpword.readthedocs.io/en/latest/templates-processing.html#setcomplexvalue nor https://phpword.readthedocs.io/en/latest/templates-processing.html#setvalue, and therefore it's not obvious if this is by design or a missing feature (or even a bug). @troosan, can you comment on this?

As a (temporary) workaround, I'm using something along the lines of

$newline = new PreserveText('</w:t><w:br/><w:t>');
while (isset($templateProcessor->getVariableCount()['newline'])) {
  $templateProcessor->setComplexValue('newline', $newline);
}

to replace ${newline} until all occurrences are replaced.

rimi-itk avatar Jan 03 '22 21:01 rimi-itk

https://github.com/PHPOffice/PHPWord/issues/2038 has been labeled “WontFix”.

rimi-itk avatar Jan 03 '22 21:01 rimi-itk

I'm not sure why the solution using setComplextValue with PreserveText doesn't work for me. I have to use cloneBlock to generate lines. Here is my solution:

  1. Update your template with a block definition:
${lines}
${line}
${/lines}
  1. Prepare an array of strings for replacement:
$replacements = [
    ['line' => 'line 1 text'],
    ['line' => 'line 2 text'],
    ...
];
  1. Invoke cloneBlock:
$templateProcessor->cloneBlock('lines', 0, true, false, $replacements);

zhouyixiang avatar May 06 '22 10:05 zhouyixiang

I'm not sure why the solution using setComplextValue with PreserveText doesn't work for me. I have to use cloneBlock to generate lines. Here is my solution:

  1. Update your template with a block definition:
${lines}
${line}
${/lines}
  1. Prepare an array of strings for replacement:
$replacements = [
    ['line' => 'line 1 text'],
    ['line' => 'line 2 text'],
    ...
];
  1. Invoke cloneBlock:
$templateProcessor->cloneBlock('lines', 0, true, false, $replacements);

+1 for me.

mredl avatar Feb 01 '23 08:02 mredl