add HTML table parsing
This commit is contained in:
parent
c9350d3e80
commit
8eb72c976a
|
|
@ -14,6 +14,20 @@ $html .= '<ul><li>Item 1</li><li>Item 2</li><ul><li>Item 2.1</li><li>Item 2.1</l
|
||||||
$html .= '<p>Ordered (numbered) list:</p>';
|
$html .= '<p>Ordered (numbered) list:</p>';
|
||||||
$html .= '<ol><li>Item 1</li><li>Item 2</li></ol>';
|
$html .= '<ol><li>Item 1</li><li>Item 2</li></ol>';
|
||||||
|
|
||||||
|
$html .= '<table style="width: 50%; border: 6px #0000FF double;">
|
||||||
|
<thead>
|
||||||
|
<tr style="background-color: #FF0000; text-align: center; color: #FFFFFF; font-weight: bold; ">
|
||||||
|
<th>header a</th>
|
||||||
|
<th>header b</th>
|
||||||
|
<th style="background-color: #FFFF00; border-width: 12px"><span style="background-color: #00FF00;">header c</span></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td style="border-style: dotted;">1</td><td colspan="2">2</td></tr>
|
||||||
|
<tr><td>4</td><td>5</td><td>6</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>';
|
||||||
|
|
||||||
\PhpOffice\PhpWord\Shared\Html::addHtml($section, $html);
|
\PhpOffice\PhpWord\Shared\Html::addHtml($section, $html);
|
||||||
|
|
||||||
// Save file
|
// Save file
|
||||||
|
|
|
||||||
|
|
@ -296,25 +296,40 @@ class Converter
|
||||||
*/
|
*/
|
||||||
public static function cssToPoint($value)
|
public static function cssToPoint($value)
|
||||||
{
|
{
|
||||||
preg_match('/^[+-]?([0-9]+.?[0-9]+)?(px|em|ex|%|in|cm|mm|pt|pc)$/i', $value, $matches);
|
if ($value == '0') {
|
||||||
$size = $matches[1];
|
return 0;
|
||||||
$unit = $matches[2];
|
|
||||||
|
|
||||||
switch ($unit) {
|
|
||||||
case 'pt':
|
|
||||||
return $size;
|
|
||||||
case 'px':
|
|
||||||
return self::pixelToPoint($size);
|
|
||||||
case 'cm':
|
|
||||||
return self::cmToPoint($size);
|
|
||||||
case 'mm':
|
|
||||||
return self::cmToPoint($size / 10);
|
|
||||||
case 'in':
|
|
||||||
return self::inchToPoint($size);
|
|
||||||
case 'pc':
|
|
||||||
return self::picaToPoint($size);
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
if (preg_match('/^[+-]?([0-9]+\.?[0-9]*)?(px|em|ex|%|in|cm|mm|pt|pc)$/i', $value, $matches)) {
|
||||||
|
$size = $matches[1];
|
||||||
|
$unit = $matches[2];
|
||||||
|
|
||||||
|
switch ($unit) {
|
||||||
|
case 'pt':
|
||||||
|
return $size;
|
||||||
|
case 'px':
|
||||||
|
return self::pixelToPoint($size);
|
||||||
|
case 'cm':
|
||||||
|
return self::cmToPoint($size);
|
||||||
|
case 'mm':
|
||||||
|
return self::cmToPoint($size / 10);
|
||||||
|
case 'in':
|
||||||
|
return self::inchToPoint($size);
|
||||||
|
case 'pc':
|
||||||
|
return self::picaToPoint($size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms a size in CSS format (eg. 10px, 10px, ...) to twips
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public static function cssToTwip($value)
|
||||||
|
{
|
||||||
|
return self::pointToTwip(self::cssToPoint($value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@
|
||||||
namespace PhpOffice\PhpWord\Shared;
|
namespace PhpOffice\PhpWord\Shared;
|
||||||
|
|
||||||
use PhpOffice\PhpWord\Element\AbstractContainer;
|
use PhpOffice\PhpWord\Element\AbstractContainer;
|
||||||
|
use PhpOffice\PhpWord\Element\Row;
|
||||||
|
use PhpOffice\PhpWord\Element\Table;
|
||||||
use PhpOffice\PhpWord\SimpleType\Jc;
|
use PhpOffice\PhpWord\SimpleType\Jc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -99,7 +101,7 @@ class Html
|
||||||
protected static function parseNode($node, $element, $styles = array(), $data = array())
|
protected static function parseNode($node, $element, $styles = array(), $data = array())
|
||||||
{
|
{
|
||||||
// Populate styles array
|
// Populate styles array
|
||||||
$styleTypes = array('font', 'paragraph', 'list');
|
$styleTypes = array('font', 'paragraph', 'list', 'table', 'row', 'cell');
|
||||||
foreach ($styleTypes as $styleType) {
|
foreach ($styleTypes as $styleType) {
|
||||||
if (!isset($styles[$styleType])) {
|
if (!isset($styles[$styleType])) {
|
||||||
$styles[$styleType] = array();
|
$styles[$styleType] = array();
|
||||||
|
|
@ -124,10 +126,11 @@ class Html
|
||||||
'u' => array('Property', null, null, $styles, null, 'underline', 'single'),
|
'u' => array('Property', null, null, $styles, null, 'underline', 'single'),
|
||||||
'sup' => array('Property', null, null, $styles, null, 'superScript', true),
|
'sup' => array('Property', null, null, $styles, null, 'superScript', true),
|
||||||
'sub' => array('Property', null, null, $styles, null, 'subScript', true),
|
'sub' => array('Property', null, null, $styles, null, 'subScript', true),
|
||||||
'span' => array('Property', null, null, $styles, null, 'span', $node),
|
'span' => array('Span', $node, null, $styles, null, null, null),
|
||||||
'table' => array('Table', $node, $element, $styles, null, 'addTable', true),
|
'table' => array('Table', $node, $element, $styles, null, null, null),
|
||||||
'tr' => array('Table', $node, $element, $styles, null, 'addRow', true),
|
'tr' => array('Row', $node, $element, $styles, null, null, null),
|
||||||
'td' => array('Table', $node, $element, $styles, null, 'addCell', true),
|
'td' => array('Cell', $node, $element, $styles, null, null, null),
|
||||||
|
'th' => array('Cell', $node, $element, $styles, null, null, null),
|
||||||
'ul' => array('List', null, null, $styles, $data, 3, null),
|
'ul' => array('List', null, null, $styles, $data, 3, null),
|
||||||
'ol' => array('List', null, null, $styles, $data, 7, null),
|
'ol' => array('List', null, null, $styles, $data, 7, null),
|
||||||
'li' => array('ListItem', $node, $element, $styles, $data, null, null),
|
'li' => array('ListItem', $node, $element, $styles, $data, null, null),
|
||||||
|
|
@ -179,7 +182,7 @@ class Html
|
||||||
$cNodes = $node->childNodes;
|
$cNodes = $node->childNodes;
|
||||||
if (count($cNodes) > 0) {
|
if (count($cNodes) > 0) {
|
||||||
foreach ($cNodes as $cNode) {
|
foreach ($cNodes as $cNode) {
|
||||||
if ($element instanceof AbstractContainer) {
|
if ($element instanceof AbstractContainer || $element instanceof Table || $element instanceof Row) {
|
||||||
self::parseNode($cNode, $element, $styles, $data);
|
self::parseNode($cNode, $element, $styles, $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -197,7 +200,7 @@ class Html
|
||||||
*/
|
*/
|
||||||
private static function parseParagraph($node, $element, &$styles)
|
private static function parseParagraph($node, $element, &$styles)
|
||||||
{
|
{
|
||||||
$styles['paragraph'] = self::parseInlineStyle($node, $styles['paragraph']);
|
$styles['paragraph'] = self::recursiveParseStylesInHierarchy($node, $styles['paragraph']);
|
||||||
$newElement = $element->addTextRun($styles['paragraph']);
|
$newElement = $element->addTextRun($styles['paragraph']);
|
||||||
|
|
||||||
return $newElement;
|
return $newElement;
|
||||||
|
|
@ -231,7 +234,12 @@ class Html
|
||||||
*/
|
*/
|
||||||
private static function parseText($node, $element, &$styles)
|
private static function parseText($node, $element, &$styles)
|
||||||
{
|
{
|
||||||
$styles['font'] = self::parseInlineStyle($node, $styles['font']);
|
$styles['font'] = self::recursiveParseStylesInHierarchy($node, $styles['font']);
|
||||||
|
|
||||||
|
//alignment applies on paragraph, not on font. Let's copy it there
|
||||||
|
if (isset($styles['font']['alignment'])) {
|
||||||
|
$styles['paragraph']['alignment'] = $styles['font']['alignment'];
|
||||||
|
}
|
||||||
|
|
||||||
if (is_callable(array($element, 'addText'))) {
|
if (is_callable(array($element, 'addText'))) {
|
||||||
$element->addText($node->nodeValue, $styles['font'], $styles['paragraph']);
|
$element->addText($node->nodeValue, $styles['font'], $styles['paragraph']);
|
||||||
|
|
@ -247,16 +255,18 @@ class Html
|
||||||
*/
|
*/
|
||||||
private static function parseProperty(&$styles, $argument1, $argument2)
|
private static function parseProperty(&$styles, $argument1, $argument2)
|
||||||
{
|
{
|
||||||
if ($argument1 !== 'span') {
|
$styles['font'][$argument1] = $argument2;
|
||||||
$styles['font'][$argument1] = $argument2;
|
}
|
||||||
} else {
|
|
||||||
if (!is_null($argument2->attributes)) {
|
/**
|
||||||
$nodeAttr = $argument2->attributes->getNamedItem('style');
|
* Parse span node
|
||||||
if (!is_null($nodeAttr) && property_exists($nodeAttr, 'value')) {
|
*
|
||||||
$styles['font'] = self::parseStyle($nodeAttr, $styles['font']);
|
* @param \DOMNode $node
|
||||||
}
|
* @param array &$styles
|
||||||
}
|
*/
|
||||||
}
|
private static function parseSpan($node, &$styles)
|
||||||
|
{
|
||||||
|
self::parseInlineStyle($node, $styles['font']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -270,11 +280,11 @@ class Html
|
||||||
*
|
*
|
||||||
* @todo As soon as TableItem, RowItem and CellItem support relative width and height
|
* @todo As soon as TableItem, RowItem and CellItem support relative width and height
|
||||||
*/
|
*/
|
||||||
private static function parseTable($node, $element, &$styles, $argument1)
|
private static function parseTable($node, $element, &$styles)
|
||||||
{
|
{
|
||||||
$styles['paragraph'] = self::parseInlineStyle($node, $styles['paragraph']);
|
$elementStyles = self::parseInlineStyle($node, $styles['table']);
|
||||||
|
|
||||||
$newElement = $element->$argument1();
|
$newElement = $element->addTable($elementStyles);
|
||||||
|
|
||||||
// $attributes = $node->attributes;
|
// $attributes = $node->attributes;
|
||||||
// if ($attributes->getNamedItem('width') !== null) {
|
// if ($attributes->getNamedItem('width') !== null) {
|
||||||
|
|
@ -291,6 +301,62 @@ class Html
|
||||||
return $newElement;
|
return $newElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a table row
|
||||||
|
*
|
||||||
|
* @param \DOMNode $node
|
||||||
|
* @param \PhpOffice\PhpWord\Element\Table $element
|
||||||
|
* @param array &$styles
|
||||||
|
* @return \PhpOffice\PhpWord\Element\AbstractContainer $element
|
||||||
|
*/
|
||||||
|
private static function parseRow($node, $element, &$styles)
|
||||||
|
{
|
||||||
|
$rowStyles = self::parseInlineStyle($node, $styles['row']);
|
||||||
|
if ($node->parentNode->nodeName == 'thead') {
|
||||||
|
$rowStyles['tblHeader'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $element->addRow(null, $rowStyles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse table cell
|
||||||
|
*
|
||||||
|
* @param \DOMNode $node
|
||||||
|
* @param \PhpOffice\PhpWord\Element\Table $element
|
||||||
|
* @param array &$styles
|
||||||
|
* @return \PhpOffice\PhpWord\Element\AbstractContainer $element
|
||||||
|
*/
|
||||||
|
private static function parseCell($node, $element, &$styles)
|
||||||
|
{
|
||||||
|
$cellStyles = self::recursiveParseStylesInHierarchy($node, $styles['cell']);
|
||||||
|
|
||||||
|
$colspan = $node->getAttribute('colspan');
|
||||||
|
if (!empty($colspan)) {
|
||||||
|
$cellStyles['gridSpan'] = $colspan - 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $element->addCell(null, $cellStyles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively parses styles on parent nodes
|
||||||
|
* TODO if too slow, add caching of parent nodes, !! everything is static here so watch out for concurrency !!
|
||||||
|
*
|
||||||
|
* @param \DOMNode $node
|
||||||
|
* @param array &$styles
|
||||||
|
*/
|
||||||
|
private static function recursiveParseStylesInHierarchy(\DOMNode $node, array $style)
|
||||||
|
{
|
||||||
|
$parentStyle = self::parseInlineStyle($node, array());
|
||||||
|
$style = array_merge($parentStyle, $style);
|
||||||
|
if ($node->parentNode != null && XML_ELEMENT_NODE == $node->parentNode->nodeType) {
|
||||||
|
$style = self::recursiveParseStylesInHierarchy($node->parentNode, $style);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $style;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse list node
|
* Parse list node
|
||||||
*
|
*
|
||||||
|
|
@ -400,9 +466,59 @@ class Html
|
||||||
}
|
}
|
||||||
$styles['italic'] = $tValue;
|
$styles['italic'] = $tValue;
|
||||||
break;
|
break;
|
||||||
|
case 'border-color':
|
||||||
|
$styles['color'] = trim($cValue, '#');
|
||||||
|
break;
|
||||||
|
case 'border-width':
|
||||||
|
$styles['borderSize'] = Converter::cssToPoint($cValue);
|
||||||
|
break;
|
||||||
|
case 'border-style':
|
||||||
|
$styles['borderStyle'] = self::mapBorderStyle($cValue);
|
||||||
|
break;
|
||||||
|
case 'width':
|
||||||
|
if (preg_match('/([0-9]+[a-z]+)/', $cValue, $matches)) {
|
||||||
|
$styles['width'] = Converter::cssToTwip($matches[1]);
|
||||||
|
$styles['unit'] = \PhpOffice\PhpWord\Style\Table::WIDTH_TWIP;
|
||||||
|
} elseif (preg_match('/([0-9]+)%/', $cValue, $matches)) {
|
||||||
|
$styles['width'] = $matches[1] * 50;
|
||||||
|
$styles['unit'] = \PhpOffice\PhpWord\Style\Table::WIDTH_PERCENT;
|
||||||
|
} elseif (preg_match('/([0-9]+)/', $cValue, $matches)) {
|
||||||
|
$styles['width'] = $matches[1];
|
||||||
|
$styles['unit'] = \PhpOffice\PhpWord\Style\Table::WIDTH_AUTO;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'border':
|
||||||
|
if (preg_match('/([0-9]+[^0-9]*)\s+(\#[a-fA-F0-9]+)\s+([a-z]+)/', $cValue, $matches)) {
|
||||||
|
$styles['borderSize'] = Converter::cssToPoint($matches[1]);
|
||||||
|
$styles['borderColor'] = trim($matches[2], '#');
|
||||||
|
$styles['borderStyle'] = self::mapBorderStyle($matches[3]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $styles;
|
return $styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms a CSS border style into a word border style
|
||||||
|
*
|
||||||
|
* @param string $cssBorderStyle
|
||||||
|
* @return null|string
|
||||||
|
*/
|
||||||
|
private static function mapBorderStyle($cssBorderStyle)
|
||||||
|
{
|
||||||
|
if ($cssBorderStyle == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
switch ($cssBorderStyle) {
|
||||||
|
case 'none':
|
||||||
|
case 'dashed':
|
||||||
|
case 'dotted':
|
||||||
|
case 'double':
|
||||||
|
return $cssBorderStyle;
|
||||||
|
case 'solid':
|
||||||
|
return 'single';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,13 @@ class Border extends AbstractStyle
|
||||||
*/
|
*/
|
||||||
protected $borderTopColor;
|
protected $borderTopColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Border Top Style
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $borderTopStyle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Border Left Size
|
* Border Left Size
|
||||||
*
|
*
|
||||||
|
|
@ -50,6 +57,13 @@ class Border extends AbstractStyle
|
||||||
*/
|
*/
|
||||||
protected $borderLeftColor;
|
protected $borderLeftColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Border Left Style
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $borderLeftStyle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Border Right Size
|
* Border Right Size
|
||||||
*
|
*
|
||||||
|
|
@ -64,6 +78,13 @@ class Border extends AbstractStyle
|
||||||
*/
|
*/
|
||||||
protected $borderRightColor;
|
protected $borderRightColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Border Right Style
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $borderRightStyle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Border Bottom Size
|
* Border Bottom Size
|
||||||
*
|
*
|
||||||
|
|
@ -78,6 +99,13 @@ class Border extends AbstractStyle
|
||||||
*/
|
*/
|
||||||
protected $borderBottomColor;
|
protected $borderBottomColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Border Bottom Style
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $borderBottomStyle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get border size
|
* Get border size
|
||||||
*
|
*
|
||||||
|
|
@ -140,6 +168,37 @@ class Border extends AbstractStyle
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get border style
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getBorderStyle()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
$this->getBorderTopStyle(),
|
||||||
|
$this->getBorderLeftStyle(),
|
||||||
|
$this->getBorderRightStyle(),
|
||||||
|
$this->getBorderBottomStyle(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set border style
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setBorderStyle($value = null)
|
||||||
|
{
|
||||||
|
$this->setBorderTopStyle($value);
|
||||||
|
$this->setBorderLeftStyle($value);
|
||||||
|
$this->setBorderRightStyle($value);
|
||||||
|
$this->setBorderBottomStyle($value);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get border top size
|
* Get border top size
|
||||||
*
|
*
|
||||||
|
|
@ -186,6 +245,29 @@ class Border extends AbstractStyle
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get border top style
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getBorderTopStyle()
|
||||||
|
{
|
||||||
|
return $this->borderTopStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set border top Style
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setBorderTopStyle($value = null)
|
||||||
|
{
|
||||||
|
$this->borderTopStyle = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get border left size
|
* Get border left size
|
||||||
*
|
*
|
||||||
|
|
@ -232,6 +314,29 @@ class Border extends AbstractStyle
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get border left style
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getBorderLeftStyle()
|
||||||
|
{
|
||||||
|
return $this->borderLeftStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set border left style
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setBorderLeftStyle($value = null)
|
||||||
|
{
|
||||||
|
$this->borderLeftStyle = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get border right size
|
* Get border right size
|
||||||
*
|
*
|
||||||
|
|
@ -278,6 +383,29 @@ class Border extends AbstractStyle
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get border right style
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getBorderRightStyle()
|
||||||
|
{
|
||||||
|
return $this->borderRightStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set border right style
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setBorderRightStyle($value = null)
|
||||||
|
{
|
||||||
|
$this->borderRightStyle = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get border bottom size
|
* Get border bottom size
|
||||||
*
|
*
|
||||||
|
|
@ -324,6 +452,29 @@ class Border extends AbstractStyle
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get border bottom style
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getBorderBottomStyle()
|
||||||
|
{
|
||||||
|
return $this->borderBottomStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set border bottom style
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setBorderBottomStyle($value = null)
|
||||||
|
{
|
||||||
|
$this->borderBottomStyle = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if any of the border is not null
|
* Check if any of the border is not null
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,31 @@ class Cell extends Border
|
||||||
const VALIGN_BOTTOM = 'bottom';
|
const VALIGN_BOTTOM = 'bottom';
|
||||||
const VALIGN_BOTH = 'both';
|
const VALIGN_BOTH = 'both';
|
||||||
|
|
||||||
|
//Text direction constants
|
||||||
/**
|
/**
|
||||||
* Text direction constants
|
* Left to Right, Top to Bottom
|
||||||
*
|
*/
|
||||||
* @const string
|
const TEXT_DIR_LRTB = 'lrTb';
|
||||||
|
/**
|
||||||
|
* Top to Bottom, Right to Left
|
||||||
|
*/
|
||||||
|
const TEXT_DIR_TBRL = 'tbRl';
|
||||||
|
/**
|
||||||
|
* Bottom to Top, Left to Right
|
||||||
*/
|
*/
|
||||||
const TEXT_DIR_BTLR = 'btLr';
|
const TEXT_DIR_BTLR = 'btLr';
|
||||||
const TEXT_DIR_TBRL = 'tbRl';
|
/**
|
||||||
|
* Left to Right, Top to Bottom Rotated
|
||||||
|
*/
|
||||||
|
const TEXT_DIR_LRTBV = 'lrTbV';
|
||||||
|
/**
|
||||||
|
* Top to Bottom, Right to Left Rotated
|
||||||
|
*/
|
||||||
|
const TEXT_DIR_TBRLV = 'tbRlV';
|
||||||
|
/**
|
||||||
|
* Top to Bottom, Left to Right Rotated
|
||||||
|
*/
|
||||||
|
const TEXT_DIR_TBLRV = 'tbLrV';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vertical merge (rowspan) constants
|
* Vertical merge (rowspan) constants
|
||||||
|
|
@ -93,6 +111,20 @@ class Cell extends Border
|
||||||
*/
|
*/
|
||||||
private $shading;
|
private $shading;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Width
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $width;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Width type
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $widthType = Table::WIDTH_TWIP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get vertical align.
|
* Get vertical align.
|
||||||
*
|
*
|
||||||
|
|
@ -236,6 +268,51 @@ class Cell extends Border
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell width
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getWidth()
|
||||||
|
{
|
||||||
|
return $this->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set cell width
|
||||||
|
*
|
||||||
|
* @param int $value
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setWidth($value)
|
||||||
|
{
|
||||||
|
$this->setIntVal($value);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get width type
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getWidthType()
|
||||||
|
{
|
||||||
|
return $this->widthType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set width type
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function setWidthType($value)
|
||||||
|
{
|
||||||
|
$this->widthType = $this->setEnumVal($value, array(Table::WIDTH_AUTO, Table::WIDTH_PERCENT, Table::WIDTH_TWIP), Table::WIDTH_TWIP);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get default border color
|
* Get default border color
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ class Cell extends AbstractStyle
|
||||||
$styleWriter = new MarginBorder($xmlWriter);
|
$styleWriter = new MarginBorder($xmlWriter);
|
||||||
$styleWriter->setSizes($style->getBorderSize());
|
$styleWriter->setSizes($style->getBorderSize());
|
||||||
$styleWriter->setColors($style->getBorderColor());
|
$styleWriter->setColors($style->getBorderColor());
|
||||||
|
$styleWriter->setStyles($style->getBorderStyle());
|
||||||
$styleWriter->setAttributes(array('defaultColor' => CellStyle::DEFAULT_BORDER_COLOR));
|
$styleWriter->setAttributes(array('defaultColor' => CellStyle::DEFAULT_BORDER_COLOR));
|
||||||
$styleWriter->write();
|
$styleWriter->write();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,13 @@ class MarginBorder extends AbstractStyle
|
||||||
*/
|
*/
|
||||||
private $colors = array();
|
private $colors = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Border styles
|
||||||
|
*
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
private $styles = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Other attributes
|
* Other attributes
|
||||||
*
|
*
|
||||||
|
|
@ -62,7 +69,8 @@ class MarginBorder extends AbstractStyle
|
||||||
if (isset($this->colors[$i])) {
|
if (isset($this->colors[$i])) {
|
||||||
$color = $this->colors[$i];
|
$color = $this->colors[$i];
|
||||||
}
|
}
|
||||||
$this->writeSide($xmlWriter, $sides[$i], $this->sizes[$i], $color);
|
$style = isset($this->styles[$i]) ? $this->styles[$i] : 'single';
|
||||||
|
$this->writeSide($xmlWriter, $sides[$i], $this->sizes[$i], $color, $style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -74,8 +82,9 @@ class MarginBorder extends AbstractStyle
|
||||||
* @param string $side
|
* @param string $side
|
||||||
* @param int $width
|
* @param int $width
|
||||||
* @param string $color
|
* @param string $color
|
||||||
|
* @param string $borderStyle
|
||||||
*/
|
*/
|
||||||
private function writeSide(XMLWriter $xmlWriter, $side, $width, $color = null)
|
private function writeSide(XMLWriter $xmlWriter, $side, $width, $color = null, $borderStyle = 'solid')
|
||||||
{
|
{
|
||||||
$xmlWriter->startElement('w:' . $side);
|
$xmlWriter->startElement('w:' . $side);
|
||||||
if (!empty($this->colors)) {
|
if (!empty($this->colors)) {
|
||||||
|
|
@ -84,9 +93,9 @@ class MarginBorder extends AbstractStyle
|
||||||
$color = $this->attributes['defaultColor'];
|
$color = $this->attributes['defaultColor'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$xmlWriter->writeAttribute('w:val', 'single');
|
$xmlWriter->writeAttribute('w:val', $borderStyle);
|
||||||
$xmlWriter->writeAttribute('w:sz', $width);
|
$xmlWriter->writeAttribute('w:sz', $width);
|
||||||
$xmlWriter->writeAttribute('w:color', $color);
|
$xmlWriter->writeAttributeIf($color != null, 'w:color', $color);
|
||||||
if (!empty($this->attributes)) {
|
if (!empty($this->attributes)) {
|
||||||
if (isset($this->attributes['space'])) {
|
if (isset($this->attributes['space'])) {
|
||||||
$xmlWriter->writeAttribute('w:space', $this->attributes['space']);
|
$xmlWriter->writeAttribute('w:space', $this->attributes['space']);
|
||||||
|
|
@ -119,6 +128,16 @@ class MarginBorder extends AbstractStyle
|
||||||
$this->colors = $value;
|
$this->colors = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set border styles.
|
||||||
|
*
|
||||||
|
* @param string[] $value
|
||||||
|
*/
|
||||||
|
public function setStyles($value)
|
||||||
|
{
|
||||||
|
$this->styles = $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set attributes.
|
* Set attributes.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,9 @@ class Shading extends AbstractStyle
|
||||||
$xmlWriter = $this->getXmlWriter();
|
$xmlWriter = $this->getXmlWriter();
|
||||||
|
|
||||||
$xmlWriter->startElement('w:shd');
|
$xmlWriter->startElement('w:shd');
|
||||||
$xmlWriter->writeAttribute('w:val', $style->getPattern());
|
$xmlWriter->writeAttributeIf(!is_null($style->getPattern()), 'w:val', $style->getPattern());
|
||||||
$xmlWriter->writeAttribute('w:color', $style->getColor());
|
$xmlWriter->writeAttributeIf(!is_null($style->getColor()), 'w:color', $style->getColor());
|
||||||
$xmlWriter->writeAttribute('w:fill', $style->getFill());
|
$xmlWriter->writeAttributeIf(!is_null($style->getFill()), 'w:fill', $style->getFill());
|
||||||
$xmlWriter->endElement();
|
$xmlWriter->endElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,25 +187,23 @@ class HtmlTest extends \PHPUnit\Framework\TestCase
|
||||||
{
|
{
|
||||||
$phpWord = new \PhpOffice\PhpWord\PhpWord();
|
$phpWord = new \PhpOffice\PhpWord\PhpWord();
|
||||||
$section = $phpWord->addSection();
|
$section = $phpWord->addSection();
|
||||||
$html = '
|
$html = '<table style="width: 50%; border: 6px #0000FF solid;">
|
||||||
<table style="width: 50%; border: 6px #0000FF solid;">
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr style="background-color: #FF0000; text-align: center; color: #FFFFFF; font-weight: bold; ">
|
<tr style="background-color: #FF0000; text-align: center; color: #FFFFFF; font-weight: bold; ">
|
||||||
<th>a</th>
|
<th>header a</th>
|
||||||
<th>b</th>
|
<th>header b</th>
|
||||||
<th>c</th>
|
<th style="border-color: #00FF00; border-width: 3px">header c</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>1</td><td colspan="2">2</td></tr>
|
<tr><td style="border-style: dotted;">1</td><td colspan="2">2</td></tr>
|
||||||
<tr><td>4</td><td>5</td><td>6</td></tr>
|
<tr><td>4</td><td>5</td><td>6</td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>';
|
</table>';
|
||||||
Html::addHtml($section, $html);
|
Html::addHtml($section, $html);
|
||||||
|
|
||||||
$doc = TestHelperDOCX::getDocument($phpWord, 'Word2007');
|
$doc = TestHelperDOCX::getDocument($phpWord, 'Word2007');
|
||||||
// echo $doc->printXml();
|
$this->assertTrue($doc->elementExists('/w:document/w:body/w:tbl'));
|
||||||
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p'));
|
$this->assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr/w:tc'));
|
||||||
// $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:tbl/w:tr/w:tc'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase
|
||||||
$elements = array(
|
$elements = array(
|
||||||
'CheckBox', 'Container', 'Footnote', 'Image', 'Link', 'ListItem', 'ListItemRun',
|
'CheckBox', 'Container', 'Footnote', 'Image', 'Link', 'ListItem', 'ListItemRun',
|
||||||
'Object', 'PreserveText', 'Table', 'Text', 'TextBox', 'TextBreak', 'Title', 'TOC',
|
'Object', 'PreserveText', 'Table', 'Text', 'TextBox', 'TextBreak', 'Title', 'TOC',
|
||||||
'Field', 'Line', 'Shape', 'Chart', 'FormField', 'SDT',
|
'Field', 'Line', 'Shape', 'Chart', 'FormField', 'SDT', 'Bookmark',
|
||||||
);
|
);
|
||||||
foreach ($elements as $element) {
|
foreach ($elements as $element) {
|
||||||
$objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $element;
|
$objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $element;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue