Skip to content

Commit 9fe3d71

Browse files
authored
Merge branch 'master' into valuebinder
2 parents 1b64b42 + 3194757 commit 9fe3d71

Some content is hidden

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

53 files changed

+958
-161
lines changed

CHANGELOG.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,35 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com)
66
and this project adheres to [Semantic Versioning](https://semver.org).
77

8-
## 2024-09-29 - 3.0.0
8+
## TBD - 3.4.0
9+
10+
### Added
11+
12+
- Nothing yet.
13+
14+
### Changed
15+
16+
- Nothing yet.
17+
18+
### Deprecated
19+
20+
- IREADER::SKIP_EMPTY_CELLS - use its alias IGNORE_EMPTY_CELLS instead.
21+
22+
### Moved
23+
24+
- Nothing yet.
25+
26+
### Fixed
27+
28+
- Xls Writer Condtional Rules Applied to Whole Rows or Columns. [Issue #3185](https://github.com/PHPOffice/PhpSpreadsheet/issues/3185) [PR #4152](https://github.com/PHPOffice/PhpSpreadsheet/pull/4152)
29+
- Xlsx Writer Duplicate ContentTypes Entry for Background Image. [Issue #4179](https://github.com/PHPOffice/PhpSpreadsheet/issues/4179) [PR #4180](https://github.com/PHPOffice/PhpSpreadsheet/pull/4180)
30+
- Check strictNullComparison outside of loops. [PR #3347](https://github.com/PHPOffice/PhpSpreadsheet/pull/3347)
31+
- SUMIFS Does Not Require xlfn. [Issue #4182](https://github.com/PHPOffice/PhpSpreadsheet/issues/4182) [PR #4186](https://github.com/PHPOffice/PhpSpreadsheet/pull/4186)
32+
- Image Transparency/Opacity with Html Reader Changes. [Discussion #4117](https://github.com/PHPOffice/PhpSpreadsheet/discussions/4117) [PR #4142](https://github.com/PHPOffice/PhpSpreadsheet/pull/4142)
33+
- Option to Write Hyperlink Rather Than Label to Csv. [Issue #1412](https://github.com/PHPOffice/PhpSpreadsheet/issues/1412) [PR #4151](https://github.com/PHPOffice/PhpSpreadsheet/pull/4151)
34+
- Invalid Html Due to Cached Filesize. [Issue #1107](https://github.com/PHPOffice/PhpSpreadsheet/issues/1107) [PR #4184](https://github.com/PHPOffice/PhpSpreadsheet/pull/4184)
35+
36+
## 2024-09-29 - 3.3.0 (no 3.0.\*, 3.1.\*, 3.2.\*)
937

1038
### Dynamic Arrays
1139

composer.lock

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

docs/topics/reading-and-writing-to-file.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,19 +1113,19 @@ Flags that are available that can be passed to the Reader in this way include:
11131113

11141114
- $reader::LOAD_WITH_CHARTS
11151115
- $reader::READ_DATA_ONLY
1116-
- $reader::IGNORE_EMPTY_CELLS
1117-
- $reader::SKIP_EMPTY_CELLS (synonym for IGNORE_EMPTY_CELLS)
1118-
1119-
| Readers | LOAD_WITH_CHARTS | READ_DATA_ONLY | IGNORE_EMPTY_CELLS |
1120-
|----------|------------------|----------------|--------------------|
1121-
| Xlsx | YES | YES | YES |
1122-
| Xls | NO | YES | YES |
1123-
| Xml | NO | NO | NO |
1124-
| Ods | NO | YES | NO |
1125-
| Gnumeric | NO | YES | NO |
1126-
| Html | N/A | N/A | N/A |
1127-
| Slk | N/A | NO | NO |
1128-
| Csv | N/A | NO | NO |
1116+
- $reader::IGNORE_EMPTY_CELLS
1117+
- $reader::IGNORE_ROWS_WITH_NO_CELLS
1118+
1119+
| Readers | LOAD_WITH_CHARTS | READ_DATA_ONLY | IGNORE_EMPTY_CELLS | IGNORE_ROWS_WITH_NO_CELLS |
1120+
|----------|------------------|----------------|--------------------|---------------------------|
1121+
| Xlsx | YES | YES | YES | YES |
1122+
| Xls | NO | YES | YES | NO |
1123+
| Xml | NO | NO | NO | NO |
1124+
| Ods | NO | YES | NO | NO |
1125+
| Gnumeric | NO | YES | NO | NO |
1126+
| Html | N/A | N/A | N/A | N/A |
1127+
| Slk | N/A | NO | NO | NO |
1128+
| Csv | N/A | NO | NO | NO |
11291129

11301130
Likewise, when saving a file using a Writer, loaded charts will not be saved unless you explicitly tell the Writer to include them:
11311131

@@ -1162,5 +1162,5 @@ Two or more flags can be passed together using PHP's `|` operator.
11621162

11631163
```php
11641164
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile("myExampleFile.xlsx");
1165-
$reader->load("spreadsheetWithCharts.xlsx", $reader::READ_DATA_ONLY | $reader::SKIP_EMPTY_CELLS);
1165+
$reader->load("spreadsheetWithCharts.xlsx", $reader::READ_DATA_ONLY | $reader::IGNORE_EMPTY_CELLS);
11661166
```

samples/Basic4/53_ImageOpacity.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
require __DIR__ . '/../Header.php';
4+
5+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
6+
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
7+
8+
//var_dump(realpath(__DIR__ . '/../images/blue_square.png'));
9+
//exit();
10+
11+
$path = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'images/blue_square.png';
12+
$spreadsheet = new Spreadsheet();
13+
$spreadsheet->getProperties()->setTitle('53_ImageOpacity');
14+
15+
$helper->log('Add image to spreadsheet 6 times with different opacities');
16+
$sheet = $spreadsheet->getActiveSheet();
17+
$sheet->setTitle('Squares different opacities');
18+
$sheet->setShowGridLines(false);
19+
20+
$drawing = new Drawing();
21+
$drawing->setName('Blue Square opacity not specified');
22+
$drawing->setPath($path);
23+
$drawing->setCoordinates('A1');
24+
$drawing->setCoordinates2('B5');
25+
$drawing->setWorksheet($sheet);
26+
27+
$drawing = new Drawing();
28+
$drawing->setName('Blue Square opacity 80%');
29+
$drawing->setPath($path);
30+
$drawing->setCoordinates('C1');
31+
$drawing->setCoordinates2('D5');
32+
$drawing->setOpacity(80000);
33+
$drawing->setWorksheet($sheet);
34+
35+
$drawing = new Drawing();
36+
$drawing->setName('Blue Square opacity 60%');
37+
$drawing->setPath($path);
38+
$drawing->setCoordinates('E1');
39+
$drawing->setCoordinates2('F5');
40+
$drawing->setOpacity(60000);
41+
$drawing->setWorksheet($sheet);
42+
43+
$drawing = new Drawing();
44+
$drawing->setName('Blue Square opacity 40%');
45+
$drawing->setPath($path);
46+
$drawing->setCoordinates('A8');
47+
$drawing->setCoordinates2('B12');
48+
$drawing->setOpacity(40000);
49+
$drawing->setWorksheet($sheet);
50+
51+
$drawing = new Drawing();
52+
$drawing->setName('Blue Square opacity 20%');
53+
$drawing->setPath($path);
54+
$drawing->setCoordinates('C8');
55+
$drawing->setCoordinates2('D12');
56+
$drawing->setOpacity(20000);
57+
$drawing->setWorksheet($sheet);
58+
59+
$drawing = new Drawing();
60+
$drawing->setName('Blue Square opacity 0%');
61+
$drawing->setPath($path);
62+
$drawing->setCoordinates('E8');
63+
$drawing->setCoordinates2('F12');
64+
$drawing->setOpacity(0);
65+
$drawing->setWorksheet($sheet);
66+
67+
// Save
68+
$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Html', 'Dompdf', 'Mpdf']);
69+
$spreadsheet->disconnectWorksheets();

samples/images/blue_square.png

2.3 KB
Loading

samples/templates/27template.xlsx

582 Bytes
Binary file not shown.

src/PhpSpreadsheet/Calculation/Calculation.php

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4160,8 +4160,10 @@ private function internalParseFormula(string $formula, ?Cell $cell = null): bool
41604160
}
41614161
}
41624162
} elseif ($expectedArgumentCount != '*') {
4163-
preg_match('/(\d*)([-+,])(\d*)/', $expectedArgumentCount, $argMatch);
4164-
switch ($argMatch[2] ?? '') {
4163+
if (1 !== preg_match('/(\d*)([-+,])(\d*)/', $expectedArgumentCount, $argMatch)) {
4164+
$argMatch = ['', '', '', ''];
4165+
}
4166+
switch ($argMatch[2]) {
41654167
case '+':
41664168
if ($argumentCount < $argMatch[1]) {
41674169
$argumentCountError = true;
@@ -4234,7 +4236,7 @@ private function internalParseFormula(string $formula, ?Cell $cell = null): bool
42344236
// do we now have a function/variable/number?
42354237
$expectingOperator = true;
42364238
$expectingOperand = false;
4237-
$val = $match[1];
4239+
$val = $match[1] ?? '';
42384240
$length = strlen($val);
42394241

42404242
if (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/miu', $val, $matches)) {
@@ -4290,7 +4292,7 @@ private function internalParseFormula(string $formula, ?Cell $cell = null): bool
42904292
$rangeStartCellRef = $output[count($output) - 2]['value'] ?? '';
42914293
}
42924294
preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/miu', $rangeStartCellRef, $rangeStartMatches);
4293-
if ($rangeStartMatches[2] !== $matches[2]) {
4295+
if (isset($rangeStartMatches[2]) && $rangeStartMatches[2] !== $matches[2]) {
42944296
return $this->raiseFormulaError('3D Range references are not yet supported');
42954297
}
42964298
}
@@ -4380,7 +4382,7 @@ private function internalParseFormula(string $formula, ?Cell $cell = null): bool
43804382
$valx = $val;
43814383
$endRowColRef = ($refSheet !== null) ? $refSheet->getHighestDataColumn($valx) : AddressRange::MAX_COLUMN; // Max 16,384 columns for Excel2007
43824384
$val = "{$rangeWS2}{$endRowColRef}{$val}";
4383-
} elseif (ctype_alpha($val) && strlen($val ?? '') <= 3) {
4385+
} elseif (ctype_alpha($val) && is_string($val) && strlen($val) <= 3) {
43844386
// Column range
43854387
$stackItemType = 'Column Reference';
43864388
$endRowColRef = ($refSheet !== null) ? $refSheet->getHighestDataRow($val) : AddressRange::MAX_ROW; // Max 1,048,576 rows for Excel2007
@@ -4545,6 +4547,12 @@ private static function dataTestReference(array &$operandData): mixed
45454547
return $operand;
45464548
}
45474549

4550+
private static int $matchIndex8 = 8;
4551+
4552+
private static int $matchIndex9 = 9;
4553+
4554+
private static int $matchIndex10 = 10;
4555+
45484556
/**
45494557
* @return array<int, mixed>|false
45504558
*/
@@ -4908,12 +4916,17 @@ private function processTokenStack(mixed $tokens, ?string $cellID = null, ?Cell
49084916
} elseif (preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/i', $token ?? '', $matches)) {
49094917
$cellRef = null;
49104918

4911-
if (isset($matches[8])) {
4919+
/* Phpstan says matches[8/9/10] is never set,
4920+
and code coverage report seems to confirm.
4921+
Appease PhpStan for now;
4922+
probably delete this block later.
4923+
*/
4924+
if (isset($matches[self::$matchIndex8])) {
49124925
if ($cell === null) {
49134926
// We can't access the range, so return a REF error
49144927
$cellValue = ExcelError::REF();
49154928
} else {
4916-
$cellRef = $matches[6] . $matches[7] . ':' . $matches[9] . $matches[10];
4929+
$cellRef = $matches[6] . $matches[7] . ':' . $matches[self::$matchIndex9] . $matches[self::$matchIndex10];
49174930
if ($matches[2] > '') {
49184931
$matches[2] = trim($matches[2], "\"'");
49194932
if ((str_contains($matches[2], '[')) || (str_contains($matches[2], ']'))) {

src/PhpSpreadsheet/Calculation/Functions.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,10 @@ public static function ifCondition(mixed $condition): string
164164

165165
return str_replace('""""', '""', '=' . $condition);
166166
}
167-
preg_match('/(=|<[>=]?|>=?)(.*)/', $condition, $matches);
168-
[, $operator, $operand] = $matches;
167+
$operator = $operand = '';
168+
if (1 === preg_match('/(=|<[>=]?|>=?)(.*)/', $condition, $matches)) {
169+
[, $operator, $operand] = $matches;
170+
}
169171

170172
$operand = self::operandSpecialHandling($operand);
171173
if (is_numeric(trim($operand, '"'))) {

src/PhpSpreadsheet/Calculation/Information/Value.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,11 @@ public static function isFormula(mixed $cellReference = '', ?Cell $cell = null):
210210

211211
$fullCellReference = Functions::trimTrailingRange($fullCellReference);
212212

213-
preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $fullCellReference, $matches);
214-
215-
$fullCellReference = $matches[6] . $matches[7];
216-
$worksheetName = str_replace("''", "'", trim($matches[2], "'"));
213+
$worksheetName = '';
214+
if (1 == preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $fullCellReference, $matches)) {
215+
$fullCellReference = $matches[6] . $matches[7];
216+
$worksheetName = str_replace("''", "'", trim($matches[2], "'"));
217+
}
217218

218219
$worksheet = (!empty($worksheetName))
219220
? $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheetName)

src/PhpSpreadsheet/Calculation/LookupRef/Formula.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ public static function text(mixed $cellReference = '', ?Cell $cell = null): stri
2020
return ExcelError::REF();
2121
}
2222

23-
preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellReference, $matches);
24-
25-
$cellReference = $matches[6] . $matches[7];
26-
$worksheetName = trim($matches[3], "'");
27-
$worksheet = (!empty($worksheetName))
28-
? $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheetName)
29-
: $cell->getWorksheet();
23+
$worksheet = null;
24+
if (1 === preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellReference, $matches)) {
25+
$cellReference = $matches[6] . $matches[7];
26+
$worksheetName = trim($matches[3], "'");
27+
$worksheet = (!empty($worksheetName))
28+
? $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheetName)
29+
: $cell->getWorksheet();
30+
}
3031

3132
if (
3233
$worksheet === null

0 commit comments

Comments
 (0)