Skip to content

Commit 701f770

Browse files
committed
Html parser (addHtml) - support width in tables & cells
1 parent 21f4bb3 commit 701f770

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

src/PhpWord/Shared/Html.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,19 @@ protected static function parseInlineStyle($node, $styles = array())
106106
case 'lang':
107107
$styles['lang'] = $attribute->value;
108108
break;
109+
case 'width':
110+
// tables, cells
111+
$val = trim($attribute->value);
112+
if(false !== strpos($val, '%')){
113+
// e.g. <table width="100%"> or <td width=50%>
114+
$styles['width'] = intval($val) * 50;
115+
$styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT;
116+
}else{
117+
// e.g. <table width="250> where "250" = 250px (always pixels)
118+
$styles['width'] = Converter::pixelToTwip($val);
119+
$styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP;
120+
}
121+
break;
109122
}
110123
}
111124
}
@@ -361,7 +374,11 @@ protected static function parseCell($node, $element, &$styles)
361374
if (!empty($colspan)) {
362375
$cellStyles['gridSpan'] = $colspan - 0;
363376
}
364-
$cell = $element->addCell(null, $cellStyles);
377+
378+
// set cell width to control column widths
379+
$width = isset($cellStyles['width']) ? $cellStyles['width'] : null;
380+
unset($cellStyles['width']); // would not apply
381+
$cell = $element->addCell($width, $cellStyles);
365382

366383
if (self::shouldAddTextRun($node)) {
367384
return $cell->addTextRun(self::parseInlineStyle($node, $styles['paragraph']));

tests/PhpWord/Shared/HtmlTest.php

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,4 +632,74 @@ public function testParseLetterSpacing()
632632
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:rPr/w:spacing'));
633633
$this->assertEquals(150 * 15, $doc->getElement('/w:document/w:body/w:p/w:r/w:rPr/w:spacing')->getAttribute('w:val'));
634634
}
635+
636+
/**
637+
* Parse widths in tables and cells, which also allows for controlling column width
638+
*/
639+
public function testParseTableAndCellWidth()
640+
{
641+
$phpWord = new \PhpOffice\PhpWord\PhpWord();
642+
$section = $phpWord->addSection([
643+
'orientation' => \PhpOffice\PhpWord\Style\Section::ORIENTATION_LANDSCAPE,
644+
]);
645+
646+
// borders & backgrounds are here just for better visual comparison
647+
$html = <<<HTML
648+
<table style="border: 1px #000000 solid; width: 100%;">
649+
<tr>
650+
<td style="width: 25%; border: 1px #000000 solid; text-align: center;">25%</td>
651+
<td>
652+
<table width="400" style="border: 1px #000000 solid; background-color: #EEEEEE;">
653+
<tr>
654+
<th colspan="3" style="border: 1px #000000 solid;">400px</th>
655+
</tr>
656+
<tr>
657+
<th>T2.R2.C1</th>
658+
<th style="width: 50pt; border: 1px #FF0000 dashed; background-color: #FFFFFF">50pt</th>
659+
<th>T2.R2.C3</th>
660+
</tr>
661+
<tr>
662+
<th width="300" colspan="2" style="border: 1px #000000 solid;">300px</th>
663+
<th style="border: 1px #000000 solid;">T2.R3.C3</th>
664+
</tr>
665+
</table>
666+
</td>
667+
</tr>
668+
</table>
669+
HTML;
670+
671+
Html::addHtml($section, $html);
672+
$doc = TestHelperDOCX::getDocument($phpWord, 'Word2007');
673+
674+
// outer table grid
675+
$xpath = '/w:document/w:body/w:tbl/w:tblGrid/w:gridCol';
676+
$this->assertTrue($doc->elementExists($xpath));
677+
$this->assertEquals(25 * 50, $doc->getElement($xpath)->getAttribute('w:w'));
678+
$this->assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type'));
679+
680+
// <td style="width: 25%; ...
681+
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:tcW';
682+
$this->assertTrue($doc->elementExists($xpath));
683+
$this->assertEquals(25 * 50, $doc->getElement($xpath)->getAttribute('w:w'));
684+
$this->assertEquals('pct', $doc->getElement($xpath)->getAttribute('w:type'));
685+
686+
// <table width="400" .. 400px = 6000 twips (400 / 96 * 1440)
687+
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tbl/w:tr/w:tc/w:tcPr/w:tcW';
688+
$this->assertTrue($doc->elementExists($xpath));
689+
$this->assertEquals(6000, $doc->getElement($xpath)->getAttribute('w:w'));
690+
$this->assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type'));
691+
692+
// <th style="width: 50pt; .. 50pt = 750 twips (50 / 72 * 1440)
693+
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tbl/w:tr[2]/w:tc[2]/w:tcPr/w:tcW';
694+
$this->assertTrue($doc->elementExists($xpath));
695+
$this->assertEquals(1000, $doc->getElement($xpath)->getAttribute('w:w'));
696+
$this->assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type'));
697+
698+
// <th width="300" .. 300px = 4500 twips (300 / 96 * 1440)
699+
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tbl/w:tr[3]/w:tc/w:tcPr/w:tcW';
700+
$this->assertTrue($doc->elementExists($xpath));
701+
$this->assertEquals(4500, $doc->getElement($xpath)->getAttribute('w:w'));
702+
$this->assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type'));
703+
}
704+
635705
}

0 commit comments

Comments
 (0)