From 83604f2a16fbb0374747299173abe691b24916da Mon Sep 17 00:00:00 2001 From: Jorick Schram Date: Mon, 3 Jun 2024 10:00:43 +0200 Subject: [PATCH] Implement per cell styling for openspout (#359) * Don't filter out DateTime values * Implement per cell styling of openspout * Remove obsolete parameter * Fix styling * Update to reflect openspout changes * Fix StyleCI linting --- composer.json | 2 +- src/Exportable.php | 36 +++++++++++++++++++++++++++++------- tests/FastExcelTest.php | 26 ++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 2f6202f..047df41 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "require": { "php": "^8.0", "illuminate/support": "^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0", - "openspout/openspout": "^4.1.1" + "openspout/openspout": "^4.24" }, "require-dev": { "illuminate/database": "^6.20.12 || ^7.30.4 || ^8.24.0 || ^9.0 || ^10.0 || ^11.0", diff --git a/src/Exportable.php b/src/Exportable.php index 8b063ec..7aada0f 100644 --- a/src/Exportable.php +++ b/src/Exportable.php @@ -2,6 +2,7 @@ namespace Rap2hpoutre\FastExcel; +use DateTimeInterface; use Generator; use Illuminate\Support\Collection; use Illuminate\Support\Str; @@ -26,6 +27,9 @@ trait Exportable private $header_style; private $rows_style; + /** @var Style[] */ + private $column_styles = []; + /** * @param AbstractOptions $options * @@ -33,6 +37,14 @@ trait Exportable */ abstract protected function setOptions(&$options); + /** @param Style[] $styles */ + public function setColumnStyles($styles): static + { + $this->column_styles = $styles; + + return $this; + } + /** * @param string $path * @param callable|null $callback @@ -182,19 +194,19 @@ private function writeRowsFromCollection($writer, Collection $collection, ?calla $all_rows = $collection->map(function ($value) { return Row::fromValues($value); })->toArray(); - if ($this->rows_style) { - $this->addRowsWithStyle($writer, $all_rows, $this->rows_style); + if ($this->rows_style || count($this->column_styles)) { + $this->addRowsWithStyle($writer, $all_rows, $this->rows_style, $this->column_styles); } else { $writer->addRows($all_rows); } } - private function addRowsWithStyle($writer, $all_rows, $rows_style) + private function addRowsWithStyle($writer, $all_rows, $rows_style, $column_styles) { $styled_rows = []; // Style rows one by one foreach ($all_rows as $row) { - $styled_rows[] = Row::fromValues($row->toArray(), $rows_style); + $styled_rows[] = $this->createRow($row->toArray(), $rows_style, $column_styles); } $writer->addRows($styled_rows); } @@ -215,7 +227,7 @@ private function writeRowsFromGenerator($writer, Generator $generator, ?callable $this->writeHeader($writer, $item); } // Write rows (one by one). - $writer->addRow(Row::fromValues($item->toArray(), $this->rows_style)); + $writer->addRow($this->createRow($item->toArray(), $this->rows_style, $this->column_styles)); } } @@ -236,7 +248,7 @@ private function writeHeader($writer, $first_row) } $keys = array_keys(is_array($first_row) ? $first_row : $first_row->toArray()); - $writer->addRow(Row::fromValues($keys, $this->header_style)); + $writer->addRow($this->createRow($keys, $this->header_style)); // $writer->addRow(WriterEntityFactory::createRowFromArray($keys, $this->header_style)); } @@ -280,7 +292,7 @@ private function transformRow($data) return collect($data)->map(function ($value) { return is_null($value) ? (string) $value : $value; })->filter(function ($value) { - return is_string($value) || is_int($value) || is_float($value); + return is_string($value) || is_int($value) || is_float($value) || $value instanceof DateTimeInterface; }); } @@ -307,4 +319,14 @@ public function rowsStyle(Style $style) return $this; } + + /** + * Create openspout row from values with optional row and cell styling. + * + * @SuppressWarnings(PHPMD.StaticAccess) + */ + private function createRow(array $values = [], ?Style $rows_style = null, array $column_styles = []): Row + { + return Row::fromValuesWithStyles($values, $rows_style, $column_styles); + } } diff --git a/tests/FastExcelTest.php b/tests/FastExcelTest.php index 4372fdc..71a88bd 100644 --- a/tests/FastExcelTest.php +++ b/tests/FastExcelTest.php @@ -4,6 +4,7 @@ use OpenSpout\Common\Entity\Style\Color; use OpenSpout\Common\Entity\Style\Style; +use OpenSpout\Common\Exception\IOException; use OpenSpout\Reader\XLSX\Options; use Rap2hpoutre\FastExcel\FastExcel; use Rap2hpoutre\FastExcel\SheetCollection; @@ -13,6 +14,31 @@ */ class FastExcelTest extends TestCase { + /** + * @throws IOException + * @throws \OpenSpout\Writer\Exception\WriterNotOpenedException + * @throws \OpenSpout\Reader\Exception\ReaderNotOpenedException + * @throws \OpenSpout\Common\Exception\UnsupportedTypeException + * @throws \OpenSpout\Common\Exception\InvalidArgumentException + */ + public function testExportXlsxWithDates() + { + $collection = collect([ + ['col1' => new \DateTimeImmutable('1980-09-18 00:00:00.000000')], + ['col1' => new \DateTimeImmutable('2018-07-02 00:00:00.000000')], + ]); + + $file = __DIR__.'/test-dates-export.xlsx'; + (new FastExcel(clone $collection)) + ->setColumnStyles([ + 0 => (new Style())->setFormat('mm/dd/yyyy'), + ]) + ->export($file); + + $this->assertEquals($collection, (new FastExcel())->import($file)); + unlink($file); + } + /** * @throws \OpenSpout\Common\Exception\IOException * @throws \OpenSpout\Common\Exception\UnsupportedTypeException