Skip to content

Commit 7ce0184

Browse files
committed
Don't Interfere with SelectedCells And Other Changes
Xls Reader processing Conditionals interferes with the previously established SelectedCells. Make sure that value is restored. StopIfTrue should always be set for Xls spreadsheet. Set NoFormatSet to true unless any of Font, Fill, or Borders is specified in Conditional Style. In my notes for PR PHPOffice#3372, I mentioned that I could not include some Xls tests because of errors in the software at that time. This PR fixes those errors, so I am adding the missing test, and making the equivalent Xlsx test more comprehensive.
1 parent 313dcc5 commit 7ce0184

File tree

4 files changed

+88
-4
lines changed

4 files changed

+88
-4
lines changed

src/PhpSpreadsheet/Reader/Xls.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
703703
// Parse the individual sheets
704704
$this->activeSheetSet = false;
705705
foreach ($this->sheets as $sheet) {
706+
$selectedCells = '';
706707
if ($sheet['sheetType'] != 0x00) {
707708
// 0x00: Worksheet, 0x02: Chart, 0x06: Visual Basic module
708709
continue;
@@ -910,7 +911,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
910911

911912
break;
912913
case self::XLS_TYPE_SELECTION:
913-
$this->readSelection();
914+
$selectedCells = $this->readSelection();
914915

915916
break;
916917
case self::XLS_TYPE_MERGEDCELLS:
@@ -1112,6 +1113,9 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
11121113
$this->phpSheet->getComment($cellAddress)->setAuthor($noteDetails['author'])->setText($this->parseRichText($noteDetails['objTextData']['text']));
11131114
}
11141115
}
1116+
if ($selectedCells !== '') {
1117+
$this->phpSheet->setSelectedCells($selectedCells);
1118+
}
11151119
}
11161120
if ($this->activeSheetSet === false) {
11171121
$this->spreadsheet->setActiveSheetIndex(0);
@@ -4376,10 +4380,11 @@ private function readPane(): void
43764380
/**
43774381
* Read SELECTION record. There is one such record for each pane in the sheet.
43784382
*/
4379-
private function readSelection(): void
4383+
private function readSelection(): string
43804384
{
43814385
$length = self::getUInt2d($this->data, $this->pos + 2);
43824386
$recordData = $this->readRecordData($this->data, $this->pos + 4, $length);
4387+
$selectedCells = '';
43834388

43844389
// move stream pointer to next record
43854390
$this->pos += 4 + $length;
@@ -4421,6 +4426,8 @@ private function readSelection(): void
44214426

44224427
$this->phpSheet->setSelectedCells($selectedCells);
44234428
}
4429+
4430+
return $selectedCells;
44244431
}
44254432

44264433
private function includeCellRangeFiltered(string $cellRangeAddress): bool
@@ -7410,6 +7417,7 @@ private function readCFRule(array $cellRangeAddresses): void
74107417
$options = self::getInt4d($recordData, 6);
74117418

74127419
$style = new Style(false, true); // non-supervisor, conditional
7420+
$noFormatSet = true;
74137421
//$this->getCFStyleOptions($options, $style);
74147422

74157423
$hasFontRecord = (bool) ((0x04000000 & $options) >> 26);
@@ -7429,6 +7437,7 @@ private function readCFRule(array $cellRangeAddresses): void
74297437
$fontStyle = substr($recordData, $offset, 118);
74307438
$this->getCFFontStyle($fontStyle, $style);
74317439
$offset += 118;
7440+
$noFormatSet = false;
74327441
}
74337442

74347443
if ($hasAlignmentRecord === true) {
@@ -7441,12 +7450,14 @@ private function readCFRule(array $cellRangeAddresses): void
74417450
$borderStyle = substr($recordData, $offset, 8);
74427451
$this->getCFBorderStyle($borderStyle, $style, $hasBorderLeft, $hasBorderRight, $hasBorderTop, $hasBorderBottom);
74437452
$offset += 8;
7453+
$noFormatSet = false;
74447454
}
74457455

74467456
if ($hasFillRecord === true) {
74477457
$fillStyle = substr($recordData, $offset, 4);
74487458
$this->getCFFillStyle($fillStyle, $style);
74497459
$offset += 4;
7460+
$noFormatSet = false;
74507461
}
74517462

74527463
if ($hasProtectionRecord === true) {
@@ -7474,7 +7485,7 @@ private function readCFRule(array $cellRangeAddresses): void
74747485
$offset += $size2;
74757486
}
74767487

7477-
$this->setCFRules($cellRangeAddresses, $type, $operator, $formula1, $formula2, $style);
7488+
$this->setCFRules($cellRangeAddresses, $type, $operator, $formula1, $formula2, $style, $noFormatSet);
74787489
}
74797490

