Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing Color of text in setValue() #1448

Open
pandora-iuz opened this issue Aug 9, 2018 · 7 comments
Open

Changing Color of text in setValue() #1448

pandora-iuz opened this issue Aug 9, 2018 · 7 comments

Comments

@pandora-iuz
Copy link

pandora-iuz commented Aug 9, 2018

This is:

I am a Chinese PHP development engineer.

I do the word scan software. I want to have some wrong words or sentences in the word file. Add the background color.

What shall I do?

I'd like to change the following way, but I don't know how to change it.

$document ->setValue('rowValue', 'Sun', array("color"=>"0000ff", "bgColor" => "fbbb10"));

Ask the expert to give a suggestion.

This question has been asked by codeplex in the past

image

@icy2003
Copy link

icy2003 commented Jan 30, 2019

TemplateProcessor only change simple line, if you open docx by zip software, you'll find a file named "document.xml" contains all the structure in it. I mean , if you tried open it, you will know this kind of "setValue" function is not possible exists...except using regular expression

@pandora-iuz
Copy link
Author

pandora-iuz commented Jan 30, 2019

Thank you very much

I have already done it with regular, but the effect is not very good.

  1. the overall effect is good < w:t>Hello Word</w:t >
  2. this situation will not work < w:t>Hello</w:t> <w:t>Word</w:t >

Who can optimize this regularity or have a better plan?

My current plan:

`<?php

namespace PhpOffice\PhpWord;

class Template extends TemplateProcessor
{
public $tempDocumentMainPart;

public function __construct($documentTemplate)
{
    parent::__construct($documentTemplate);
}

static $wordArr;
static $color = 'yellow';

/**
 * 多个词替换目前替换背景色功能兼容性交互,但是性能较差
 *
 * @param $word
 * @param $color
 * @example {
 *  $template = new \PhpOffice\PhpWord\Template($path);
 *  $template->setWordBgColor($txt, 'yellow');
 * }
 */
public function setWordArrBgColor($word, $color)
{
    self::$wordArr = array_unique($word);
    if (!empty(self::$wordArr)) {

        self::$color  = $color;

        if ($this->tempDocumentHeaders) $this->tempDocumentHeaders = $this->_replace($this->tempDocumentHeaders);
        if ($this->tempDocumentMainPart) $this->tempDocumentMainPart = $this->_replace($this->tempDocumentMainPart);
        if ($this->tempDocumentFooters) $this->tempDocumentFooters = $this->_replace($this->tempDocumentFooters);
    }
}

private function _replace($content) {

    return preg_replace_callback(
        '/<w:r\b([^>]*)>((?:(?!<\w:r>)[\s\S])*)<w:t[^>]*>((?:(?!<\/w:r>)[\s\S])*)<\/w:t><\/w:r[^>]*>/iUs',
        function ($matches) {
            //print_r($matches);

            if (!empty(trim($matches[3]))) {

                $text = $matches[3];

                foreach (self::$wordArr AS $value) {

                    // 判断关键词在字符串中是否存在
                    if (false !== strpos($text, $value)) {

                        if (trim($text) == $value) {
                            $matches[0] = str_ireplace('</w:rPr>', '<w:highlight w:val="'.self::$color.'"/></w:rPr>', $matches[0]);
                        } else {

                            // 背景色属性
                            $bgAttr = empty($matches[2])
                                ? '<w:rPr><w:highlight w:val="'.self::$color.'"/></w:rPr>'
                                : str_ireplace('</w:rPr>', '<w:highlight w:val="'.self::$color.'"/></w:rPr>', $matches[2]);

                            $matches[0] = str_ireplace($value,
                                '</w:t></w:r><w:r'.$matches[1].'>'.$bgAttr.'<w:t>'.$value.'</w:t></w:r><w:r'.$matches[1].'>'.$matches[2].'<w:t>',
                                $matches[0]);
                            $matches[0] = preg_replace('/<w:r\b[^>]*>(?:(?!<\w:t>)[\s\S])*<w:t[^>]*><\/w:t><\/w:r[^>]*>/iUs', '', $matches[0]);
                        }
                    }
                }

            }

            return $matches[0];
        },
        $content);
}

}`

@icy2003
Copy link

icy2003 commented Jan 30, 2019

@Allen-Yufeng you can try “Simple HTML DOM Parser” to extract xml, come here to find the document translated by me......
ok, I'm chinese too....funny.thx for your solution(if you have better answer, show others,thx)
I'm a writer not programmer,I'm a writer not programmer,I'm a writer not programmer
Important things are to be repeated for 3 times

@troosan
Copy link
Contributor

troosan commented Jan 30, 2019

I'm currently working on a method to allow replacing a ${macro} with for instance a TextRun, which can contain formatting. Like this

$title = new TextRun();
$title->addText('This title has been set ', array('bold' => true, 'italic' => true, 'color' => 'blue'));
$title->addText('dynamically', array('bold' => true, 'italic' => true, 'color' => 'red', 'underline' => 'single'));
$templateProcessor->setComplexBlock('title', $title);

@icy2003
Copy link

icy2003 commented Feb 1, 2019

I'm currently working on a method to allow replacing a ${macro} with for instance a TextRun, which can contain formatting. Like this

$title = new TextRun();
$title->addText('This title has been set ', array('bold' => true, 'italic' => true, 'color' => 'blue'));
$title->addText('dynamically', array('bold' => true, 'italic' => true, 'color' => 'red', 'underline' => 'single'));
$templateProcessor->setComplexBlock('title', $title);

@troosan that's amazing and when can I see this new characteristic, just give me a probable time, I am looking forward to it

@troosan
Copy link
Contributor

troosan commented Feb 2, 2019

Pull request is ready !
You can have a look already, I'll soon merge it in the develop branch
here it is: #1565

If you have any remarks, they're welcome

@jay-knight
Copy link

jay-knight commented Nov 20, 2020

This is useful, but would it be possible to allow a complex type/AbstractElement to be passed to setValue/setValues/cloneRowAndSetValues, and those methods decide how to handle it based on what gets passed in? My use case would look something like this ($items is a Laravel Collection in this example, the map() method returns the array of arrays that cloneRowAndSetValues expects):

$missing = new TextRun();
$missing->addText('Missing Value', array('color' => 'red'));
$templateProcessor->cloneRowAndSetValues("first_value", $items->values()->map(function($item) use ($missing) {
    return [
        "first_value" => $item->first_value ?? $missing,
        "second_value" => $item->second_value ?? $missing,
        "third_value" => $item->third_value ?? $missing,
    ];
}));

Then TemplateProcessor could determine how to replace the placeholder based on the type of what gets passed in. That would sure make for simpler code, and I'm not even sure I could do this within cloned table rows the way thing work right now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants