Merge pull request #88 from jeroenmoors/develop

Clone table rows on the fly when using a template document
This commit is contained in:
Progi1984 2014-03-07 21:59:56 +01:00
commit 3ed25886f8
3 changed files with 147 additions and 0 deletions

View File

@ -152,6 +152,99 @@ class PHPWord_Template
return $matches[1];
}
/**
* Find the start position of the nearest table row before $offset
*
* @param mixed $offset
*/
private function _findRowStart($offset) {
$rowStart = strrpos($this->_documentXML, "<w:tr ", ((strlen($this->_documentXML) - $offset) * -1));
if (!$rowStart) {
$rowStart = strrpos($this->_documentXML, "<w:tr>", ((strlen($this->_documentXML) - $offset) * -1));
}
if (!$rowStart) {
trigger_error("Can not find the start position of the row to clone.");
return false;
}
return $rowStart;
}
/**
* Find the end position of the nearest table row after $offset
*
* @param mixed $offset
*/
private function _findRowEnd($offset) {
$rowEnd = strpos($this->_documentXML, "</w:tr>", $offset) + 7;
return $rowEnd;
}
/**
* Get a slice of a string
*
* @param mixed $offset
*/
private function _getSlice($startPosition, $endPosition = 0) {
if (!$endPosition) {
$endPosition = strlen($this->_documentXML);
}
return substr($this->_documentXML, $startPosition, ($endPosition - $startPosition));
}
/**
* Clone a table row in a template document
*
* @param mixed $search
* @param mixed $numberOfClones
*/
public function cloneRow($search, $numberOfClones) {
if(substr($search, 0, 2) !== '${' && substr($search, -1) !== '}') {
$search = '${'.$search.'}';
}
$tagPos = strpos($this->_documentXML, $search);
if (!$tagPos) {
trigger_error("Can not clone row, template variable not found or variable contains markup.");
return false;
}
$rowStart = $this->_findRowStart($tagPos);
$rowEnd = $this->_findRowEnd($tagPos);
$xmlRow = $this->_getSlice($rowStart, $rowEnd);
// Check if there's a cell spanning multiple rows.
if (preg_match('#<w:vMerge w:val="restart"/>#', $xmlRow)) {
$extraRowStart = $rowEnd;
$extraRowEnd = $rowEnd;
while(true) {
$extraRowStart = $this->_findRowStart($extraRowEnd + 1);
$extraRowEnd = $this->_findRowEnd($extraRowEnd + 1);
// If extraRowEnd is lower then 7, there was no next row found.
if ($extraRowEnd < 7) {
break;
}
// If tmpXmlRow doesn't contain continue, this row is no longer part of the spanned row.
$tmpXmlRow = $this->_getSlice($extraRowStart, $extraRowEnd);
if (!preg_match('#<w:vMerge/>#', $tmpXmlRow) && !preg_match('#<w:vMerge w:val="continue" />#', $tmpXmlRow)) {
break;
}
// This row was a spanned row, update $rowEnd and search for the next row.
$rowEnd = $extraRowEnd;
}
$xmlRow = $this->_getSlice($rowStart, $rowEnd);
}
$result = $this->_getSlice(0, $rowStart);
for ($i = 1; $i <= $numberOfClones; $i++) {
$result .= preg_replace('/\$\{(.*?)\}/','\${\\1#'.$i.'}', $xmlRow);
}
$result .= $this->_getSlice($rowEnd);
$this->_documentXML = $result;
}
/**
* Save Template
*

Binary file not shown.

View File

@ -0,0 +1,54 @@
<?php
require_once '../Classes/PHPWord.php';
$PHPWord = new PHPWord();
$document = $PHPWord->loadTemplate('Sample_07_TemplateCloneRow.docx');
// Simple table
$document->cloneRow('rowValue', 10);
$document->setValue('rowValue#1', 'Sun');
$document->setValue('rowValue#2', 'Mercury');
$document->setValue('rowValue#3', 'Venus');
$document->setValue('rowValue#4', 'Earth');
$document->setValue('rowValue#5', 'Mars');
$document->setValue('rowValue#6', 'Jupiter');
$document->setValue('rowValue#7', 'Saturn');
$document->setValue('rowValue#8', 'Uranus');
$document->setValue('rowValue#9', 'Neptun');
$document->setValue('rowValue#10', 'Pluto');
$document->setValue('rowNumber#1', '1');
$document->setValue('rowNumber#2', '2');
$document->setValue('rowNumber#3', '3');
$document->setValue('rowNumber#4', '4');
$document->setValue('rowNumber#5', '5');
$document->setValue('rowNumber#6', '6');
$document->setValue('rowNumber#7', '7');
$document->setValue('rowNumber#8', '8');
$document->setValue('rowNumber#9', '9');
$document->setValue('rowNumber#10', '10');
$document->setValue('weekday', date('l'));
$document->setValue('time', date('H:i'));
// Table with a spanned cell
$document->cloneRow('userId', 3);
$document->setValue('userId#1', '1');
$document->setValue('userFirstName#1', 'James');
$document->setValue('userName#1', 'Taylor');
$document->setValue('userPhone#1', '+1 428 889 773');
$document->setValue('userId#2', '2');
$document->setValue('userFirstName#2', 'Robert');
$document->setValue('userName#2', 'Bell');
$document->setValue('userPhone#2', '+1 428 889 774');
$document->setValue('userId#3', '3');
$document->setValue('userFirstName#3', 'Michael');
$document->setValue('userName#3', 'Ray');
$document->setValue('userPhone#3', '+1 428 889 775');
$document->save('Sample_03_TemplateCloneRow_result.docx');