Skip to content

Commit 765037e

Browse files
committed
Ensure that correct calendar (read from the spreadsheet when loaded) is used for all date-related calculations and formatting
1 parent 3964087 commit 765037e

File tree

8 files changed

+107
-10
lines changed

8 files changed

+107
-10
lines changed

src/PhpSpreadsheet/Cell/Cell.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use PhpOffice\PhpSpreadsheet\Style\Style;
1616
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
1717
use Throwable;
18-
use function _PHPStan_59fb0a3b2\RingCentral\Psr7\str;
1918

2019
class Cell
2120
{
@@ -192,7 +191,6 @@ public function getFormattedValue(): string
192191
SharedDate::setExcelCalendar($currentCalendar);
193192

194193
return $formattedValue;
195-
196194
}
197195

198196
/**
@@ -407,9 +405,10 @@ private function processArrayResult(
407405
public function getCalculatedValue(bool $asArray = false, bool $resetLog = true)
408406
{
409407
if ($this->dataType === DataType::TYPE_FORMULA) {
408+
$currentCalendar = SharedDate::getExcelCalendar();
409+
SharedDate::setExcelCalendar($this->getWorksheet()->getParent()->getExcelCalendar());
410+
410411
try {
411-
// $currentCalendar = SharedDate::getExcelCalendar();
412-
// SharedDate::setExcelCalendar($this->getWorksheet()->getParent()->getExcelCalendar());
413412
$coordinate = $this->getCoordinate();
414413
$worksheet = $this->getWorksheet();
415414
$value = $this->value;
@@ -437,7 +436,7 @@ public function getCalculatedValue(bool $asArray = false, bool $resetLog = true)
437436
$this->getWorksheet()->setSelectedCells($selected);
438437
$this->getWorksheet()->getParent()->setActiveSheetIndex($index);
439438
} catch (Exception $ex) {
440-
// SharedDate::setExcelCalendar($currentCalendar);
439+
SharedDate::setExcelCalendar($currentCalendar);
441440
if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->calculatedValue !== null)) {
442441
return $this->calculatedValue; // Fallback for calculations referencing external files.
443442
} elseif (preg_match('/[Uu]ndefined (name|offset: 2|array key 2)/', $ex->getMessage()) === 1) {
@@ -449,7 +448,7 @@ public function getCalculatedValue(bool $asArray = false, bool $resetLog = true)
449448
);
450449
}
451450

452-
// SharedDate::setExcelCalendar($currentCalendar);
451+
SharedDate::setExcelCalendar($currentCalendar);
453452
if ($result === '#Not Yet Implemented') {
454453
return $this->calculatedValue; // Fallback if calculation engine does not support the formula.
455454
}

tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/AllSetupTeardown.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,13 @@ protected function tearDown(): void
5555
}
5656
}
5757

58-
protected static function setMac1904(): void
58+
protected static function setMac1904(?Worksheet $worksheet = null): void
5959
{
60-
Date::setExcelCalendar(Date::CALENDAR_MAC_1904);
60+
if ($worksheet === null) {
61+
Date::setExcelCalendar(Date::CALENDAR_MAC_1904);
62+
} else {
63+
$worksheet->getParent()->setExcelCalendar(Date::CALENDAR_MAC_1904);
64+
}
6165
}
6266

6367
protected static function setUnixReturn(): void

tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/IsoWeekNumTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ public function providerISOWEEKNUM(): array
3535
public function testISOWEEKNUM1904($expectedResult, $dateValue): void
3636
{
3737
$this->mightHaveException($expectedResult);
38-
self::setMac1904();
3938
$sheet = $this->getSheet();
39+
self::setMac1904($sheet);
4040
$sheet->getCell('A1')->setValue("=ISOWEEKNUM($dateValue)");
4141
$sheet->getCell('B1')->setValue('1954-11-23');
4242
self::assertSame($expectedResult, $sheet->getCell('A1')->getCalculatedValue());

tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/WeekNumTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ public function providerWEEKNUM(): array
3333
public function testWEEKNUM1904($expectedResult, string $formula): void
3434
{
3535
$this->mightHaveException($expectedResult);
36-
self::setMac1904();
3736
$sheet = $this->getSheet();
37+
self::setMac1904($sheet);
3838
$sheet->getCell('B1')->setValue('1954-11-23');
3939
$sheet->getCell('A1')->setValue("=WEEKNUM($formula)");
4040
self::assertSame($expectedResult, $sheet->getCell('A1')->getCalculatedValue());

tests/PhpSpreadsheetTests/Reader/Xls/DateReaderTest.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,76 @@ public function testReadExcel1904Spreadsheet(): void
4242
self::assertSame(43464, $worksheet->getCell('A2')->getValue());
4343
self::assertSame('2022-12-31', $worksheet->getCell('A2')->getFormattedValue());
4444
}
45+
46+
public function testNewDateInLoadedExcel1900Spreadsheet(): void
47+
{
48+
$filename = 'tests/data/Reader/XLS/1900_Calendar.xls';
49+
$reader = new Xls();
50+
$spreadsheet = $reader->load($filename);
51+
52+
$worksheet = $spreadsheet->getActiveSheet();
53+
$worksheet->getCell('A4')->setValue('=DATE(2023,1,1)');
54+
self::assertEquals(44927, $worksheet->getCell('A4')->getCalculatedValue());
55+
}
56+
57+
public function testNewDateInLoadedExcel1904Spreadsheet(): void
58+
{
59+
$filename = 'tests/data/Reader/XLS/1904_Calendar.xls';
60+
$reader = new Xls();
61+
$spreadsheet = $reader->load($filename);
62+
63+
$worksheet = $spreadsheet->getActiveSheet();
64+
$worksheet->getCell('A4')->setValue('=DATE(2023,1,1)');
65+
self::assertEquals(43465, $worksheet->getCell('A4')->getCalculatedValue());
66+
}
67+
68+
public function testSwitchCalendars(): void
69+
{
70+
$filename1900 = 'tests/data/Reader/XLS/1900_Calendar.xls';
71+
$reader1900 = new Xls();
72+
$spreadsheet1900 = $reader1900->load($filename1900);
73+
$worksheet1900 = $spreadsheet1900->getActiveSheet();
74+
75+
$filename1904 = 'tests/data/Reader/XLS/1904_Calendar.xls';
76+
$reader1904 = new Xls();
77+
$spreadsheet1904 = $reader1904->load($filename1904);
78+
$worksheet1904 = $spreadsheet1904->getActiveSheet();
79+
80+
self::assertSame(44562, $worksheet1900->getCell('A1')->getValue());
81+
self::assertSame('2022-01-01', $worksheet1900->getCell('A1')->getFormattedValue());
82+
self::assertSame(44926, $worksheet1900->getCell('A2')->getValue());
83+
self::assertSame('2022-12-31', $worksheet1900->getCell('A2')->getFormattedValue());
84+
self::assertSame(44561, $worksheet1900->getCell('B1')->getCalculatedValue());
85+
self::assertSame('2021-12-31', $worksheet1900->getCell('B1')->getFormattedValue());
86+
self::assertSame(44927, $worksheet1900->getCell('B2')->getCalculatedValue());
87+
self::assertSame('2023-01-01', $worksheet1900->getCell('B2')->getFormattedValue());
88+
89+
self::assertSame(43100, $worksheet1904->getCell('A1')->getValue());
90+
self::assertSame('2022-01-01', $worksheet1904->getCell('A1')->getFormattedValue());
91+
self::assertSame(43464, $worksheet1904->getCell('A2')->getValue());
92+
self::assertSame('2022-12-31', $worksheet1904->getCell('A2')->getFormattedValue());
93+
self::assertSame(43099, $worksheet1904->getCell('B1')->getCalculatedValue());
94+
self::assertSame('2021-12-31', $worksheet1904->getCell('B1')->getFormattedValue());
95+
self::assertSame(43465, $worksheet1904->getCell('B2')->getCalculatedValue());
96+
self::assertSame('2023-01-01', $worksheet1904->getCell('B2')->getFormattedValue());
97+
98+
// Check that accessing date values from one spreadsheet doesn't break accessing correct values from another
99+
self::assertSame(44561, $worksheet1900->getCell('B1')->getCalculatedValue());
100+
self::assertSame('2021-12-31', $worksheet1900->getCell('B1')->getFormattedValue());
101+
self::assertSame(44927, $worksheet1900->getCell('B2')->getCalculatedValue());
102+
self::assertSame('2023-01-01', $worksheet1900->getCell('B2')->getFormattedValue());
103+
self::assertSame(44562, $worksheet1900->getCell('A1')->getValue());
104+
self::assertSame('2022-01-01', $worksheet1900->getCell('A1')->getFormattedValue());
105+
self::assertSame(44926, $worksheet1900->getCell('A2')->getValue());
106+
self::assertSame('2022-12-31', $worksheet1900->getCell('A2')->getFormattedValue());
107+
108+
self::assertSame(43099, $worksheet1904->getCell('B1')->getCalculatedValue());
109+
self::assertSame('2021-12-31', $worksheet1904->getCell('B1')->getFormattedValue());
110+
self::assertSame(43465, $worksheet1904->getCell('B2')->getCalculatedValue());
111+
self::assertSame('2023-01-01', $worksheet1904->getCell('B2')->getFormattedValue());
112+
self::assertSame(43100, $worksheet1904->getCell('A1')->getValue());
113+
self::assertSame('2022-01-01', $worksheet1904->getCell('A1')->getFormattedValue());
114+
self::assertSame(43464, $worksheet1904->getCell('A2')->getValue());
115+
self::assertSame('2022-12-31', $worksheet1904->getCell('A2')->getFormattedValue());
116+
}
45117
}

tests/PhpSpreadsheetTests/Reader/Xlsx/DateReaderTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,28 @@ public function testReadExcel1904Spreadsheet(): void
5151
self::assertSame('2023-01-01', $worksheet->getCell('B2')->getFormattedValue());
5252
}
5353

54+
public function testNewDateInLoadedExcel1900Spreadsheet(): void
55+
{
56+
$filename = 'tests/data/Reader/XLSX/1900_Calendar.xlsx';
57+
$reader = new Xlsx();
58+
$spreadsheet = $reader->load($filename);
59+
60+
$worksheet = $spreadsheet->getActiveSheet();
61+
$worksheet->getCell('A4')->setValue('=DATE(2023,1,1)');
62+
self::assertEquals(44927, $worksheet->getCell('A4')->getCalculatedValue());
63+
}
64+
65+
public function testNewDateInLoadedExcel1904Spreadsheet(): void
66+
{
67+
$filename = 'tests/data/Reader/XLSX/1904_Calendar.xlsx';
68+
$reader = new Xlsx();
69+
$spreadsheet = $reader->load($filename);
70+
71+
$worksheet = $spreadsheet->getActiveSheet();
72+
$worksheet->getCell('A4')->setValue('=DATE(2023,1,1)');
73+
self::assertEquals(43465, $worksheet->getCell('A4')->getCalculatedValue());
74+
}
75+
5476
public function testSwitchCalendars(): void
5577
{
5678
$filename1900 = 'tests/data/Reader/XLSX/1900_Calendar.xlsx';
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)