Skip to content

Commit da76f0d

Browse files
authored
Merge branch 'master' into issue2768
2 parents c286fb8 + 27221ee commit da76f0d

Some content is hidden

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

67 files changed

+4882
-460
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.

.php-cs-fixer.dist.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
'braces' => true,
2222
'cast_spaces' => true,
2323
'class_attributes_separation' => ['elements' => ['method' => 'one', 'property' => 'one']], // const are often grouped with other related const
24-
'class_definition' => true,
24+
'class_definition' => false,
2525
'class_keyword_remove' => false, // ::class keyword gives us better support in IDE
2626
'combine_consecutive_issets' => true,
2727
'combine_consecutive_unsets' => true,

CHANGELOG.md

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

1010
### Added
1111

12-
- Implementation of the FILTER(), SORT(), SORTBY() and UNIQUE() Lookup/Reference (array) functions
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)
14+
- 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.
15+
- Implementation of the FILTER(), SORT(), SORTBY() and UNIQUE() Lookup/Reference (array) functions.
1316
- Implementation of the ISREF() Information function.
1417
- Added support for reading "formatted" numeric values from Csv files; although default behaviour of reading these values as strings is preserved.
1518

16-
(i.e a value of "12,345.67" can be read as numeric `1235.67`, not simply as a string `"12,345.67"`, if the `castFormattedNumberToNumeric()` setting is enabled.
19+
(i.e a value of "12,345.67" can be read as numeric `12345.67`, not simply as a string `"12,345.67"`, if the `castFormattedNumberToNumeric()` setting is enabled.
1720

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

20-
- 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)
2124
- Limited support for Xls Reader to handle Conditional Formatting:
2225

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

28+
- Add ability to suppress Mac line ending check for CSV [#2623](https://github.com/PHPOffice/PhpSpreadsheet/pull/2623)
29+
- Initial support for creating and writing Tables (Xlsx Writer only) [PR #2671](https://github.com/PHPOffice/PhpSpreadsheet/pull/2671)
30+
31+
See `/samples/Table` for examples of use.
32+
33+
Note that PreCalculateFormulas needs to be disabled when saving spreadsheets containing tables with formulae (totals or column formulae).
34+
2535
### Changed
2636

2737
- Gnumeric Reader now loads number formatting for cells.
@@ -37,26 +47,55 @@ and this project adheres to [Semantic Versioning](https://semver.org).
3747
### Deprecated
3848

3949
- All Excel Function implementations in `Calculation\Functions` (including the Error functions) have been moved to dedicated classes for groups of related functions. See the docblocks against all the deprecated methods for details of the new methods to call instead. At some point, these old classes will be deleted.
50+
- Worksheet methods that reference cells "byColumnandRow". All such methods have an equivalent that references the cell by its address (e.g. '`E3'` rather than `5, 3`).
51+
52+
These functions now accept either a cell address string (`'E3')` or an array with columnId and rowId (`[5, 3]`) or a new `CellAddress` object as their `cellAddress`/`coordinate` argument.
53+
This includes the methods:
54+
- `setCellValueByColumnAndRow()` use the equivalent `setCellValue()`
55+
- `setCellValueExplicitByColumnAndRow()` use the equivalent `setCellValueExplicit()`
56+
- `getCellByColumnAndRow()` use the equivalent `getCell()`
57+
- `cellExistsByColumnAndRow()` use the equivalent `cellExists()`
58+
- `getStyleByColumnAndRow()` use the equivalent `getStyle()`
59+
- `setBreakByColumnAndRow()` use the equivalent `setBreak()`
60+
- `mergeCellsByColumnAndRow()` use the equivalent `mergeCells()`
61+
- `unmergeCellsByColumnAndRow()` use the equivalent `unmergeCells()`
62+
- `protectCellsByColumnAndRow()` use the equivalent `protectCells()`
63+
- `unprotectCellsByColumnAndRow()` use the equivalent `unprotectCells()`
64+
- `setAutoFilterByColumnAndRow()` use the equivalent `setAutoFilter()`
65+
- `freezePaneByColumnAndRow()` use the equivalent `freezePane()`
66+
- `getCommentByColumnAndRow()` use the equivalent `getComment()`
67+
- `setSelectedCellByColumnAndRow()` use the equivalent `setSelectedCells()`
68+
69+
This change provides more consistency in the methods (not every "by cell address" method has an equivalent "byColumnAndRow" method);
70+
and the "by cell address" methods often provide more flexibility, such as allowing a range of cells, or referencing them by passing the defined name of a named range as the argument.
4071

4172
### Removed
4273

4374
- Nothing
4475

4576
### Fixed
4677

78+
- 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)
79+
- 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)
4780
- 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)
4881
- Allow `INDIRECT()` to accept row/column ranges as well as cell ranges [PR #2687](https://github.com/PHPOffice/PhpSpreadsheet/pull/2687)
4982
- Fix bug when deleting cells with hyperlinks, where the hyperlink was then being "inherited" by whatever cell moved to that cell address.
5083
- Fix bug in Conditional Formatting in the Xls Writer that resulted in a broken file when there were multiple conditional ranges in a worksheet.
5184
- Fix Conditional Formatting in the Xls Writer to work with rules that contain string literals, cell references and formulae.
5285
- 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)
53-
- Fixed behaviour of XLSX font style vertical align settings.
86+
- Fixed behaviour of XLSX font style vertical align settings [PR #2619](https://github.com/PHPOffice/PhpSpreadsheet/pull/2619)
5487
- Resolved formula translations to handle separators (row and column) for array functions as well as for function argument separators; and cleanly handle nesting levels.
5588

5689
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).
5790

5891
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.
5992
- 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)
93+
- 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)
94+
- Use color palette if supplied [Issue #2499](https://github.com/PHPOffice/PhpSpreadsheet/issues/2499) [PR #2595](https://github.com/PHPOffice/PhpSpreadsheet/pull/2595)
95+
- Xls reader treat drawing offsets as int rather than float [PR #2648](https://github.com/PHPOffice/PhpSpreadsheet/pull/2648)
96+
- Handle booleans in conditional styles properly [PR #2654](https://github.com/PHPOffice/PhpSpreadsheet/pull/2654)
97+
- 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.
98+
- 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)
6099

61100
## 1.22.0 - 2022-02-18
62101

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.

0 commit comments

Comments
 (0)