Forum


Replies: 6   Views: 713
Using cloneblock to clone elements
Topic closed:
Please note this is an old forum thread. Information in this post may be out-to-date and/or erroneous.
Every phpdocx version includes new features and improvements. Previously unsupported features may have been added to newer releases, or past issues may have been corrected.
We encourage you to download the current phpdocx version and check the Documentation available.

Posted by philip0908  · 10-05-2022 - 00:06

I am trying for hours now but I can't get it to work. I am using my own wrapper class called "MSWord". What am I missing? Replacing template variables works, so there is no error with synchronization between the wrapper class and phpdocx. The content in the BLOCK in the word document is a row from a table - if that makes any difference.

class MSWord {

  private $framework_object = false;

  private $path = "ready_to_download";
  private $targets = array('header', 'document', 'footer', 'footnote', 'footnotes', 'endnote', 'endnotes', 'comment', 'comments');

  public function __construct($path_to_template_file = false) {
        
    require_once(K :: gI('K')->getPhitPath()."features/phpdocx/classes/CreateDocx.php");
    error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); // In case phpdocx turned it on
            
      if ($path_to_template_file) {

        $this->framework_object = new CreateDocxFromTemplate($path_to_template_file);
        $this->framework_object->setTemplateSymbol('${', '}');

      }

  }

  public function getTemplateVariablesNew() {

    return $this->framework_object->getTemplateVariables();

  }

  public function replaceTemplateVariables($replacement_variables) {

     $options = array('parseLineBreaks' => true, "type" => "inline");

    foreach ($this->targets as $target) {

      $options['target'] = $target;
      $this->framework_object->replaceVariableByText($replacement_variables, $options);

    }

  }

  public function cloneBlock($block_name, $copies, $replacement_variables = false, $settings = false) {

    $this->framework_object->cloneBlock($block_name, $copies);        

  }

  public function saveFinalDocument($path_to_new_document) {

    $this->framework_object->createDocx($path_to_new_document);

  }

}

And I try to call it like this:

 

$word_object = new MSWord($path_to_submission_file);


// Clone blocks
$word_object->cloneBlock("CONTACT_PERSONS", 5);

// Save new document
$word_object->saveFinalDocument($submission_templates_path."/ready_to_download/".uniqid());

Word doc looks like this:

${BLOCK_CONTACT_PERSONS}
- ${contact_person_name}        
- ${contact_person_email}       
- ${contact_person_phone}
${BLOCK_CONTACT_PERSONS}

 

Posted by admin  · 10-05-2022 - 05:40

Hello,

Please note that the second parameter in the cloneBlock method is the following:

occurrence      Position of the block to be cloned. 1 as default.

that is the occurrence of the placeholder to be cloned, not the number of times to be cloned.

When your code does:

$word_object->cloneBlock("CONTACT_PERSONS", 5);

it tries to clone the fifth position of the block CONTACT_PERSONS in the document.

Also note that cloneBlock works with elements in the same level (sibling elements between the block placeholders). You can't use cloneBlock with the first block placeholder added in a row in a table and the end block placeholder added in another row; they must be added as siblings of the same parent. If this is your case, you need to use the cloneWordContent method included in DOCXPath.

If you send your DOCX to contact[at]phpdocx.com we can generate a sample script.

Regards.

Posted by philip0908  · 10-05-2022 - 06:14

Admin - Thank you very much, that was helpful and I just sent an email with a sample document to use the cloneWordContent-method. Now I need to find out how to use the cloneWordContent-Method to clone the row of a table and replace the contained template variables with new values that I provide via an Array - just as I would do with cloneBlock-method. Is that possible?

Best, Philip

Posted by admin  · 10-05-2022 - 07:22

Hello,

You can use the cloneBlock method with your document but it will clone the sibling elements between the block placeholders (the table in your document):

$docx = new CreateDocxFromTemplate('sample.docx');
$docx->setTemplateSymbol('${', '}');

$docx->cloneBlock('CONTACT_PERSONS');

$docx->createDocx('output');

If you only want to clone a specific row, then you need to use the cloneWordContent method:

$docx = new CreateDocxFromTemplate('sample.docx');
$docx->setTemplateSymbol('${', '}');

$referenceToBeCloned = array(
    'customQuery' => '//w:tbl/w:tr[contains(., "${contact_person_name}")]',
);
$docx->cloneWordContent($referenceToBeCloned, $referenceToBeCloned);

$docx->createDocx('output');

cloneWordContent uses XPath internally. This sample code gets the row based on a specific content, but any XPath query can be used.

Also please note that to fill a table that contains placeholders, the recommended method is replaceTableVariable (https://www.phpdocx.com/api-documentation/templates/replace-table-variable-Word-document):

$docx = new CreateDocxFromTemplate('sample.docx');
$docx->setTemplateSymbol('${', '}');

$data = array(
    array(
        'contact_person_name' => 'Name A',
        'contact_person_email' => 'email1@email.com',
        'contact_person_mobile' => '000001',
    ),
    array(
        'contact_person_name' => 'Name B',
        'contact_person_email' => 'email2@email.com',
        'contact_person_mobile' => '000002',
    ),
);

$docx->replaceTableVariable($data, array('parseLineBreaks' => true));

$docx->createDocx('output');

If needed you can use replaceTableVariable adding new placeholders instead of values so you can do any other tasks.

Please check and test all previous samples so you can choose the one that best suits your needs.

Regards.

Posted by philip0908  · 10-05-2022 - 16:08

Thank you very much for that in depth answer. The service is phenomenal! Will try it now.

Posted by philip0908  · 10-05-2022 - 16:17

Looks like I don't even need to clone the word content. Using replaceTableVariable with an Array clones the content already. Is that intended?

$data = array(
  array(
   'contact_person_name' => 'Name A',
   'contact_person_email' => 'email1@email.com',
   'contact_person_mobile' => '000001',
  ),
  array(
   'contact_person_name' => 'Name B',
   'contact_person_email' => 'email2@email.com',
   'contact_person_mobile' => '000002',
  ),
);
                                                
$word_object->getFrameworkObject()->replaceTableVariable($data, array('parseLineBreaks' => true));

 

Posted by admin  · 10-05-2022 - 18:48

Hello,

The replaceTableVariable method fills a table replacing the placeholders (adding a new row for each array content cloning the table row). Please check the documentation available on the API documentation page (https://www.phpdocx.com/api-documentation/templates/replace-table-variable-Word-document) and the included samples that detail everything about this method.
The goal of this method (replaceTableVariable) is the following: Replaces a group of variables within a set of table rows. On the practical guide (https://www.phpdocx.com/documentation/practical/adding-content-to-a-template) you can also read about this method and a first sample:

Just like with the lists, you can add tables to the template by making a table with the styles that you want and define a row with the variables to replace. This row will be replaced for as many rows as needed with new values, keeping the original table styles.

cloneBlock allows cloning multiple contents and cloneWordContent allows cloning specific contents based on XPath queries. For your DOCX and table, replaceTableVariable is the recommended method.

Regards.