Merge pull request #103 from box/use_number_columns_repeated
Use number-columns-repeated in ODS writer
This commit is contained in:
commit
3f0016f753
@ -135,7 +135,7 @@ abstract class AbstractWorkbook implements WorkbookInterface
|
||||
* If shouldCreateNewSheetsAutomatically option is set to true, it will handle pagination
|
||||
* with the creation of new worksheets if one worksheet has reached its maximum capicity.
|
||||
*
|
||||
* @param array $dataRow Array containing data to be written.
|
||||
* @param array $dataRow Array containing data to be written. Cannot be empty.
|
||||
* Example $dataRow = ['data1', 1234, null, '', 'data5'];
|
||||
* @param \Box\Spout\Writer\Style\Style $style Style to be applied to the row.
|
||||
* @return void
|
||||
|
@ -7,7 +7,6 @@ use Box\Spout\Common\Exception\IOException;
|
||||
use Box\Spout\Common\Helper\StringHelper;
|
||||
use Box\Spout\Writer\Common\Helper\CellHelper;
|
||||
use Box\Spout\Writer\Common\Internal\WorksheetInterface;
|
||||
use Box\Spout\Writer\Common\Sheet;
|
||||
|
||||
/**
|
||||
* Class Worksheet
|
||||
@ -126,7 +125,7 @@ class Worksheet implements WorksheetInterface
|
||||
/**
|
||||
* Adds data to the worksheet.
|
||||
*
|
||||
* @param array $dataRow Array containing data to be written.
|
||||
* @param array $dataRow Array containing data to be written. Cannot be empty.
|
||||
* Example $dataRow = ['data1', 1234, null, '', 'data5'];
|
||||
* @param \Box\Spout\Writer\Style\Style $style Style to be applied to the row. NULL means use default style.
|
||||
* @return void
|
||||
@ -135,36 +134,26 @@ class Worksheet implements WorksheetInterface
|
||||
*/
|
||||
public function addRow($dataRow, $style)
|
||||
{
|
||||
$this->maxNumColumns = max($this->maxNumColumns, count($dataRow));
|
||||
$styleIndex = ($style->getId() + 1); // 1-based
|
||||
$cellsCount = count($dataRow);
|
||||
$this->maxNumColumns = max($this->maxNumColumns, $cellsCount);
|
||||
|
||||
$data = ' <table:table-row table:style-name="ro1">' . PHP_EOL;
|
||||
|
||||
foreach($dataRow as $cellValue) {
|
||||
$data .= ' <table:table-cell table:style-name="ce' . $styleIndex . '"';
|
||||
$currentCellIndex = 0;
|
||||
$nextCellIndex = 1;
|
||||
|
||||
if (CellHelper::isNonEmptyString($cellValue)) {
|
||||
$data .= ' office:value-type="string" calcext:value-type="string">' . PHP_EOL;
|
||||
for ($i = 0; $i < $cellsCount; $i++) {
|
||||
$currentCellValue = $dataRow[$currentCellIndex];
|
||||
|
||||
$cellValueLines = explode("\n", $cellValue);
|
||||
foreach ($cellValueLines as $cellValueLine) {
|
||||
$data .= ' <text:p>' . $this->stringsEscaper->escape($cellValueLine) . '</text:p>' . PHP_EOL;
|
||||
}
|
||||
if (!array_key_exists($nextCellIndex, $dataRow) || $currentCellValue !== $dataRow[$nextCellIndex]) {
|
||||
$numTimesValueRepeated = ($nextCellIndex - $currentCellIndex);
|
||||
$data .= $this->getCellContent($currentCellValue, $styleIndex, $numTimesValueRepeated);
|
||||
|
||||
$data .= ' </table:table-cell>' . PHP_EOL;
|
||||
} else if (CellHelper::isBoolean($cellValue)) {
|
||||
$data .= ' office:value-type="boolean" calcext:value-type="boolean" office:value="' . $cellValue . '">' . PHP_EOL;
|
||||
$data .= ' <text:p>' . $cellValue . '</text:p>' . PHP_EOL;
|
||||
$data .= ' </table:table-cell>' . PHP_EOL;
|
||||
} else if (CellHelper::isNumeric($cellValue)) {
|
||||
$data .= ' office:value-type="float" calcext:value-type="float" office:value="' . $cellValue . '">' . PHP_EOL;
|
||||
$data .= ' <text:p>' . $cellValue . '</text:p>' . PHP_EOL;
|
||||
$data .= ' </table:table-cell>' . PHP_EOL;
|
||||
} else if (empty($cellValue)) {
|
||||
$data .= '/>' . PHP_EOL;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . gettype($cellValue));
|
||||
$currentCellIndex = $nextCellIndex;
|
||||
}
|
||||
|
||||
$nextCellIndex++;
|
||||
}
|
||||
|
||||
$data .= ' </table:table-row>' . PHP_EOL;
|
||||
@ -178,6 +167,49 @@ class Worksheet implements WorksheetInterface
|
||||
$this->lastWrittenRowIndex++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cell XML content, given its value.
|
||||
*
|
||||
* @param mixed $cellValue The value to be written
|
||||
* @param int $styleIndex Index of the used style
|
||||
* @param int $numTimesValueRepeated Number of times the value is consecutively repeated
|
||||
* @return string The cell XML content
|
||||
* @throws \Box\Spout\Common\Exception\InvalidArgumentException If a cell value's type is not supported
|
||||
*/
|
||||
protected function getCellContent($cellValue, $styleIndex, $numTimesValueRepeated)
|
||||
{
|
||||
$data = ' <table:table-cell table:style-name="ce' . $styleIndex . '"';
|
||||
|
||||
if ($numTimesValueRepeated !== 1) {
|
||||
$data .= ' table:number-columns-repeated="' . $numTimesValueRepeated . '"';
|
||||
}
|
||||
|
||||
if (CellHelper::isNonEmptyString($cellValue)) {
|
||||
$data .= ' office:value-type="string" calcext:value-type="string">' . PHP_EOL;
|
||||
|
||||
$cellValueLines = explode("\n", $cellValue);
|
||||
foreach ($cellValueLines as $cellValueLine) {
|
||||
$data .= ' <text:p>' . $this->stringsEscaper->escape($cellValueLine) . '</text:p>' . PHP_EOL;
|
||||
}
|
||||
|
||||
$data .= ' </table:table-cell>' . PHP_EOL;
|
||||
} else if (CellHelper::isBoolean($cellValue)) {
|
||||
$data .= ' office:value-type="boolean" calcext:value-type="boolean" office:value="' . $cellValue . '">' . PHP_EOL;
|
||||
$data .= ' <text:p>' . $cellValue . '</text:p>' . PHP_EOL;
|
||||
$data .= ' </table:table-cell>' . PHP_EOL;
|
||||
} else if (CellHelper::isNumeric($cellValue)) {
|
||||
$data .= ' office:value-type="float" calcext:value-type="float" office:value="' . $cellValue . '">' . PHP_EOL;
|
||||
$data .= ' <text:p>' . $cellValue . '</text:p>' . PHP_EOL;
|
||||
$data .= ' </table:table-cell>' . PHP_EOL;
|
||||
} else if (empty($cellValue)) {
|
||||
$data .= '/>' . PHP_EOL;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . gettype($cellValue));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the worksheet
|
||||
*
|
||||
|
@ -118,7 +118,7 @@ EOD;
|
||||
/**
|
||||
* Adds data to the worksheet.
|
||||
*
|
||||
* @param array $dataRow Array containing data to be written.
|
||||
* @param array $dataRow Array containing data to be written. Cannot be empty.
|
||||
* Example $dataRow = ['data1', 1234, null, '', 'data5'];
|
||||
* @param \Box\Spout\Writer\Style\Style $style Style to be applied to the row. NULL means use default style.
|
||||
* @return void
|
||||
|
@ -195,6 +195,48 @@ class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertValueWasWrittenToSheet($fileName, 1, 10.2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function dataProviderForTestAddRowShouldUseNumberColumnsRepeatedForRepeatedValues()
|
||||
{
|
||||
return [
|
||||
[['ods--11', 'ods--11', 'ods--11'], 1, 3],
|
||||
[['', ''], 1, 2],
|
||||
[[true, true, true, true], 1, 4],
|
||||
[[1.1, 1.1], 1, 2],
|
||||
[['foo', 'bar'], 2, 0],
|
||||
];
|
||||
}
|
||||
/**
|
||||
* @dataProvider dataProviderForTestAddRowShouldUseNumberColumnsRepeatedForRepeatedValues
|
||||
*
|
||||
* @param array $dataRow
|
||||
* @param int $expectedNumTableCells
|
||||
* @param int $expectedNumColumnsRepeated
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldUseNumberColumnsRepeatedForRepeatedValues($dataRow, $expectedNumTableCells, $expectedNumColumnsRepeated)
|
||||
{
|
||||
$fileName = 'test_add_row_should_use_number_columns_repeated.ods';
|
||||
$this->writeToODSFile([$dataRow], $fileName);
|
||||
|
||||
$sheetXmlNode = $this->getSheetXmlNode($fileName, 1);
|
||||
$tableCellNodes = $sheetXmlNode->getElementsByTagName('table-cell');
|
||||
|
||||
$this->assertEquals($expectedNumTableCells, $tableCellNodes->length);
|
||||
|
||||
if ($expectedNumTableCells === 1) {
|
||||
$tableCellNode = $tableCellNodes->item(0);
|
||||
$numColumnsRepeated = intval($tableCellNode->getAttribute('table:number-columns-repeated'));
|
||||
$this->assertEquals($expectedNumColumnsRepeated, $numColumnsRepeated);
|
||||
} else {
|
||||
foreach ($tableCellNodes as $tableCellNode) {
|
||||
$this->assertFalse($tableCellNode->hasAttribute('table:number-columns-repeated'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
@ -423,12 +465,34 @@ class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertNotContains($valueAsXmlString, $sheetXmlAsString, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @param int $sheetIndex
|
||||
* @return \DOMNode
|
||||
*/
|
||||
private function getSheetXmlNode($fileName, $sheetIndex)
|
||||
{
|
||||
$xmlReader = $this->moveReaderToCorrectTableNode($fileName, $sheetIndex);
|
||||
return $xmlReader->expand();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @param int $sheetIndex
|
||||
* @return string
|
||||
*/
|
||||
private function getSheetXmlNodeAsString($fileName, $sheetIndex)
|
||||
{
|
||||
$xmlReader = $this->moveReaderToCorrectTableNode($fileName, $sheetIndex);
|
||||
return $xmlReader->readOuterXml();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @param int $sheetIndex
|
||||
* @return XMLReader
|
||||
*/
|
||||
private function moveReaderToCorrectTableNode($fileName, $sheetIndex)
|
||||
{
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
$pathToSheetFile = $resourcePath . '#content.xml';
|
||||
@ -441,6 +505,6 @@ class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
$xmlReader->readUntilNodeFound('table:table');
|
||||
}
|
||||
|
||||
return $xmlReader->readOuterXml();
|
||||
return $xmlReader;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user