11

我有一个 docx 文件,我需要替换一些文本。这是在 codeigniter 框架内完成的;这是代码:

$this->load->library('word');       
$template = $this->word->loadTemplate($_SERVER['DOCUMENT_ROOT'].'/doc/assets/doc3.docx');
$template->setValue('replacename', 'new');
$template->save($_SERVER['DOCUMENT_ROOT'].'/doc/assets/helloWorld.docx');

当我打开新文件时,我仍然得到“replacename”而不是“new”。"replacename" 格式为 Verdana 字体,9pt 字体大小(无下划线或粗体)。为什么它不起作用?从 setValue 函数(和 doc 文件)中删除 ${ } 它可以工作

4

7 回答 7

7

事实证明,当您将文本添加到 word 文件时,有时会在底层 xml 文件中创建额外的标签。所以(伪代码)${NAME}可以变成<tag1>${</tag1><tag2>NAME</tag2><tag3>}</tag3>

正因为如此,phpword 找不到你的针。

我正在使用带有 microsoft word 的 mac,我可以剪切 word 文件的所有内容并再次粘贴它们。

Word 将重新创建 ${NAME} 是 1 个标签而不是 3 个标签的基础 xml 文件。

于 2015-02-22T14:09:11.967 回答
5

我在http://phpword.codeplex.com/workitem/57中找到了解决方案……问题似乎出在 word 生成自己的代码时。

对于解决方案,只需将您的模板的扩展名重命名为 zip,将名为“document.xml”的文件签入“word”文件夹,然后搜索您的代码值......它应该是这样的:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 wp14">
    <w:body>
        <w:p w:rsidR="00AC49DC" w:rsidRDefault="00243DD6">
            <w:r>
                <w:t>${test1}</w:t>
            </w:r>
        </w:p>
        <w:p w:rsidR="00243DD6" w:rsidRDefault="00243DD6">
            <w:r>
                <w:t>${test2}</w:t>
            </w:r>
        </w:p>
        <w:p w:rsidR="00243DD6" w:rsidRDefault="00243DD6">
            <w:r>
                <w:t>${test3}</w:t>
            </w:r>
        </w:p>
        <w:p w:rsidR="00243DD6" w:rsidRDefault="00243DD6">
            <w:r>
                <w:t>${test4}</w:t>
            </w:r>
        </w:p>
        <w:p w:rsidR="00243DD6" w:rsidRDefault="00243DD6">
            <w:r>
                <w:t>${</w:t>
            </w:r>
            <w:bookmarkStart w:id="0" w:name="_GoBack"/>
            <w:bookmarkEnd w:id="0"/>
            <w:r>
                <w:t>test5}</w:t>
            </w:r>
        </w:p>
        <w:sectPr w:rsidR="00243DD6" w:rsidSect="00C107D0">
            <w:pgSz w:w="12240" w:h="15840" w:code="1"/>
            <w:pgMar w:top="907" w:right="907" w:bottom="907" w:left="907" w:header="720" w:footer="720" w:gutter="0"/>
            <w:cols w:space="720"/>
            <w:docGrid w:linePitch="272"/>
        </w:sectPr>
    </w:body>
</w:document>
于 2014-01-30T16:29:06.990 回答
4

只需将 2 个函数添加到文件“TemplateProcessor.php”

public  function setValueAdvanced($search_replace)
    {
        foreach ($this->tempDocumentHeaders as $index => $headerXML) {
            $this->tempDocumentHeaders[$index] = $this->setValueForPartAdvanced($this->tempDocumentHeaders[$index], $search_replace);
        }

        $this->tempDocumentMainPart = $this->setValueForPartAdvanced($this->tempDocumentMainPart, $search_replace);

        foreach ($this->tempDocumentFooters as $index => $headerXML) {
            $this->tempDocumentFooters[$index] = $this->setValueForPartAdvanced($this->tempDocumentFooters[$index], $search_replace);
        }
    }
