Skip to content

Commit 2cbf08c

Browse files
authored
Merge pull request #4207 from oleibman/sheetindex
Change Hash Code for Worksheet
2 parents e92a4ff + 889bdeb commit 2cbf08c

File tree

15 files changed

+131
-34
lines changed

15 files changed

+131
-34
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@ and this project adheres to [Semantic Versioning](https://semver.org).
2121

2222
### Deprecated
2323

24-
- Nothing yet.
24+
- Worksheet::getHashCode is no longer needed.
2525

2626
### Fixed
2727

2828
- Add support for `<s>` tag when converting HTML to RichText. [Issue #4223](https://github.com/PHPOffice/PhpSpreadsheet/issues/4223) [PR #4224](https://github.com/PHPOffice/PhpSpreadsheet/pull/4224)
29+
- Change hash code for worksheet. [Issue #4192](https://github.com/PHPOffice/PhpSpreadsheet/issues/4192) [PR #4207](https://github.com/PHPOffice/PhpSpreadsheet/pull/4207)
2930

3031
## 2024-11-10 - 3.4.0
3132

src/PhpSpreadsheet/Cell/Cell.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ public function setValueExplicit(mixed $value, string $dataType = DataType::TYPE
324324
self::updateIfCellIsTableHeader($this->getParent()?->getParent(), $this, $oldValue, $value);
325325
$worksheet = $this->getWorksheet();
326326
$spreadsheet = $worksheet->getParent();
327-
if (isset($spreadsheet)) {
327+
if (isset($spreadsheet) && $spreadsheet->getIndex($worksheet, true) >= 0) {
328328
$originalSelected = $worksheet->getSelectedCells();
329329
$activeSheetIndex = $spreadsheet->getActiveSheetIndex();
330330
$style = $this->getStyle();

src/PhpSpreadsheet/ReferenceHelper.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -921,7 +921,7 @@ private function updateNamedRange(DefinedName $definedName, Worksheet $worksheet
921921
{
922922
$cellAddress = $definedName->getValue();
923923
$asFormula = ($cellAddress[0] === '=');
924-
if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) {
924+
if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashInt() === $worksheet->getHashInt()) {
925925
/**
926926
* If we delete the entire range that is referenced by a Named Range, MS Excel sets the value to #REF!
927927
* PhpSpreadsheet still only does a basic adjustment, so the Named Range will still reference Cells.
@@ -940,7 +940,7 @@ private function updateNamedRange(DefinedName $definedName, Worksheet $worksheet
940940

941941
private function updateNamedFormula(DefinedName $definedName, Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): void
942942
{
943-
if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) {
943+
if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashInt() === $worksheet->getHashInt()) {
944944
/**
945945
* If we delete the entire range that is referenced by a Named Formula, MS Excel sets the value to #REF!
946946
* PhpSpreadsheet still only does a basic adjustment, so the Named Formula will still reference Cells.

src/PhpSpreadsheet/Spreadsheet.php

+6-2
Original file line numberDiff line numberDiff line change
@@ -660,13 +660,17 @@ public function getSheetByNameOrThrow(string $worksheetName): Worksheet
660660
*
661661
* @return int index
662662
*/
663-
public function getIndex(Worksheet $worksheet): int
663+
public function getIndex(Worksheet $worksheet, bool $noThrow = false): int
664664
{
665+
$wsHash = $worksheet->getHashInt();
665666
foreach ($this->workSheetCollection as $key => $value) {
666-
if ($value->getHashCode() === $worksheet->getHashCode()) {
667+
if ($value->getHashInt() === $wsHash) {
667668
return $key;
668669
}
669670
}
671+
if ($noThrow) {
672+
return -1;
673+
}
670674

671675
throw new Exception('Sheet does not exist.');
672676
}

src/PhpSpreadsheet/Worksheet/BaseDrawing.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ public function getHashCode(): string
414414
return md5(
415415
$this->name
416416
. $this->description
417-
. (($this->worksheet === null) ? '' : $this->worksheet->getHashCode())
417+
. (($this->worksheet === null) ? '' : (string) $this->worksheet->getHashInt())
418418
. $this->coordinates
419419
. $this->offsetX
420420
. $this->offsetY

src/PhpSpreadsheet/Worksheet/Worksheet.php

+16-18
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
use PhpOffice\PhpSpreadsheet\Comment;
2121
use PhpOffice\PhpSpreadsheet\DefinedName;
2222
use PhpOffice\PhpSpreadsheet\Exception;
23-
use PhpOffice\PhpSpreadsheet\IComparable;
2423
use PhpOffice\PhpSpreadsheet\ReferenceHelper;
2524
use PhpOffice\PhpSpreadsheet\RichText\RichText;
2625
use PhpOffice\PhpSpreadsheet\Shared;
@@ -32,7 +31,7 @@
3231
use PhpOffice\PhpSpreadsheet\Style\Protection as StyleProtection;
3332
use PhpOffice\PhpSpreadsheet\Style\Style;
3433

35-
class Worksheet implements IComparable
34+
class Worksheet
3635
{
3736
// Break types
3837
public const BREAK_NONE = 0;
@@ -305,15 +304,10 @@ class Worksheet implements IComparable
305304
*/
306305
private ?Color $tabColor = null;
307306

308-
/**
309-
* Dirty flag.
310-
*/
311-
private bool $dirty = true;
312-
313307
/**
314308
* Hash.
315309
*/
316-
private string $hash;
310+
private int $hash;
317311

318312
/**
319313
* CodeName.
@@ -355,6 +349,7 @@ public function __construct(?Spreadsheet $parent = null, string $title = 'Worksh
355349
$this->autoFilter = new AutoFilter('', $this);
356350
// Table collection
357351
$this->tableCollection = new ArrayObject();
352+
$this->hash = spl_object_id($this);
358353
}
359354

360355
/**
@@ -383,6 +378,12 @@ public function __destruct()
383378
unset($this->rowDimensions, $this->columnDimensions, $this->tableCollection, $this->drawingCollection, $this->chartCollection, $this->autoFilter);
384379
}
385380

381+
public function __wakeup(): void
382+
{
383+
$this->hash = spl_object_id($this);
384+
$this->parent = null;
385+
}
386+
386387
/**
387388
* Return the cell collection.
388389
*/
@@ -897,7 +898,6 @@ public function setTitle(string $title, bool $updateFormulaCellReferences = true
897898

898899
// Set title
899900
$this->title = $title;
900-
$this->dirty = true;
901901

902902
if ($this->parent && $this->parent->getCalculationEngine()) {
903903
// New title
@@ -1032,7 +1032,6 @@ public function getProtection(): Protection
10321032
public function setProtection(Protection $protection): static
10331033
{
10341034
$this->protection = $protection;
1035-
$this->dirty = true;
10361035

10371036
return $this;
10381037
}
@@ -3014,7 +3013,7 @@ private function validateNamedRange(string $definedName, bool $returnNullIfInval
30143013

30153014
if ($namedRange->getLocalOnly()) {
30163015
$worksheet = $namedRange->getWorksheet();
3017-
if ($worksheet === null || $this->getHashCode() !== $worksheet->getHashCode()) {
3016+
if ($worksheet === null || $this->hash !== $worksheet->getHashInt()) {
30183017
if ($returnNullIfInvalid) {
30193018
return null;
30203019
}
@@ -3154,17 +3153,15 @@ public function garbageCollect(): static
31543153
}
31553154

31563155
/**
3157-
* Get hash code.
3158-
*
3159-
* @return string Hash code
3156+
* @deprecated 3.5.0 use getHashInt instead.
31603157
*/
31613158
public function getHashCode(): string
31623159
{
3163-
if ($this->dirty) {
3164-
$this->hash = md5($this->title . $this->autoFilter . ($this->protection->isProtectionEnabled() ? 't' : 'f') . __CLASS__);
3165-
$this->dirty = false;
3166-
}
3160+
return (string) $this->hash;
3161+
}
31673162

3163+
public function getHashInt(): int
3164+
{
31683165
return $this->hash;
31693166
}
31703167

@@ -3493,6 +3490,7 @@ public function __clone()
34933490
}
34943491
}
34953492
}
3493+
$this->hash = spl_object_id($this);
34963494
}
34973495

34983496
/**

src/PhpSpreadsheet/Writer/Xlsx/Style.php

+1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ public function writeStyles(Spreadsheet $spreadsheet): string
142142

143143
// dxf
144144
for ($i = 0; $i < $this->getParentWriter()->getStylesConditionalHashTable()->count(); ++$i) {
145+
/** @var ?Conditional */
145146
$thisstyle = $this->getParentWriter()->getStylesConditionalHashTable()->getByIndex($i);
146147
if ($thisstyle !== null) {
147148
$this->writeCellStyleDxf($objWriter, $thisstyle->getStyle());

tests/PhpSpreadsheetTests/Shared/DateTest.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use DateTimeZone;
1010
use PhpOffice\PhpSpreadsheet\Exception;
1111
use PhpOffice\PhpSpreadsheet\Shared\Date;
12+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
1213
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
1314
use PHPUnit\Framework\TestCase;
1415

@@ -207,7 +208,7 @@ public function testVarious(): void
207208
$date = Date::PHPToExcel('2020-01-01');
208209
self::assertEquals(43831.0, $date);
209210

210-
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
211+
$spreadsheet = new Spreadsheet();
211212
$sheet = $spreadsheet->getActiveSheet();
212213
$sheet->setCellValue('B1', 'x');
213214
/** @var float|int|string */
@@ -249,6 +250,7 @@ public function testVarious(): void
249250
->getNumberFormat()
250251
->setFormatCode('yyyy-mm-dd');
251252
self::assertFalse(Date::isDateTime($cella4));
253+
$spreadsheet->disconnectWorksheets();
252254
}
253255

254256
public function testRoundMicroseconds(): void

tests/PhpSpreadsheetTests/Shared/StringHelperInvalidCharTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@ public function testInvalidChar(): void
4343
$sheet->getCell("A$row")->getValue()
4444
);
4545
}
46+
$spreadsheet->disconnectWorksheets();
4647
}
4748
}

tests/PhpSpreadsheetTests/Style/BorderRangeTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public function testBorderRangeInAction(): void
6262
}
6363
}
6464
}
65+
$spreadsheet->disconnectWorksheets();
6566
}
6667

6768
public function testBorderRangeDirectly(): void
@@ -71,5 +72,6 @@ public function testBorderRangeDirectly(): void
7172
$sheet = $spreadsheet->getActiveSheet();
7273
$style = $sheet->getStyle('A1:C1')->getBorders()->getTop()->setBorderStyle(Border::BORDER_THIN);
7374
self::assertSame('A1:C1', $style->getSelectedCells(), 'getSelectedCells should not change after a style operation on a border range');
75+
$spreadsheet->disconnectWorksheets();
7476
}
7577
}

tests/PhpSpreadsheetTests/Style/BorderTest.php

+9
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public function testAllBorders(): void
3131
self::assertSame(Border::BORDER_THIN, $borders->getRight()->getBorderStyle());
3232
self::assertSame(Border::BORDER_THIN, $borders->getLeft()->getBorderStyle());
3333
self::assertSame(Border::BORDER_NONE, $borders->getDiagonal()->getBorderStyle());
34+
$spreadsheet->disconnectWorksheets();
3435
}
3536

3637
public function testAllBordersArray(): void
@@ -45,6 +46,7 @@ public function testAllBordersArray(): void
4546
self::assertSame(Border::BORDER_THIN, $borders->getRight()->getBorderStyle());
4647
self::assertSame(Border::BORDER_THIN, $borders->getLeft()->getBorderStyle());
4748
self::assertSame(Border::BORDER_NONE, $borders->getDiagonal()->getBorderStyle());
49+
$spreadsheet->disconnectWorksheets();
4850
}
4951

