PHPWord icon indicating copy to clipboard operation
PHPWord copied to clipboard

addText() function and text formatting (new line "\n")

Open simogeo opened this issue 10 years ago • 27 comments

Hi,

I have a problem regarding formatting text. Actually, it seems, all \n are not interpreted when opening file with Word 2007. Here are some screenshots :

This is how it appears in LibreOffice : lo

And how it (sadly) appears in Word 2007 :

w2007

ANy help would be welcome ! I use last stable version - 0.12.0. Thanks !


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

simogeo avatar Jun 12 '15 14:06 simogeo

Hi,

you maybe misunderstood how phpword works.

addText is for adding a paragraph with text. The text is not seperated by line breaks. If you would like to add line breaks then use addTextRun.

With a textrun you can add text and textbreaks within one paragraph.

$text = "foo\nbar\nfoobar";
$textlines = explode("\n", $text);

$textrun = $section->addTextRun();
$textrun->addText(array_shift($textlines));
foreach($textlines as $line) {
    $textrun->addTextBreak();
    // maybe twice if you want to seperate the text
    // $textrun->addTextBreak(2);
    $textrun->addText($line);
}

RKaczmarek avatar Jun 17 '15 10:06 RKaczmarek

Thanks for your interest on that. But why not an optional parameter for commodity ? here is my proposed idea (not sure it works since it is not tested)

simogeo avatar Jun 17 '15 10:06 simogeo

How to apply this in the template? e.g.: $templateProcessor->setValue....

morrido avatar Sep 09 '15 01:09 morrido

I second morrido. How do you do it in a template?

cbloss avatar Oct 26 '15 19:10 cbloss

$text = "foo\nbar\nfoobar"; $textlines = explode("\n", $text);

