diff --git a/CHANGELOG.md b/CHANGELOG.md
index f93b7ac0f3..5235895506 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Improved TextDirection for styling a cell by @terryzwt in #2429
- Word2007 Reader : Added option to disable loading images by @aelliott1485 in #2450
- HTML Writer : Added border-spacing to default styles for table by @kernusr in #2451
+- Word2007 Reader : Support for table cell borders and margins by @kernusr in #2454
### Bug fixes
diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php
index 418661d6f0..3ab8995f9e 100644
--- a/src/PhpWord/Reader/Word2007/AbstractPart.php
+++ b/src/PhpWord/Reader/Word2007/AbstractPart.php
@@ -385,9 +385,8 @@ protected function readTable(XMLReader $xmlReader, DOMElement $domNode, $parent,
} elseif ('w:tc' == $rowNode->nodeName) { // Cell
$cellWidth = $xmlReader->getAttribute('w:w', $rowNode, 'w:tcPr/w:tcW');
$cellStyle = null;
- $cellStyleNode = $xmlReader->getElement('w:tcPr', $rowNode);
- if (null !== $cellStyleNode) {
- $cellStyle = $this->readCellStyle($xmlReader, $cellStyleNode);
+ if ($xmlReader->elementExists('w:tcPr', $rowNode)) {
+ $cellStyle = $this->readCellStyle($xmlReader, $rowNode);
}
$cell = $row->addCell($cellWidth, $cellStyle);
@@ -573,7 +572,7 @@ private function readTableIndent(XMLReader $xmlReader, DOMElement $domNode)
/**
* Read w:tcPr.
*
- * @return array
+ * @return null|array
*/
private function readCellStyle(XMLReader $xmlReader, DOMElement $domNode)
{
@@ -585,8 +584,24 @@ private function readCellStyle(XMLReader $xmlReader, DOMElement $domNode)
'bgColor' => [self::READ_VALUE, 'w:shd', 'w:fill'],
'noWrap' => [self::READ_VALUE, 'w:noWrap', null, null, true],
];
+ $style = null;
- return $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
+ if ($xmlReader->elementExists('w:tcPr', $domNode)) {
+ $styleNode = $xmlReader->getElement('w:tcPr', $domNode);
+
+ $borders = ['top', 'left', 'bottom', 'right'];
+ foreach ($borders as $side) {
+ $ucfSide = ucfirst($side);
+
+ $styleDefs['border' . $ucfSide . 'Size'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:sz'];
+ $styleDefs['border' . $ucfSide . 'Color'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:color'];
+ $styleDefs['border' . $ucfSide . 'Style'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:val'];
+ }
+
+ $style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs);
+ }
+
+ return $style;
}
/**
diff --git a/src/PhpWord/Style/Border.php b/src/PhpWord/Style/Border.php
index 2ee69be56f..28e340c040 100644
--- a/src/PhpWord/Style/Border.php
+++ b/src/PhpWord/Style/Border.php
@@ -22,6 +22,8 @@
*/
class Border extends AbstractStyle
{
+ const DEFAULT_MARGIN = 1440; // In twips.
+
/**
* Border Top Size.
*
@@ -106,6 +108,34 @@ class Border extends AbstractStyle
*/
protected $borderBottomStyle;
+ /**
+ * Top margin spacing.
+ *
+ * @var float|int
+ */
+ protected $marginTop = self::DEFAULT_MARGIN;
+
+ /**
+ * Left margin spacing.
+ *
+ * @var float|int
+ */
+ protected $marginLeft = self::DEFAULT_MARGIN;
+
+ /**
+ * Right margin spacing.
+ *
+ * @var float|int
+ */
+ protected $marginRight = self::DEFAULT_MARGIN;
+
+ /**
+ * Bottom margin spacing.
+ *
+ * @var float|int
+ */
+ protected $marginBottom = self::DEFAULT_MARGIN;
+
/**
* Get border size.
*
@@ -501,4 +531,100 @@ public function hasBorder()
return $borders !== array_filter($borders, 'is_null');
}
+
+ /**
+ * Get Margin Top.
+ *
+ * @return float|int
+ */
+ public function getMarginTop()
+ {
+ return $this->marginTop;
+ }
+
+ /**
+ * Set Margin Top.
+ *
+ * @param float|int $value
+ *
+ * @return self
+ */
+ public function setMarginTop($value = null)
+ {
+ $this->marginTop = $this->setNumericVal($value, self::DEFAULT_MARGIN);
+
+ return $this;
+ }
+
+ /**
+ * Get Margin Left.
+ *
+ * @return float|int
+ */
+ public function getMarginLeft()
+ {
+ return $this->marginLeft;
+ }
+
+ /**
+ * Set Margin Left.
+ *
+ * @param float|int $value
+ *
+ * @return self
+ */
+ public function setMarginLeft($value = null)
+ {
+ $this->marginLeft = $this->setNumericVal($value, self::DEFAULT_MARGIN);
+
+ return $this;
+ }
+
+ /**
+ * Get Margin Right.
+ *
+ * @return float|int
+ */
+ public function getMarginRight()
+ {
+ return $this->marginRight;
+ }
+
+ /**
+ * Set Margin Right.
+ *
+ * @param float|int $value
+ *
+ * @return self
+ */
+ public function setMarginRight($value = null)
+ {
+ $this->marginRight = $this->setNumericVal($value, self::DEFAULT_MARGIN);
+
+ return $this;
+ }
+
+ /**
+ * Get Margin Bottom.
+ *
+ * @return float|int
+ */
+ public function getMarginBottom()
+ {
+ return $this->marginBottom;
+ }
+
+ /**
+ * Set Margin Bottom.
+ *
+ * @param float|int $value
+ *
+ * @return self
+ */
+ public function setMarginBottom($value = null)
+ {
+ $this->marginBottom = $this->setNumericVal($value, self::DEFAULT_MARGIN);
+
+ return $this;
+ }
}
diff --git a/src/PhpWord/Style/Section.php b/src/PhpWord/Style/Section.php
index d4ede285e7..3b08aa5f38 100644
--- a/src/PhpWord/Style/Section.php
+++ b/src/PhpWord/Style/Section.php
@@ -40,7 +40,6 @@ class Section extends Border
*/
const DEFAULT_WIDTH = 11905.511811024; // In twips.
const DEFAULT_HEIGHT = 16837.79527559; // In twips.
- const DEFAULT_MARGIN = 1440; // In twips.
const DEFAULT_GUTTER = 0; // In twips.
const DEFAULT_HEADER_HEIGHT = 720; // In twips.
const DEFAULT_FOOTER_HEIGHT = 720; // In twips.
@@ -77,34 +76,6 @@ class Section extends Border
*/
private $pageSizeH = self::DEFAULT_HEIGHT;
- /**
- * Top margin spacing.
- *
- * @var float|int
- */
- private $marginTop = self::DEFAULT_MARGIN;
-
- /**
- * Left margin spacing.
- *
- * @var float|int
- */
- private $marginLeft = self::DEFAULT_MARGIN;
-
- /**
- * Right margin spacing.
- *
- * @var float|int
- */
- private $marginRight = self::DEFAULT_MARGIN;
-
- /**
- * Bottom margin spacing.
- *
- * @var float|int
- */
- private $marginBottom = self::DEFAULT_MARGIN;
-
/**
* Page gutter spacing.
*
@@ -344,102 +315,6 @@ public function setPageSizeH($value = null)
return $this;
}
- /**
- * Get Margin Top.
- *
- * @return float|int
- */
- public function getMarginTop()
- {
- return $this->marginTop;
- }
-
- /**
- * Set Margin Top.
- *
- * @param float|int $value
- *
- * @return self
- */
- public function setMarginTop($value = null)
- {
- $this->marginTop = $this->setNumericVal($value, self::DEFAULT_MARGIN);
-
- return $this;
- }
-
- /**
- * Get Margin Left.
- *
- * @return float|int
- */
- public function getMarginLeft()
- {
- return $this->marginLeft;
- }
-
- /**
- * Set Margin Left.
- *
- * @param float|int $value
- *
- * @return self
- */
- public function setMarginLeft($value = null)
- {
- $this->marginLeft = $this->setNumericVal($value, self::DEFAULT_MARGIN);
-
- return $this;
- }
-
- /**
- * Get Margin Right.
- *
- * @return float|int
- */
- public function getMarginRight()
- {
- return $this->marginRight;
- }
-
- /**
- * Set Margin Right.
- *
- * @param float|int $value
- *
- * @return self
- */
- public function setMarginRight($value = null)
- {
- $this->marginRight = $this->setNumericVal($value, self::DEFAULT_MARGIN);
-
- return $this;
- }
-
- /**
- * Get Margin Bottom.
- *
- * @return float|int
- */
- public function getMarginBottom()
- {
- return $this->marginBottom;
- }
-
- /**
- * Set Margin Bottom.
- *
- * @param float|int $value
- *
- * @return self
- */
- public function setMarginBottom($value = null)
- {
- $this->marginBottom = $this->setNumericVal($value, self::DEFAULT_MARGIN);
-
- return $this;
- }
-
/**
* Get gutter.
*
diff --git a/tests/PhpWordTests/Reader/Word2007/StyleTest.php b/tests/PhpWordTests/Reader/Word2007/StyleTest.php
index be80dc513e..015a3cfcb7 100644
--- a/tests/PhpWordTests/Reader/Word2007/StyleTest.php
+++ b/tests/PhpWordTests/Reader/Word2007/StyleTest.php
@@ -17,6 +17,7 @@
namespace PhpOffice\PhpWordTests\Reader\Word2007;
+use PhpOffice\PhpWord\SimpleType\Border;
use PhpOffice\PhpWord\SimpleType\TblWidth;
use PhpOffice\PhpWord\SimpleType\VerticalJc;
use PhpOffice\PhpWord\Style;
@@ -48,28 +49,6 @@ public function testReadTableLayout(): void
self::assertEquals(Table::LAYOUT_FIXED, $elements[0]->getStyle()->getLayout());
}
- /**
- * Test reading of cell spacing.
- */
- public function testReadCellSpacing(): void
- {
- $documentXml = '
-
-
-
- ';
-
- $phpWord = $this->getDocumentFromString(['document' => $documentXml]);
-
- $elements = $phpWord->getSection(0)->getElements();
- self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]);
- self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle());
- /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */
- $tableStyle = $elements[0]->getStyle();
- self::assertEquals(TblWidth::AUTO, $tableStyle->getUnit());
- self::assertEquals(10.5, $tableStyle->getCellSpacing());
- }
-
/**
* Test reading of table position.
*/
@@ -102,6 +81,90 @@ public function testReadTablePosition(): void
self::assertEquals(60, $tableStyle->getTblpY());
}
+ public function testReadTableCellNoWrap(): void
+ {
+ $documentXml = '
+
+
+
+
+
+
+
+ ';
+
+ $phpWord = $this->getDocumentFromString(['document' => $documentXml]);
+
+ $elements = $phpWord->getSection(0)->getElements();
+ self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]);
+ $rows = $elements[0]->getRows();
+ $cells = $rows[0]->getCells();
+ self::assertTrue($cells[0]->getStyle()->getNoWrap());
+ }
+
+ /**
+ * Test reading of cell spacing.
+ */
+ public function testReadTableCellSpacing(): void
+ {
+ $documentXml = '
+
+
+
+ ';
+
+ $phpWord = $this->getDocumentFromString(['document' => $documentXml]);
+
+ $elements = $phpWord->getSection(0)->getElements();
+ self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]);
+ self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle());
+ /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */
+ $tableStyle = $elements[0]->getStyle();
+ self::assertEquals(TblWidth::AUTO, $tableStyle->getUnit());
+ self::assertEquals(10.5, $tableStyle->getCellSpacing());
+ }
+
+ public function testReadTableCellStyle(): void
+ {
+ $documentXml = '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ';
+
+ $phpWord = $this->getDocumentFromString(['document' => $documentXml]);
+
+ $elements = $phpWord->getSection(0)->getElements();
+ self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]);
+ $rows = $elements[0]->getRows();
+ self::assertInstanceOf('PhpOffice\PhpWord\Element\Row', $rows[0]);
+ $cells = $rows[0]->getCells();
+ self::assertInstanceOf('PhpOffice\PhpWord\Element\Cell', $cells[0]);
+ $styleCell = $cells[0]->getStyle();
+ self::assertInstanceOf('PhpOffice\PhpWord\Style\Cell', $styleCell);
+
+ self::assertEquals(4, $styleCell->getBorderTopSize());
+ self::assertEquals(Border::SINGLE, $styleCell->getBorderTopStyle());
+ self::assertEquals('auto', $styleCell->getBorderTopColor());
+
+ self::assertEquals(4, $styleCell->getBorderBottomSize());
+ self::assertEquals(Border::DOUBLE, $styleCell->getBorderBottomStyle());
+ self::assertEquals('auto', $styleCell->getBorderBottomColor());
+ }
+
/**
* Test reading of position.
*/
@@ -190,27 +253,6 @@ public function testReadHidden(): void
self::assertTrue($fontStyle->isHidden());
}
- public function testReadTableCellNoWrap(): void
- {
- $documentXml = '
-
-
-
-
-
-
-
- ';
-
- $phpWord = $this->getDocumentFromString(['document' => $documentXml]);
-
- $elements = $phpWord->getSection(0)->getElements();
- self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]);
- $rows = $elements[0]->getRows();
- $cells = $rows[0]->getCells();
- self::assertTrue($cells[0]->getStyle()->getNoWrap());
- }
-
public function testReadHeading(): void
{
Style::resetStyles();