Skip to content

Commit a4ee68b

Browse files
authored
Merge branch 'master' into issue484
2 parents 3c67aba + 216db02 commit a4ee68b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+622
-836
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ and this project adheres to [Semantic Versioning](https://semver.org). Thia is a
3636

3737
### Fixed
3838

39-
- Xlsx Writer eliminate xml:space from non-text nodes. [Issue #4542](https://github.com/PHPOffice/PhpSpreadsheet/issues/4542) [PR #4556](https://github.com/PHPOffice/PhpSpreadsheet/pull/4556)
4039
- Header/Footer images expand location. [Issue #484](https://github.com/PHPOffice/PhpSpreadsheet/issues/484) [Issue #1318](https://github.com/PHPOffice/PhpSpreadsheet/issues/1318) [PR #4572](https://github.com/PHPOffice/PhpSpreadsheet/pull/4572)
40+
- Create uninitialized cell if used in calculation. [Issue #4558](https://github.com/PHPOffice/PhpSpreadsheet/issues/4558) [Issue #4530](https://github.com/PHPOffice/PhpSpreadsheet/issues/4530) [PR #4565](https://github.com/PHPOffice/PhpSpreadsheet/pull/4565)
41+
- Shared/Date::isDateTime handle cells which calculate as arrays. [Issue #4557](https://github.com/PHPOffice/PhpSpreadsheet/issues/4557) [PR #4562](https://github.com/PHPOffice/PhpSpreadsheet/pull/4562)
42+
- Xlsx Writer eliminate xml:space from non-text nodes. [Issue #4542](https://github.com/PHPOffice/PhpSpreadsheet/issues/4542) [PR #4556](https://github.com/PHPOffice/PhpSpreadsheet/pull/4556)## 2025-07-23 - 4.5.0
4143

4244
## 2025-07-23 - 4.5.0
4345

composer.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/PhpSpreadsheet/Calculation/Calculation.php

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,7 @@ public function __construct(?Spreadsheet $spreadsheet = null)
207207
public static function getInstance(?Spreadsheet $spreadsheet = null): self
208208
{
209209
if ($spreadsheet !== null) {
210-
$instance = $spreadsheet->getCalculationEngine();
211-
if (isset($instance)) {
212-
return $instance;
213-
}
210+
return $spreadsheet->getCalculationEngine();
214211
}
215212

216213
if (!self::$instance) {
@@ -220,6 +217,20 @@ public static function getInstance(?Spreadsheet $spreadsheet = null): self
220217
return self::$instance;
221218
}
222219

220+
/**
221+
* Intended for use only via a destructor.
222+
*
223+
* @internal
224+
*/
225+
public static function getInstanceOrNull(?Spreadsheet $spreadsheet = null): ?self
226+
{
227+
if ($spreadsheet !== null) {
228+
return $spreadsheet->getCalculationEngineOrNull();
229+
}
230+
231+
return null;
232+
}
233+
223234
/**
224235
* Flush the calculation cache for any existing instance of this class
225236
* but only if a Calculation instance exists.
@@ -1999,6 +2010,9 @@ private function processTokenStack(false|array $tokens, ?string $cellID = null,
19992010
$this->debugLog->writeDebugLog('Evaluating Cell %s in worksheet %s', $cellRef, $matches[2]);
20002011
if ($pCellParent !== null && $this->spreadsheet !== null) {
20012012
$cellSheet = $this->spreadsheet->getSheetByName($matches[2]);
2013+
if ($cellSheet && !$cellSheet->cellExists($cellRef)) {
2014+
$cellSheet->setCellValue($cellRef, null);
2015+
}
20022016
if ($cellSheet && $cellSheet->cellExists($cellRef)) {
20032017
$cellValue = $this->extractCellRange($cellRef, $this->spreadsheet->getSheetByName($matches[2]), false);
20042018
$cell->attach($pCellParent);
@@ -2503,7 +2517,7 @@ protected function raiseFormulaError(string $errorMessage, int $code = 0, ?Throw
25032517
*
25042518
* @return mixed[] Array of values in range if range contains more than one element. Otherwise, a single value is returned.
25052519
*/
2506-
public function extractCellRange(string &$range = 'A1', ?Worksheet $worksheet = null, bool $resetLog = true): array
2520+
public function extractCellRange(string &$range = 'A1', ?Worksheet $worksheet = null, bool $resetLog = true, bool $createCell = false): array
25072521
{
25082522
// Return value
25092523
/** @var mixed[][] */
@@ -2525,6 +2539,9 @@ public function extractCellRange(string &$range = 'A1', ?Worksheet $worksheet =
25252539
if (!isset($aReferences[1])) {
25262540
// Single cell in range
25272541
sscanf($aReferences[0], '%[A-Z]%d', $currentCol, $currentRow);
2542+
if ($createCell && $worksheet !== null && !$worksheet->cellExists($aReferences[0])) {
2543+
$worksheet->setCellValue($aReferences[0], null);
2544+
}
25282545
if ($worksheet !== null && $worksheet->cellExists($aReferences[0])) {
25292546
$temp = $worksheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
25302547
if ($this->getInstanceArrayReturnType() === self::RETURN_ARRAY_AS_ARRAY) {
@@ -2541,6 +2558,9 @@ public function extractCellRange(string &$range = 'A1', ?Worksheet $worksheet =
25412558
foreach ($aReferences as $reference) {
25422559
// Extract range
25432560
sscanf($reference, '%[A-Z]%d', $currentCol, $currentRow);
2561+
if ($createCell && $worksheet !== null && !$worksheet->cellExists($reference)) {
2562+
$worksheet->setCellValue($reference, null);
2563+
}
25442564
if ($worksheet !== null && $worksheet->cellExists($reference)) {
25452565
$temp = $worksheet->getCell($reference)->getCalculatedValue($resetLog);
25462566
if ($this->getInstanceArrayReturnType() === self::RETURN_ARRAY_AS_ARRAY) {

src/PhpSpreadsheet/Calculation/Financial/Amortization.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ public static function AMORDEGRC(
5454
$salvage = Functions::flattenSingleValue($salvage);
5555
$period = Functions::flattenSingleValue($period);
5656
$rate = Functions::flattenSingleValue($rate);
57-
$basis = ($basis === null)
58-
? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
59-
: Functions::flattenSingleValue($basis);
57+
$basis = Functions::flattenSingleValue($basis) ?? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD;
6058

6159
try {
6260
$cost = FinancialValidations::validateFloat($cost);
@@ -141,9 +139,7 @@ public static function AMORLINC(
141139
$salvage = Functions::flattenSingleValue($salvage);
142140
$period = Functions::flattenSingleValue($period);
143141
$rate = Functions::flattenSingleValue($rate);
144-
$basis = ($basis === null)
145-
? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
146-
: Functions::flattenSingleValue($basis);
142+
$basis = Functions::flattenSingleValue($basis) ?? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD;
147143

148144
try {
149145
$cost = FinancialValidations::validateFloat($cost);

src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ public static function futureValue(
3838
): string|float {
3939
$rate = Functions::flattenSingleValue($rate);
4040
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
41-
$payment = ($payment === null) ? 0.0 : Functions::flattenSingleValue($payment);
42-
$presentValue = ($presentValue === null) ? 0.0 : Functions::flattenSingleValue($presentValue);
43-
$type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type);
41+
$payment = Functions::flattenSingleValue($payment) ?? 0.0;
42+
$presentValue = Functions::flattenSingleValue($presentValue) ?? 0.0;
43+
$type = Functions::flattenSingleValue($type) ?? FinancialConstants::PAYMENT_END_OF_PERIOD;
4444

4545
try {
4646
$rate = CashFlowValidations::validateRate($rate);
@@ -77,9 +77,9 @@ public static function presentValue(
7777
): string|float {
7878
$rate = Functions::flattenSingleValue($rate);
7979
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
80-
$payment = ($payment === null) ? 0.0 : Functions::flattenSingleValue($payment);
81-
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
82-
$type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type);
80+
$payment = Functions::flattenSingleValue($payment) ?? 0.0;
81+
$futureValue = Functions::flattenSingleValue($futureValue) ?? 0.0;
82+
$type = Functions::flattenSingleValue($type) ?? FinancialConstants::PAYMENT_END_OF_PERIOD;
8383

8484
try {
8585
$rate = CashFlowValidations::validateRate($rate);
@@ -122,8 +122,8 @@ public static function periods(
122122
$rate = Functions::flattenSingleValue($rate);
123123
$payment = Functions::flattenSingleValue($payment);
124124
$presentValue = Functions::flattenSingleValue($presentValue);
125-
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
126-
$type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type);
125+
$futureValue = Functions::flattenSingleValue($futureValue) ?? 0.0;
126+
$type = Functions::flattenSingleValue($type) ?? FinancialConstants::PAYMENT_END_OF_PERIOD;
127127

128128
try {
129129
$rate = CashFlowValidations::validateRate($rate);

src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Cumulative.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public static function interest(
4141
$presentValue = Functions::flattenSingleValue($presentValue);
4242
$start = Functions::flattenSingleValue($start);
4343
$end = Functions::flattenSingleValue($end);
44-
$type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type);
44+
$type = Functions::flattenSingleValue($type) ?? FinancialConstants::PAYMENT_END_OF_PERIOD;
4545

4646
try {
4747
$rate = CashFlowValidations::validateRate($rate);
@@ -104,7 +104,7 @@ public static function principal(
104104
$presentValue = Functions::flattenSingleValue($presentValue);
105105
$start = Functions::flattenSingleValue($start);
106106
$end = Functions::flattenSingleValue($end);
107-
$type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type);
107+
$type = Functions::flattenSingleValue($type) ?? FinancialConstants::PAYMENT_END_OF_PERIOD;
108108

109109
try {
110110
$rate = CashFlowValidations::validateRate($rate);

src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public static function payment(
4343
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
4444
$presentValue = Functions::flattenSingleValue($presentValue);
4545
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
46-
$type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type);
46+
$type = Functions::flattenSingleValue($type) ?? FinancialConstants::PAYMENT_END_OF_PERIOD;
4747

4848
try {
4949
$interestRate = CashFlowValidations::validateRate($interestRate);
@@ -160,9 +160,9 @@ public static function rate(
160160
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
161161
$payment = Functions::flattenSingleValue($payment);
162162
$presentValue = Functions::flattenSingleValue($presentValue);
163-
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
164-
$type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type);
165-
$guess = ($guess === null) ? 0.1 : Functions::flattenSingleValue($guess);
163+
$futureValue = Functions::flattenSingleValue($futureValue) ?? 0.0;
164+
$type = Functions::flattenSingleValue($type) ?? FinancialConstants::PAYMENT_END_OF_PERIOD;
165+
$guess = Functions::flattenSingleValue($guess) ?? 0.1;
166166

167167
try {
168168
$numberOfPeriods = CashFlowValidations::validateFloat($numberOfPeriods);

src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Payments.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ public static function annuity(
2727
mixed $interestRate,
2828
mixed $numberOfPeriods,
2929
mixed $presentValue,
30-
mixed $futureValue = 0,
30+
mixed $futureValue = 0.0,
3131
mixed $type = FinancialConstants::PAYMENT_END_OF_PERIOD
3232
): string|float {
3333
$interestRate = Functions::flattenSingleValue($interestRate);
3434
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
3535
$presentValue = Functions::flattenSingleValue($presentValue);
36-
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
37-
$type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type);
36+
$futureValue = Functions::flattenSingleValue($futureValue) ?? 0.0;
37+
$type = Functions::flattenSingleValue($type) ?? FinancialConstants::PAYMENT_END_OF_PERIOD;
3838

3939
try {
4040
$interestRate = CashFlowValidations::validateRate($interestRate);
@@ -83,7 +83,7 @@ public static function interestPayment(
8383
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
8484
$presentValue = Functions::flattenSingleValue($presentValue);
8585
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
86-
$type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type);
86+
$type = Functions::flattenSingleValue($type) ?? FinancialConstants::PAYMENT_END_OF_PERIOD;
8787

8888
try {
8989
$interestRate = CashFlowValidations::validateRate($interestRate);

src/PhpSpreadsheet/Calculation/Financial/Coupons.php

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,7 @@ public static function COUPDAYBS(
4949
$settlement = Functions::flattenSingleValue($settlement);
5050
$maturity = Functions::flattenSingleValue($maturity);
5151
$frequency = Functions::flattenSingleValue($frequency);
52-
$basis = ($basis === null)
53-
? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
54-
: Functions::flattenSingleValue($basis);
52+
$basis = Functions::flattenSingleValue($basis) ?? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD;
5553

5654
try {
5755
$settlement = FinancialValidations::validateSettlementDate($settlement);
@@ -110,9 +108,7 @@ public static function COUPDAYS(
110108
$settlement = Functions::flattenSingleValue($settlement);
111109
$maturity = Functions::flattenSingleValue($maturity);
112110
$frequency = Functions::flattenSingleValue($frequency);
113-
$basis = ($basis === null)
114-
? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
115-
: Functions::flattenSingleValue($basis);
111+
$basis = Functions::flattenSingleValue($basis) ?? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD;
116112

117113
try {
118114
$settlement = FinancialValidations::validateSettlementDate($settlement);
@@ -179,9 +175,7 @@ public static function COUPDAYSNC(
179175
$settlement = Functions::flattenSingleValue($settlement);
180176
$maturity = Functions::flattenSingleValue($maturity);
181177
$frequency = Functions::flattenSingleValue($frequency);
182-
$basis = ($basis === null)
183-
? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
184-
: Functions::flattenSingleValue($basis);
178+
$basis = Functions::flattenSingleValue($basis) ?? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD;
185179

186180
try {
187181
$settlement = FinancialValidations::validateSettlementDate($settlement);
@@ -244,9 +238,7 @@ public static function COUPNCD(
244238
$settlement = Functions::flattenSingleValue($settlement);
245239
$maturity = Functions::flattenSingleValue($maturity);
246240
$frequency = Functions::flattenSingleValue($frequency);
247-
$basis = ($basis === null)
248-
? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
249-
: Functions::flattenSingleValue($basis);
241+
$basis = Functions::flattenSingleValue($basis) ?? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD;
250242

251243
try {
252244
$settlement = FinancialValidations::validateSettlementDate($settlement);
@@ -296,9 +288,7 @@ public static function COUPNUM(
296288
$settlement = Functions::flattenSingleValue($settlement);
297289
$maturity = Functions::flattenSingleValue($maturity);
298290
$frequency = Functions::flattenSingleValue($frequency);
299-
$basis = ($basis === null)
300-
? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
301-
: Functions::flattenSingleValue($basis);
291+
$basis = Functions::flattenSingleValue($basis) ?? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD;
302292

303293
try {
304294
$settlement = FinancialValidations::validateSettlementDate($settlement);
@@ -355,9 +345,7 @@ public static function COUPPCD(
355345
$settlement = Functions::flattenSingleValue($settlement);
356346
$maturity = Functions::flattenSingleValue($maturity);
357347
$frequency = Functions::flattenSingleValue($frequency);
358-
$basis = ($basis === null)
359-
? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
360-
: Functions::flattenSingleValue($basis);
348+
$basis = Functions::flattenSingleValue($basis) ?? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD;
361349

362350
try {
363351
$settlement = FinancialValidations::validateSettlementDate($settlement);

src/PhpSpreadsheet/Calculation/Financial/Securities/AccruedInterest.php

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,8 @@ public static function periodic(
6060
$settlement = Functions::flattenSingleValue($settlement);
6161
$rate = Functions::flattenSingleValue($rate);
6262
$parValue = ($parValue === null) ? 1000 : Functions::flattenSingleValue($parValue);
63-
$frequency = ($frequency === null)
64-
? FinancialConstants::FREQUENCY_ANNUAL
65-
: Functions::flattenSingleValue($frequency);
66-
$basis = ($basis === null)
67-
? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
68-
: Functions::flattenSingleValue($basis);
63+
$frequency = Functions::flattenSingleValue($frequency) ?? FinancialConstants::FREQUENCY_ANNUAL;
64+
$basis = Functions::flattenSingleValue($basis) ?? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD;
6965

7066
try {
7167
$issue = SecurityValidations::validateIssueDate($issue);
@@ -126,9 +122,7 @@ public static function atMaturity(
126122
$settlement = Functions::flattenSingleValue($settlement);
127123
$rate = Functions::flattenSingleValue($rate);
128124
$parValue = ($parValue === null) ? 1000 : Functions::flattenSingleValue($parValue);
129-
$basis = ($basis === null)
130-
? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
131-
: Functions::flattenSingleValue($basis);
125+
$basis = Functions::flattenSingleValue($basis) ?? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD;
132126

133127
try {
134128
$issue = SecurityValidations::validateIssueDate($issue);

0 commit comments

Comments
 (0)