Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ v0.15.0 (?? ??? 2018)
- Fix parsing of `<w:br/>` tag. @troosan #1274
- Bookmark are not writton as internal link in html writer @troosan #1263
- It should be possible to add a Footnote in a ListItemRun @troosan #1287 #1287
- Fix colspan and rowspan for tables in HTML Writer @mattbolt #1292
- Fix parsing of Heading and Title formating @troosan @gthomas2 #465
- Fix Dateformat typo, fix hours casing, add Month-Day-Year formats @ComputerTinker #591

Expand Down
22 changes: 11 additions & 11 deletions samples/Sample_09_Tables.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,20 @@
$table = $section->addTable('Colspan Rowspan');

$row = $table->addRow();

$row->addCell(null, array('vMerge' => 'restart'))->addText('A');
$row->addCell(null, array('gridSpan' => 2, 'vMerge' => 'restart'))->addText('B');
$row->addCell()->addText('1');
$row->addCell(1000, array('vMerge' => 'restart'))->addText('A');
$row->addCell(1000, array('gridSpan' => 2, 'vMerge' => 'restart'))->addText('B');
$row->addCell(1000)->addText('1');

$row = $table->addRow();
$row->addCell(null, array('vMerge' => 'continue'));
$row->addCell(null, array('vMerge' => 'continue', 'gridSpan' => 2));
$row->addCell()->addText('2');
$row->addCell(1000, array('vMerge' => 'continue'));
$row->addCell(1000, array('vMerge' => 'continue', 'gridSpan' => 2));
$row->addCell(1000)->addText('2');

$row = $table->addRow();
$row->addCell(null, array('vMerge' => 'continue'));
$row->addCell()->addText('C');
$row->addCell()->addText('D');
$row->addCell()->addText('3');
$row->addCell(1000, array('vMerge' => 'continue'));
$row->addCell(1000)->addText('C');
$row->addCell(1000)->addText('D');
$row->addCell(1000)->addText('3');

// 5. Nested table

Expand Down
58 changes: 50 additions & 8 deletions src/PhpWord/Writer/HTML/Element/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,60 @@ public function write()
$rowCount = count($rows);
if ($rowCount > 0) {
$content .= '<table>' . PHP_EOL;
foreach ($rows as $row) {
for ($i = 0; $i < $rowCount; $i++) {
/** @var $row \PhpOffice\PhpWord\Element\Row Type hint */
$rowStyle = $row->getStyle();
$rowStyle = $rows[$i]->getStyle();
// $height = $row->getHeight();
$tblHeader = $rowStyle->isTblHeader();
$content .= '<tr>' . PHP_EOL;
foreach ($row->getCells() as $cell) {
$writer = new Container($this->parentWriter, $cell);
$cellTag = $tblHeader ? 'th' : 'td';
$content .= "<{$cellTag}>" . PHP_EOL;
$content .= $writer->write();
$content .= "</{$cellTag}>" . PHP_EOL;
$rowCells = $rows[$i]->getCells();
$rowCellCount = count($rowCells);
for ($j = 0; $j < $rowCellCount; $j++) {
$cellStyle = $rowCells[$j]->getStyle();
$cellColSpan = $cellStyle->getGridSpan();
$cellRowSpan = 1;
$cellVMerge = $cellStyle->getVMerge();
// If this is the first cell of the vertical merge, find out how man rows it spans
if ($cellVMerge === 'restart') {
for ($k = $i + 1; $k < $rowCount; $k++) {
$kRowCells = $rows[$k]->getCells();
if (isset($kRowCells[$j])) {
if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') {
$cellRowSpan++;
} else {
break;
}
} else {
break;
}
}
}
// Ignore cells that are merged vertically with previous rows
if ($cellVMerge !== 'continue') {
$cellTag = $tblHeader ? 'th' : 'td';
$cellColSpanAttr = (is_numeric($cellColSpan) && ($cellColSpan > 1) ? " colspan=\"{$cellColSpan}\"" : '');
$cellRowSpanAttr = ($cellRowSpan > 1 ? " rowspan=\"{$cellRowSpan}\"" : '');
$content .= "<{$cellTag}{$cellColSpanAttr}{$cellRowSpanAttr}>" . PHP_EOL;
$writer = new Container($this->parentWriter, $rowCells[$j]);
$content .= $writer->write();
if ($cellRowSpan > 1) {
// There shouldn't be any content in the subsequent merged cells, but lets check anyway
for ($k = $i + 1; $k < $rowCount; $k++) {
$kRowCells = $rows[$k]->getCells();
if (isset($kRowCells[$j])) {
if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') {
$writer = new Container($this->parentWriter, $kRowCells[$j]);
$content .= $writer->write();
} else {
break;
}
} else {
break;
}
}
}
$content .= "</{$cellTag}>" . PHP_EOL;
}
}
$content .= '</tr>' . PHP_EOL;
}
Expand Down
67 changes: 64 additions & 3 deletions tests/PhpWord/Writer/HTML/ElementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,73 @@ public function testWriteTrackChanges()
$text2 = $section->addText('my other text');
$text2->setTrackChange(new TrackChange(TrackChange::DELETED, 'another author', new \DateTime()));

$htmlWriter = new HTML($phpWord);
$dom = new \DOMDocument();
$dom->loadHTML($htmlWriter->getContent());
$dom = $this->getAsHTML($phpWord);
$xpath = new \DOMXpath($dom);

$this->assertTrue($xpath->query('/html/body/p[1]/ins')->length == 1);
$this->assertTrue($xpath->query('/html/body/p[2]/del')->length == 1);
}