5052
public function testAllBordersArrayNotSupervisor(): void
@@ -86,6 +88,7 @@ public function testOutline(): void
8688
self::assertSame(Border::BORDER_THIN, $sheet->getCell('B2')->getStyle()->getBorders()->getBottom()->getBorderStyle());
8789
self::assertSame(Border::BORDER_NONE, $sheet->getCell('B2')->getStyle()->getBorders()->getLeft()->getBorderStyle());
8890
self::assertSame(Border::BORDER_NONE, $sheet->getCell('B2')->getStyle()->getBorders()->getTop()->getBorderStyle());
91+
$spreadsheet->disconnectWorksheets();
8992
}
9093

9194
public function testInside(): void
@@ -115,6 +118,7 @@ public function testInside(): void
115118
self::assertSame(Border::BORDER_NONE, $sheet->getCell('B2')->getStyle()->getBorders()->getBottom()->getBorderStyle());
116119
self::assertSame(Border::BORDER_THIN, $sheet->getCell('B2')->getStyle()->getBorders()->getLeft()->getBorderStyle());
117120
self::assertSame(Border::BORDER_THIN, $sheet->getCell('B2')->getStyle()->getBorders()->getTop()->getBorderStyle());
121+
$spreadsheet->disconnectWorksheets();
118122
}
119123

