我在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');
在模板中添加、删除或替换图像.docx你可以把它添加到你的模板处理器.php文件中,(它适用于我的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;
}
阿拉伯数字。
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. 也添加此功能:
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. 而这个:
function limpiarString($str) {
return str_replace(
array('&', '<', '>', "'n"),
array('&', '<', '>', "'n" . '<w:br/>'),
$str
);
}
5. 使用方法:
//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');
他的几乎未经测试。 但这对我有用(尽管我的略有不同(:
将以下函数添加到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");
}
}
使用实际图像创建一个文档以用作占位符(此解决方案不允许设置图像的 With &height 或多个扩展名(。 解压缩文档并检查 Word/媒体文件夹中的文件名。使用此文件名作为 save_image 函数的$id。
您现在可以使用:
$document->save_image('image1',$image_path,$document);
我创建了一些函数来扩展 Jerome 的解决方案。问题是,为了更改图片,我们必须知道它在docx文件中的引用名称。对于普通用户来说,这可能很难找到(您必须"解压缩"docx,然后手动找到您的图片(。
我的解决方案可以通过替代文本引用图片(它需要采用通常的格式:${abc}(因此,不必知道单词如何命名占位符图片,变量就足够了。以下是有关如何添加替代文本的链接:http://accessproject.colostate.edu/udl/modules/word/tut_alt_text.php?display=pg_2
我只修改了模板处理器.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');
现在,您可以使用 $this->temporaryDocumentRels 从 document.xml.rels 中读取内容
保留杰罗姆的代码:
/**
* 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;
}
模板处理器.php中的修改已完成。
现在,您可以通过调用以下命令来替换映像:
$templateProcessor->setImageValue($templateProcessor->getImgFileName($templateProcessor->seachImagerId("abc")),$replace);
您还可以在 TemplateProcessor 中创建一个函数.php它调用它:
public function setImageValueAlt($searchAlt, $replace){
$this->setImageValue($this->getImgFileName($this->seachImagerId($searchAlt)),$replace);
}
我正在寻找添加图像的解决方案。我读了很多文章,我只找到了适合旧版本的解决方案。更改并最终确定获取代码的决定。
让我们继续更改文件模板处理器.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('d.m.Y 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');
*.docx 的名称修改为 *.zip
打开 zip 文件夹
查看"word/media/****
"的图形名称是替换名称
对于setImageValue($search, $replace)
$search must be equls $replace OR use $this->zipClass->renameName ($replace , $search);
对于在 2020 年及以后阅读本文的任何人来说,PhpWord 现在都有 setImageValue(( 方法,文档可以在这里找到:https://phpword.readthedocs.io/en/latest/templates-processing.html#setimagevalue
如果您将.docx模板作为.zip存档打开,您将在 word/media/文件夹中找到所有媒体文件,然后您需要找到占位符图像并替换它。我通过以下方式做到了:
$this->templateProcessor->zip()->pclzipAddFile($imageUrl, 'word/media/image1.png');
在这种情况下,图像样式与模板中的样式相同。
感谢这篇文章中的所有精彩答案,终于我提出了在phpword 1.0.0版本中替换图像的解决方案,并想在这里分享我的代码: (非常感谢@csanády-bálint的详细编码(
我的问题,
- 我怎样才能知道图像的 rId?
- 我怎么知道图像是JPG或PNG或其他?
我发现图像将以 image1、image2、image3 等的命名模式开头,因此,我将概念修改为不是通过 rId 获取图像,而是切换到按名称获取图像,并且可以同时忽略图像扩展名。
我只修改了模板处理器.php
首先将其添加到类中:
/**
* Content of document rels (in XML format) of the temporary document.
*
* @var string
*/
private $temporaryDocumentRels;
接下来,将以下内容添加到构造函数的末尾(公共函数 __construct($documentTemplate((
$this->temporaryDocumentRels = $this->zipClass->getFromName($this->getRelationsName($this->getMainPartName()));
最后,只需将以下新功能添加到TemplaceProcessor.php
/**
* Replace image by name
*
* @param string $search
* @param mixed $replace
*/
public function replaceImage($search, $replace): void
{
$fileNameStart = strpos($this->temporaryDocumentRels, $search);
$fileName = strstr(substr($this->temporaryDocumentRels, $fileNameStart), '"', true);
$this->zipClass->addFromString("word/media/" . $fileName, $replace);
}
最后但并非最不重要的一点是,用法:
$templateProcessor = new 'PhpOffice'PhpWord'TemplateProcessor('files/template.docx');
// image in file, eg. image1, image2, and so on
$search = 'image1';
// replacement image, can be from global http as well,
// like https://legacy.gscdn.nl/archives/images/HassVivaCatFight.jpg
$replace = 'replacement_image.png';
$fileGetContents = file_get_contents($replace);
if ($fileGetContents !== false) {
$templateProcessor->replaceImage($search, $fileGetContents);
}
图像替换由以下代码完成:
$this->zipClass->addFromString("word/media/" . $fileName, $replace);
我在 zip(( 类(公共函数 zip(((的描述中找到了代码的地方
要替换图像:$templateProcessor->zip((->AddFromString("word/media/image1.jpg",file_get_contents($file((;
希望对您有所帮助!