diff --git a/docs/topics/accessing-cells.md b/docs/topics/accessing-cells.md
index edb71514..a777afc1 100644
--- a/docs/topics/accessing-cells.md
+++ b/docs/topics/accessing-cells.md
@@ -422,8 +422,10 @@ foreach ($worksheet->getRowIterator() as $row) {
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(FALSE); // This loops through all cells,
// even if a cell value is not set.
- // By default, only cells that have a value
- // set will be iterated.
+ // For 'TRUE', we loop through cells
+ // only when their value is set.
+ // If this method is not called,
+ // the default value is 'false'.
foreach ($cellIterator as $cell) {
echo '
' .
$cell->getValue() .
diff --git a/src/PhpSpreadsheet/Style/Style.php b/src/PhpSpreadsheet/Style/Style.php
index c1aa319e..f7c1be23 100644
--- a/src/PhpSpreadsheet/Style/Style.php
+++ b/src/PhpSpreadsheet/Style/Style.php
@@ -42,13 +42,6 @@ class Style extends Supervisor
*/
protected $numberFormat;
- /**
- * Conditional styles.
- *
- * @var Conditional[]
- */
- protected $conditionalStyles;
-
/**
* Protection.
*
@@ -85,7 +78,6 @@ class Style extends Supervisor
parent::__construct($isSupervisor);
// Initialise values
- $this->conditionalStyles = [];
$this->font = new Font($isSupervisor, $isConditional);
$this->fill = new Fill($isSupervisor, $isConditional);
$this->borders = new Borders($isSupervisor, $isConditional);
@@ -212,6 +204,8 @@ class Style extends Supervisor
$rangeEnd = Coordinate::coordinateFromString($rangeB);
// Translate column into index
+ $rangeStart0 = $rangeStart[0];
+ $rangeEnd0 = $rangeEnd[0];
$rangeStart[0] = Coordinate::columnIndexFromString($rangeStart[0]);
$rangeEnd[0] = Coordinate::columnIndexFromString($rangeEnd[0]);
@@ -361,6 +355,13 @@ class Style extends Supervisor
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
$oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true;
}
+ foreach ($this->getActiveSheet()->getColumnIterator($rangeStart0, $rangeEnd0) as $columnIterator) {
+ $cellIterator = $columnIterator->getCellIterator();
+ $cellIterator->setIterateOnlyExistingCells(true);
+ foreach ($cellIterator as $columnCell) {
+ $columnCell->getStyle()->applyFromArray($pStyles);
+ }
+ }
break;
case 'ROW':
@@ -372,6 +373,13 @@ class Style extends Supervisor
$oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true;
}
}
+ foreach ($this->getActiveSheet()->getRowIterator((int) $rangeStart[1], (int) $rangeEnd[1]) as $rowIterator) {
+ $cellIterator = $rowIterator->getCellIterator();
+ $cellIterator->setIterateOnlyExistingCells(true);
+ foreach ($cellIterator as $rowCell) {
+ $rowCell->getStyle()->applyFromArray($pStyles);
+ }
+ }
break;
case 'CELL':
@@ -599,18 +607,12 @@ class Style extends Supervisor
*/
public function getHashCode()
{
- $hashConditionals = '';
- foreach ($this->conditionalStyles as $conditional) {
- $hashConditionals .= $conditional->getHashCode();
- }
-
return md5(
$this->fill->getHashCode() .
$this->font->getHashCode() .
$this->borders->getHashCode() .
$this->alignment->getHashCode() .
$this->numberFormat->getHashCode() .
- $hashConditionals .
$this->protection->getHashCode() .
($this->quotePrefix ? 't' : 'f') .
__CLASS__
diff --git a/src/PhpSpreadsheet/Worksheet/ColumnCellIterator.php b/src/PhpSpreadsheet/Worksheet/ColumnCellIterator.php
index 12420d77..714ee7ce 100644
--- a/src/PhpSpreadsheet/Worksheet/ColumnCellIterator.php
+++ b/src/PhpSpreadsheet/Worksheet/ColumnCellIterator.php
@@ -92,10 +92,11 @@ class ColumnCellIterator extends CellIterator
*/
public function seek($row = 1)
{
+ if ($this->onlyExistingCells && !($this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $row))) {
+ throw new PhpSpreadsheetException('In "IterateOnlyExistingCells" mode and Cell does not exist');
+ }
if (($row < $this->startRow) || ($row > $this->endRow)) {
throw new PhpSpreadsheetException("Row $row is out of range ({$this->startRow} - {$this->endRow})");
- } elseif ($this->onlyExistingCells && !($this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $row))) {
- throw new PhpSpreadsheetException('In "IterateOnlyExistingCells" mode and Cell does not exist');
}
$this->currentRow = $row;
@@ -113,7 +114,7 @@ class ColumnCellIterator extends CellIterator
/**
* Return the current cell in this worksheet column.
*
- * @return null|\PhpOffice\PhpSpreadsheet\Cell\Cell
+ * @return \PhpOffice\PhpSpreadsheet\Cell\Cell
*/
public function current()
{
@@ -180,18 +181,12 @@ class ColumnCellIterator extends CellIterator
) {
++$this->startRow;
}
- if ($this->startRow > $this->endRow) {
- throw new PhpSpreadsheetException('No cells exist within the specified range');
- }
while (
(!$this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $this->endRow)) &&
($this->endRow >= $this->startRow)
) {
--$this->endRow;
}
- if ($this->endRow < $this->startRow) {
- throw new PhpSpreadsheetException('No cells exist within the specified range');
- }
}
}
}
diff --git a/src/PhpSpreadsheet/Worksheet/RowCellIterator.php b/src/PhpSpreadsheet/Worksheet/RowCellIterator.php
index f5576dc7..9b9d54eb 100644
--- a/src/PhpSpreadsheet/Worksheet/RowCellIterator.php
+++ b/src/PhpSpreadsheet/Worksheet/RowCellIterator.php
@@ -93,12 +93,14 @@ class RowCellIterator extends CellIterator
*/
public function seek($column = 'A')
{
+ $columnx = $column;
$column = Coordinate::columnIndexFromString($column);
- if (($column < $this->startColumnIndex) || ($column > $this->endColumnIndex)) {
- throw new PhpSpreadsheetException("Column $column is out of range ({$this->startColumnIndex} - {$this->endColumnIndex})");
- } elseif ($this->onlyExistingCells && !($this->worksheet->cellExistsByColumnAndRow($column, $this->rowIndex))) {
+ if ($this->onlyExistingCells && !($this->worksheet->cellExistsByColumnAndRow($column, $this->rowIndex))) {
throw new PhpSpreadsheetException('In "IterateOnlyExistingCells" mode and Cell does not exist');
}
+ if (($column < $this->startColumnIndex) || ($column > $this->endColumnIndex)) {
+ throw new PhpSpreadsheetException("Column $columnx is out of range ({$this->startColumnIndex} - {$this->endColumnIndex})");
+ }
$this->currentColumnIndex = $column;
return $this;
@@ -181,15 +183,9 @@ class RowCellIterator extends CellIterator
while ((!$this->worksheet->cellExistsByColumnAndRow($this->startColumnIndex, $this->rowIndex)) && ($this->startColumnIndex <= $this->endColumnIndex)) {
++$this->startColumnIndex;
}
- if ($this->startColumnIndex > $this->endColumnIndex) {
- throw new PhpSpreadsheetException('No cells exist within the specified range');
- }
while ((!$this->worksheet->cellExistsByColumnAndRow($this->endColumnIndex, $this->rowIndex)) && ($this->endColumnIndex >= $this->startColumnIndex)) {
--$this->endColumnIndex;
}
- if ($this->endColumnIndex < $this->startColumnIndex) {
- throw new PhpSpreadsheetException('No cells exist within the specified range');
- }
}
}
}
diff --git a/tests/PhpSpreadsheetTests/Style/StyleTest.php b/tests/PhpSpreadsheetTests/Style/StyleTest.php
index b695a50b..6f157709 100644
--- a/tests/PhpSpreadsheetTests/Style/StyleTest.php
+++ b/tests/PhpSpreadsheetTests/Style/StyleTest.php
@@ -3,6 +3,7 @@
namespace PhpOffice\PhpSpreadsheetTests\Style;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Style\Fill;
use PHPUnit\Framework\TestCase;
class StyleTest extends TestCase
@@ -19,4 +20,141 @@ class StyleTest extends TestCase
$outArray = $cell1style->getStyleArray($styleArray);
self::assertEquals($styleArray, $outArray['quotePrefix']);
}
+
+ public function testStyleColumn(): void
+ {
+ $spreadsheet = new Spreadsheet();
+ $sheet = $spreadsheet->getActiveSheet();
+ $cellCoordinates = 'A:B';
+ $styleArray = [
+ 'font' => [
+ 'bold' => true,
+ ],
+ ];
+ $sheet->getStyle($cellCoordinates)->applyFromArray($styleArray);
+ $sheet->setCellValue('A1', 'xxxa1');
+ $sheet->setCellValue('A2', 'xxxa2');
+ $sheet->setCellValue('A3', 'xxxa3');
+ $sheet->setCellValue('B1', 'xxxa1');
+ $sheet->setCellValue('B2', 'xxxa2');
+ $sheet->setCellValue('B3', 'xxxa3');
+ $sheet->setCellValue('C1', 'xxxc1');
+ $sheet->setCellValue('C2', 'xxxc2');
+ $sheet->setCellValue('C3', 'xxxc3');
+ $styleArray = [
+ 'font' => [
+ 'italic' => true,
+ ],
+ ];
+ $sheet->getStyle($cellCoordinates)->applyFromArray($styleArray);
+ self::assertTrue($sheet->getStyle('A1')->getFont()->getBold());
+ self::assertTrue($sheet->getStyle('B2')->getFont()->getBold());
+ self::assertFalse($sheet->getStyle('C3')->getFont()->getBold());
+ self::assertTrue($sheet->getStyle('A1')->getFont()->getItalic());
+ self::assertTrue($sheet->getStyle('B2')->getFont()->getItalic());
+ self::assertFalse($sheet->getStyle('C3')->getFont()->getItalic());
+ }
+
+ public function testStyleRow(): void
+ {
+ $spreadsheet = new Spreadsheet();
+ $sheet = $spreadsheet->getActiveSheet();
+ $cellCoordinates = '2:3';
+ $styleArray = [
+ 'font' => [
+ 'bold' => true,
+ ],
+ ];
+ $sheet->getStyle($cellCoordinates)->applyFromArray($styleArray);
+ $sheet->setCellValue('A1', 'xxxa1');
+ $sheet->setCellValue('A2', 'xxxa2');
+ $sheet->setCellValue('A3', 'xxxa3');
+ $sheet->setCellValue('B1', 'xxxa1');
+ $sheet->setCellValue('B2', 'xxxa2');
+ $sheet->setCellValue('B3', 'xxxa3');
+ $sheet->setCellValue('C1', 'xxxc1');
+ $sheet->setCellValue('C2', 'xxxc2');
+ $sheet->setCellValue('C3', 'xxxc3');
+ $styleArray = [
+ 'font' => [
+ 'italic' => true,
+ ],
+ ];
+ $sheet->getStyle($cellCoordinates)->applyFromArray($styleArray);
+ self::assertFalse($sheet->getStyle('A1')->getFont()->getBold());
+ self::assertTrue($sheet->getStyle('B2')->getFont()->getBold());
+ self::assertTrue($sheet->getStyle('C3')->getFont()->getBold());
+ self::assertFalse($sheet->getStyle('A1')->getFont()->getItalic());
+ self::assertTrue($sheet->getStyle('B2')->getFont()->getItalic());
+ self::assertTrue($sheet->getStyle('C3')->getFont()->getItalic());
+ }
+
+ public function testIssue1712A(): void
+ {
+ $spreadsheet = new Spreadsheet();
+ $sheet = $spreadsheet->getActiveSheet();
+ $rgb = '4467b8';
+ $sheet->fromArray(['OK', 'KO']);
+ $spreadsheet->getActiveSheet()
+ ->getStyle('A1')
+ ->getFill()
+ ->setFillType(Fill::FILL_SOLID)
+ ->getStartColor()
+ ->setRGB($rgb);
+ $spreadsheet->getActiveSheet()
+ ->getStyle('B')
+ ->getFill()
+ ->setFillType(Fill::FILL_SOLID)
+ ->getStartColor()
+ ->setRGB($rgb);
+ self::assertEquals($rgb, $sheet->getCell('A1')->getStyle()->getFill()->getStartColor()->getRGB());
+ self::assertEquals($rgb, $sheet->getCell('B1')->getStyle()->getFill()->getStartColor()->getRGB());
+ }
+
+ public function testIssue1712B(): void
+ {
+ $spreadsheet = new Spreadsheet();
+ $sheet = $spreadsheet->getActiveSheet();
+ $rgb = '4467b8';
+ $spreadsheet->getActiveSheet()
+ ->getStyle('A1')
+ ->getFill()
+ ->setFillType(Fill::FILL_SOLID)
+ ->getStartColor()
+ ->setRGB($rgb);
+ $spreadsheet->getActiveSheet()
+ ->getStyle('B')
+ ->getFill()
+ ->setFillType(Fill::FILL_SOLID)
+ ->getStartColor()
+ ->setRGB($rgb);
+ $sheet->fromArray(['OK', 'KO']);
+ self::assertEquals($rgb, $sheet->getCell('A1')->getStyle()->getFill()->getStartColor()->getRGB());
+ self::assertEquals($rgb, $sheet->getCell('B1')->getStyle()->getFill()->getStartColor()->getRGB());
+ }
+
+ public function testStyleLoopUpwards(): void
+ {
+ $spreadsheet = new Spreadsheet();
+ $sheet = $spreadsheet->getActiveSheet();
+ $cellCoordinates = 'C5:A3';
+ $styleArray = [
+ 'font' => [
+ 'bold' => true,
+ ],
+ ];
+ $sheet->getStyle($cellCoordinates)->applyFromArray($styleArray);
+ $sheet->setCellValue('A1', 'xxxa1');
+ $sheet->setCellValue('A2', 'xxxa2');
+ $sheet->setCellValue('A3', 'xxxa3');
+ $sheet->setCellValue('B1', 'xxxa1');
+ $sheet->setCellValue('B2', 'xxxa2');
+ $sheet->setCellValue('B3', 'xxxa3');
+ $sheet->setCellValue('C1', 'xxxc1');
+ $sheet->setCellValue('C2', 'xxxc2');
+ $sheet->setCellValue('C3', 'xxxc3');
+ self::assertFalse($sheet->getStyle('A1')->getFont()->getBold());
+ self::assertFalse($sheet->getStyle('B2')->getFont()->getBold());
+ self::assertTrue($sheet->getStyle('C3')->getFont()->getBold());
+ }
}
diff --git a/tests/PhpSpreadsheetTests/Worksheet/ColumnCellIterator2Test.php b/tests/PhpSpreadsheetTests/Worksheet/ColumnCellIterator2Test.php
new file mode 100644
index 00000000..c542d89e
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Worksheet/ColumnCellIterator2Test.php
@@ -0,0 +1,75 @@
+getActiveSheet();
+ $sheet->getCell('B2')->setValue('cellb2');
+ $sheet->getCell('B6')->setValue('cellb6');
+
+ $iterator = new ColumnCellIterator($sheet, 'B', 1, 8);
+ if (isset($existing)) {
+ $iterator->setIterateOnlyExistingCells($existing);
+ }
+ $lastCoordinate = '';
+ $firstCoordinate = '';
+ foreach ($iterator as $cell) {
+ $lastCoordinate = $cell->getCoordinate();
+ if (!$firstCoordinate) {
+ $firstCoordinate = $lastCoordinate;
+ }
+ }
+ self::assertEquals($expectedResultFirst, $firstCoordinate);
+ self::assertEquals($expectedResultLast, $lastCoordinate);
+ }
+
+ public function providerExistingCell(): array
+ {
+ return [
+ [null, 'B1', 'B8'],
+ [false, 'B1', 'B8'],
+ [true, 'B2', 'B6'],
+ ];
+ }
+
+ /**
+ * @dataProvider providerEmptyColumn
+ */
+ public function testEmptyColumn(?bool $existing, int $expectedResult): void
+ {
+ $spreadsheet = new Spreadsheet();
+ $sheet = $spreadsheet->getActiveSheet();
+ $sheet->getCell('B2')->setValue('cellb2');
+ $sheet->getCell('B6')->setValue('cellb6');
+
+ $iterator = new ColumnCellIterator($sheet, 'C');
+ if (isset($existing)) {
+ $iterator->setIterateOnlyExistingCells($existing);
+ }
+ $numCells = 0;
+ foreach ($iterator as $cell) {
+ ++$numCells;
+ }
+ self::assertEquals($expectedResult, $numCells);
+ }
+
+ public function providerEmptyColumn(): array
+ {
+ return [
+ [null, 6],
+ [false, 6],
+ [true, 0],
+ ];
+ }
+}
diff --git a/tests/PhpSpreadsheetTests/Worksheet/ColumnCellIteratorTest.php b/tests/PhpSpreadsheetTests/Worksheet/ColumnCellIteratorTest.php
index 2083f347..1fa25330 100644
--- a/tests/PhpSpreadsheetTests/Worksheet/ColumnCellIteratorTest.php
+++ b/tests/PhpSpreadsheetTests/Worksheet/ColumnCellIteratorTest.php
@@ -71,11 +71,21 @@ class ColumnCellIteratorTest extends TestCase
public function testSeekOutOfRange(): void
{
$this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class);
-
+ $this->expectExceptionMessage('Row 1 is out of range');
$iterator = new ColumnCellIterator($this->mockWorksheet, 'A', 2, 4);
$iterator->seek(1);
}
+ public function testSeekNotExisting(): void
+ {
+ $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class);
+ $this->expectExceptionMessage('Cell does not exist');
+
+ $iterator = new ColumnCellIterator($this->mockWorksheet, 'A', 2, 4);
+ $iterator->setIterateOnlyExistingCells(true);
+ $iterator->seek(2);
+ }
+
public function testPrevOutOfRange(): void
{
$iterator = new ColumnCellIterator($this->mockWorksheet, 'A', 2, 4);
diff --git a/tests/PhpSpreadsheetTests/Worksheet/RowCellIterator2Test.php b/tests/PhpSpreadsheetTests/Worksheet/RowCellIterator2Test.php
new file mode 100644
index 00000000..20d10da9
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Worksheet/RowCellIterator2Test.php
@@ -0,0 +1,75 @@
+getActiveSheet();
+ $sheet->getCell('C2')->setValue('cellb2');
+ $sheet->getCell('F2')->setValue('cellf2');
+
+ $iterator = new RowCellIterator($sheet, 2, 'B', 'H');
+ if (isset($existing)) {
+ $iterator->setIterateOnlyExistingCells($existing);
+ }
+ $lastCoordinate = '';
+ $firstCoordinate = '';
+ foreach ($iterator as $cell) {
+ $lastCoordinate = $cell->getCoordinate();
+ if (!$firstCoordinate) {
+ $firstCoordinate = $lastCoordinate;
+ }
+ }
+ self::assertEquals($expectedResultFirst, $firstCoordinate);
+ self::assertEquals($expectedResultLast, $lastCoordinate);
+ }
+
+ public function providerExistingCell(): array
+ {
+ return [
+ [null, 'B2', 'H2'],
+ [false, 'B2', 'H2'],
+ [true, 'C2', 'F2'],
+ ];
+ }
+
+ /**
+ * @dataProvider providerEmptyRow
+ */
+ public function testEmptyRow(?bool $existing, int $expectedResult): void
+ {
+ $spreadsheet = new Spreadsheet();
+ $sheet = $spreadsheet->getActiveSheet();
+ $sheet->getCell('B2')->setValue('cellb2');
+ $sheet->getCell('F2')->setValue('cellf2');
+
+ $iterator = new RowCellIterator($sheet, '3');
+ if (isset($existing)) {
+ $iterator->setIterateOnlyExistingCells($existing);
+ }
+ $numCells = 0;
+ foreach ($iterator as $cell) {
+ ++$numCells;
+ }
+ self::assertEquals($expectedResult, $numCells);
+ }
+
+ public function providerEmptyRow(): array
+ {
+ return [
+ [null, 6],
+ [false, 6],
+ [true, 0],
+ ];
+ }
+}
diff --git a/tests/PhpSpreadsheetTests/Worksheet/RowCellIteratorTest.php b/tests/PhpSpreadsheetTests/Worksheet/RowCellIteratorTest.php
index bc2c16dc..4105c91c 100644
--- a/tests/PhpSpreadsheetTests/Worksheet/RowCellIteratorTest.php
+++ b/tests/PhpSpreadsheetTests/Worksheet/RowCellIteratorTest.php
@@ -73,9 +73,22 @@ class RowCellIteratorTest extends TestCase
public function testSeekOutOfRange(): void
{
$this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class);
+ $this->expectExceptionMessage('Column A is out of range');
$iterator = new RowCellIterator($this->mockWorksheet, 2, 'B', 'D');
- $iterator->seek(1);
+ self::assertFalse($iterator->getIterateOnlyExistingCells());
+ self::assertEquals(2, $iterator->getCurrentColumnIndex());
+ $iterator->seek('A');
+ }
+
+ public function testSeekNotExisting(): void
+ {
+ $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class);
+ $this->expectExceptionMessage('Cell does not exist');
+
+ $iterator = new RowCellIterator($this->mockWorksheet, 2, 'B', 'D');
+ $iterator->setIterateOnlyExistingCells(true);
+ $iterator->seek('B');
}
public function testPrevOutOfRange(): void
|