Nuestros mejores investigadores agotaron sus depósitos de café, por su búsqueda todo el tiempo por la solución, hasta que Amanda encontró la contestación en GitLab así que en este momento la comparte contigo.
Solución:
El siguiente código es la versión actualizada del de TotPeRo (¡gracias de nuevo por tu código!), Para el último phpOffice (0.11) que ha evolucionado un poco.
/**
* 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);
Se puede llamar con:
$document->setImageValue('image1.jpg', 'my_image.jpg');
Si desea agregar, eliminar o reemplazar la imagen en template.docx, puede agregar esto a su archivo TemplateProcessor.php (me funciona con la versión PhpWord 0.14.0):
1.
// 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. Agregue esta función también:
public function setImg( $strKey, $img)
$strKey = '$'.$strKey.'';
$relationTmpl = ' ';
$imgTmpl = ' ';
$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 = ' ';
$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.=''.$this->limpiarString($img['dataImg']).' ';
$aReplace = array($imgName, $imgExt);
$toAddType .= str_replace($aSearchType, $aReplace, $typeTmpl) ;
$aReplace = array($rid, $imgName);
$toAdd .= str_replace($aSearch, $aReplace, $relationTmpl);
$this->tempDocumentMainPart=str_replace('' . $strKey . ' ', $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('', $toAddType, $this->_types) . '';
$this->_rels = str_replace('', $toAdd, $this->_rels) . '';
4. Y esto:
function limpiarString($str)
return str_replace(
array('&', '<', '>', "n"),
array('&', '<', '>', "n" . ' '),
$str
);
5. Cómo utilizar:
//open your template
$templateProcessor = new PhpOfficePhpWordTemplateProcessor('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');
Creé algunas funciones para extender la solución de Jerome. El problema era que para cambiar la imagen teníamos que saber su nombre de referencia en el archivo docx. Esto podría ser difícil de encontrar para un usuario medio (tienes que “descomprimir” el docx y encontrar tu imagen manualmente).
Mi solución hace posible hacer referencia a imágenes mediante texto alternativo (debe estar en el formato habitual: $ abc) para que uno no tenga que saber cómo la palabra nombra la imagen del marcador de posición, la variable es suficiente. Aquí hay un enlace sobre cómo agregar textos alternativos: http://accessproject.colostate.edu/udl/modules/word/tut_alt_text.php?display=pg_2
Solo modifiqué TemplateProcessor.php
Primero agregue esto a la clase:
/**
* Content of document rels (in XML format) of the temporary document.
*
* @var string
*/
private $temporaryDocumentRels;
La función constructora (función pública __construct ($ documentTemplate)) debe extenderse al final. Agrega esto:
$this->temporaryDocumentRels = $this->zipClass->getFromName('word/_rels/document.xml.rels');
Ahora puede leer cosas de document.xml.rels usando $ this-> temporaryDocumentRels
Mantenga el código de Jerome:
/**
* 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);
Esta función regresa con el rId de la imagen que etiquetó:
/**
* Search for the labeled image's 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;
Y esto devuelve el nombre del archivo de imágenes, si sabe que es rId:
/**
* Get img filename with it's 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;
Las modificaciones en TemplateProcessor.php están hechas.
Ahora puede reemplazar la imagen llamando a esto:
$templateProcessor->setImageValue($templateProcessor->getImgFileName($templateProcessor->seachImagerId("abc")),$replace);
También puede crear una función en TemplateProcessor.php que lo llame como:
public function setImageValueAlt($searchAlt, $replace)
$this->setImageValue($this->getImgFileName($this->seachImagerId($searchAlt)),$replace);