0

I have a PHP application that is meant to merge user data with a DOCX word document, I am using phpoffice/phpword library for this task. The issue is that some variables are irregularly replaced while most of the variables are simply not replaced at all. The variables I am replacing with do not contain special characters, no symbols, etc. just basic letters and numbers.

Template Document

.. contract between our company and propertyname with offices at address1, address2, postalcode cityname, countryname ("Customer").

Code - Option1: Replace placeholder via setValue as recommended in the official documentation.

// template file
$file = '../../public/formats/contracts/'.$filename;

$phpword = new \PhpOffice\PhpWord\TemplateProcessor($file);

$phpword->setValue('propertyname', $hotel_name);
$phpword->setValue('address1', $street_1);
$phpword->setValue('address2', $street_2);
$phpword->setValue('postalcode', $zip_code);
$phpword->setValue('cityname', $city);
$phpword->setValue('countryname', $country);

$phpword->saveAs('../../public/formats/generated/'.$created_at.'_'.$filename);

Result: no placeholder variables get replaced. Tried to rename the placeholders (Eg. ${address1} or %%ADDRESS_1%% or address_1) but not result.

Code - Option 2: Replace placeholders all in one go via setValues array

// template file
$file = '../../public/formats/contracts/'.$filename;

$phpword = new \PhpOffice\PhpWord\TemplateProcessor($file);

$phpword->setValues(array('propertyname' => $hotel_name, 'address1' => $street_1, 'address2' => $street_2, 'postalcode' => $zip_code, 'cityname' => $city, 'countryname' => $country));

$phpword->saveAs('../../public/formats/generated/'.$created_at.'_'.$filename);

Result: no placeholder variables get replaced.

Many users complained about the same issue and ultimately had limited success by utilising the phpWord ZipArchive function documented here (5 years old).

Code - Option 3: Unzip docx file, open document.xml and replace strings there directly

// Creating the new document...
$zip = new \PhpOffice\PhpWord\Shared\ZipArchive();

$document_xml = 'word/document.xml';                                        // docx content file
$template = '../../public/formats/contracts/'.$filename;                        // template file
$new_file = '../../public/formats/generated/'.$created_at.'_'.$filename;    // new file after merge
// create copy of template in temporary folder
copy($template, $new_file);

if ($zip->open($new_file) === TRUE) {
    $content = $zip->getFromName($document_xml);                            // Read contents into memory
    $content = str_replace('propertyname', $hotel_name, $content);          // property name
    $content = str_replace('address1', $street_1, $content);                // address 1
    $content = str_replace('address1', $street_2, $content);                // address 2

    $zip->addFromString($document_xml, $content);                           // replace content
    $return = $zip->close();                                                // write changes to filesystem.
    if ($return == TRUE) {
        $result_arr[] = array('status' => 'success', 'response' => 'Format successfully merged', 'filename' => $created_at . '_' . $filename);
    }
}

Result: replaces some variables irregularly. Variable propertyname gets replaced only when the placeholder is propertyname but not if property_name. Variable address1 (value: "Streetname 123") never got replaced no matter the placeholder spelling, but variable address2 (value: "Some District") gets replaced all the time.

Bottom Line:

I made sure to use the latest version of phpWord, I am running PHP 8.0.2 and Apache2 on a Ubuntu 20.04 LTS machine. There seems to be no consistency for the replacement issue, it occurs irregularly and replaces some variables some time.

If anyone has any suggestions on what could be the culprit here, I much appreciate any help. Otherwise, I spent way too much time on this and am happy to look at alternative packages that can do the trick.

Thank you

Armitage2k
  • 1,164
  • 2
  • 27
  • 59
  • Any place to get your file for testing purpose ? I do have an open source library that actually using PhpWord/PhpSpreadsheet to helps in replacing the variable in document template. You can test your file there thru the demo site first: [PhpOfficeTemplate](https://demo.rightpristine.com/xiang/PhpOfficeTemplate/demo/). If my lib resolve your issue, feel free to explore my coding in the src/PhpWordTemplate.php. It is open source, happy coding ! – Zeikman Feb 03 '23 at 12:57

1 Answers1

0

When I create a new document, and type the 2 texts Test1 and Test2, and look at the "document.xml" (when opening the document using something like 7zip manager)

I do see this part:

<w:p w:rsidR="007F7B9F" w:rsidRDefault="0012064F">
  <w:r>
    <w:t>Test1</w:t>
  </w:r>
</w:p>
<w:p w:rsidR="0012064F" w:rsidRDefault="0012064F">
  <w:r>
    <w:t>Test2</w:t>
  </w:r>
</w:p>

When you re-open the document using Word, and change Test2 to TEst2, the document.xml looks like this:

<w:p w:rsidR="007F7B9F" w:rsidRDefault="0012064F">
  <w:r>
    <w:t>Test1</w:t>
  </w:r>
</w:p>
<w:p w:rsidR="0012064F" w:rsidRDefault="0012064F">
  <w:r>
    <w:t>T</w:t>
  </w:r>
  <w:r w:rsidR="00271840">
    <w:t>E</w:t>
  </w:r>
  <w:bookmarkStart w:id="0" w:name="_GoBack"/>
  <w:bookmarkEnd w:id="0"/>
  <w:r>
    <w:t>st2</w:t>
  </w:r>
</w:p>

It would be very hard to find TEst2 if we are just looking at the "document.xml" from the compressed document.

NOTE: I do not know, and have not looked at, phpword to check how that product deals with above problem.

Luuk
  • 12,245
  • 5
  • 22
  • 33
  • I understand the sentiment, but that is why options #1 and #2 exist, as they handle the replacement while the template file is processed as opposed to manually editing the xml. The question is, why are options #1 and #2 not working? – Armitage2k Mar 13 '22 at 09:34