protected  function setValueForPartAdvanced($documentPartXML, $search_replace)
    {
        $pattern = '/<w:t>(.*?)<\/w:t>/';
        $rplStringBeginOffcetsStack = array();
        $rplStringEndOffcetsStack = array();
        $rplCleanedStrings = array();
        $stringsToClean = array();
        preg_match_all($pattern, $documentPartXML, $words, PREG_OFFSET_CAPTURE);

        $bux_founded = false;
        $searching_started = false;
        foreach($words[1] as $key_of_words => $word)
        {
            $exploded_chars = str_split($word[0]);
            foreach($exploded_chars as $key_of_chars => $char)
            {
                if ($bux_founded)
                {
                    if ($searching_started)
                    {
                        if ($char == "}")
                        {
                            $bux_founded = false;
                            $searching_started = false;
                            array_push($rplStringEndOffcetsStack, ($word[1]+mb_strlen($word[0])+6));
                        }
                    }
                    else
                    {
                        if ($char == "{")
                        {
                            $searching_started = true;
                        }
                        else
                        {
                            $bux_founded = false;
                            array_pop($rplStringBeginOffcetsStack);
                        }
                    }
                }
                else
                {
                    if ($char == "$")
                    {
                        $bux_founded = true;
                        array_push($rplStringBeginOffcetsStack, $word[1]-5);
                    }
                }
            }
        }
        for($index=0; $index<count($rplStringEndOffcetsStack); $index++)
        {
            $string_to_clean = substr($documentPartXML, $rplStringBeginOffcetsStack[$index], ($rplStringEndOffcetsStack[$index]-$rplStringBeginOffcetsStack[$index]));
            array_push($stringsToClean, $string_to_clean);
            preg_match_all($pattern, $string_to_clean, $words_to_concat);
            $cleaned_string = implode("", $words_to_concat[1]);
            $cleaned_string = preg_replace('/[${}]+/', '', $cleaned_string);
            array_push($rplCleanedStrings, $cleaned_string);
        }
        for ($index=0; $index<count($rplCleanedStrings); $index++)
        {
            foreach($search_replace as $key_search => $replace)
            {
                if ($rplCleanedStrings[$index] == $key_search)
                {
                    $documentPartXML = str_replace($stringsToClean[$index], "<w:t>".$replace."</w:t>", $documentPartXML);
                    break;
                }
            }
        }
        return $documentPartXML;
    }

如何使用:使用数组作为函数“setValueAdvanced”的唯一参数,其中“key” - 我们要替换的单词,“value” - 我们要粘贴的短语。重要提示:在 MS Word 文件中,使用“${word_to_replace}”来“标记”我们要替换的单词,但数组的键应该是“word_to_replace”,没有“${}”

示例代码:

require_once 'PhpWord/Autoloader.php';

use PhpOffice\PhpWord\Autoloader;
use PhpOffice\PhpWord\Settings;

define('CLI', (PHP_SAPI == 'cli') ? true : false);
define('EOL', CLI ? PHP_EOL : '<br />');
define('SCRIPT_FILENAME', basename($_SERVER['SCRIPT_FILENAME'], '.php'));
define('IS_INDEX', SCRIPT_FILENAME == 'index');

Autoloader::register();
Settings::loadConfig();

$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('your_file_name.docx');
$search_replace_array = array(
    'msword_hello'=>'Hello', #inside a MS Word file ${msword_hello} will change to Hello
    'msword_world'=>'World' #${msword_world} will change to World
);
$templateProcessor->setValueAdvanced($search_replace_array);


$templateProcessor->saveAs('your_file_name_changed.docx');
于 2016-04-18T17:53:44.443 回答
2

您可以使用带有新方法 setValue() 的新模板类

<w:p w:rsidR="00243DD6" w:rsidRDefault="00243DD6">
        <w:r>
            <w:t>{</w:t>
        </w:r>
        <w:bookmarkStart w:id="0" w:name="_GoBack"/>
        <w:bookmarkEnd w:id="0"/>
        <w:r>
            <w:t>test5}</w:t>
        </w:r>
    </w:p>

新方法可以替换它 setValue('test5', 'MyValue');

下载新课程:https ://github.com/Arisse/PHPWord_CloneRow

于 2014-02-13T09:53:16.870 回答
2

在这里我努力工作,

setValue 函数不起作用,因为它包含生成到 web 后的 word 格式。因此找不到您可能替换的文本。

解决方案只需将您​​的 ${replaceKey} 输入到记事本并将其复制到 your_template.docx 它对我有用。

记事本使模板中不包含所有单词格式,因此函数 setValue 可以按预期找到它。

希望对大家有所帮助。

于 2017-01-24T10:09:37.037 回答
1

我的解决方案

function replaceText($element, $variable, $value) {
$text_class = 'PhpOffice\PhpWord\Element\Text';
$table_class = 'PhpOffice\PhpWord\Element\Table';
foreach ($element as $e) {
    if (get_class($e) !== $text_class && method_exists($e, 'getElements')) {
        replaceText($e->getElements(), $variable, $value);
    } elseif (get_class($e) === $text_class && ($match_count = substr_count($e->getText(), $variable))) {
        for ($i = 1; $i <= $match_count; $i++) {
            $e->setText(str_replace($variable, $value, $e->getText()));
        }
    } elseif (get_class($e) === $table_class && ($row_count = count($e->getRows()))) {
        foreach ($e->getRows() as $row) {
            foreach ($row->getCells() as $cell) {
                replaceText($cell->getElements(), $variable, $value);
            }
        }
    }
}

}

$path = public_path('test.docx'); // Path to template document. public_path() Laravel function
$objReader = \PhpOffice\PhpWord\IOFactory::createReader('Word2007'); // Here can be 'ODText' = .odt, 'Word2007' = .docx etc.
$docx = $objReader->load($path);
replaceText($docx->getSections(), '${text}', 'This will be in your document'); // '${text}' can be any text like 'Simple text'
$docx->save('test2.docx');
于 2018-01-12T12:21:29.530 回答
0

我从模板创建了一个循环模板,在该模板中填写了所需的 $ {Value} 值。我将结果合并并保存为新模板。所以它接受了贵重物品

于 2017-09-17T10:58:43.793 回答