/**
* Tests writing table with col span
*/
public function testWriteColSpan()
{
$phpWord = new PhpWord();
$section = $phpWord->addSection();
$table = $section->addTable();
$row1 = $table->addRow();
$cell11 = $row1->addCell(1000, array('gridSpan' => 2));
$cell11->addText('cell spanning 2 bellow');
$row2 = $table->addRow();
$cell21 = $row2->addCell(500);
$cell21->addText('first cell');
$cell22 = $row2->addCell(500);
$cell22->addText('second cell');

$dom = $this->getAsHTML($phpWord);
$xpath = new \DOMXpath($dom);

$this->assertTrue($xpath->query('/html/body/table/tr[1]/td')->length == 1);
$this->assertEquals('2', $xpath->query('/html/body/table/tr/td[1]')->item(0)->attributes->getNamedItem('colspan')->textContent);
$this->assertTrue($xpath->query('/html/body/table/tr[2]/td')->length == 2);
}

/**
* Tests writing table with row span
*/
public function testWriteRowSpan()
{
$phpWord = new PhpWord();
$section = $phpWord->addSection();
$table = $section->addTable();

$row1 = $table->addRow();
$row1->addCell(1000, array('vMerge' => 'restart'))->addText('row spanning 3 bellow');
$row1->addCell(500)->addText('first cell being spanned');

$row2 = $table->addRow();
$row2->addCell(null, array('vMerge' => 'continue'));
$row2->addCell(500)->addText('second cell being spanned');

$row3 = $table->addRow();
$row3->addCell(null, array('vMerge' => 'continue'));
$row3->addCell(500)->addText('third cell being spanned');

$dom = $this->getAsHTML($phpWord);
$xpath = new \DOMXpath($dom);

$this->assertTrue($xpath->query('/html/body/table/tr[1]/td')->length == 2);
$this->assertEquals('3', $xpath->query('/html/body/table/tr[1]/td[1]')->item(0)->attributes->getNamedItem('rowspan')->textContent);
$this->assertTrue($xpath->query('/html/body/table/tr[2]/td')->length == 1);
}

private function getAsHTML(PhpWord $phpWord)
{
$htmlWriter = new HTML($phpWord);
$dom = new \DOMDocument();
$dom->loadHTML($htmlWriter->getContent());

return $dom;
}
}