From bb8fbef5883bf704bcbcee2e47a7725c7c47265a Mon Sep 17 00:00:00 2001 From: Jon Nott Date: Thu, 10 Feb 2022 19:46:02 +0000 Subject: [PATCH] Add setCellVerticalAlignment() & allow setShouldWrapText() to be explicitly set as false MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - add Common\Entity\Style\CellVerticalAlignment - duplicate get/set/hasSet/shouldApply methods for CellAlignment in Common\Entity\Style\Style for CellVerticalAlignment instead, plus corresponding properties - add setCellVerticalAlignment method to Common\Creator\Style\StyleBuilder - add vertical alignment to StyleMerger:: mergeCellProperties() - adjust wrapText logic in mergeCellProperties() to fix issue https://github.com/box/spout/issues/829 - apply vertical cell styling for both XLSX and ODS, via corresponding StyleManager classes - transform vertical alignment ‘center’ to ‘middle’ for ODS - fix logic around wrapText such that the choice whether to include wrapping styles depends on hasSetWrapText() being true, and then use shouldWrapText() thereafter to either set wrapping or no wrapping (for XLSX, wrapText=“1” or wrapText=“0”, for ODS, wrap-option=wrap or wrap-option=no-wrap). previously there was no way to set wrapping to be OFF, only to set it to be ON. - add new tests to ensure shouldWrapText(false) results in the correct negated wrapText (XLSX) / wrap-option (ODS) styles - add new tests to StyleBuilderTest for vertical alignment - add vertical alignment to documentation.md --- docs/_pages/documentation.md | 325 ++++++++++++++++++ .../Entity/Style/CellVerticalAlignment.php | 36 ++ src/Common/Entity/Style/Style.php | 42 +++ .../Common/Manager/Style/StyleMerger.php | 7 +- src/Writer/ODS/Manager/Style/StyleManager.php | 33 +- .../XLSX/Manager/Style/StyleManager.php | 9 +- tests/Writer/Common/Creator/StyleTest.php | 13 + tests/Writer/ODS/WriterWithStyleTest.php | 18 + tests/Writer/XLSX/WriterWithStyleTest.php | 17 + 9 files changed, 490 insertions(+), 10 deletions(-) create mode 100755 docs/_pages/documentation.md create mode 100644 src/Common/Entity/Style/CellVerticalAlignment.php diff --git a/docs/_pages/documentation.md b/docs/_pages/documentation.md new file mode 100755 index 00000000..30d9cf52 --- /dev/null +++ b/docs/_pages/documentation.md @@ -0,0 +1,325 @@ +--- +layout: doc +title: Documentation +permalink: /docs/ +--- + +## Configuration for CSV + +It is possible to configure both the CSV reader and writer to adapt them to your requirements: + +```php +use Box\Spout\Reader\Common\Creator\ReaderEntityFactory; + +$reader = ReaderEntityFactory::createReaderFromFile('/path/to/file.csv'); +/** All of these methods have to be called before opening the reader. */ +$reader->setFieldDelimiter('|'); +$reader->setFieldEnclosure('@'); + +``` + +Additionally, if you need to read non UTF-8 files, you can specify the encoding of your file this way: + +```php +$reader->setEncoding('UTF-16LE'); +``` + +By default, the writer generates CSV files encoded in UTF-8, with a BOM. +It is however possible to not include the BOM: + +```php +use Box\Spout\Writer\Common\Creator\WriterEntityFactory; + +$writer = WriterEntityFactory::createWriterFromFile('/path/to/file.csv'); +$writer->setShouldAddBOM(false); +``` + + +## Configuration for XLSX and ODS + +### New sheet creation + +It is possible to change the behavior of the writers when the maximum number of rows (*1,048,576*) has been written in the current sheet. By default, a new sheet is automatically created so that writing can keep going but that may not always be preferable. + +```php + +use Box\Spout\Writer\Common\Creator\WriterEntityFactory; + +$writer = WriterEntityFactory::createODSWriter(); +$writer->setShouldCreateNewSheetsAutomatically(true); // default value +$writer->setShouldCreateNewSheetsAutomatically(false); // will stop writing new data when limit is reached +``` + +### Using a custom temporary folder + +Processing XLSX and ODS files requires temporary files to be created. By default, {{ site.spout_html }} will use the system default temporary folder (as returned by `sys_get_temp_dir()`). It is possible to override this by explicitly setting it on the reader or writer: + +```php +use Box\Spout\Writer\Common\Creator\WriterEntityFactory; + +$writer = WriterEntityFactory::createXLSXWriter(); +$writer->setTempFolder($customTempFolderPath); +``` + +### Strings storage (XLSX writer) + +XLSX files support different ways to store the string values: +* Shared strings are meant to optimize file size by separating strings from the sheet representation and ignoring strings duplicates (if a string is used three times, only one string will be stored) +* Inline strings are less optimized (as duplicate strings are all stored) but is faster to process + +In order to keep the memory usage really low, {{ site.spout_html }} does not de-duplicate strings when using shared strings. It is nevertheless possible to use this mode. + +```php +use Box\Spout\Writer\Common\Creator\WriterEntityFactory; + +$writer = WriterEntityFactory::createXLSXWriter(); +$writer->setShouldUseInlineStrings(true); // default (and recommended) value +$writer->setShouldUseInlineStrings(false); // will use shared strings +``` + +> #### Note on Apple Numbers and iOS support +> +> Apple's products (Numbers and the iOS previewer) don't support inline strings and display empty cells instead. Therefore, if these platforms need to be supported, make sure to use shared strings! + +### Date/Time formatting + +When reading a spreadsheet containing dates or times, {{ site.spout_html }} returns the values by default as `DateTime` objects. +It is possible to change this behavior and have a formatted date returned instead (e.g. "2016-11-29 1:22 AM"). The format of the date corresponds to what is specified in the spreadsheet. + +```php +use Box\Spout\Reader\Common\Creator\ReaderEntityFactory; + +$reader = ReaderEntityFactory::createXLSXReader(); +$reader->setShouldFormatDates(false); // default value +$reader->setShouldFormatDates(true); // will return formatted dates +``` + + +## Empty rows + +By default, when {{ site.spout_html }} reads a spreadsheet it skips empty rows and only return rows containing data. +This behavior can be changed so that {{ site.spout_html }} returns all rows: + +```php +use Box\Spout\Reader\Common\Creator\ReaderEntityFactory; + +$reader = ReaderEntityFactory::createReaderFromFile('/path/to/file.ext'); +$reader->setShouldPreserveEmptyRows(true); +``` + + +## Styling + +### Available styles + +{{ site.spout_html }} supports styling at a row and cell level. It is possible to customize the fonts, backgrounds, alignment as well as borders. + +For fonts and alignments, {{ site.spout_html }} does not support all the possible formatting options yet. But you can find the most important ones: + +| Category | Property | API +|:---------------------|:------------------------|:-------------------------------------- +| Font | Bold | `StyleBuilder::setFontBold()` +| | Italic | `StyleBuilder::setFontItalic()` +| | Underline | `StyleBuilder::setFontUnderline()` +| | Strikethrough | `StyleBuilder::setFontStrikethrough()` +| | Font name | `StyleBuilder::setFontName('Arial')` +| | Font size | `StyleBuilder::setFontSize(14)` +| | Font color | `StyleBuilder::setFontColor(Color::BLUE)`
`StyleBuilder::setFontColor(Color::rgb(0, 128, 255))` +| Alignment | Cell alignment | `StyleBuilder::setCellAlignment(CellAlignment::CENTER)` +| | Cell vertical alignment | `StyleBuilder::setCellVerticalAlignment(CellVerticalAlignment::CENTER)` +| | Wrap text | `StyleBuilder::setShouldWrapText(true)` +| Format _(XLSX only)_ | Number format | `StyleBuilder::setFormat('0.000')` +| | Date format | `StyleBuilder::setFormat('m/d/yy h:mm')` + +### Styling rows + +It is possible to apply some formatting options to a row. In this case, all cells of the row will have the same style: + +```php +use Box\Spout\Writer\Common\Creator\WriterEntityFactory; +use Box\Spout\Writer\Common\Creator\Style\StyleBuilder; +use Box\Spout\Common\Entity\Style\CellAlignment; +use Box\Spout\Common\Entity\Style\Color; + +$writer = WriterEntityFactory::createXLSXWriter(); +$writer->openToFile($filePath); + +/** Create a style with the StyleBuilder */ +$style = (new StyleBuilder()) + ->setFontBold() + ->setFontSize(15) + ->setFontColor(Color::BLUE) + ->setShouldWrapText() + ->setCellAlignment(CellAlignment::RIGHT) + ->setCellVerticalAlignment(CellVerticalAlignment::BOTTOM) + ->setBackgroundColor(Color::YELLOW) + ->build(); + +/** Create a row with cells and apply the style to all cells */ +$row = WriterEntityFactory::createRowFromArray(['Carl', 'is', 'great'], $style); + +/** Add the row to the writer */ +$writer->addRow($row); +$writer->close(); +``` + +Adding borders to a row requires a ```Border``` object. + +```php +use Box\Spout\Common\Entity\Style\Border; +use Box\Spout\Writer\Common\Creator\Style\BorderBuilder; +use Box\Spout\Common\Entity\Style\Color; +use Box\Spout\Writer\Common\Creator\Style\StyleBuilder; +use Box\Spout\Writer\Common\Creator\WriterEntityFactory; + +$border = (new BorderBuilder()) + ->setBorderBottom(Color::GREEN, Border::WIDTH_THIN, Border::STYLE_DASHED) + ->build(); + +$style = (new StyleBuilder()) + ->setBorder($border) + ->build(); + +$writer = WriterEntityFactory::createXLSXWriter(); +$writer->openToFile($filePath); + +$cells = WriterEntityFactory::createCell('Border Bottom Green Thin Dashed'); +$row = WriterEntityFactory::createRow($cells); +$row->setStyle($style); +$writer->addRow($row); + +$writer->close(); +``` + +### Styling cells + +The same styling techniques as described in [Styling rows](#styling-rows) can be applied to individual cells of a row as well. + +Cell styles are inherited from the parent row and the default row style respectively. + +The styles applied to a specific cell will override any parent styles if present. + +Example: + +```php +use Box\Spout\Common\Entity\Style\Color; +use Box\Spout\Writer\Common\Creator\Style\StyleBuilder; +use Box\Spout\Writer\Common\Creator\WriterEntityFactory; + +$defaultStyle = (new StyleBuilder()) + ->setFontSize(8) + ->build(); + +$writer = WriterEntityFactory::createXLSXWriter(); +$writer->setDefaultRowStyle($defaultStyle) + ->openToFile($filePath); + +$zebraBlackStyle = (new StyleBuilder()) + ->setBackgroundColor(Color::BLACK) + ->setFontColor(Color::WHITE) + ->setFontSize(10) + ->build(); + +$zebraWhiteStyle = (new StyleBuilder()) + ->setBackgroundColor(Color::WHITE) + ->setFontColor(Color::BLACK) + ->setFontItalic() + ->build(); + +$cells = [ + WriterEntityFactory::createCell('Ze', $zebraBlackStyle), + WriterEntityFactory::createCell('bra', $zebraWhiteStyle) +]; + +$rowStyle = (new StyleBuilder()) + ->setFontBold() + ->build(); + +$row = WriterEntityFactory::createRow($cells, $rowStyle); + +$writer->addRow($row); +$writer->close(); +``` + +### Default style + +{{ site.spout_html }} will use a default style for all created rows. This style can be overridden this way: + +```php +$defaultStyle = (new StyleBuilder()) + ->setFontName('Arial') + ->setFontSize(11) + ->build(); + +$writer = WriterEntityFactory::createXLSXWriter(); +$writer->setDefaultRowStyle($defaultStyle) + ->openToFile($filePath); +``` + + +## Playing with sheets + +When creating a XLSX or ODS file, it is possible to control which sheet the data will be written into. At any time, you can retrieve or set the current sheet: + +```php +$firstSheet = $writer->getCurrentSheet(); +$writer->addRow($rowForSheet1); // writes the row to the first sheet + +$newSheet = $writer->addNewSheetAndMakeItCurrent(); +$writer->addRow($rowForSheet2); // writes the row to the new sheet + +$writer->setCurrentSheet($firstSheet); +$writer->addRow($anotherRowForSheet1); // append the row to the first sheet +``` + +It is also possible to retrieve all the sheets currently created: +```php +$sheets = $writer->getSheets(); +``` + +It is possible to retrieve some sheet's attributes when reading: +```php +foreach ($reader->getSheetIterator() as $sheet) { + $sheetName = $sheet->getName(); + $isSheetVisible = $sheet->isVisible(); + $isSheetActive = $sheet->isActive(); // active sheet when spreadsheet last saved +} +``` + +If you rely on the sheet's name in your application, you can customize it this way: + +```php +// Accessing the sheet name when writing +$sheet = $writer->getCurrentSheet(); +$sheetName = $sheet->getName(); + +// Customizing the sheet name when writing +$sheet = $writer->getCurrentSheet(); +$sheet->setName('My custom name'); +``` + +> Please note that Excel has some restrictions on the sheet's name: +> * it must not be blank +> * it must not exceed 31 characters +> * it must not contain these characters: \ / ? * : [ or ] +> * it must not start or end with a single quote +> * it must be unique +> +> Handling these restrictions is the developer's responsibility. {{ site.spout_html }} does not try to automatically change the sheet's name, as one may rely on this name to be exactly what was passed in. + + +## Fluent interface + +Because fluent interfaces are great, you can use them with {{ site.spout_html }}: + +```php +use Box\Spout\Writer\WriterEntityFactory; + +$writer = WriterEntityFactory::createWriterFromFile('path/to/file.ext'); +$writer->setTempFolder($customTempFolderPath) + ->setShouldUseInlineStrings(true) + ->openToFile($filePath) + ->addRow($headerRow) + ->addRows($dataRows) + ->close(); +``` diff --git a/src/Common/Entity/Style/CellVerticalAlignment.php b/src/Common/Entity/Style/CellVerticalAlignment.php new file mode 100644 index 00000000..107cab01 --- /dev/null +++ b/src/Common/Entity/Style/CellVerticalAlignment.php @@ -0,0 +1,36 @@ + 1, + self::BASELINE => 1, + self::BOTTOM => 1, + self::CENTER => 1, + self::DISTRIBUTED => 1, + self::JUSTIFY => 1, + self::TOP => 1, + ]; + + /** + * @return bool Whether the given cell vertical alignment is valid + */ + public static function isValid(string $cellVerticalAlignment): bool + { + return isset(self::$VALID_ALIGNMENTS[$cellVerticalAlignment]); + } +} diff --git a/src/Common/Entity/Style/Style.php b/src/Common/Entity/Style/Style.php index 955950c4..e4921dfa 100644 --- a/src/Common/Entity/Style/Style.php +++ b/src/Common/Entity/Style/Style.php @@ -4,6 +4,7 @@ namespace OpenSpout\Common\Entity\Style; +use Box\Spout\Common\Entity\Style\CellVerticalAlignment; use OpenSpout\Common\Exception\InvalidArgumentException; /** @@ -75,6 +76,15 @@ final class Style /** @var bool Whether the cell alignment property was set */ private bool $hasSetCellAlignment = false; + /** @var bool Whether specific cell vertical alignment should be applied */ + private bool $shouldApplyCellVerticalAlignment = false; + + /** @var string Cell vertical alignment */ + private string $cellVerticalAlignment; + + /** @var bool Whether the cell vertical alignment property was set */ + private bool $hasSetCellVerticalAlignment = false; + /** @var bool Whether the text should wrap in the cell (useful for long or multi-lines text) */ private bool $shouldWrapText = false; @@ -290,6 +300,11 @@ public function getCellAlignment(): string return $this->cellAlignment; } + public function getCellVerticalAlignment(): string + { + return $this->cellVerticalAlignment; + } + /** * @param string $cellAlignment The cell alignment */ @@ -307,11 +322,33 @@ public function setCellAlignment(string $cellAlignment): self return $this; } + /** + * @param string $cellVerticalAlignment The cell vertical alignment + */ + public function setCellVerticalAlignment(string $cellVerticalAlignment): self + { + if (!CellVerticalAlignment::isValid($cellVerticalAlignment)) { + throw new InvalidArgumentException('Invalid cell vertical alignment value'); + } + + $this->cellVerticalAlignment = $cellVerticalAlignment; + $this->hasSetCellVerticalAlignment = true; + $this->shouldApplyCellVerticalAlignment = true; + $this->isEmpty = false; + + return $this; + } + public function hasSetCellAlignment(): bool { return $this->hasSetCellAlignment; } + public function hasSetCellVerticalAlignment(): bool + { + return $this->hasSetCellVerticalAlignment; + } + /** * @return bool Whether specific cell alignment should be applied */ @@ -320,6 +357,11 @@ public function shouldApplyCellAlignment(): bool return $this->shouldApplyCellAlignment; } + public function shouldApplyCellVerticalAlignment(): bool + { + return $this->shouldApplyCellVerticalAlignment; + } + public function shouldWrapText(): bool { return $this->shouldWrapText; diff --git a/src/Writer/Common/Manager/Style/StyleMerger.php b/src/Writer/Common/Manager/Style/StyleMerger.php index 726b405c..eb9fe244 100644 --- a/src/Writer/Common/Manager/Style/StyleMerger.php +++ b/src/Writer/Common/Manager/Style/StyleMerger.php @@ -72,8 +72,8 @@ private function mergeOtherFontProperties(Style $styleToUpdate, Style $style, St */ private function mergeCellProperties(Style $styleToUpdate, Style $style, Style $baseStyle): void { - if (!$style->hasSetWrapText() && $baseStyle->shouldWrapText()) { - $styleToUpdate->setShouldWrapText(); + if (!$style->hasSetWrapText() && $baseStyle->hasSetWrapText()) { + $styleToUpdate->setShouldWrapText($baseStyle->shouldWrapText()); } if (!$style->hasSetShrinkToFit() && $baseStyle->shouldShrinkToFit()) { $styleToUpdate->setShouldShrinkToFit(); @@ -81,6 +81,9 @@ private function mergeCellProperties(Style $styleToUpdate, Style $style, Style $ if (!$style->hasSetCellAlignment() && $baseStyle->shouldApplyCellAlignment()) { $styleToUpdate->setCellAlignment($baseStyle->getCellAlignment()); } + if (!$style->hasSetCellVerticalAlignment() && $baseStyle->shouldApplyCellVerticalAlignment()) { + $styleToUpdate->setCellVerticalAlignment($baseStyle->getCellVerticalAlignment()); + } if (null === $style->getBorder() && null !== ($border = $baseStyle->getBorder())) { $styleToUpdate->setBorder($border); } diff --git a/src/Writer/ODS/Manager/Style/StyleManager.php b/src/Writer/ODS/Manager/Style/StyleManager.php index 6b5545e2..795c2897 100644 --- a/src/Writer/ODS/Manager/Style/StyleManager.php +++ b/src/Writer/ODS/Manager/Style/StyleManager.php @@ -4,6 +4,7 @@ namespace OpenSpout\Writer\ODS\Manager\Style; +use Box\Spout\Common\Entity\Style\CellVerticalAlignment; use OpenSpout\Common\Entity\Style\Border; use OpenSpout\Common\Entity\Style\BorderPart; use OpenSpout\Common\Entity\Style\CellAlignment; @@ -316,12 +317,13 @@ private function getFontSectionContent(Style $style): string */ private function getParagraphPropertiesSectionContent(Style $style): string { - if (!$style->shouldApplyCellAlignment()) { + if (!$style->shouldApplyCellAlignment() && !$style->shouldApplyCellVerticalAlignment()) { return ''; } return 'getCellAlignmentSectionContent($style) + . $this->getCellVerticalAlignmentSectionContent($style) .'/>'; } @@ -335,6 +337,16 @@ private function getCellAlignmentSectionContent(Style $style): string $this->transformCellAlignment($style->getCellAlignment()) ); } + /** + * Returns the contents of the cell vertical alignment definition for the "" section + */ + private function getCellVerticalAlignmentSectionContent(Style $style): string + { + return \sprintf( + ' fo:vertical-align="%s" ', + $this->transformCellVerticalAlignment($style->getCellVerticalAlignment()) + ); + } /** * Even though "left" and "right" alignments are part of the spec, and interpreted @@ -349,6 +361,17 @@ private function transformCellAlignment(string $cellAlignment): string default => $cellAlignment, }; } + + /** + * Spec uses 'middle' rather than 'center' + * http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1420236_253892949 + */ + private function transformCellVerticalAlignment(string $cellVerticalAlignment): string + { + return ($cellVerticalAlignment === CellVerticalAlignment::CENTER) + ? 'middle' + : $cellVerticalAlignment; + } /** * Returns the contents of the "" section, inside "" section. @@ -357,8 +380,8 @@ private function getTableCellPropertiesSectionContent(Style $style): string { $content = 'shouldWrapText()) { - $content .= $this->getWrapTextXMLContent(); + if ($style->hasSetWrapText()) { + $content .= $this->getWrapTextXMLContent($style->shouldWrapText()); } if (null !== ($border = $style->getBorder())) { @@ -377,9 +400,9 @@ private function getTableCellPropertiesSectionContent(Style $style): string /** * Returns the contents of the wrap text definition for the "" section. */ - private function getWrapTextXMLContent(): string + private function getWrapTextXMLContent(bool $shouldWrapText): string { - return ' fo:wrap-option="wrap" style:vertical-align="automatic" '; + return ' fo:wrap-option="' . ($shouldWrapText ? '' : 'no-') . 'wrap" style:vertical-align="automatic" '; } /** diff --git a/src/Writer/XLSX/Manager/Style/StyleManager.php b/src/Writer/XLSX/Manager/Style/StyleManager.php index ab4d656c..ea83d506 100644 --- a/src/Writer/XLSX/Manager/Style/StyleManager.php +++ b/src/Writer/XLSX/Manager/Style/StyleManager.php @@ -238,14 +238,17 @@ private function getCellXfsSectionContent(): string $content .= sprintf(' applyBorder="%d"', (bool) $style->getBorder()); - if ($style->shouldApplyCellAlignment() || $style->shouldWrapText() || $style->shouldShrinkToFit()) { + if ($style->shouldApplyCellAlignment() || $style->shouldApplyCellVerticalAlignment() || $style->hasSetWrapText() || $style->shouldShrinkToFit()) { $content .= ' applyAlignment="1">'; $content .= 'shouldApplyCellAlignment()) { $content .= sprintf(' horizontal="%s"', $style->getCellAlignment()); } - if ($style->shouldWrapText()) { - $content .= ' wrapText="1"'; + if ($style->shouldApplyCellVerticalAlignment()) { + $content .= \sprintf(' vertical="%s"', $style->getCellVerticalAlignment()); + } + if ($style->hasSetWrapText()) { + $content .= ' wrapText="' . ($style->shouldWrapText() ? '1' : '0') . '"'; } if ($style->shouldShrinkToFit()) { $content .= ' shrinkToFit="true"'; diff --git a/tests/Writer/Common/Creator/StyleTest.php b/tests/Writer/Common/Creator/StyleTest.php index dc932844..fc2a7453 100644 --- a/tests/Writer/Common/Creator/StyleTest.php +++ b/tests/Writer/Common/Creator/StyleTest.php @@ -4,6 +4,7 @@ namespace OpenSpout\Writer\Common\Creator\Style; +use Box\Spout\Common\Entity\Style\CellVerticalAlignment; use OpenSpout\Common\Entity\Style\Border; use OpenSpout\Common\Entity\Style\BorderPart; use OpenSpout\Common\Entity\Style\CellAlignment; @@ -46,9 +47,21 @@ public function testStyleBuilderShouldApplyCellAlignment(): void self::assertTrue($style->shouldApplyCellAlignment()); } + public function testStyleBuilderShouldApplyCellVerticalAlignment(): void + { + $style = (new Style())->setCellVerticalAlignment(CellVerticalAlignment::CENTER); + $this->assertTrue($style->shouldApplyCellVerticalAlignment()); + } + public function testStyleBuilderShouldThrowOnInvalidCellAlignment(): void { $this->expectException(InvalidArgumentException::class); (new Style())->setCellAlignment('invalid_cell_alignment'); } + + public function testStyleBuilderShouldThrowOnInvalidCellVerticalAlignment(): void + { + $this->expectException(InvalidArgumentException::class); + (new Style())->setCellVerticalAlignment('invalid_cell_alignment'); + } } diff --git a/tests/Writer/ODS/WriterWithStyleTest.php b/tests/Writer/ODS/WriterWithStyleTest.php index 87e7e4e3..5a2990b3 100644 --- a/tests/Writer/ODS/WriterWithStyleTest.php +++ b/tests/Writer/ODS/WriterWithStyleTest.php @@ -168,6 +168,24 @@ public function testAddRowShouldAddWrapTextAlignmentInfoInStylesXmlFileIfSpecifi $this->assertFirstChildHasAttributeEquals('wrap', $customStyleElement, 'table-cell-properties', 'fo:wrap-option'); } + public function testAddRowShouldAddNegatedWrapTextAlignmentInfoInStylesXmlFileIfSpecified(): void + { + $fileName = 'test_add_row_should_add_negated_wrap_text_alignment.ods'; + + $style = (new Style())->setShouldWrapText(false); + $dataRows = $this->createStyledRowsFromValues([ + ['ods--11', 'ods--12'], + ], $style); + + $this->writeToODSFile($dataRows, $fileName); + + $styleElements = $this->getCellStyleElementsFromContentXmlFile($fileName); + $this->assertCount(2, $styleElements, 'There should be 2 styles (default and custom)'); + + $customStyleElement = $styleElements[1]; + $this->assertFirstChildHasAttributeEquals('no-wrap', $customStyleElement, 'table-cell-properties', 'fo:wrap-option'); + } + public function testAddRowShouldApplyWrapTextIfCellContainsNewLine(): void { $fileName = 'test_add_row_should_apply_wrap_text_if_new_lines.ods'; diff --git a/tests/Writer/XLSX/WriterWithStyleTest.php b/tests/Writer/XLSX/WriterWithStyleTest.php index e14ca248..181bfd0c 100644 --- a/tests/Writer/XLSX/WriterWithStyleTest.php +++ b/tests/Writer/XLSX/WriterWithStyleTest.php @@ -248,6 +248,23 @@ public function testAddRowShouldAddWrapTextAlignmentInfoInStylesXmlFileIfSpecifi $this->assertFirstChildHasAttributeEquals('1', $xfElement, 'alignment', 'wrapText'); } + public function testAddRowShouldAddNegatedWrapTextAlignmentInfoInStylesXmlFileIfSpecified(): void + { + $fileName = 'test_add_row_should_add_negated_wrap_text_alignment.xlsx'; + + $style = (new Style())->setShouldWrapText(false)->; + $dataRows = $this->createStyledRowsFromValues([ + ['xlsx--11', 'xlsx--12'], + ], $style); + + $this->writeToXLSXFile($dataRows, $fileName); + + $cellXfsDomElement = $this->getXmlSectionFromStylesXmlFile($fileName, 'cellXfs'); + $xfElement = $cellXfsDomElement->getElementsByTagName('xf')->item(1); + $this->assertEquals(1, $xfElement->getAttribute('applyAlignment')); + $this->assertFirstChildHasAttributeEquals('0', $xfElement, 'alignment', 'wrapText'); + } + public function testAddRowShouldApplyWrapTextIfCellContainsNewLine(): void { $fileName = 'test_add_row_should_apply_wrap_text_if_new_lines.xlsx';