protected function writeShapeTable(XMLWriter $objWriter, ShapeTable $shape, $shapeId)
{
// p:graphicFrame
$objWriter->startElement('p:graphicFrame');
// p:nvGraphicFramePr
$objWriter->startElement('p:nvGraphicFramePr');
// p:cNvPr
$objWriter->startElement('p:cNvPr');
$objWriter->writeAttribute('id', $shapeId);
$objWriter->writeAttribute('name', $shape->getName());
$objWriter->writeAttribute('descr', $shape->getDescription());
$objWriter->endElement();
// p:cNvGraphicFramePr
$objWriter->startElement('p:cNvGraphicFramePr');
// a:graphicFrameLocks
$objWriter->startElement('a:graphicFrameLocks');
$objWriter->writeAttribute('noGrp', '1');
$objWriter->endElement();
$objWriter->endElement();
// p:nvPr
$objWriter->startElement('p:nvPr');
if ($shape->isPlaceholder()) {
$objWriter->startElement('p:ph');
$objWriter->writeAttribute('type', $shape->getPlaceholder()->getType());
$objWriter->endElement();
}
$objWriter->endElement();
$objWriter->endElement();
// p:xfrm
$objWriter->startElement('p:xfrm');
// a:off
$objWriter->startElement('a:off');
$objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
$objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
$objWriter->endElement();
// a:ext
$objWriter->startElement('a:ext');
$objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
$objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
$objWriter->endElement();
$objWriter->endElement();
// a:graphic
$objWriter->startElement('a:graphic');
// a:graphicData
$objWriter->startElement('a:graphicData');
$objWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/table');
// a:tbl
$objWriter->startElement('a:tbl');
// a:tblPr
$objWriter->startElement('a:tblPr');
$objWriter->writeAttribute('firstRow', '1');
$objWriter->writeAttribute('bandRow', '1');
$objWriter->endElement();
// a:tblGrid
$objWriter->startElement('a:tblGrid');
// Write cell widths
$countCells = count($shape->getRow(0)->getCells());
for ($cell = 0; $cell < $countCells; $cell++) {
// a:gridCol
$objWriter->startElement('a:gridCol');
// Calculate column width
$width = $shape->getRow(0)->getCell($cell)->getWidth();
if ($width == 0) {
$colCount = count($shape->getRow(0)->getCells());
$totalWidth = $shape->getWidth();
$width = $totalWidth / $colCount;
}
$objWriter->writeAttribute('w', CommonDrawing::pixelsToEmu($width));
$objWriter->endElement();
}
$objWriter->endElement();
// Colspan / rowspan containers
$colSpan = array();
$rowSpan = array();
// Default border style
$defaultBorder = new Border();
// Write rows
$countRows = count($shape->getRows());
for ($row = 0; $row < $countRows; $row++) {
// a:tr
$objWriter->startElement('a:tr');
$objWriter->writeAttribute('h', CommonDrawing::pixelsToEmu($shape->getRow($row)->getHeight()));
// Write cells
$countCells = count($shape->getRow($row)->getCells());
for ($cell = 0; $cell < $countCells; $cell++) {
// Current cell
$currentCell = $shape->getRow($row)->getCell($cell);
// Next cell right
$nextCellRight = $shape->getRow($row)->getCell($cell + 1, true);
// Next cell below
$nextRowBelow = $shape->getRow($row + 1, true);
$nextCellBelow = null;
if ($nextRowBelow != null) {
$nextCellBelow = $nextRowBelow->getCell($cell, true);
}
// a:tc
$objWriter->startElement('a:tc');
// Colspan
if ($currentCell->getColSpan() > 1) {
$objWriter->writeAttribute('gridSpan', $currentCell->getColSpan());
$colSpan[$row] = $currentCell->getColSpan() - 1;
} elseif (isset($colSpan[$row]) && $colSpan[$row] > 0) {
$colSpan[$row]--;
$objWriter->writeAttribute('hMerge', '1');
}
// Rowspan
if ($currentCell->getRowSpan() > 1) {
$objWriter->writeAttribute('rowSpan', $currentCell->getRowSpan());
$rowSpan[$cell] = $currentCell->getRowSpan() - 1;
} elseif (isset($rowSpan[$cell]) && $rowSpan[$cell] > 0) {
$rowSpan[$cell]--;
$objWriter->writeAttribute('vMerge', '1');
}
// a:txBody
$objWriter->startElement('a:txBody');
// a:bodyPr
$objWriter->startElement('a:bodyPr');
$objWriter->writeAttribute('wrap', 'square');
$objWriter->writeAttribute('rtlCol', '0');
// a:spAutoFit
$objWriter->writeElement('a:spAutoFit', null);
$objWriter->endElement();
// a:lstStyle
$objWriter->writeElement('a:lstStyle', null);
// Write paragraphs
$this->writeParagraphs($objWriter, $currentCell->getParagraphs());
$objWriter->endElement();
// a:tcPr
$objWriter->startElement('a:tcPr');
// Alignment (horizontal)
$firstParagraph = $currentCell->getParagraph(0);
$verticalAlign = $firstParagraph->getAlignment()->getVertical();
if ($verticalAlign != Alignment::VERTICAL_BASE && $verticalAlign != Alignment::VERTICAL_AUTO) {
$objWriter->writeAttribute('anchor', $verticalAlign);
}
// Determine borders
$borderLeft = $currentCell->getBorders()->getLeft();
$borderRight = $currentCell->getBorders()->getRight();
$borderTop = $currentCell->getBorders()->getTop();
$borderBottom = $currentCell->getBorders()->getBottom();
$borderDiagonalDown = $currentCell->getBorders()->getDiagonalDown();
$borderDiagonalUp = $currentCell->getBorders()->getDiagonalUp();
// Fix PowerPoint implementation
if (!is_null($nextCellRight) && $nextCellRight->getBorders()->getRight()->getHashCode() != $defaultBorder->getHashCode()) {
$borderRight = $nextCellRight->getBorders()->getLeft();
}
if (!is_null($nextCellBelow) && $nextCellBelow->getBorders()->getBottom()->getHashCode() != $defaultBorder->getHashCode()) {
$borderBottom = $nextCellBelow->getBorders()->getTop();
}
// Write borders
$this->writeBorder($objWriter, $borderLeft, 'L');
$this->writeBorder($objWriter, $borderRight, 'R');
$this->writeBorder($objWriter, $borderTop, 'T');
$this->writeBorder($objWriter, $borderBottom, 'B');
$this->writeBorder($objWriter, $borderDiagonalDown, 'TlToBr');
$this->writeBorder($objWriter, $borderDiagonalUp, 'BlToTr');
// Fill
$this->writeFill($objWriter, $currentCell->getFill());
$objWriter->endElement();
$objWriter->endElement();
}
$objWriter->endElement();
}
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement();
}