PHPOffice / PHPWord

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

New line with templateProcessor #1322

Open R-Benjamin opened 6 years ago

R-Benjamin commented 6 years ago

This is:

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

lon9man commented 6 years ago

+1

R-Benjamin commented 6 years ago

Hi,

Any news about it ?

Thanks

maba4891 commented 6 years ago

+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.

ozilion commented 6 years ago

+1

Hydro8 commented 6 years ago

+1, any news ?

maba4891 commented 6 years ago

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

maba4891 commented 6 years ago

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.

ghost commented 5 years ago

Any news on this issue?

simogeo commented 5 years ago

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

xavenix commented 5 years ago

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.

victor-ponamariov commented 4 years ago

+1

gautiermichelin commented 4 years ago

help please, +1

lyt8384 commented 4 years ago

+1

ozilion commented 4 years ago

+1

damienlaguerre commented 4 years ago

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.

mukiraz commented 4 years ago

I added </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 commented 4 years ago

I added </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...

Gadeoli commented 3 years ago

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?

damienlaguerre commented 3 years ago

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

Gadeoli commented 3 years ago

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

rimi-itk commented 2 years ago

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 commented 2 years ago

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

zhouyixiang commented 2 years ago

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}
  2. Prepare an array of strings for replacement:
    $replacements = [
    ['line' => 'line 1 text'],
    ['line' => 'line 2 text'],
    ...
    ];
  3. Invoke cloneBlock:
    $templateProcessor->cloneBlock('lines', 0, true, false, $replacements);
mredl commented 1 year ago

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.