120124
public function testHorizontal(): void
@@ -144,6 +148,7 @@ public function testHorizontal(): void
144148
self::assertSame(Border::BORDER_NONE, $sheet->getCell('B2')->getStyle()->getBorders()->getBottom()->getBorderStyle());
145149
self::assertSame(Border::BORDER_NONE, $sheet->getCell('B2')->getStyle()->getBorders()->getLeft()->getBorderStyle());
146150
self::assertSame(Border::BORDER_THIN, $sheet->getCell('B2')->getStyle()->getBorders()->getTop()->getBorderStyle());
151+
$spreadsheet->disconnectWorksheets();
147152
}
148153

149154
public function testVertical(): void
@@ -173,6 +178,7 @@ public function testVertical(): void
173178
self::assertSame(Border::BORDER_NONE, $sheet->getCell('B2')->getStyle()->getBorders()->getBottom()->getBorderStyle());
174179
self::assertSame(Border::BORDER_THIN, $sheet->getCell('B2')->getStyle()->getBorders()->getLeft()->getBorderStyle());
175180
self::assertSame(Border::BORDER_NONE, $sheet->getCell('B2')->getStyle()->getBorders()->getTop()->getBorderStyle());
181+
$spreadsheet->disconnectWorksheets();
176182
}
177183

178184
public function testNoSupervisorAllBorders(): void
@@ -213,6 +219,7 @@ public function testNoSupervisorHorizontal(): void
213219
public function testGetSharedComponentPseudo(): void
214220
{
215221
$this->expectException(PhpSpreadsheetException::class);
222+
$this->expectExceptionMessage('pseudo-border');
216223
$spreadsheet = new Spreadsheet();
217224
$sheet = $spreadsheet->getActiveSheet();
218225
$sheet->getStyle('A1')->getBorders()->getHorizontal()->setBorderStyle(Border::BORDER_MEDIUM);
@@ -233,6 +240,7 @@ public function testBorderStyle(): void
233240
$border->setBorderStyle(Border::BORDER_THIN)->setColor(new Color('FFFF0000'));
234241
self::assertEquals('FFFF0000', $border->getColor()->getARGB());
235242
self::assertEquals(Border::BORDER_THIN, $border->getBorderStyle());
243+
$spreadsheet->disconnectWorksheets();
236244
}
237245

238246
public function testDiagonalDirection(): void
@@ -245,5 +253,6 @@ public function testDiagonalDirection(): void
245253

246254
self::assertSame(Border::BORDER_MEDIUM, $borders->getDiagonal()->getBorderStyle());
247255
self::assertSame(Borders::DIAGONAL_BOTH, $borders->getDiagonalDirection());
256+
$spreadsheet->disconnectWorksheets();
248257
}
249258
}

tests/PhpSpreadsheetTests/Style/ConditionalFormatting/Wizard/WizardFactoryTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public function testWizardFromConditional(string $sheetName, string $cellAddress
6666
$wizard = Wizard::fromConditional($conditional);
6767
self::assertEquals($expectedWizads[$index], $wizard::class);
6868
}
69+
$spreadsheet->disconnectWorksheets();
6970
}
7071

