PHPで帳票出力する際、PDF出力ではなくて、WORD出力できるようにしてほしいという依頼がきたので、PHPWordというライブラリを使うことにしました。
PHPWordはテンプレートを呼び出して差し替えたい文字を修正すればいいのですが、1枚のテンプレートで複数枚のwordを抽出する方法がわかりませんでした。
そこで、調べてみるとTemplate.phpにAddPage関数+αを加えて使用すれば可能ということがわかりました。
52行目付近
/**
* Document XML
*
* @var string
*/
private $_documentXML;
//以下を追加
private $_documentXMLSEQ;
private $_documentXMLFINAL;
private $_documentXMLREM;
//追加ここまで
74行目付近
/**
* Create a new Template Object
*
* @param string $strFilename
*/
public function __construct($strFilename) {
$path = dirname($strFilename);
$this->_tempFileName = $path.DIRECTORY_SEPARATOR.time().'.docx';
copy($strFilename, $this->_tempFileName); // Copy the source File to the temp File
$this->_objZip = new ZipArchive();
$this->_objZip->open($this->_tempFileName);
//Get xml
$this->_documentXML = $this->_objZip->getFromName('word/document.xml');
//追加ここから
preg_match_all('/${.+?}/', $this->_documentXML, $matches, PREG_SET_ORDER);
foreach ($matches as $val) {
$oldval = $val[0];
$newval = preg_replace('/<.+?>/', '', $val[0]);
$newval = str_replace(' ', '', $newval );
$this->_documentXML = str_replace($oldval, $newval, $this->_documentXML);
}
//Get code between body tag
$this->_documentXMLSEQ = $this->getTextBetweenTags($this->_documentXML, 'w:body');
//Get code outside tag and place string to replace later
$count = null;
$this->_documentXMLREM = preg_replace('/<w:body>(.*?)</w:body>/i', '[xmlremain]', $this->_documentXML, -1, $count);
//Set code as string to replace
$this->_documentXML = $this->_documentXMLSEQ;
//追加ここまで
}
//追加ここから
public function getTextBetweenTags($string, $tagname) {
$pattern = "/<$tagname>(.*?)</$tagname>/";
preg_match($pattern, $string, $matches);
return $matches[1];
}
//追加ここまで
好きな箇所に挿入
/**
* Adds new page in the document
*/
public function addPage() {
$this->_documentXMLFINAL .= $this->_documentXML;
$this->_documentXML = $this->_documentXMLSEQ;
}
95行目付近
/**
* Saves Template
* @param string $strFilename
*/
public function save($strFilename) {
if(file_exists($strFilename)) {
unlink($strFilename);
}
//追加ここから
$this->_documentXMLFINAL .= $this->_documentXML;
$this->_documentXML = str_replace('[xmlremain]', '<w:body>'.$this->_documentXMLFINAL.'</w:body>', $this->_documentXMLREM);
//追加ここまで
$this->_objZip->addFromString('word/document.xml', $this->_documentXML);
// Close zip file
if($this->_objZip->close() === false) {
throw new Exception('Could not close zip file.');
}
rename($this->_tempFileName, $strFilename);
}
上記の修正でdocxを作成するとエラーが発生する場合があります。
原因を調べてみるとどうやら図形を使うとidの変更ができずid重複になりエラーになってしまうようです。
図形を使わないテンプレートにすると問題なかったので、できるだけ図形を使わない方向で対処しました。
この場合だと複数テンプレートで1つのwordを作成できないので、時間があれば複数テンプレ―トでも出力可能にしたいな……。
参考