$textrun = $section->addTextRun(); $textrun->addText(array_shift($textlines)); foreach($textlines as $line) { $textrun->addTextBreak(); // maybe twice if you want to seperate the text // $textrun->addTextBreak(2); $textrun->addText($line); }

This also works (I just used it) :

$text = "foo\nbar\nfoobar";
$textlines = explode("\n", $text);

for ($i = 0; $i < sizeof($textlines); $i++) {
    $section->addText($textlines[$i]);
}

Motchouk avatar Feb 10 '16 11:02 Motchouk

I, just like @morrido and @cbloss here, would like to know if this is usable in a template. Please answer. Thx in advance

feakuru avatar Dec 15 '16 13:12 feakuru

@feakuru @morrido @cbloss Looks for me like <w:br /> is interpreted as a newline in proper Word. In libreoffice it just looks like a space (was frustrating me).

so e.g.

$templateProcessor->setValue(name_address, 'John <w:br /> 123 fake street');

Dvlv avatar Jan 05 '17 15:01 Dvlv

I used "\n" and then the regex $text = preg_replace('~\R~u', '</w:t><w:br/><w:t>', $text);.

BafS avatar Feb 03 '17 22:02 BafS

Awesome @RKaczmarek, exactly what I needed. Thank you. The solution works for addListItemRuns as well as that is what I was using.

geigel avatar Oct 18 '17 00:10 geigel

@RKaczmarek & @BafS in my case: $text='aaa\nbbb' $text = preg_replace('~\R~u', '</w:t><w:br/><w:t>', $text); $templateProcessor->setValue('sp'.$i.'z1#'.$j,$text);

write in word: 'aaa\nbbb'

guenter47 avatar Nov 25 '17 16:11 guenter47

replace simple quotes by double quotes :

$text="aaa\nbbb"

simogeo avatar Nov 25 '17 17:11 simogeo

@feakuru @morrido @cbloss Looks for me like <w:br /> is interpreted as a newline in proper Word. In libreoffice it just looks like a space (was frustrating me).

so e.g.

$templateProcessor->setValue(name_address, 'John <w:br /> 123 fake street');

https://github.com/PHPOffice/PHPWord/issues/838

nacesprin avatar Jul 31 '19 09:07 nacesprin

@feakuru @morrido @cbloss Looks for me like <w:br /> is interpreted as a newline in proper Word. In libreoffice it just looks like a space (was frustrating me).

so e.g.

$templateProcessor->setValue(name_address, 'John <w:br /> 123 fake street');

As @BafS answered, add \n to the text you want to format, like this: $templateProcessor->setValue("value_to_change", "value\nthat _will_replace");

After that, go to your TemplateProcessor.php file and find the setValueForPart($ search, $ replace, $ documentPartXML, $ limit). In the first line of this function, add: $replace = preg_replace('~\R~u', '</w:t><w:br/><w:t>', $replace);

This worked perfectly for me in LibreOffice and Word. I hope this helps someone.

joaodos3v avatar Sep 09 '19 12:09 joaodos3v

Here's the true answer to "How to add newline while template processing"

You can't just replace \n with </w:t><w:br/><w:t> because that will BREAK PARAGRAPHS. This means that tab stops that have been set on the placeholder will not carry over to the next line!

The real solution is to always use a complex type instead of using strings.

So in my function instead of returning a string I do this:

            $res = "some text\n with\n newlines\tand\ttabs
            $textlines = explode("\n", $res);
            $textrun = new PhpOffice\PhpWord\Element\TextRun();
            $textrun->addText(array_shift($textlines));
            foreach ($textlines as $line) {
                $textrun->addTextBreak();
                $textrun->addText($line);
            }
            return $textrun;

and in the template processor driver I use:

$templateProcessor->setComplexValue($key, $textrun);

this will result in newlines and tab stops and other paragraph related things are preserved in the next lines!

This allows you to create basic tables with tab stops and not worry about them breaking after the new lines.

Francesco-Manicardi avatar Jan 10 '21 22:01 Francesco-Manicardi

setComplexValue($key, $textrun) throws an error when there are multiple lines. Apparently setComplexBlock($key, $textrun) should be used instead, but that deletes all the other text present in the same line.

jjdejong avatar Jan 13 '21 09:01 jjdejong

setComplexValue($key, $textrun) throws an error when there are multiple lines.

What is the error thrown? I'm using it in production right now and I'm not having any problems. Also, it looks like setComplexValue also deletes all other text in the same line.

Francesco-Manicardi avatar Jan 13 '21 09:01 Francesco-Manicardi

I get "Trying to access array offset on value of type bool" in line 277 of TemplateProcessor.php.

So if the "Value" flavor also deletes all other text, what's the difference between the "Value" and "Block" flavors ?

jjdejong avatar Jan 13 '21 09:01 jjdejong

I'll take that back, the "Value" flavor does work in most cases, but there is just one situation in my application where it throws the error. I need to find out still.

jjdejong avatar Jan 13 '21 09:01 jjdejong

That's the same error I have, but in PhpSpreadsheet instead. Let me know if you get to the root of it, i still haven't understood what causes it. My solutino was just putting everything in a try catch block and call it a day

Francesco-Manicardi avatar Jan 13 '21 09:01 Francesco-Manicardi

Also, it looks like setComplexValue also deletes all other text in the same line.

Are you sure ? Not in my case. That would be the difference between the Block and Value flavors.

jjdejong avatar Jan 13 '21 09:01 jjdejong

Yes, i have a .docx template like this: image

As you can see there's content to the right of the placeholder. when i call setComplexValue with a textRun, that text gets deleted this is the result of the setComplexValue image

Francesco-Manicardi avatar Jan 13 '21 09:01 Francesco-Manicardi

As you can see there's content to the right of the placeholder. when i call setComplexValue with a textRun, that text gets deleted this is the result of the setComplexValue

Ah, in my case it's text on the left that is preserved.

jjdejong avatar Jan 13 '21 09:01 jjdejong

That's the same error I have, but in PhpSpreadsheet instead. Let me know if you get to the root of it, i still haven't understood what causes it. My solution was just putting everything in a try catch block and call it a day

This happens when the ${macro} is not present in the template. Maybe a bug, because this should not generate an error.

jjdejong avatar Jan 13 '21 09:01 jjdejong

@jjdejong @Pocciox what versions of PHP are you using?

geigel avatar Jan 13 '21 12:01 geigel

I am using version 7.4 :)

Il mer 13 gen 2021, 13:22 Art Geigel [email protected] ha scritto:

@jjdejong https://github.com/jjdejong @Pocciox https://github.com/Pocciox what versions of PHP are you using?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/PHPOffice/PHPWord/issues/553#issuecomment-759413944, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHXWIFVLYIQIUYW6PVF3AWDSZWGBTANCNFSM4BIEI6LA .

Francesco-Manicardi avatar Jan 13 '21 12:01 Francesco-Manicardi

7.4 too

jjdejong avatar Jan 13 '21 12:01 jjdejong

I'm on 7.4 too. I agree with @jjdejong , in my case the text on the left is well preserved when I use setComplexValue instead of setComplexBlock (this last one deletes all the content which already exists in the paragraph where the macro is applied).

damienfa avatar Sep 26 '21 01:09 damienfa