74807491
/*private function getCFStyleOptions(int $options, Style $style): void
@@ -7604,12 +7615,14 @@ private function readCFFormula(string $recordData, int $offset, int $size): floa
76047615
}
76057616
}
76067617

7607-
private function setCFRules(array $cellRanges, string $type, string $operator, null|float|int|string $formula1, null|float|int|string $formula2, Style $style): void
7618+
private function setCFRules(array $cellRanges, string $type, string $operator, null|float|int|string $formula1, null|float|int|string $formula2, Style $style, bool $noFormatSet): void
76087619
{
76097620
foreach ($cellRanges as $cellRange) {
76107621
$conditional = new Conditional();
7622+
$conditional->setNoFormatSet($noFormatSet);
76117623
$conditional->setConditionType($type);
76127624
$conditional->setOperatorType($operator);
7625+
$conditional->setStopIfTrue(true);
76137626
if ($formula1 !== null) {
76147627
$conditional->addCondition($formula1);
76157628
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xls;
6+
7+
use PhpOffice\PhpSpreadsheet\Reader\Xls as XlsReader;
8+
use PHPUnit\Framework\TestCase;
9+
10+
class Issue3202Test extends TestCase
11+
{
12+
public function testSelectedCellWithConditionals(): void
13+
{
14+
// Unknown index notice when loading
15+
$filename = 'tests/data/Reader/XLS/issue.3202.xls';
16+
$reader = new XlsReader();
17+
$spreadsheet = $reader->load($filename);
18+
$sheet = $spreadsheet->getActiveSheet();
19+
self::assertSame('A2', $sheet->getSelectedCells());
20+
21+
$collection = $sheet->getConditionalStylesCollection();
22+
self::assertCount(1, $collection);
23+
$conditionalArray = $collection['A1:A5'];
24+
self::assertCount(3, $conditionalArray);
25+
26+
$conditions = $conditionalArray[0]->getConditions();
27+
self::assertCount(1, $conditions);
28+
self::assertSame('$A1=3', $conditions[0]);
29+
self::assertTrue($conditionalArray[0]->getNoFormatSet());
30+
self::assertTrue($conditionalArray[0]->getStopIfTrue());
31+
32+
$conditions = $conditionalArray[1]->getConditions();
33+
self::assertCount(1, $conditions);
34+
self::assertSame('$A1>5', $conditions[0]);
35+
self::assertFalse($conditionalArray[1]->getNoFormatSet());
36+
self::assertTrue($conditionalArray[1]->getStopIfTrue());
37+
38+
$conditions = $conditionalArray[2]->getConditions();
39+
self::assertCount(1, $conditions);
40+
self::assertSame('$A1>1', $conditions[0]);
41+
self::assertFalse($conditionalArray[2]->getNoFormatSet());
42+
self::assertTrue($conditionalArray[2]->getStopIfTrue());
43+
44+
$spreadsheet->disconnectWorksheets();
45+
}
46+
}

tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalNoFormatSetTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,31 @@ public function testNoFormatTest(): void
3333

3434
$reader = new XlsxReader();
3535
$spreadsheet = $reader->load($testfile);
36+
$sheet = $spreadsheet->getactiveSheet();
37+
38+
$collection = $sheet->getConditionalStylesCollection();
39+
self::assertCount(1, $collection);
40+
$conditionalArray = $collection['A1:A5'];
41+
self::assertCount(3, $conditionalArray);
42+
43+
$conditions = $conditionalArray[0]->getConditions();
44+
self::assertCount(1, $conditions);
45+
self::assertSame('$A1=3', $conditions[0]);
46+
self::assertTrue($conditionalArray[0]->getNoFormatSet());
47+
self::assertTrue($conditionalArray[0]->getStopIfTrue());
48+
49+
$conditions = $conditionalArray[1]->getConditions();
50+
self::assertCount(1, $conditions);
51+
self::assertSame('$A1>5', $conditions[0]);
52+
self::assertFalse($conditionalArray[1]->getNoFormatSet());
53+
self::assertTrue($conditionalArray[1]->getStopIfTrue());
54+
55+
$conditions = $conditionalArray[2]->getConditions();
56+
self::assertCount(1, $conditions);
57+
self::assertSame('$A1>1', $conditions[0]);
58+
self::assertFalse($conditionalArray[2]->getNoFormatSet());
59+
self::assertFalse($conditionalArray[2]->getStopIfTrue());
60+
3661
$outfile = File::temporaryFilename();
3762
$writer = new XlsxWriter($spreadsheet);
3863
$writer->save($outfile);

tests/data/Reader/XLS/issue.3202.xls

31 KB
Binary file not shown.

0 commit comments

Comments
 (0)