How to add / install images on a template PHPOffice / PHPWord?

I have an instance of a template in PHPWord. Can I replace or add an image? Something like setImageValue?

$phpWord = new \PhpOffice\PhpWord\Template('a.docx'); $phpWord->setImageValue('IMAGE_PLACEHOLDER', 'a.jpg'); $phpWord->saveAs('b.docx'); 

Is this possible?

+7
php phpword
source share
6 answers

The following code is an updated version of one of TotPeRo (thanks again for your code!), For the latest phpOffice (0.11), which has developed

 /** * Set a new image * * @param string $search * @param string $replace */ public function setImageValue($search, $replace) { // Sanity check if (!file_exists($replace)) { return; } // Delete current image $this->zipClass->deleteName('word/media/' . $search); // Add a new one $this->zipClass->addFile($replace, 'word/media/' . $search); } 

You can call with:

 $document->setImageValue('image1.jpg', 'my_image.jpg'); 
+7
source share

its quite a lot of unverified. but this works for me (although mine is a little different):

add the following function to PHPWord/Template.php :

  public function save_image($id,$filepath,&$document=null) { if(file_exists($filepath)) { $this->_objZip->deleteName('word/media/'.$id); $this->_objZip->addFile ($filepath,'word/media/'.$id); //$document->setValue($id.'::width', "300px"); //$document->setValue($id.'::height', "300px"); } } 

create a document with the actual image that will be used as a place holder (this solution does not allow you to set the addition and height of the image or several extensions). unzip documnt and check the file name in the word / media folder. use this file name as $ id for the save_image function.

now you can use:

 $document->save_image('image1',$image_path,$document); 
+2
source share

I created some features to extend Jerome's solution. The problem was that to change the picture, we needed to know this link name in the docx file. It can be difficult to find out for the average user (you need to “unzip” the docx and find the image manually).

My solution allows you to refer to images in alt text (it should be in the usual format: $ {abc}) so you don’t need to know how word names represent a placeholder image, a variable is enough. Here's a link on how to add alt texts: http://accessproject.colostate.edu/udl/modules/word/tut_alt_text.php?display=pg_2

I just modified TemplateProcessor.php

First add this to the class:

 /** * Content of document rels (in XML format) of the temporary document. * * @var string */ private $temporaryDocumentRels; 

The constructor function (public function __construct ($ documentTemplate)) should be expanded at the end. Add this:

 $this->temporaryDocumentRels = $this->zipClass->getFromName('word/_rels/document.xml.rels'); 

Now you can read material from document.xml.rels with $ this-> temporDocumentRels

Save Jerome's code:

 /** * Set a new image * * @param string $search * @param string $replace */ public function setImageValue($search, $replace){ // Sanity check if (!file_exists($replace)) { return; } // Delete current image $this->zipClass->deleteName('word/media/' . $search); // Add a new one $this->zipClass->addFile($replace, 'word/media/' . $search); } 

This function returns with rId the image you marked:

 /** * Search for the labeled image rId * * @param string $search */ public function seachImagerId($search){ if (substr($search, 0, 2) !== '${' && substr($search, -1) !== '}') { $search = '${' . $search . '}'; } $tagPos = strpos($this->temporaryDocumentMainPart, $search); $rIdStart = strpos($this->temporaryDocumentMainPart, 'r:embed="',$tagPos)+9; $rId=strstr(substr($this->temporaryDocumentMainPart, $rIdStart),'"', true); return $rId; } 

And this returns the image file name if you know its rId:

 /** * Get img filename with it rId * * @param string $rId */ public function getImgFileName($rId){ $tagPos = strpos($this->temporaryDocumentRels, $rId); $fileNameStart = strpos($this->temporaryDocumentRels, 'Target="media/',$tagPos)+14; $fileName=strstr(substr($this->temporaryDocumentRels, $fileNameStart),'"', true); return $fileName; } 

Changes made to TemplateProcessor.php.

Now you can replace the image by calling this:

 $templateProcessor->setImageValue($templateProcessor->getImgFileName($templateProcessor->seachImagerId("abc")),$replace); 

You can also create a function in TemplateProcessor.php that calls it like:

 public function setImageValueAlt($searchAlt, $replace){ $this->setImageValue($this->getImgFileName($this->seachImagerId($searchAlt)),$replace); } 
+2
source share

If you want to add, delete or replace the image in template.docx, you can add it to your TemplateProcessor.php file (it works for me with PhpWord version 0.14.0):

one.

 // add this in the class protected $_rels; protected $_types; public function __construct($documentTemplate){ // add this line to this function $this->_countRels=100; } 

2.

 public function save() { //add this snippet to this function after $this->zipClass->addFromString('word/document.xml', $this->tempDocumentMainPart); if($this->_rels!=""){ $this->zipClass->addFromString('word/_rels/document.xml.rels', $this->_rels); } if($this->_types!=""){ $this->zipClass->addFromString('[Content_Types].xml', $this->_types); } } 

3. Add this function as well:

 public function setImg( $strKey, $img){ $strKey = '${'.$strKey.'}'; $relationTmpl = '<Relationship Id="RID" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/IMG"/>'; $imgTmpl = '<w:pict><v:shape type="#_x0000_t75" style="width:WIDpx;height:HEIpx"><v:imagedata r:id="RID" o:title=""/></v:shape></w:pict>'; $toAdd = $toAddImg = $toAddType = ''; $aSearch = array('RID', 'IMG'); $aSearchType = array('IMG', 'EXT'); $countrels=$this->_countRels++; //I'm work for jpg files, if you are working with other images types -> Write conditions here $imgExt = 'jpg'; $imgName = 'img' . $countrels . '.' . $imgExt; $this->zipClass->deleteName('word/media/' . $imgName); $this->zipClass->addFile($img['src'], 'word/media/' . $imgName); $typeTmpl = '<Override PartName="/word/media/'.$imgName.'" ContentType="image/EXT"/>'; $rid = 'rId' . $countrels; $countrels++; list($w,$h) = getimagesize($img['src']); if(isset($img['swh'])) //Image proportionally larger side { if($w<=$h) { $ht=(int)$img['swh']; $ot=$w/$h; $wh=(int)$img['swh']*$ot; $wh=round($wh); } if($w>=$h) { $wh=(int)$img['swh']; $ot=$h/$w; $ht=(int)$img['swh']*$ot; $ht=round($ht); } $w=$wh; $h=$ht; } if(isset($img['size'])) { $w = $img['size'][0]; $h = $img['size'][1]; } $toAddImg .= str_replace(array('RID', 'WID', 'HEI'), array($rid, $w, $h), $imgTmpl) ; if(isset($img['dataImg'])) { $toAddImg.='<w:br/><w:t>'.$this->limpiarString($img['dataImg']).'</w:t><w:br/>'; } $aReplace = array($imgName, $imgExt); $toAddType .= str_replace($aSearchType, $aReplace, $typeTmpl) ; $aReplace = array($rid, $imgName); $toAdd .= str_replace($aSearch, $aReplace, $relationTmpl); $this->tempDocumentMainPart=str_replace('<w:t>' . $strKey . '</w:t>', $toAddImg, $this->tempDocumentMainPart); //print $this->tempDocumentMainPart; if($this->_rels=="") { $this->_rels=$this->zipClass->getFromName('word/_rels/document.xml.rels'); $this->_types=$this->zipClass->getFromName('[Content_Types].xml'); } $this->_types = str_replace('</Types>', $toAddType, $this->_types) . '</Types>'; $this->_rels = str_replace('</Relationships>', $toAdd, $this->_rels) . '</Relationships>'; } 

4. And this:

 function limpiarString($str) { return str_replace( array('&', '<', '>', "\n"), array('&amp;', '&lt;', '&gt;', "\n" . '<w:br/>'), $str ); } 

5. How to use:

 //open your template $templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('files/template.docx'); //add image to selector $templateProcessor->setImg('selector',array('src' => 'image.jpg','swh'=>'200', 'size'=>array(0=>$width, 1=>$height)); // You can also clone row if you need //$templateProcessor->cloneRow('NAME_IN_TEMPLATE', NUMBER_OF_TABLE_RECORDS); $templateProcessor->cloneRow('SELECTOR', 4); //save header("Content-Disposition: attachment; filename='helloWord.docx'"); $templateProcessor->saveAs('php://output'); 
+2
source share

I was looking for a solution to add an image. I read many articles, I found suitable solutions for older versions. Change and final decision to receive the code.

Let's move on to changing the TemplateProcessor.php file

 public function __construct($documentTemplate) { //add to this function $this->_countRels=100; //start id for relationship between image and document.xml } public function save() { //add to this function after $this->zipClass->addFromString('word/document.xml', $this->tempDocumentMainPart); if($this->_rels!="") { $this->zipClass->addFromString('word/_rels/document.xml.rels', $this->_rels); } if($this->_types!="") { $this->zipClass->addFromString('[Content_Types].xml', $this->_types); } } //add function public function setImg( $strKey, $img){ $strKey = '${'.$strKey.'}'; $relationTmpl = '<Relationship Id="RID" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/IMG"/>'; $imgTmpl = '<w:pict><v:shape type="#_x0000_t75" style="width:WIDpx;height:HEIpx"><v:imagedata r:id="RID" o:title=""/></v:shape></w:pict>'; $toAdd = $toAddImg = $toAddType = ''; $aSearch = array('RID', 'IMG'); $aSearchType = array('IMG', 'EXT'); $countrels=$this->_countRels++; //I'm work for jpg files, if you are working with other images types -> Write conditions here $imgExt = 'jpg'; $imgName = 'img' . $countrels . '.' . $imgExt; $this->zipClass->deleteName('word/media/' . $imgName); $this->zipClass->addFile($img['src'], 'word/media/' . $imgName); $typeTmpl = '<Override PartName="/word/media/'.$imgName.'" ContentType="image/EXT"/>'; $rid = 'rId' . $countrels; $countrels++; list($w,$h) = getimagesize($img['src']); if(isset($img['swh'])) //Image proportionally larger side { if($w<=$h) { $ht=(int)$img['swh']; $ot=$w/$h; $wh=(int)$img['swh']*$ot; $wh=round($wh); } if($w>=$h) { $wh=(int)$img['swh']; $ot=$h/$w; $ht=(int)$img['swh']*$ot; $ht=round($ht); } $w=$wh; $h=$ht; } if(isset($img['size'])) { $w = $img['size'][0]; $h = $img['size'][1]; } $toAddImg .= str_replace(array('RID', 'WID', 'HEI'), array($rid, $w, $h), $imgTmpl) ; if(isset($img['dataImg'])) { $toAddImg.='<w:br/><w:t>'.$this->limpiarString($img['dataImg']).'</w:t><w:br/>'; } $aReplace = array($imgName, $imgExt); $toAddType .= str_replace($aSearchType, $aReplace, $typeTmpl) ; $aReplace = array($rid, $imgName); $toAdd .= str_replace($aSearch, $aReplace, $relationTmpl); $this->tempDocumentMainPart=str_replace('<w:t>' . $strKey . '</w:t>', $toAddImg, $this->tempDocumentMainPart); //print $this->tempDocumentMainPart; if($this->_rels=="") { $this->_rels=$this->zipClass->getFromName('word/_rels/document.xml.rels'); $this->_types=$this->zipClass->getFromName('[Content_Types].xml'); } $this->_types = str_replace('</Types>', $toAddType, $this->_types) . '</Types>'; $this->_rels = str_replace('</Relationships>', $toAdd, $this->_rels) . '</Relationships>'; } //add function function limpiarString($str) { return str_replace( array('&', '<', '>', "\n"), array('&amp;', '&lt;', '&gt;', "\n" . '<w:br/>'), $str ); } //HOW TO USE??? $templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('templ.docx'); //static zone $templateProcessor->setValue('date', htmlspecialchars(date('dmY G:i:s'))); //$templateProcessor->cloneRow('NAME_IN_TEMPLATE', NUMBER_OF_TABLE_RECORDS); $templateProcessor->cloneRow('AVTOR', 3); //variant 1 //dynamic zone $templateProcessor->setValue('AVTOR#1', htmlspecialchars('Garry')); $templateProcessor->setValue('NAME#1', htmlspecialchars('Black Horse')); $templateProcessor->setValue('SIZES#1', htmlspecialchars('100x300')); /*$img = array( 'src' => 'image.jpg',//path 'swh'=>'350',//Image proportionally larger side 'size'=>array(580, 280) );*/ $templateProcessor->setImg('IMGD#1',array('src' => 'image.jpg','swh'=>'250')); $templateProcessor->setValue('AVTOR#2', htmlspecialchars('Barry')); $templateProcessor->setValue('NAME#2', htmlspecialchars('White Horse')); $templateProcessor->setValue('SIZES#2', htmlspecialchars('200x500')); $templateProcessor->setImg('IMGD#2',array('src' => 'image2.jpg','swh'=>'250')); $templateProcessor->setValue('AVTOR#3', htmlspecialchars('Backer')); $templateProcessor->setValue('NAME#3', htmlspecialchars('Another Side')); $templateProcessor->setValue('SIZES#3', htmlspecialchars('120x430')); $templateProcessor->setImg('IMGD#3',array('src' => 'image3.jpg','swh'=>'250')); //variant 2 $templateProcessor->cloneRow('AVTOR', count($output['ID'])); for($i=0;$i<count($output['ID']);$i++) { $templateProcessor->setValue('AVTOR'.'#'.($i+1), htmlspecialchars($output['AVTOR'][$i])); $templateProcessor->setValue('NAME'.'#'.($i+1), htmlspecialchars($output['PNAM'][$i])); //GetImg($output['ID'][$i]) my function return image path $templateProcessor->setImg('IMGD'.'#'.($i+1), array('src'=>GetImg($output['ID'][$i]),'swh'=>'250')); } //Save $templateProcessor->saveAs('testTemplate.docx'); 
+1
source share

change the name *. docx on * .zip

open the zip folder

browse " word/media/**** ", the naming name should replace the name

for setImageValue($search, $replace)

 $search must be equls $replace OR use $this->zipClass->renameName ($replace , $search); 
0
source share

All Articles