diff --git a/src/Spout/Writer/Common/Cell.php b/src/Spout/Writer/Common/Cell.php
new file mode 100644
index 0000000..bbb0d91
--- /dev/null
+++ b/src/Spout/Writer/Common/Cell.php
@@ -0,0 +1,166 @@
+setValue($value);
+ }
+
+ /**
+ * @param $value mixed
+ */
+ public function setValue($value)
+ {
+ $this->value = $value;
+ $this->type = $this->detectType($value);
+ }
+
+ /**
+ * @return mixed|null
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * @return int|null
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Get the current value type
+ * @return int
+ */
+ protected function detectType($value)
+ {
+ if (CellHelper::isBoolean($value)) {
+ return self::TYPE_BOOLEAN;
+ } elseif (CellHelper::isEmpty($value)) {
+ return self::TYPE_EMPTY;
+ } elseif (CellHelper::isNumeric($this->getValue())) {
+ return self::TYPE_NUMERIC;
+ } elseif (CellHelper::isNonEmptyString($value)) {
+ return self::TYPE_STRING;
+ } else {
+ return self::TYPE_ERROR;
+ }
+ }
+
+ /**
+ * @return bool
+ */
+ public function isBoolean()
+ {
+ return $this->type === self::TYPE_BOOLEAN;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isEmpty()
+ {
+ return $this->type === self::TYPE_EMPTY;
+ }
+
+ /**
+ * Not used at the moment
+ * @return bool
+ */
+ public function isFormula()
+ {
+ return $this->type === self::TYPE_FORMULA;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isNumeric()
+ {
+ return $this->type === self::TYPE_NUMERIC;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isString()
+ {
+ return $this->type === self::TYPE_STRING;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isError()
+ {
+ return $this->type === self::TYPE_ERROR;
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ return (string)$this->value;
+ }
+}
diff --git a/src/Spout/Writer/ODS/Internal/Worksheet.php b/src/Spout/Writer/ODS/Internal/Worksheet.php
index 0920b6d..9c44798 100644
--- a/src/Spout/Writer/ODS/Internal/Worksheet.php
+++ b/src/Spout/Writer/ODS/Internal/Worksheet.php
@@ -5,6 +5,7 @@ namespace Box\Spout\Writer\ODS\Internal;
use Box\Spout\Common\Exception\InvalidArgumentException;
use Box\Spout\Common\Exception\IOException;
use Box\Spout\Common\Helper\StringHelper;
+use Box\Spout\Writer\Common\Cell;
use Box\Spout\Writer\Common\Helper\CellHelper;
use Box\Spout\Writer\Common\Internal\WorksheetInterface;
@@ -191,27 +192,34 @@ class Worksheet implements WorksheetInterface
$data .= ' table:number-columns-repeated="' . $numTimesValueRepeated . '"';
}
- if (CellHelper::isNonEmptyString($cellValue)) {
+ /** @TODO Remove code duplication with XLSX writer: https://github.com/box/spout/pull/383#discussion_r113292746 */
+ if ($cellValue instanceof Cell) {
+ $cell = $cellValue;
+ } else {
+ $cell = new Cell($cellValue);
+ }
+
+ if ($cell->isString()) {
$data .= ' office:value-type="string" calcext:value-type="string">';
- $cellValueLines = explode("\n", $cellValue);
+ $cellValueLines = explode("\n", $cell->getValue());
foreach ($cellValueLines as $cellValueLine) {
$data .= '' . $this->stringsEscaper->escape($cellValueLine) . '';
}
$data .= '';
- } else if (CellHelper::isBoolean($cellValue)) {
- $data .= ' office:value-type="boolean" calcext:value-type="boolean" office:boolean-value="' . $cellValue . '">';
- $data .= '' . $cellValue . '';
+ } else if ($cell->isBoolean()) {
+ $data .= ' office:value-type="boolean" calcext:value-type="boolean" office:boolean-value="' . $cell->getValue() . '">';
+ $data .= '' . $cell->getValue() . '';
$data .= '';
- } else if (CellHelper::isNumeric($cellValue)) {
- $data .= ' office:value-type="float" calcext:value-type="float" office:value="' . $cellValue . '">';
- $data .= '' . $cellValue . '';
+ } else if ($cell->isNumeric()) {
+ $data .= ' office:value-type="float" calcext:value-type="float" office:value="' . $cell->getValue() . '">';
+ $data .= '' . $cell->getValue() . '';
$data .= '';
- } else if (empty($cellValue)) {
+ } else if ($cell->isEmpty()) {
$data .= '/>';
} else {
- throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . gettype($cellValue));
+ throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . gettype($cell->getValue()));
}
return $data;
diff --git a/src/Spout/Writer/XLSX/Internal/Worksheet.php b/src/Spout/Writer/XLSX/Internal/Worksheet.php
index b5a3dc7..7f71829 100644
--- a/src/Spout/Writer/XLSX/Internal/Worksheet.php
+++ b/src/Spout/Writer/XLSX/Internal/Worksheet.php
@@ -5,6 +5,7 @@ namespace Box\Spout\Writer\XLSX\Internal;
use Box\Spout\Common\Exception\InvalidArgumentException;
use Box\Spout\Common\Exception\IOException;
use Box\Spout\Common\Helper\StringHelper;
+use Box\Spout\Writer\Common\Cell;
use Box\Spout\Writer\Common\Helper\CellHelper;
use Box\Spout\Writer\Common\Internal\WorksheetInterface;
@@ -213,13 +214,20 @@ EOD;
$cellXML = 'getCellXMLFragmentForNonEmptyString($cellValue);
- } else if (CellHelper::isBoolean($cellValue)) {
- $cellXML .= ' t="b">' . intval($cellValue) . '';
- } else if (CellHelper::isNumeric($cellValue)) {
- $cellXML .= '>' . $cellValue . '';
- } else if (empty($cellValue)) {
+ /** @TODO Remove code duplication with ODS writer: https://github.com/box/spout/pull/383#discussion_r113292746 */
+ if ($cellValue instanceof Cell) {
+ $cell = $cellValue;
+ } else {
+ $cell = new Cell($cellValue);
+ }
+
+ if ($cell->isString()) {
+ $cellXML .= $this->getCellXMLFragmentForNonEmptyString($cell->getValue());
+ } else if ($cell->isBoolean()) {
+ $cellXML .= ' t="b">' . intval($cell->getValue()) . '';
+ } else if ($cell->isNumeric()) {
+ $cellXML .= '>' . $cell->getValue() . '';
+ } else if ($cell->isEmpty()) {
if ($this->styleHelper->shouldApplyStyleOnEmptyCell($styleId)) {
$cellXML .= '/>';
} else {
@@ -228,7 +236,7 @@ EOD;
$cellXML = '';
}
} else {
- throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . gettype($cellValue));
+ throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . gettype($cell->getValue()));
}
return $cellXML;
diff --git a/tests/Spout/Writer/CSV/WriterTest.php b/tests/Spout/Writer/CSV/WriterTest.php
index 9558129..c2f1d2c 100644
--- a/tests/Spout/Writer/CSV/WriterTest.php
+++ b/tests/Spout/Writer/CSV/WriterTest.php
@@ -5,6 +5,7 @@ namespace Box\Spout\Writer\CSV;
use Box\Spout\TestUsingResource;
use Box\Spout\Common\Type;
use Box\Spout\Common\Helper\EncodingHelper;
+use Box\Spout\Writer\Common\Cell;
use Box\Spout\Writer\WriterFactory;
/**
@@ -177,6 +178,19 @@ class WriterTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('#This is, a comma#,csv--12,csv--13', $writtenContent, 'The fields should be enclosed with #');
}
+ /**
+ * @return void
+ */
+ public function testWriteShouldAcceptCellObjects()
+ {
+ $allRows = [
+ [new Cell('String Value'), new Cell(1)]
+ ];
+ $writtenContent = $this->writeToCsvFileAndReturnWrittenContent($allRows, 'csv_with_cell_objects.csv');
+ $writtenContent = $this->trimWrittenContent($writtenContent);
+ $this->assertEquals('"String Value",1', $writtenContent);
+ }
+
/**
* @param array $allRows
* @param string $fileName
diff --git a/tests/Spout/Writer/ODS/WriterTest.php b/tests/Spout/Writer/ODS/WriterTest.php
index 836e679..df60af9 100644
--- a/tests/Spout/Writer/ODS/WriterTest.php
+++ b/tests/Spout/Writer/ODS/WriterTest.php
@@ -6,6 +6,7 @@ use Box\Spout\Common\Exception\SpoutException;
use Box\Spout\Common\Type;
use Box\Spout\Reader\Wrapper\XMLReader;
use Box\Spout\TestUsingResource;
+use Box\Spout\Writer\Common\Cell;
use Box\Spout\Writer\Common\Helper\ZipHelper;
use Box\Spout\Writer\WriterFactory;
@@ -463,6 +464,47 @@ class WriterTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('application/vnd.oasis.opendocument.spreadsheet', $finfo->file($resourcePath));
}
+ /**
+ * @return void
+ */
+ public function testWriteShouldAcceptCellObjects()
+ {
+ $fileName = 'test_writer_should_accept_cell_objects.ods';
+ $dataRows = [
+ [new Cell('ods--11'), new Cell('ods--12')],
+ [new Cell('ods--21'), new Cell('ods--22'), new Cell('ods--23')],
+ ];
+
+ $this->writeToODSFile($dataRows, $fileName);
+
+ foreach ($dataRows as $dataRow) {
+ /** @var Cell $cell */
+ foreach ($dataRow as $cell) {
+ $this->assertValueWasWritten($fileName, $cell->getValue());
+ }
+ }
+ }
+
+ /**
+ * @return void
+ */
+ public function testWriteShouldAcceptCellObjectsWithDifferentValueTypes()
+ {
+ $fileName = 'test_writer_should_accept_cell_objects_with_types.ods';
+ $dataRows = [
+ [new Cell('i am a string'), new Cell(51465), new Cell(true), new Cell(51465.5)],
+ ];
+
+ $this->writeToODSFile($dataRows, $fileName);
+
+ foreach ($dataRows as $dataRow) {
+ /** @var Cell $cell */
+ foreach ($dataRow as $cell) {
+ $this->assertValueWasWritten($fileName, (string)$cell->getValue(), '', true);
+ }
+ }
+ }
+
/**
* @param array $allRows
* @param string $fileName
@@ -527,6 +569,7 @@ class WriterTest extends \PHPUnit_Framework_TestCase
$xmlContents = file_get_contents('zip://' . $pathToContentFile);
$this->assertContains($value, $xmlContents, $message);
+
}
/**
diff --git a/tests/Spout/Writer/XLSX/WriterTest.php b/tests/Spout/Writer/XLSX/WriterTest.php
index c7f4f96..fe89deb 100644
--- a/tests/Spout/Writer/XLSX/WriterTest.php
+++ b/tests/Spout/Writer/XLSX/WriterTest.php
@@ -5,6 +5,7 @@ namespace Box\Spout\Writer\XLSX;
use Box\Spout\Common\Exception\SpoutException;
use Box\Spout\Common\Type;
use Box\Spout\TestUsingResource;
+use Box\Spout\Writer\Common\Cell;
use Box\Spout\Writer\WriterFactory;
use Box\Spout\Writer\XLSX\Internal\Worksheet;
@@ -507,6 +508,60 @@ class WriterTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', $finfo->file($resourcePath));
}
+ /**
+ * @return void
+ */
+ public function testWriterShouldAcceptCellObjects()
+ {
+ $fileName = 'test_writer_should_accept_cell_objects.xlsx';
+ $dataRows = [
+ [new Cell('xlsx--11'), new Cell('xlsx--12')],
+ [new Cell('xlsx--21'), new Cell('xlsx--22'), new Cell('xlsx--23')],
+ ];
+
+ $this->writeToXLSXFile($dataRows, $fileName, $shouldUseInlineStrings = false);
+
+ foreach ($dataRows as $dataRow) {
+ /** @var Cell $cell */
+ foreach ($dataRow as $cell) {
+ $this->assertSharedStringWasWritten($fileName, $cell->getValue());
+ }
+ }
+ }
+
+ /**
+ * @return void
+ */
+ public function testWriteShouldAcceptCellObjectsWithDifferentValueTypes()
+ {
+ $fileName = 'test_writer_should_accept_cell_objects_with_types.xlsx';
+
+ $dataRowsShared = [
+ [new Cell('i am a string')],
+ ];
+ $dataRowsInline = [
+ [new Cell(51465), new Cell(true), new Cell(51465.5)]
+ ];
+
+ $dataRows = array_merge($dataRowsShared, $dataRowsInline);
+
+ $this->writeToXLSXFile($dataRows, $fileName, $shouldUseInlineStrings = false);
+
+ foreach ($dataRowsShared as $dataRow) {
+ /** @var Cell $cell */
+ foreach ($dataRow as $cell) {
+ $this->assertSharedStringWasWritten($fileName, (string)$cell->getValue());
+ }
+ }
+
+ foreach ($dataRowsInline as $dataRow) {
+ /** @var Cell $cell */
+ foreach ($dataRow as $cell) {
+ $this->assertInlineDataWasWrittenToSheet($fileName, 1, $cell->getValue());
+ }
+ }
+ }
+
/**
* @param array $allRows
* @param string $fileName