parent
962367c95f
commit
96f3f666d6
|
@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Support to write merged cells in ODS format [#287](https://github.com/PHPOffice/PhpSpreadsheet/issues/287)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -696,8 +696,8 @@ class Ods extends BaseReader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merged cells
|
// Merged cells
|
||||||
if ($childNode->hasAttributeNS($tableNs, 'number-columns-spanned')
|
if ($cellData->hasAttributeNS($tableNs, 'number-columns-spanned')
|
||||||
|| $childNode->hasAttributeNS($tableNs, 'number-rows-spanned')
|
|| $cellData->hasAttributeNS($tableNs, 'number-rows-spanned')
|
||||||
) {
|
) {
|
||||||
if (($type !== DataType::TYPE_NULL) || (!$this->readDataOnly)) {
|
if (($type !== DataType::TYPE_NULL) || (!$this->readDataOnly)) {
|
||||||
$columnTo = $columnID;
|
$columnTo = $columnID;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||||
|
@ -183,6 +184,7 @@ class Content extends WriterPart
|
||||||
|
|
||||||
$this->writeCellSpan($objWriter, $column, $prevColumn);
|
$this->writeCellSpan($objWriter, $column, $prevColumn);
|
||||||
$objWriter->startElement('table:table-cell');
|
$objWriter->startElement('table:table-cell');
|
||||||
|
$this->writeCellMerge($objWriter, $cell);
|
||||||
|
|
||||||
// Style XF
|
// Style XF
|
||||||
$style = $cell->getXfIndex();
|
$style = $cell->getXfIndex();
|
||||||
|
@ -363,4 +365,29 @@ class Content extends WriterPart
|
||||||
$writer->endElement(); // Close style:style
|
$writer->endElement(); // Close style:style
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write attributes for merged cell.
|
||||||
|
*
|
||||||
|
* @param XMLWriter $objWriter
|
||||||
|
* @param Cell $cell
|
||||||
|
*
|
||||||
|
* @throws \PhpOffice\PhpSpreadsheet\Exception
|
||||||
|
*/
|
||||||
|
private function writeCellMerge(XMLWriter $objWriter, Cell $cell)
|
||||||
|
{
|
||||||
|
if (!$cell->isMergeRangeValueCell()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mergeRange = Coordinate::splitRange($cell->getMergeRange());
|
||||||
|
list($startCell, $endCell) = $mergeRange[0];
|
||||||
|
$start = Coordinate::coordinateFromString($startCell);
|
||||||
|
$end = Coordinate::coordinateFromString($endCell);
|
||||||
|
$columnSpan = Coordinate::columnIndexFromString($end[0]) - Coordinate::columnIndexFromString($start[0]) + 1;
|
||||||
|
$rowSpan = $end[1] - $start[1] + 1;
|
||||||
|
|
||||||
|
$objWriter->writeAttribute('table:number-columns-spanned', $columnSpan);
|
||||||
|
$objWriter->writeAttribute('table:number-rows-spanned', $rowSpan);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class MergedCells extends TestCase
|
||||||
|
{
|
||||||
|
public function providerMergedCells()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
// ['Html'],
|
||||||
|
// ['Xls'],
|
||||||
|
// ['Xlsx'],
|
||||||
|
['Ods'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerMergedCells
|
||||||
|
*
|
||||||
|
* @param string $format
|
||||||
|
*/
|
||||||
|
public function testMergedCells($format)
|
||||||
|
{
|
||||||
|
$filename = tempnam(sys_get_temp_dir(), strtolower($format));
|
||||||
|
$this->writeMergedCells($filename, $format);
|
||||||
|
$actual = $this->readMergedCells($filename, $format);
|
||||||
|
unlink($filename);
|
||||||
|
|
||||||
|
self::assertSame(1, $actual, "Format $format failed, could not read 1 merged cell");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function writeMergedCells($filename, $format)
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$spreadsheet->setActiveSheetIndex(0);
|
||||||
|
$spreadsheet->getActiveSheet()->setCellValue('A1', '1');
|
||||||
|
$spreadsheet->getActiveSheet()->setCellValue('B1', '2');
|
||||||
|
$spreadsheet->getActiveSheet()->setCellValue('A2', '33');
|
||||||
|
$spreadsheet->getActiveSheet()->mergeCells('A2:B2');
|
||||||
|
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, $format);
|
||||||
|
|
||||||
|
$writer->save($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function readMergedCells($filename, $format)
|
||||||
|
{
|
||||||
|
$reader = IOFactory::createReader($format);
|
||||||
|
$spreadsheet = $reader->load($filename);
|
||||||
|
$n = 0;
|
||||||
|
foreach ($spreadsheet->getWorksheetIterator() as $worksheet) {
|
||||||
|
foreach ($worksheet->getMergeCells() as $cells) {
|
||||||
|
++$n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $n;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue