У меня есть экземпляр шаблона на PHPWord. Можно ли заменить или добавить изображение? Что-то вроде setImageValue?
$phpWord = new \PhpOffice\PhpWord\Template('a.docx'); $phpWord->setImageValue('IMAGE_PLACEHOLDER', 'a.jpg'); $phpWord->saveAs('b.docx');
Что-то вроде этого возможно?
Следующий код – это обновленная версия версии TotPeRo (еще раз спасибо за ваш код!), Для последнего phpOffice (0.11), который немного изменился
/** * 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); }
Можно вызвать с помощью:
$document->setImageValue('image1.jpg', 'my_image.jpg');
его довольно много непроверено. но это работает для меня (хотя мой немного отличается):
добавьте следующую функцию в 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"); } }
создайте документ с фактическим изображением, которое будет использоваться в качестве держателя места (это решение не позволяет установить высоту изображения и несколько расширений). разархивируйте documnt и проверьте имя файла в папке word / media. используйте это имя файла как $ id для функции save_image.
теперь вы можете использовать:
$document->save_image('image1',$image_path,$document);
Я создал некоторые функции для расширения решения Джерома. Проблема заключалась в том, что для изменения картины нам нужно было знать ее имя ссылки в файле docx. Это может быть трудно узнать для обычного пользователя (вам нужно «распаковать» docx и найти свое изображение вручную).
Мое решение позволяет ссылаться на изображения по тексту alt (оно должно быть в обычном формате: $ {abc}), поэтому вам не нужно знать, как имена слов представляют собой изображение заполнителя, переменной достаточно. Вот ссылка о том, как добавить альт-тексты: http://accessproject.colostate.edu/udl/modules/word/tut_alt_text.php?display=pg_2
Я только изменил TemplateProcessor.php
Сначала добавьте это в класс:
/** * Content of document rels (in XML format) of the temporary document. * * @var string */ private $temporaryDocumentRels;
Функция конструктора (публичная функция __construct ($ documentTemplate)) должна быть расширена в конце. Добавь это:
$this->temporaryDocumentRels = $this->zipClass->getFromName('word/_rels/document.xml.rels');
Теперь вы можете читать материал из document.xml.rels, используя $ this-> temporDocumentRels
Сохраните код Джерома:
/** * 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); }
Эта функция возвращает с rId изображения, которое вы отметили:
/** * 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; }
И это возвращает имя файла изображений, если вы знаете, что это 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; }
Сделаны изменения в TemplateProcessor.php.
Теперь вы можете заменить изображение, вызвав это:
$templateProcessor->setImageValue($templateProcessor->getImgFileName($templateProcessor->seachImagerId("abc")),$replace);
Вы также можете создать функцию в TemplateProcessor.php, которая называет ее так:
public function setImageValueAlt($searchAlt, $replace){ $this->setImageValue($this->getImgFileName($this->seachImagerId($searchAlt)),$replace); }
изменить имя * .docx на * .zip
откройте папку zip
просмотрите « word/media/****
», имя именования должно заменить имя
для setImageValue($search, $replace)
$search must be equls $replace OR use $this->zipClass->renameName ($replace , $search);
Я искал решение для добавления изображения. Я прочитал много статей, я нашел подходящие решения для более старых версий. Изменение и окончательное решение о получении кода.
Перейдем к изменению файла TemplateProcessor.php
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('&', '<', '>', "\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');
Ну, возможно, этого не было, когда вы разместили вопрос, но это документация, и это работает как шарм. Просто разместите его для будущих посетителей.
$section->addImage( 'imageUrl.jpg', array( 'width' => 600, 'marginTop' => -1, 'marginLeft' => -1, 'wrappingStyle' => 'behind' )