7172
public static function conditionalProvider(): array

tests/PhpSpreadsheetTests/Style/StyleTest.php

+9
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public function testStyleOddMethods(): void
2424
$styleArray = ['alignment' => ['textRotation' => 45]];
2525
$outArray = $cell1style->getStyleArray($styleArray);
2626
self::assertEquals($styleArray, $outArray['quotePrefix']);
27+
$spreadsheet->disconnectWorksheets();
2728
}
2829

2930
public function testStyleColumn(): void
@@ -58,6 +59,7 @@ public function testStyleColumn(): void
5859
self::assertTrue($sheet->getStyle('A1')->getFont()->getItalic());
5960
self::assertTrue($sheet->getStyle('B2')->getFont()->getItalic());
6061
self::assertFalse($sheet->getStyle('C3')->getFont()->getItalic());
62+
$spreadsheet->disconnectWorksheets();
6163
}
6264

6365
public function testStyleIsReused(): void
@@ -81,6 +83,7 @@ public function testStyleIsReused(): void
8183
$spreadsheet->garbageCollect();
8284

8385
self::assertCount(3, $spreadsheet->getCellXfCollection());
86+
$spreadsheet->disconnectWorksheets();
8487
}
8588

8689
public function testStyleRow(): void
@@ -115,6 +118,7 @@ public function testStyleRow(): void
115118
self::assertFalse($sheet->getStyle('A1')->getFont()->getItalic());
116119
self::assertTrue($sheet->getStyle('B2')->getFont()->getItalic());
117120
self::assertTrue($sheet->getStyle('C3')->getFont()->getItalic());
121+
$spreadsheet->disconnectWorksheets();
118122
}
119123

120124
public function testIssue1712A(): void
@@ -137,6 +141,7 @@ public function testIssue1712A(): void
137141
->setRGB($rgb);
138142
self::assertEquals($rgb, $sheet->getCell('A1')->getStyle()->getFill()->getStartColor()->getRGB());
139143
self::assertEquals($rgb, $sheet->getCell('B1')->getStyle()->getFill()->getStartColor()->getRGB());
144+
$spreadsheet->disconnectWorksheets();
140145
}
141146

142147
public function testIssue1712B(): void
@@ -159,6 +164,7 @@ public function testIssue1712B(): void
159164
$sheet->fromArray(['OK', 'KO']);
160165
self::assertEquals($rgb, $sheet->getCell('A1')->getStyle()->getFill()->getStartColor()->getRGB());
161166
self::assertEquals($rgb, $sheet->getCell('B1')->getStyle()->getFill()->getStartColor()->getRGB());
167+
$spreadsheet->disconnectWorksheets();
162168
}
163169

164170
public function testStyleLoopUpwards(): void
@@ -184,6 +190,7 @@ public function testStyleLoopUpwards(): void
184190
self::assertFalse($sheet->getStyle('A1')->getFont()->getBold());
185191
self::assertFalse($sheet->getStyle('B2')->getFont()->getBold());
186192
self::assertTrue($sheet->getStyle('C3')->getFont()->getBold());
193+
$spreadsheet->disconnectWorksheets();
187194
}
188195

189196
public function testStyleCellAddressObject(): void
@@ -195,6 +202,7 @@ public function testStyleCellAddressObject(): void
195202
$style->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
196203

197204
self::assertSame(NumberFormat::FORMAT_DATE_YYYYMMDDSLASH, $style->getNumberFormat()->getFormatCode());
205+
$spreadsheet->disconnectWorksheets();
198206
}
199207

200208
public function testStyleCellRangeObject(): void
@@ -208,5 +216,6 @@ public function testStyleCellRangeObject(): void
208216
$style->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
209217

210218
self::assertSame(NumberFormat::FORMAT_DATE_YYYYMMDDSLASH, $style->getNumberFormat()->getFormatCode());
219+
$spreadsheet->disconnectWorksheets();
211220
}
212221
}

0 commit comments

Comments
 (0)