Skip to content

Commit 1d99dc8

Browse files
Merge branch 'PHPOffice:master' into Table-for-Xlsx
2 parents 530e664 + ed11a41 commit 1d99dc8

35 files changed

+678
-303
lines changed

.github/ISSUE_TEMPLATE.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
2626

2727
// add code that show the issue here...
2828
```
29+
If this is an issue with reading a specific spreadsheet file, then it may be appropriate to provide a sample file that demonstrates the problem; but please keep it as small as possible, and sanitize any confidential information before uploading.
30+
31+
### What features do you think are causing the issue
32+
33+
- [ ] Reader
34+
- [ ] Writer
35+
- [ ] Styles
36+
- [ ] Data Validations
37+
- [ ] Formula Calulations
38+
- [ ] Charts
39+
- [ ] AutoFilter
40+
- [ ] Form Elements
41+
42+
### Does an issue affect all spreadsheet file formats? If not, which formats are affected?
2943

3044

3145
### Which versions of PhpSpreadsheet and PHP are affected?

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,21 @@ This is:
33
```
44
- [ ] a bugfix
55
- [ ] a new feature
6+
- [ ] refactoring
7+
- [ ] additional unit tests
68
```
79

810
Checklist:
911

1012
- [ ] Changes are covered by unit tests
13+
- [ ] Changes are covered by existing unit tests
14+
- [ ] New unit tests have been added
1115
- [ ] Code style is respected
1216
- [ ] Commit message explains **why** the change is made (see https://github.com/erlang/otp/wiki/Writing-good-commit-messages)
1317
- [ ] CHANGELOG.md contains a short summary of the change
1418
- [ ] Documentation is updated as necessary
1519

1620
### Why this change is needed?
21+
22+
Provide an explanation of why this change is needed, with links to any Issues (if appropriate).
23+
If this is a bugfix or a new feature, and there are no existing Issues, then please also create an issue that will make it easier to track progress with this PR.

CHANGELOG.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org).
99

1010
### Added
1111

12+
- Ods Writer support for Freeze Pane [Issue #2013](https://github.com/PHPOffice/PhpSpreadsheet/issues/2013) [PR #2755](https://github.com/PHPOffice/PhpSpreadsheet/pull/2755)
13+
- Ods Writer support for setting column width/row height (including the use of AutoSize) [Issue #2346](https://github.com/PHPOffice/PhpSpreadsheet/issues/2346) [PR #2753](https://github.com/PHPOffice/PhpSpreadsheet/pull/2753)
1214
- Introduced CellAddress, CellRange, RowRange and ColumnRange value objects that can be used as an alternative to a string value (e.g. `'C5'`, `'B2:D4'`, `'2:2'` or `'B:C'`) in appropriate contexts.
1315
- Implementation of the FILTER(), SORT(), SORTBY() and UNIQUE() Lookup/Reference (array) functions.
1416
- Implementation of the ISREF() Information function.
@@ -18,11 +20,13 @@ and this project adheres to [Semantic Versioning](https://semver.org).
1820

1921
This functionality is locale-aware, using the server's locale settings to identify the thousands and decimal separators.
2022

21-
- Support for two cell anchor drawing of images. [#2532](https://github.com/PHPOffice/PhpSpreadsheet/pull/2532)
23+
- Support for two cell anchor drawing of images. [#2532](https://github.com/PHPOffice/PhpSpreadsheet/pull/2532) [#2674](https://github.com/PHPOffice/PhpSpreadsheet/pull/2674)
2224
- Limited support for Xls Reader to handle Conditional Formatting:
2325

2426
Ranges and Rules are read, but style is currently limited to font size, weight and color; and to fill style and color.
2527

28+
- Add ability to suppress Mac line ending check for CSV [#2623](https://github.com/PHPOffice/PhpSpreadsheet/pull/2623)
29+
2630
### Changed
2731

2832
- Gnumeric Reader now loads number formatting for cells.
@@ -66,23 +70,28 @@ and this project adheres to [Semantic Versioning](https://semver.org).
6670

6771
### Fixed
6872

73+
- Make allowance for the AutoFilter dropdown icon in the first row of an Autofilter range when using Autosize columns. [Issue #2413](https://github.com/PHPOffice/PhpSpreadsheet/issues/2413) [PR #2754](https://github.com/PHPOffice/PhpSpreadsheet/pull/2754)
6974
- Support for "chained" ranges (e.g. `A5:C10:C20:F1`) in the Calculation Engine; and also support for using named ranges with the Range operator (e.g. `NamedRange1:NamedRange2`) [Issue #2730](https://github.com/PHPOffice/PhpSpreadsheet/issues/2730) [PR #2746](https://github.com/PHPOffice/PhpSpreadsheet/pull/2746)
7075
- Update Conditional Formatting ranges and rule conditions when inserting/deleting rows/columns [Issue #2678](https://github.com/PHPOffice/PhpSpreadsheet/issues/2678) [PR #2689](https://github.com/PHPOffice/PhpSpreadsheet/pull/2689)
7176
- Allow `INDIRECT()` to accept row/column ranges as well as cell ranges [PR #2687](https://github.com/PHPOffice/PhpSpreadsheet/pull/2687)
7277
- Fix bug when deleting cells with hyperlinks, where the hyperlink was then being "inherited" by whatever cell moved to that cell address.
7378
- Fix bug in Conditional Formatting in the Xls Writer that resulted in a broken file when there were multiple conditional ranges in a worksheet.
7479
- Fix Conditional Formatting in the Xls Writer to work with rules that contain string literals, cell references and formulae.
7580
- Fix for setting Active Sheet to the first loaded worksheet when bookViews element isn't defined [Issue #2666](https://github.com/PHPOffice/PhpSpreadsheet/issues/2666) [PR #2669](https://github.com/PHPOffice/PhpSpreadsheet/pull/2669)
76-
- Fixed behaviour of XLSX font style vertical align settings.
81+
- Fixed behaviour of XLSX font style vertical align settings [PR #2619](https://github.com/PHPOffice/PhpSpreadsheet/pull/2619)
7782
- Resolved formula translations to handle separators (row and column) for array functions as well as for function argument separators; and cleanly handle nesting levels.
7883

7984
Note that this method is used when translating Excel functions between `en_us` and other locale languages, as well as when converting formulae between different spreadsheet formats (e.g. Ods to Excel).
8085

8186
Nor is this a perfect solution, as there may still be issues when function calls have array arguments that themselves contain function calls; but it's still better than the current logic.
8287
- Fix for escaping double quotes within a formula [Issue #1971](https://github.com/PHPOffice/PhpSpreadsheet/issues/1971) [PR #2651](https://github.com/PHPOffice/PhpSpreadsheet/pull/2651)
88+
- Change open mode for output from `wb+` to `wb` [Issue #2372](https://github.com/PHPOffice/PhpSpreadsheet/issues/2372) [PR #2657](https://github.com/PHPOffice/PhpSpreadsheet/pull/2657)
89+
- Use color palette if supplied [Issue #2499](https://github.com/PHPOffice/PhpSpreadsheet/issues/2499) [PR #2595](https://github.com/PHPOffice/PhpSpreadsheet/pull/2595)
90+
- Xls reader treat drawing offsets as int rather than float [PR #2648](https://github.com/PHPOffice/PhpSpreadsheet/pull/2648)
91+
- Handle booleans in conditional styles properly [PR #2654](https://github.com/PHPOffice/PhpSpreadsheet/pull/2654)
92+
- Fix for reading files in the root directory of a ZipFile, which should not be prefixed by relative paths ("./") as dirname($filename) does by default.
8393
- Fix invalid style of cells in empty columns with columnDimensions and rows with rowDimensions in added external sheet. [PR #2739](https://github.com/PHPOffice/PhpSpreadsheet/pull/2739)
8494

85-
8695
## 1.22.0 - 2022-02-18
8796

8897
### Added

docs/topics/file-formats.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ semi-colon (`;`) are used as separators instead of a comma, although
8080
other symbols can be used. Because CSV is a text-only format, it doesn't
8181
support any data formatting options.
8282

83-
"CSV" is not a single, well-defined format (although see RFC 4180 for
83+
"CSV" is not a single, well-defined format (although see
84+
[RFC 4180](https://www.rfc-editor.org/rfc/rfc4180.html) for
8485
one definition that is commonly used). Rather, in practice the term
8586
"CSV" refers to any file that:
8687

@@ -117,5 +118,5 @@ Wide Web Consortium (W3C). However, in 2000, HTML also became an
117118
international standard (ISO/IEC 15445:2000). HTML 4.01 was published in
118119
late 1999, with further errata published through 2001. In 2004
119120
development began on HTML5 in the Web Hypertext Application Technology
120-
Working Group (WHATWG), which became a joint deliverable with the W3C in
121-
2008.
121+
Working Group (WHATWG), which became a joint deliverable with the W3C in 2008.
122+

docs/topics/reading-files.md

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@ practise), it will reject the Xls loader that it would normally use for
4444
a .xls file; and test the file using the other loaders until it finds
4545
the appropriate loader, and then use that to read the file.
4646

47+
If you know that this is an `xls` file, but don't know whether it is a
48+
genuine BIFF-format Excel or Html markup with an xls extension, you can
49+
limit the loader to check only those two possibilities by passing in an
50+
array of Readers to test against.
51+
52+
```php
53+
$inputFileName = './sampleData/example1.xls';
54+
$testAgainstFormats = [
55+
\PhpOffice\PhpSpreadsheet\IOFactory::READER_XLS,
56+
\PhpOffice\PhpSpreadsheet\IOFactory::READER_HTML,
57+
];
58+
59+
/** Load $inputFileName to a Spreadsheet Object **/
60+
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($inputFileName, 0, $testAgainstFormats);
61+
```
62+
4763
While easy to implement in your code, and you don't need to worry about
4864
the file type; this isn't the most efficient method to load a file; and
4965
it lacks the flexibility to configure the loader in any way before
@@ -118,6 +134,34 @@ $spreadsheet = $reader->load($inputFileName);
118134
See `samples/Reader/04_Simple_file_reader_using_the_IOFactory_to_identify_a_reader_to_use.php`
119135
for a working example of this code.
120136

137+
As with the IOFactory `load()` method, you can also pass an array of formats
138+
for the `identify()` method to check against if you know that it will only
139+
be in a subset of the possible formats that PhpSpreadsheet supports.
140+
141+
```php
142+
$inputFileName = './sampleData/example1.xls';
143+
$testAgainstFormats = [
144+
\PhpOffice\PhpSpreadsheet\IOFactory::READER_XLS,
145+
\PhpOffice\PhpSpreadsheet\IOFactory::READER_HTML,
146+
];
147+
148+
/** Identify the type of $inputFileName **/
149+
$inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($inputFileName, $testAgainstFormats);
150+
```
151+
152+
You can also use this to confirm that a file is what it claims to be:
153+
154+
```php
155+
$inputFileName = './sampleData/example1.xls';
156+
157+
try {
158+
/** Verify that $inputFileName really is an Xls file **/
159+
$inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($inputFileName, [\PhpOffice\PhpSpreadsheet\IOFactory::READER_XLS]);
160+
} catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) {
161+
// File isn't actually an Xls file, even though it has an xls extension
162+
}
163+
```
164+
121165
## Spreadsheet Reader Options
122166

123167
Once you have created a reader object for the workbook that you want to
@@ -146,7 +190,7 @@ $spreadsheet = $reader->load($inputFileName);
146190
See `samples/Reader/05_Simple_file_reader_using_the_read_data_only_option.php`
147191
for a working example of this code.
148192

149-
It is important to note that Workbooks (and PhpSpreadsheet) store dates
193+
It is important to note that most Workbooks (and PhpSpreadsheet) store dates
150194
and times as simple numeric values: they can only be distinguished from
151195
other numeric values by the format mask that is applied to that cell.
152196
When setting read data only to true, PhpSpreadsheet doesn't read the
@@ -162,8 +206,8 @@ Reading Only Data from a Spreadsheet File applies to Readers:
162206

163207
Reader | Y/N |Reader | Y/N |Reader | Y/N |
164208
----------|:---:|--------|:---:|--------------|:---:|
165-
Xlsx | YES | Xls | YES | Xml | YES |
166-
Ods | YES | SYLK | NO | Gnumeric | YES |
209+
Xlsx | YES | Xls | YES | Xml | YES |
210+
Ods | YES | SYLK | NO | Gnumeric | YES |
167211
CSV | NO | HTML | NO
168212

169213
### Reading Only Named WorkSheets from a File
@@ -233,8 +277,8 @@ Reading Only Named WorkSheets from a File applies to Readers:
233277

234278
Reader | Y/N |Reader | Y/N |Reader | Y/N |
235279
----------|:---:|--------|:---:|--------------|:---:|
236-
Xlsx | YES | Xls | YES | Xml | YES |
237-
Ods | YES | SYLK | NO | Gnumeric | YES |
280+
Xlsx | YES | Xls | YES | Xml | YES |
281+
Ods | YES | SYLK | NO | Gnumeric | YES |
238282
CSV | NO | HTML | NO
239283

240284
### Reading Only Specific Columns and Rows from a File (Read Filters)
@@ -381,7 +425,7 @@ Using Read Filters applies to:
381425

382426
Reader | Y/N |Reader | Y/N |Reader | Y/N |
383427
----------|:---:|--------|:---:|--------------|:---:|
384-
Xlsx | YES | Xls | YES | Xml | YES |
428+
Xlsx | YES | Xls | YES | Xml | YES |
385429
Ods | YES | SYLK | NO | Gnumeric | YES |
386430
CSV | YES | HTML | NO | | |
387431

@@ -439,7 +483,7 @@ Combining Multiple Files into a Single Spreadsheet Object applies to:
439483

440484
Reader | Y/N |Reader | Y/N |Reader | Y/N |
441485
----------|:---:|--------|:---:|--------------|:---:|
442-
Xlsx | NO | Xls | NO | Xml | NO |
486+
Xlsx | NO | Xls | NO | Xml | NO |
443487
Ods | NO | SYLK | YES | Gnumeric | NO |
444488
CSV | YES | HTML | NO
445489

@@ -516,7 +560,7 @@ Splitting a single loaded file across multiple worksheets applies to:
516560

517561
Reader | Y/N |Reader | Y/N |Reader | Y/N |
518562
----------|:---:|--------|:---:|--------------|:---:|
519-
Xlsx | NO | Xls | NO | Xml | NO |
563+
Xlsx | NO | Xls | NO | Xml | NO |
520564
Ods | NO | SYLK | NO | Gnumeric | NO |
521565
CSV | YES | HTML | NO
522566

@@ -556,7 +600,7 @@ Setting CSV delimiter applies to:
556600

557601
Reader | Y/N |Reader | Y/N |Reader | Y/N |
558602
----------|:---:|--------|:---:|--------------|:---:|
559-
Xlsx | NO | Xls | NO | Xml | NO |
603+
Xlsx | NO | Xls | NO | Xml | NO |
560604
Ods | NO | SYLK | NO | Gnumeric | NO |
561605
CSV | YES | HTML | NO
562606

@@ -594,7 +638,7 @@ Applies to:
594638

595639
Reader | Y/N |Reader | Y/N |Reader | Y/N |
596640
----------|:---:|--------|:---:|--------------|:---:|
597-
Xlsx | NO | Xls | NO | Xml | NO |
641+
Xlsx | NO | Xls | NO | Xml | NO |
598642
Ods | NO | SYLK | NO | Gnumeric | NO |
599643
CSV | YES | HTML | NO
600644

@@ -646,7 +690,7 @@ Loading using a Value Binder applies to:
646690

647691
Reader | Y/N |Reader | Y/N |Reader | Y/N
648692
----------|:---:|--------|:---:|--------------|:---:
649-
Xlsx | NO | Xls | NO | Xml | NO
693+
Xlsx | NO | Xls | NO | Xml | NO
650694
Ods | NO | SYLK | NO | Gnumeric | NO
651695
CSV | YES | HTML | YES
652696

docs/topics/recipes.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,13 +1167,15 @@ that you are setting is measured in.
11671167
Valid units are `pt` (points), `px` (pixels), `pc` (pica), `in` (inches),
11681168
`cm` (centimeters) and `mm` (millimeters).
11691169

1170+
Setting the column width to `-1` tells MS Excel to display the column using its default width.
1171+
11701172
```php
11711173
$spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(120, 'pt');
11721174
```
11731175

11741176
If you want PhpSpreadsheet to perform an automatic width calculation,
1175-
use the following code. PhpSpreadsheet will approximate the column with
1176-
to the width of the widest column value.
1177+
use the following code. PhpSpreadsheet will approximate the column width
1178+
to the width of the widest value displayed in that column.
11771179

11781180
```php
11791181
$spreadsheet->getActiveSheet()->getColumnDimension('B')->setAutoSize(true);
@@ -1266,6 +1268,18 @@ Valid units are `pt` (points), `px` (pixels), `pc` (pica), `in` (inches),
12661268
$spreadsheet->getActiveSheet()->getRowDimension('10')->setRowHeight(100, 'pt');
12671269
```
12681270

1271+
Setting the row height to `-1` tells MS Excel to display the column using its default height, which is based on the character font size.
1272+
1273+
If you have wrapped text in a cell, then the `-1` default will only set the row height to display a single line of that wrapped text.
1274+
If you need to calculate the actual height for the row, then count the lines that should be displayed (count the `\n` and add 1); then adjust for the font.
1275+
The adjustment for Calibri 11 is approximately 14.5; for Calibri 12 15.9, etc.
1276+
```php
1277+
$spreadsheet->getActiveSheet()->getRowDimension(1)->setRowHeight(
1278+
14.5 * (substr_count($sheet->getCell('A1')->getValue(), "\n") + 1)
1279+
);
1280+
```
1281+
1282+
12691283
## Show/hide a row
12701284

12711285
To set a worksheet''s row visibility, you can use the following code.

phpstan-baseline.neon

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,11 +1175,6 @@ parameters:
11751175
count: 1
11761176
path: src/PhpSpreadsheet/Cell/Coordinate.php
11771177

1178-
-
1179-
message: "#^Cannot use array destructuring on array\\|null\\.$#"
1180-
count: 1
1181-
path: src/PhpSpreadsheet/Cell/Coordinate.php
1182-
11831178
-
11841179
message: "#^Parameter \\#4 \\$currentRow of static method PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Coordinate\\:\\:validateRange\\(\\) expects int, string given\\.$#"
11851180
count: 1
@@ -3120,11 +3115,6 @@ parameters:
31203115
count: 1
31213116
path: src/PhpSpreadsheet/Reader/Xml/Style.php
31223117

3123-
-
3124-
message: "#^Cannot use array destructuring on array\\|null\\.$#"
3125-
count: 4
3126-
path: src/PhpSpreadsheet/ReferenceHelper.php
3127-
31283118
-
31293119
message: "#^Elseif condition is always true\\.$#"
31303120
count: 1
@@ -4675,11 +4665,6 @@ parameters:
46754665
count: 1
46764666
path: src/PhpSpreadsheet/Writer/Ods/Content.php
46774667

4678-
-
4679-
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, int given\\.$#"
4680-
count: 4
4681-
path: src/PhpSpreadsheet/Writer/Ods/Content.php
4682-
46834668
-
46844669
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, int\\<2, max\\> given\\.$#"
46854670
count: 3
@@ -4695,11 +4680,6 @@ parameters:
46954680
count: 1
46964681
path: src/PhpSpreadsheet/Writer/Ods/Formula.php
46974682

4698-
-
4699-
message: "#^Parameter \\#1 \\$content of method XMLWriter\\:\\:text\\(\\) expects string, int given\\.$#"
4700-
count: 2
4701-
path: src/PhpSpreadsheet/Writer/Ods/Settings.php
4702-
47034683
-
47044684
message: "#^Cannot call method getHashCode\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
47054685
count: 1

src/PhpSpreadsheet/Calculation/Functions.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use PhpOffice\PhpSpreadsheet\Cell\Cell;
66
use PhpOffice\PhpSpreadsheet\Shared\Date;
7-
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
87

98
class Functions
109
{
@@ -686,12 +685,13 @@ public static function expandDefinedName(string $coordinate, Cell $cell): string
686685
// Uppercase coordinate
687686
$pCoordinatex = strtoupper($coordinate);
688687
// Eliminate leading equal sign
689-
$pCoordinatex = Worksheet::pregReplace('/^=/', '', $pCoordinatex);
688+
$pCoordinatex = (string) preg_replace('/^=/', '', $pCoordinatex);
690689
$defined = $spreadsheet->getDefinedName($pCoordinatex, $worksheet);
691690
if ($defined !== null) {
692691
$worksheet2 = $defined->getWorkSheet();
693692
if (!$defined->isFormula() && $worksheet2 !== null) {
694-
$coordinate = "'" . $worksheet2->getTitle() . "'!" . Worksheet::pregReplace('/^=/', '', $defined->getValue());
693+
$coordinate = "'" . $worksheet2->getTitle() . "'!" .
694+
(string) preg_replace('/^=/', '', $defined->getValue());
695695
}
696696
}
697697

@@ -700,7 +700,7 @@ public static function expandDefinedName(string $coordinate, Cell $cell): string
700700

701701
public static function trimTrailingRange(string $coordinate): string
702702
{
703-
return Worksheet::pregReplace('/:[\\w\$]+$/', '', $coordinate);
703+
return (string) preg_replace('/:[\\w\$]+$/', '', $coordinate);
704704
}
705705

706706
public static function trimSheetFromCellReference(string $coordinate): string

src/PhpSpreadsheet/Cell/Coordinate.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ private static function sortCellReferenceArray(array $cellList): array
383383
// Sort the result by column and row
384384
$sortKeys = [];
385385
foreach ($cellList as $coord) {
386-
[$column, $row] = sscanf($coord, '%[A-Z]%d');
386+
sscanf($coord, '%[A-Z]%d', $column, $row);
387387
$sortKeys[sprintf('%3s%09d', $column, $row)] = $coord;
388388
}
389389
ksort($sortKeys);

0 commit comments

Comments
 (0)