reuse template in the same document [PHPword]

2019-08-11 05:35发布

问题:

I am using PHPWord as a library in My Codeigniter Project. In my project, I want to generate a .docx file that uses a template which is already working. In that template is a Sticker that will be filled up by querying the data from the database. Since I want to generate multiple stickers in one document, I have to copy the first template that I have already used and add a pagebreak. But it is not working. I can't open the document. It says, "problem with its content".

I have here my working the sample template:

And this is my code:

public function Export(){ 

    $this->load->library('PHPWord');
    $this->load->model('person_model');

    $PHPWord = new PHPWord();
    $section = $PHPWord->createSection();

    $persons= $this->person_model->DataSticker();

    $document = $PHPWord->loadTemplate('application/controllers/Sticker.docx');
    $counter=1;
    foreach($persons as $row){ 
        $this->Doc($document,$counter,$row);
        $counter+=1;
        if($counter>6){
            $counter=1;
            $section->addObject($document); 
            $section->addPageBreak();
            $document = $PHPWord->loadTemplate('application/controllers/Sticker.docx');
            $this->Doc($document,$counter,$row);
        }

    }  



     // Save File
    $objWriter = PHPWord_IOFactory::createWriter($PHPWord, 'Word2007');
    $filename = 'nameOfFile.docx';
    $objWriter->save( $filename);;
    header('Content-Description: File Transfer');
    header('Content-type: application/force-download');
    header('Content-Disposition: attachment; filename='.basename($filename));
    header('Content-Transfer-Encoding: binary');
    header('Content-Length: '.filesize($filename));
    readfile($filename);
    unlink($filename);




}
public function Doc($document,$counter,$row){
     $document->setValue('Fname'.$counter, $row->fname);
        $document->setValue('Mname'.$counter, $row->mname);
        $document->setValue('Lname'.$counter, $row->lname);
        $document->setValue('DOB'.$counter, $row->dob);
        $document->setValue('POB'.$counter,$row->pob);
        $document->setValue('Age'.$counter, $row->age);
        $document->setValue('School'.$counter, $row->school); 

}

Your help will be highly appreciated.

回答1:

This answer is related to 0.12.0 version (probably applies as well to 0.13.0 as well)... You might be using some older version as you are using the deprecated loadTemplate function.

To answer you latest question, I don't think that you can use the templates with the addObject (ok, not 100% sure about it, but quote certain). But a working approach would be to use single template file where you have one page template of your stickers defined (including your pagebreak) and wrapped around with template block tags, i.e:

${CLONEBLOCK}
Here is your sticker page definition (6 stickers + pagebreak)...
${/CLONEBLOCK}

And then in your code you would just clone this block as many times as needed:

// the class path is probably something different with your codeigniter
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('application/controllers/Sticker.docx');    
$templateProcessor->cloneBlock('CLONEBLOCK', count($persons)/6);

And you would assign your template values quite similarly:

   // note! add the limit 1 as the third parameter (otherwise it will
   // write the this value on all of the pages)
   $templateProcessor->setValue('Mname'.$counter,  $row->mname, 1);


回答2:

I know this is an old question but I was looking for a similar answer and found the missing link to make this answer work, so I wanted to share it with you.

The answer by ejuhjav is in principle correct, but with the current version as of today (v0.16.0) this will work.

In your word template, you have the following code block:

${CLONEME}
1.  ${Title}
${/CLONEME}

(the "title" being formatted as a numbered heading)

Now you want to dynamically insert x headings for example, right? So what you do is simple. You clone the block x times and then you set the value for each iteration. The error which was made in other answers is that the setValue method works as a simple search and replace. So basically you always look to replace the first ${Title} placeholder it finds and move onto the next one - but you have to make sure that the search and replace is limited to the first finding like this:

$templateProcessor->setValue('Title',  "Testtitel 1", 1);

Which will then basically iterate through each cloned heading.

This works perfectly, of course this is not done dynamically for dummy reasons:

// Template processor instance creation
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('Sample_23_TemplateBlock.docx');
$templateProcessor->cloneBlock('CLONEME', 3);
$templateProcessor->setValue('Title',  "Testtitel 1", 1);
$templateProcessor->setValue('Title',  "Testtitel 2", 1);
$templateProcessor->setValue('Title',  "Testtitel 3", 1);
$templateProcessor->saveAs('ClonedHeadings.docx');

I hope it helps someone in future.

Andreas