From 1730b75cc6cbd95fef88238169a9c12f10959650 Mon Sep 17 00:00:00 2001 From: feline Date: Mon, 20 Jul 2020 14:32:43 +0800 Subject: [PATCH 01/16] Update WorksheetManager.php fix the merging cells problem --- src/Spout/Writer/XLSX/Manager/WorksheetManager.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php index 741d0aa8..84278ec9 100644 --- a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php +++ b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php @@ -271,6 +271,17 @@ public function close(Worksheet $worksheet) } \fwrite($worksheetFilePointer, ''); + // do sth to merging cells + $mergeRanges = $worksheet->getExternalSheet()->getMergeRanges(); + if(!empty($mergeRanges)) { + $startLine = ''; + $rangeLine = ''; + foreach ($mergeRanges as $key => $range) { + $rangeLine .= ''; + } + $endLine = ''; + \fwrite($worksheetFilePointer, $startLine.$rangeLine.$endLine); + } \fwrite($worksheetFilePointer, ''); \fclose($worksheetFilePointer); } From 094c34a60c13ad0dcb3940586c3f60dcfdadac0e Mon Sep 17 00:00:00 2001 From: feline Date: Mon, 20 Jul 2020 14:33:16 +0800 Subject: [PATCH 02/16] Update WorksheetManager.php fix the space --- src/Spout/Writer/XLSX/Manager/WorksheetManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php index 84278ec9..7e99e383 100644 --- a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php +++ b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php @@ -272,7 +272,7 @@ public function close(Worksheet $worksheet) \fwrite($worksheetFilePointer, ''); // do sth to merging cells - $mergeRanges = $worksheet->getExternalSheet()->getMergeRanges(); + $mergeRanges = $worksheet->getExternalSheet()->getMergeRanges(); if(!empty($mergeRanges)) { $startLine = ''; $rangeLine = ''; From 3279c09e712c1ebdb600e3bca565697e8a6faeb3 Mon Sep 17 00:00:00 2001 From: feline Date: Mon, 20 Jul 2020 14:37:51 +0800 Subject: [PATCH 03/16] Update Sheet.php add the set and get function of the merge ranging --- src/Spout/Writer/Common/Entity/Sheet.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Spout/Writer/Common/Entity/Sheet.php b/src/Spout/Writer/Common/Entity/Sheet.php index aabdd91f..4a6d99a6 100644 --- a/src/Spout/Writer/Common/Entity/Sheet.php +++ b/src/Spout/Writer/Common/Entity/Sheet.php @@ -27,6 +27,9 @@ class Sheet /** @var SheetManager Sheet manager */ private $sheetManager; + /** @var $mergeRanges merge cell */ + private $mergeRanges; + /** * @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based) * @param string $associatedWorkbookId ID of the sheet's associated workbook @@ -108,4 +111,22 @@ public function setIsVisible($isVisible) return $this; } + + /** + * @return merge + */ + public function getMergeRanges() + { + return $this->mergeRanges; + } + + /** + * @param $mergeRanges + * @return mixed + */ + public function setMergeRanges($mergeRanges) + { + return $this->mergeRanges = $mergeRanges; + } + } From 74357ffb711aac5e44f67bb822ee363aa2b72549 Mon Sep 17 00:00:00 2001 From: feline Date: Fri, 21 Aug 2020 14:24:43 +0800 Subject: [PATCH 04/16] Update .travis.yml update --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ac931ed6..c83ce27b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,4 +58,4 @@ after_script: if [[ "$WITH_COVERAGE" == "true" ]]; then wget https://scrutinizer-ci.com/ocular.phar php ocular.phar code-coverage:upload --format=php-clover build/logs/coverage.clover - fi + fi From 59343bae9110bfc1a99532ff3c708f560bcf4e0f Mon Sep 17 00:00:00 2001 From: xiaoxiali Date: Fri, 21 Aug 2020 14:51:02 +0800 Subject: [PATCH 05/16] fix by PHP-CS-Fixer --- src/Spout/Reader/ODS/SheetIterator.php | 4 ++-- .../Reader/XLSX/Manager/SharedStringsManager.php | 2 +- src/Spout/Reader/XLSX/RowIterator.php | 2 +- src/Spout/Writer/Common/Entity/Sheet.php | 11 +++++------ .../Writer/Common/Manager/WorkbookManagerAbstract.php | 2 +- src/Spout/Writer/ODS/Creator/ManagerFactory.php | 2 +- src/Spout/Writer/WriterAbstract.php | 2 +- src/Spout/Writer/XLSX/Creator/ManagerFactory.php | 2 +- src/Spout/Writer/XLSX/Manager/WorksheetManager.php | 4 ++-- tests/Spout/Reader/CSV/SpoutTestStream.php | 4 ++-- 10 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/Spout/Reader/ODS/SheetIterator.php b/src/Spout/Reader/ODS/SheetIterator.php index f35b8523..c7b8cd9d 100644 --- a/src/Spout/Reader/ODS/SheetIterator.php +++ b/src/Spout/Reader/ODS/SheetIterator.php @@ -28,13 +28,13 @@ class SheetIterator implements IteratorInterface const XML_ATTRIBUTE_TABLE_STYLE_NAME = 'table:style-name'; const XML_ATTRIBUTE_TABLE_DISPLAY = 'table:display'; - /** @var string $filePath Path of the file to be read */ + /** @var string Path of the file to be read */ protected $filePath; /** @var \Box\Spout\Common\Manager\OptionsManagerInterface Reader's options manager */ protected $optionsManager; - /** @var InternalEntityFactory $entityFactory Factory to create entities */ + /** @var InternalEntityFactory Factory to create entities */ protected $entityFactory; /** @var XMLReader The XMLReader object that will help read sheet's XML data */ diff --git a/src/Spout/Reader/XLSX/Manager/SharedStringsManager.php b/src/Spout/Reader/XLSX/Manager/SharedStringsManager.php index caaeed76..8850a69b 100644 --- a/src/Spout/Reader/XLSX/Manager/SharedStringsManager.php +++ b/src/Spout/Reader/XLSX/Manager/SharedStringsManager.php @@ -43,7 +43,7 @@ class SharedStringsManager /** @var InternalEntityFactory Factory to create entities */ protected $entityFactory; - /** @var HelperFactory $helperFactory Factory to create helpers */ + /** @var HelperFactory Factory to create helpers */ protected $helperFactory; /** @var CachingStrategyFactory Factory to create shared strings caching strategies */ diff --git a/src/Spout/Reader/XLSX/RowIterator.php b/src/Spout/Reader/XLSX/RowIterator.php index 4af4530d..a54b8b19 100644 --- a/src/Spout/Reader/XLSX/RowIterator.php +++ b/src/Spout/Reader/XLSX/RowIterator.php @@ -35,7 +35,7 @@ class RowIterator implements IteratorInterface /** @var string Path of the XLSX file being read */ protected $filePath; - /** @var string $sheetDataXMLFilePath Path of the sheet data XML file as in [Content_Types].xml */ + /** @var string Path of the sheet data XML file as in [Content_Types].xml */ protected $sheetDataXMLFilePath; /** @var \Box\Spout\Reader\Wrapper\XMLReader The XMLReader object that will help read sheet's XML data */ diff --git a/src/Spout/Writer/Common/Entity/Sheet.php b/src/Spout/Writer/Common/Entity/Sheet.php index 4a6d99a6..3407ec7d 100644 --- a/src/Spout/Writer/Common/Entity/Sheet.php +++ b/src/Spout/Writer/Common/Entity/Sheet.php @@ -27,9 +27,9 @@ class Sheet /** @var SheetManager Sheet manager */ private $sheetManager; - /** @var $mergeRanges merge cell */ + /** @var merge cell */ private $mergeRanges; - + /** * @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based) * @param string $associatedWorkbookId ID of the sheet's associated workbook @@ -111,10 +111,10 @@ public function setIsVisible($isVisible) return $this; } - + /** - * @return merge - */ + * @return merge + */ public function getMergeRanges() { return $this->mergeRanges; @@ -128,5 +128,4 @@ public function setMergeRanges($mergeRanges) { return $this->mergeRanges = $mergeRanges; } - } diff --git a/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php b/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php index b5135555..653778c7 100644 --- a/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php +++ b/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php @@ -44,7 +44,7 @@ abstract class WorkbookManagerAbstract implements WorkbookManagerInterface /** @var InternalEntityFactory Factory to create entities */ protected $entityFactory; - /** @var ManagerFactoryInterface $managerFactory Factory to create managers */ + /** @var ManagerFactoryInterface Factory to create managers */ protected $managerFactory; /** @var Worksheet The worksheet where data will be written to */ diff --git a/src/Spout/Writer/ODS/Creator/ManagerFactory.php b/src/Spout/Writer/ODS/Creator/ManagerFactory.php index f38c5000..a5b77ee4 100644 --- a/src/Spout/Writer/ODS/Creator/ManagerFactory.php +++ b/src/Spout/Writer/ODS/Creator/ManagerFactory.php @@ -22,7 +22,7 @@ class ManagerFactory implements ManagerFactoryInterface /** @var InternalEntityFactory */ protected $entityFactory; - /** @var HelperFactory $helperFactory */ + /** @var HelperFactory */ protected $helperFactory; /** diff --git a/src/Spout/Writer/WriterAbstract.php b/src/Spout/Writer/WriterAbstract.php index d96a6280..bbaa735a 100644 --- a/src/Spout/Writer/WriterAbstract.php +++ b/src/Spout/Writer/WriterAbstract.php @@ -33,7 +33,7 @@ abstract class WriterAbstract implements WriterInterface /** @var GlobalFunctionsHelper Helper to work with global functions */ protected $globalFunctionsHelper; - /** @var HelperFactory $helperFactory */ + /** @var HelperFactory */ protected $helperFactory; /** @var OptionsManagerInterface Writer options manager */ diff --git a/src/Spout/Writer/XLSX/Creator/ManagerFactory.php b/src/Spout/Writer/XLSX/Creator/ManagerFactory.php index f27a2f2f..aa3bcd5c 100644 --- a/src/Spout/Writer/XLSX/Creator/ManagerFactory.php +++ b/src/Spout/Writer/XLSX/Creator/ManagerFactory.php @@ -24,7 +24,7 @@ class ManagerFactory implements ManagerFactoryInterface /** @var InternalEntityFactory */ protected $entityFactory; - /** @var HelperFactory $helperFactory */ + /** @var HelperFactory */ protected $helperFactory; /** diff --git a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php index 7e99e383..764b52f7 100644 --- a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php +++ b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php @@ -273,14 +273,14 @@ public function close(Worksheet $worksheet) \fwrite($worksheetFilePointer, ''); // do sth to merging cells $mergeRanges = $worksheet->getExternalSheet()->getMergeRanges(); - if(!empty($mergeRanges)) { + if (!empty($mergeRanges)) { $startLine = ''; $rangeLine = ''; foreach ($mergeRanges as $key => $range) { $rangeLine .= ''; } $endLine = ''; - \fwrite($worksheetFilePointer, $startLine.$rangeLine.$endLine); + \fwrite($worksheetFilePointer, $startLine . $rangeLine . $endLine); } \fwrite($worksheetFilePointer, ''); \fclose($worksheetFilePointer); diff --git a/tests/Spout/Reader/CSV/SpoutTestStream.php b/tests/Spout/Reader/CSV/SpoutTestStream.php index 3bfd06e1..d66e8117 100644 --- a/tests/Spout/Reader/CSV/SpoutTestStream.php +++ b/tests/Spout/Reader/CSV/SpoutTestStream.php @@ -14,10 +14,10 @@ class SpoutTestStream const PATH_TO_CSV_RESOURCES = 'tests/resources/csv/'; const CSV_EXTENSION = '.csv'; - /** @var int $position */ + /** @var int */ private $position; - /** @var resource $fileHandle */ + /** @var resource */ private $fileHandle; /** From 26348e5558113e33e5ba6389b9f43fcc6f177da0 Mon Sep 17 00:00:00 2001 From: xiaoxiali Date: Thu, 27 Aug 2020 11:24:28 +0800 Subject: [PATCH 06/16] fix the annotation --- src/Spout/Writer/XLSX/Manager/WorksheetManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php index 764b52f7..8013b8f4 100644 --- a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php +++ b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php @@ -271,7 +271,7 @@ public function close(Worksheet $worksheet) } \fwrite($worksheetFilePointer, ''); - // do sth to merging cells + // do something to merging cells $mergeRanges = $worksheet->getExternalSheet()->getMergeRanges(); if (!empty($mergeRanges)) { $startLine = ''; From cf3333f008c3abc43dd048163e23ee23ba134267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?xiaoxiali=28=E6=9D=8E=E6=99=93=E5=A4=8F=29?= Date: Wed, 16 Sep 2020 19:53:53 +0800 Subject: [PATCH 07/16] fix --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 89434694..8ad74723 100644 --- a/composer.json +++ b/composer.json @@ -1,10 +1,10 @@ { - "name": "box/spout", + "name": "sirius-box/spout", "description": "PHP Library to read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way", "type": "library", "keywords": ["php","read","write","csv","xlsx","ods","odf","open","office","excel","spreadsheet","scale","memory","stream","ooxml"], "license": "Apache-2.0", - "homepage": "https://www.github.com/box/spout", + "homepage": "https://www.github.com/palfeline/spout", "authors": [ { "name": "Adrien Loison", From 51434243ac903deff521cc621f354e6d52bbcb4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?xiaoxiali=28=E6=9D=8E=E6=99=93=E5=A4=8F=29?= Date: Fri, 18 Sep 2020 15:02:59 +0800 Subject: [PATCH 08/16] fix composer --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 8ad74723..89434694 100644 --- a/composer.json +++ b/composer.json @@ -1,10 +1,10 @@ { - "name": "sirius-box/spout", + "name": "box/spout", "description": "PHP Library to read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way", "type": "library", "keywords": ["php","read","write","csv","xlsx","ods","odf","open","office","excel","spreadsheet","scale","memory","stream","ooxml"], "license": "Apache-2.0", - "homepage": "https://www.github.com/palfeline/spout", + "homepage": "https://www.github.com/box/spout", "authors": [ { "name": "Adrien Loison", From c721aaac40f890cf4bcceb94d5cc661110392c32 Mon Sep 17 00:00:00 2001 From: a1kuzn Date: Thu, 3 Jun 2021 11:09:28 +0300 Subject: [PATCH 09/16] Add support for clear old column widths New method for clear old column widths when we want to start new sheet --- src/Spout/Writer/Common/Manager/ManagesCellSize.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Spout/Writer/Common/Manager/ManagesCellSize.php b/src/Spout/Writer/Common/Manager/ManagesCellSize.php index 8a517f0d..2ec958cb 100644 --- a/src/Spout/Writer/Common/Manager/ManagesCellSize.php +++ b/src/Spout/Writer/Common/Manager/ManagesCellSize.php @@ -29,6 +29,14 @@ public function setDefaultRowHeight($height) $this->defaultRowHeight = $height; } + /** + * Clear old column widths when we want to start new sheet + */ + public function clearColumnWidths() + { + $this->columnWidths = []; + } + /** * @param float $width * @param array $columns One or more columns with this width From bb702742c20853457856fa8f248afd779395b8c5 Mon Sep 17 00:00:00 2001 From: a1kuzn Date: Thu, 3 Jun 2021 11:27:41 +0300 Subject: [PATCH 10/16] Add support for clear old column widths New method for clear old column widths when we want to start new sheet --- src/Spout/Writer/WriterMultiSheetsAbstract.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Spout/Writer/WriterMultiSheetsAbstract.php b/src/Spout/Writer/WriterMultiSheetsAbstract.php index 0161877e..cf5873c1 100644 --- a/src/Spout/Writer/WriterMultiSheetsAbstract.php +++ b/src/Spout/Writer/WriterMultiSheetsAbstract.php @@ -166,6 +166,15 @@ public function setDefaultRowHeight(float $height) ); } + /** + * Clear old column widths when we want to start new sheet + */ + public function clearColumnWidths() + { + $this->throwIfWorkbookIsNotAvailable(); + $this->workbookManager->clearColumnWidths(); + } + /** * @param float|null $width * @param array $columns One or more columns with this width From b39349fb505476a1dd62dd088c54ec2d5e3d44af Mon Sep 17 00:00:00 2001 From: a1kuzn Date: Thu, 3 Jun 2021 11:39:21 +0300 Subject: [PATCH 11/16] Add support for clear old column widths New method for clear old column widths when we want to start new sheet --- .../Writer/Common/Manager/WorkbookManagerAbstract.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php b/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php index 604de65c..a96d3374 100644 --- a/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php +++ b/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php @@ -303,6 +303,14 @@ public function setDefaultRowHeight(float $height) $this->worksheetManager->setDefaultRowHeight($height); } + /** + * Clear old column widths when we want to start new sheet + */ + public function clearColumnWidths() + { + $this->worksheetManager->clearColumnWidths(); + } + /** * @param float $width * @param array $columns One or more columns with this width From b157b866112caeaa8cd0d502dab7d0325d2f1aae Mon Sep 17 00:00:00 2001 From: a1kuzn Date: Thu, 3 Jun 2021 11:42:12 +0300 Subject: [PATCH 12/16] Add support for clear old column widths New method for clear old column widths when we want to start new sheet --- .../Writer/Common/Manager/WorksheetManagerInterface.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Spout/Writer/Common/Manager/WorksheetManagerInterface.php b/src/Spout/Writer/Common/Manager/WorksheetManagerInterface.php index bb6758a7..0cc7ec53 100644 --- a/src/Spout/Writer/Common/Manager/WorksheetManagerInterface.php +++ b/src/Spout/Writer/Common/Manager/WorksheetManagerInterface.php @@ -21,6 +21,11 @@ public function setDefaultColumnWidth($width); */ public function setDefaultRowHeight($height); + /** + * Clear old column widths when we want to start new sheet + */ + public function clearColumnWidths(); + /** * @param float $width * @param array $columns One or more columns with this width From 03a010d07aa4324ef001b11ed72d54286633e3d9 Mon Sep 17 00:00:00 2001 From: a1kuzn Date: Thu, 3 Jun 2021 11:46:02 +0300 Subject: [PATCH 13/16] Add support for clear old column widths New method for clear old column widths when we want to start new sheet --- src/Spout/Writer/ODS/Manager/WorksheetManager.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Spout/Writer/ODS/Manager/WorksheetManager.php b/src/Spout/Writer/ODS/Manager/WorksheetManager.php index 64f6e6e6..124a30b2 100644 --- a/src/Spout/Writer/ODS/Manager/WorksheetManager.php +++ b/src/Spout/Writer/ODS/Manager/WorksheetManager.php @@ -282,6 +282,14 @@ public function setDefaultRowHeight($height) $this->styleManager->setDefaultRowHeight($height); } + /** + * Clear old column widths when we want to start new sheet + */ + public function clearColumnWidths() + { + $this->styleManager->clearColumnWidths(); + } + /** * @param float $width * @param array $columns One or more columns with this width From a1982d1421934a71150c47d129c87a9d9db5cbbc Mon Sep 17 00:00:00 2001 From: a1kuzn Date: Mon, 21 Jun 2021 16:42:55 +0300 Subject: [PATCH 14/16] Add support for add merge ranges --- src/Spout/Writer/Common/Entity/Sheet.php | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Spout/Writer/Common/Entity/Sheet.php b/src/Spout/Writer/Common/Entity/Sheet.php index 3407ec7d..199e628e 100644 --- a/src/Spout/Writer/Common/Entity/Sheet.php +++ b/src/Spout/Writer/Common/Entity/Sheet.php @@ -27,8 +27,8 @@ class Sheet /** @var SheetManager Sheet manager */ private $sheetManager; - /** @var merge cell */ - private $mergeRanges; + /** @var array merge cell */ + private array $mergeRanges = []; /** * @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based) @@ -113,7 +113,7 @@ public function setIsVisible($isVisible) } /** - * @return merge + * @return array */ public function getMergeRanges() { @@ -121,11 +121,20 @@ public function getMergeRanges() } /** - * @param $mergeRanges - * @return mixed + * @param array $mergeRanges + * @return array */ - public function setMergeRanges($mergeRanges) + public function setMergeRanges(array $mergeRanges) { return $this->mergeRanges = $mergeRanges; } + + /** + * @param $mergeRanges + * @return array + */ + public function addMergeRanges(string ...$mergeRanges) + { + return $this->mergeRanges = array_merge($this->mergeRanges, $mergeRanges); + } } From fc603382337f4877effe5bfa8cc8e41561723789 Mon Sep 17 00:00:00 2001 From: a1kuzn Date: Mon, 21 Jun 2021 17:12:47 +0300 Subject: [PATCH 15/16] Add support for merging cells by indexes --- src/Spout/Writer/Common/Entity/Sheet.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Spout/Writer/Common/Entity/Sheet.php b/src/Spout/Writer/Common/Entity/Sheet.php index 199e628e..107ef760 100644 --- a/src/Spout/Writer/Common/Entity/Sheet.php +++ b/src/Spout/Writer/Common/Entity/Sheet.php @@ -2,6 +2,7 @@ namespace Box\Spout\Writer\Common\Entity; +use Box\Spout\Writer\Common\Helper\CellHelper; use Box\Spout\Writer\Common\Manager\SheetManager; /** @@ -137,4 +138,22 @@ public function addMergeRanges(string ...$mergeRanges) { return $this->mergeRanges = array_merge($this->mergeRanges, $mergeRanges); } + + /** + * @param int $fromColumnIndexZeroBased + * @param int $fromRowIndexOneBased + * @param int $toColumnIndexZeroBased + * @param int $toRowIndexOneBased + * @return array + */ + public function addMergeRangeByIndexes( + int $fromColumnIndexZeroBased, + int $fromRowIndexOneBased, + int $toColumnIndexZeroBased, + int $toRowIndexOneBased + ) { + $fromLetter = CellHelper::getColumnLettersFromColumnIndex($fromColumnIndexZeroBased); + $toLetter = CellHelper::getColumnLettersFromColumnIndex($toColumnIndexZeroBased); + return $this->addMergeRanges("{$fromLetter}{$fromRowIndexOneBased}:{$toLetter}{$toRowIndexOneBased}"); + } } From a33c2959942f895971a7a6cb31b9fec5f1af0fc4 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 2 Jul 2021 02:07:22 +0300 Subject: [PATCH 16/16] Row Height, Vertical Alignment, Shrink To Fit --- src/Spout/Common/Entity/Row.php | 44 ++++++++++ .../Entity/Style/CellVerticalAlignment.php | 34 ++++++++ src/Spout/Common/Entity/Style/Style.php | 81 +++++++++++++++++++ .../Common/Creator/Style/StyleBuilder.php | 33 ++++++++ .../Common/Manager/Style/StyleMerger.php | 6 ++ .../XLSX/Manager/Style/StyleManager.php | 13 ++- .../Writer/XLSX/Manager/WorksheetManager.php | 6 +- tests/Spout/Writer/XLSX/WriterTest.php | 81 +++++++++++++++++++ .../Spout/Writer/XLSX/WriterWithStyleTest.php | 18 +++++ 9 files changed, 313 insertions(+), 3 deletions(-) create mode 100644 src/Spout/Common/Entity/Style/CellVerticalAlignment.php diff --git a/src/Spout/Common/Entity/Row.php b/src/Spout/Common/Entity/Row.php index 0cc49c73..3ef52b2e 100644 --- a/src/Spout/Common/Entity/Row.php +++ b/src/Spout/Common/Entity/Row.php @@ -6,6 +6,8 @@ class Row { + public const DEFAULT_HEIGHT = 15; + /** * The cells in this row * @var Cell[] @@ -18,6 +20,18 @@ class Row */ protected $style; + /** + * Row height + * @var float + */ + protected $height = self::DEFAULT_HEIGHT; + + /** + * Whether the height property was set + * @var bool + */ + protected $hasSetHeight = false; + /** * Row constructor. * @param Cell[] $cells @@ -126,4 +140,34 @@ public function toArray() return $cell->getValue(); }, $this->cells); } + + /** + * Set row height + * @param float $height + * @return Row + */ + public function setHeight($height) + { + $this->height = $height; + $this->hasSetHeight = (bool)$height; + + return $this; + } + + /** + * Returns row height + * @return float + */ + public function getHeight() + { + return $this->height; + } + + /** + * @return bool + */ + public function hasSetHeight(): bool + { + return $this->hasSetHeight; + } } diff --git a/src/Spout/Common/Entity/Style/CellVerticalAlignment.php b/src/Spout/Common/Entity/Style/CellVerticalAlignment.php new file mode 100644 index 00000000..27a4dd14 --- /dev/null +++ b/src/Spout/Common/Entity/Style/CellVerticalAlignment.php @@ -0,0 +1,34 @@ + 1, + self::CENTER => 1, + self::BOTTOM => 1, + self::JUSTIFY => 1, + self::DISTRIBUTED => 1, + ]; + + /** + * @param string $cellVerticalAlignment + * + * @return bool Whether the given cell vertical alignment is valid + */ + public static function isValid($cellVerticalAlignment) + { + return isset(self::$VALID_VERTICAL_ALIGNMENTS[$cellVerticalAlignment]); + } +} diff --git a/src/Spout/Common/Entity/Style/Style.php b/src/Spout/Common/Entity/Style/Style.php index 2bacc7af..bdbdec6f 100644 --- a/src/Spout/Common/Entity/Style/Style.php +++ b/src/Spout/Common/Entity/Style/Style.php @@ -61,11 +61,23 @@ class Style /** @var bool Whether the cell alignment property was set */ private $hasSetCellAlignment = false; + /** @var bool Whether specific cell alignment should be applied */ + private $shouldApplyCellVerticalAlignment = false; + /** @var string Cell alignment */ + private $cellVerticalAlignment; + /** @var bool Whether the cell alignment property was set */ + private $hasSetCellVerticalAlignment = false; + /** @var bool Whether the text should wrap in the cell (useful for long or multi-lines text) */ private $shouldWrapText = false; /** @var bool Whether the wrap text property was set */ private $hasSetWrapText = false; + /** @var bool Whether the cell should shrink to fit to content */ + private $shouldShrinkToFit = false; + /** @var bool Whether the shouldShrinkToFit text property was set */ + private $hasSetShrinkToFit = false; + /** @var Border */ private $border; @@ -385,6 +397,45 @@ public function shouldApplyCellAlignment() return $this->shouldApplyCellAlignment; } + /** + * @return string + */ + public function getCellVerticalAlignment() + { + return $this->cellVerticalAlignment; + } + + /** + * @param string $cellVerticalAlignment The cell vertical alignment + * + * @return Style + */ + public function setCellVerticalAlignment($cellVerticalAlignment) + { + $this->cellVerticalAlignment = $cellVerticalAlignment; + $this->hasSetCellVerticalAlignment = true; + $this->shouldApplyCellVerticalAlignment = true; + $this->isEmpty = false; + + return $this; + } + + /** + * @return bool + */ + public function hasSetCellVerticalAlignment() + { + return $this->hasSetCellVerticalAlignment; + } + + /** + * @return bool Whether specific cell vertical alignment should be applied + */ + public function shouldApplyCellVerticalAlignment() + { + return $this->shouldApplyCellVerticalAlignment; + } + /** * @return bool */ @@ -482,6 +533,36 @@ public function shouldApplyFormat() return $this->hasSetFormat; } + /** + * Sets should shrink to fit + * @param bool $shrinkToFit + * @return Style + */ + public function setShouldShrinkToFit($shrinkToFit = true) + { + $this->hasSetShrinkToFit = true; + $this->shouldShrinkToFit = $shrinkToFit; + $this->isEmpty = false; + + return $this; + } + + /** + * @return bool Whether format should be applied + */ + public function shouldShrinkToFit() + { + return $this->shouldShrinkToFit; + } + + /** + * @return bool + */ + public function hasSetShrinkToFit() + { + return $this->hasSetShrinkToFit; + } + /** * @return bool */ diff --git a/src/Spout/Writer/Common/Creator/Style/StyleBuilder.php b/src/Spout/Writer/Common/Creator/Style/StyleBuilder.php index bc2d406f..60058de8 100644 --- a/src/Spout/Writer/Common/Creator/Style/StyleBuilder.php +++ b/src/Spout/Writer/Common/Creator/Style/StyleBuilder.php @@ -4,6 +4,7 @@ use Box\Spout\Common\Entity\Style\Border; use Box\Spout\Common\Entity\Style\CellAlignment; +use Box\Spout\Common\Entity\Style\CellVerticalAlignment; use Box\Spout\Common\Entity\Style\Style; use Box\Spout\Common\Exception\InvalidArgumentException; @@ -143,6 +144,25 @@ public function setCellAlignment($cellAlignment) return $this; } + /** + * Sets the cell vertical alignment. + * + * @param string $cellVerticalAlignment The cell vertical alignment + * + * @throws InvalidArgumentException If the given cell vertical alignment is not valid + * @return StyleBuilder + */ + public function setCellVerticalAlignment($cellVerticalAlignment) + { + if (!CellVerticalAlignment::isValid($cellVerticalAlignment)) { + throw new InvalidArgumentException('Invalid cell vertical alignment value'); + } + + $this->style->setCellVerticalAlignment($cellVerticalAlignment); + + return $this; + } + /** * Set a border * @@ -183,6 +203,19 @@ public function setFormat($format) return $this; } + /** + * Set should shrink to fit + * @param bool $shrinkToFit + * @return StyleBuilder + * @api + */ + public function setShouldShrinkToFit($shrinkToFit = true) + { + $this->style->setShouldShrinkToFit($shrinkToFit); + + return $this; + } + /** * Returns the configured style. The style is cached and can be reused. * diff --git a/src/Spout/Writer/Common/Manager/Style/StyleMerger.php b/src/Spout/Writer/Common/Manager/Style/StyleMerger.php index 806c8d55..b94f06ed 100644 --- a/src/Spout/Writer/Common/Manager/Style/StyleMerger.php +++ b/src/Spout/Writer/Common/Manager/Style/StyleMerger.php @@ -85,9 +85,15 @@ private function mergeCellProperties(Style $styleToUpdate, Style $style, Style $ if (!$style->hasSetWrapText() && $baseStyle->shouldWrapText()) { $styleToUpdate->setShouldWrapText(); } + if (!$style->hasSetShrinkToFit() && $baseStyle->shouldShrinkToFit()) { + $styleToUpdate->setShouldShrinkToFit(); + } if (!$style->hasSetCellAlignment() && $baseStyle->shouldApplyCellAlignment()) { $styleToUpdate->setCellAlignment($baseStyle->getCellAlignment()); } + if (!$style->hasSetCellVerticalAlignment() && $baseStyle->shouldApplyCellVerticalAlignment()) { + $styleToUpdate->setCellVerticalAlignment($baseStyle->getCellVerticalAlignment()); + } if (!$style->getBorder() && $baseStyle->shouldApplyBorder()) { $styleToUpdate->setBorder($baseStyle->getBorder()); } diff --git a/src/Spout/Writer/XLSX/Manager/Style/StyleManager.php b/src/Spout/Writer/XLSX/Manager/Style/StyleManager.php index f0ca9d9e..89040840 100644 --- a/src/Spout/Writer/XLSX/Manager/Style/StyleManager.php +++ b/src/Spout/Writer/XLSX/Manager/Style/StyleManager.php @@ -249,15 +249,26 @@ protected function getCellXfsSectionContent() $content .= \sprintf(' applyBorder="%d"', $style->shouldApplyBorder() ? 1 : 0); - if ($style->shouldApplyCellAlignment() || $style->shouldWrapText()) { + if ( + $style->shouldApplyCellAlignment() + || $style->shouldApplyCellVerticalAlignment() + || $style->shouldWrapText() + || $style->shouldShrinkToFit() + ) { $content .= ' applyAlignment="1">'; $content .= 'shouldApplyCellAlignment()) { $content .= \sprintf(' horizontal="%s"', $style->getCellAlignment()); } + if ($style->shouldApplyCellVerticalAlignment()) { + $content .= \sprintf(' vertical="%s"', $style->getCellVerticalAlignment()); + } if ($style->shouldWrapText()) { $content .= ' wrapText="1"'; } + if ($style->shouldShrinkToFit()) { + $content .= ' shrinkToFit="1"'; + } $content .= '/>'; $content .= ''; } else { diff --git a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php index 11c32e60..2d79781f 100644 --- a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php +++ b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php @@ -181,9 +181,11 @@ private function addNonEmptyRow(Worksheet $worksheet, Row $row) $rowStyle = $row->getStyle(); $rowIndexOneBased = $worksheet->getLastWrittenRowIndex() + 1; $numCells = $row->getNumCells(); + $hasSetRowHeight = $row->hasSetHeight(); - $hasCustomHeight = $this->defaultRowHeight > 0 ? '1' : '0'; - $rowXML = ""; + $customHeight = $hasSetRowHeight || $this->defaultRowHeight > 0 ? 'customHeight="1"' : ''; + $rowHeight = $hasSetRowHeight ? "ht=\"{$row->getHeight()}\"" : ''; + $rowXML = ""; foreach ($row->getCells() as $columnIndexZeroBased => $cell) { $registeredStyle = $this->applyStyleAndRegister($cell, $rowStyle); diff --git a/tests/Spout/Writer/XLSX/WriterTest.php b/tests/Spout/Writer/XLSX/WriterTest.php index 26b37925..ca8830bb 100644 --- a/tests/Spout/Writer/XLSX/WriterTest.php +++ b/tests/Spout/Writer/XLSX/WriterTest.php @@ -7,6 +7,7 @@ use Box\Spout\Common\Exception\InvalidArgumentException; use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\SpoutException; +use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\TestUsingResource; use Box\Spout\Writer\Common\Creator\WriterEntityFactory; use Box\Spout\Writer\Exception\WriterAlreadyOpenedException; @@ -563,6 +564,48 @@ public function testAddRowShouldEscapeControlCharacters() $this->assertInlineDataWasWrittenToSheet($fileName, 1, 'control _x0015_ character'); } + /** + * @return void + */ + public function testAddRowShouldSupportRowHeights() + { + $fileName = 'test_add_row_should_support_row_heights.xlsx'; + $dataRows = $this->createRowsFromValues([ + ['First row with default height'], + ['Second row with custom height'], + ]); + + $dataRows[1]->setHeight('23'); + + $this->writeToXLSXFile($dataRows, $fileName); + $firstRow = $this->getXmlRowFromXmlFile($fileName, 1, 1); + $secondRow = $this->getXmlRowFromXmlFile($fileName, 1, 2); + $this->assertEquals('15', $firstRow->getAttribute('ht'), '1st row does not have default height.'); + $this->assertEquals('23', $secondRow->getAttribute('ht'), '2nd row does not have custom height.'); + } + + /** + * @return void + */ + public function testGeneratedFileShouldBeValidForEmptySheets() + { + $fileName = 'test_empty_sheet.xlsx'; + $this->createGeneratedFolderIfNeeded($fileName); + $resourcePath = $this->getGeneratedResourcePath($fileName); + $writer = WriterEntityFactory::createXLSXWriter(); + $writer->openToFile($resourcePath); + + $writer->addNewSheetAndMakeItCurrent(); + $writer->close(); + + $xmlReader = $this->getXmlReaderForSheetFromXmlFile($fileName, 1); + $xmlReader->setParserProperty(XMLReader::VALIDATE, true); + $this->assertTrue($xmlReader->isValid(), 'worksheet xml is not valid'); + $xmlReader->setParserProperty(XMLReader::VALIDATE, false); + $xmlReader->readUntilNodeFound('sheetData'); + $this->assertEquals('sheetData', $xmlReader->getCurrentNodeName(), 'worksheet xml does not have sheetData'); + } + /** * @return void */ @@ -677,4 +720,42 @@ private function assertSharedStringWasWritten($fileName, $sharedString, $message $this->assertStringContainsString($sharedString, $xmlContents, $message); } + + /** + * @param $fileName + * @param $sheetIndex - 1 based + * @return XMLReader + */ + private function getXmlReaderForSheetFromXmlFile($fileName, $sheetIndex) + { + $resourcePath = $this->getGeneratedResourcePath($fileName); + + $xmlReader = new XMLReader(); + $xmlReader->openFileInZip($resourcePath, 'xl/worksheets/sheet' . $sheetIndex . '.xml'); + + return $xmlReader; + } + + /** + * @param $fileName + * @param $sheetIndex - 1 based + * @param $rowIndex - 1 based + * @throws \Box\Spout\Reader\Exception\XMLProcessingException + * @return \DOMNode|null + */ + private function getXmlRowFromXmlFile($fileName, $sheetIndex, $rowIndex) + { + $xmlReader = $this->getXmlReaderForSheetFromXmlFile($fileName, $sheetIndex); + $xmlReader->readUntilNodeFound('sheetData'); + + for ($i = 0; $i < $rowIndex; $i++) { + $xmlReader->readUntilNodeFound('row'); + } + + $row = $xmlReader->expand(); + + $xmlReader->close(); + + return $row; + } } diff --git a/tests/Spout/Writer/XLSX/WriterWithStyleTest.php b/tests/Spout/Writer/XLSX/WriterWithStyleTest.php index 2571df41..c7af7be7 100644 --- a/tests/Spout/Writer/XLSX/WriterWithStyleTest.php +++ b/tests/Spout/Writer/XLSX/WriterWithStyleTest.php @@ -306,6 +306,24 @@ public function testAddRowShouldApplyCellAlignment() $this->assertFirstChildHasAttributeEquals(CellAlignment::RIGHT, $xfElement, 'alignment', 'horizontal'); } + /** + * @return void + */ + public function testAddRowShouldApplyShrinkToFit() + { + $fileName = 'test_add_row_should_apply_shrink_to_fit.xlsx'; + + $shrinkToFitStyle = (new StyleBuilder())->setShouldShrinkToFit()->build(); + $dataRows = $this->createStyledRowsFromValues([['xlsx--11']], $shrinkToFitStyle); + + $this->writeToXLSXFile($dataRows, $fileName); + + $cellXfsDomElement = $this->getXmlSectionFromStylesXmlFile($fileName, 'cellXfs'); + $xfElement = $cellXfsDomElement->getElementsByTagName('xf')->item(1); + $this->assertEquals(1, $xfElement->getAttribute('applyAlignment')); + $this->assertFirstChildHasAttributeEquals('true', $xfElement, 'alignment', 'shrinkToFit'); + } + /** * @return void */