Skip to content

Commit 2c9e2e2

Browse files
committed
Spill Operator
Spill operator now works both as trailing `#` and ARRAYANCHOR function. `#` is converted to ARRAYANCHOR when writing. I do not think it is important to convert the other way when reading. Documentation updates have started, but are a work in progress. SINGLE function is implemented. I believe it works correctly when referring to a cell, but not when referring to a cell range. No attempt is yet made to convert leading `@` to and from SINGLE; I haven't figured out how to do so without interfering with `@` in structured references. ISREF has problems. At least one of its tests was wrong, and many of those that were right were so accidentally. The code is changed, quite kludgily, so that almost all the tests are now deliberately correct. One very complicated test is incorrect; for now, I will skip it, and will open an issue when this PR is merged.
1 parent 8609b78 commit 2c9e2e2

23 files changed

+464
-34
lines changed

docs/references/function-list-by-category.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -586,5 +586,10 @@ WEBSERVICE | \PhpOffice\PhpSpreadsheet\Calculation\Web\Service::we
586586

587587
Excel Function | PhpSpreadsheet Function
588588
-------------------------|--------------------------------------
589-
ANCHORARRAY | **Not yet Implemented**
590-
SINGLE | **Not yet Implemented**
589+
590+
## CATEGORY_MICROSOFT_INTERNAL
591+
592+
Excel Function | PhpSpreadsheet Function
593+
-------------------------|--------------------------------------
594+
ANCHORARRAY | \PhpOffice\PhpSpreadsheet\Calculation\Internal\ExcelArrayPseudoFunctions::anchorArray
595+
SINGLE | \PhpOffice\PhpSpreadsheet\Calculation\Internal\ExcelArrayPseudoFunctions::single

docs/references/function-list-by-name.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ ADDRESS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpread
1515
AGGREGATE | CATEGORY_MATH_AND_TRIG | **Not yet Implemented**
1616
AMORDEGRC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Amortization::AMORDEGRC
1717
AMORLINC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Amortization::AMORLINC
18-
ANCHORARRAY | CATEGORY_UNCATEGORISED | **Not yet Implemented**
18+
ANCHORARRAY | CATEGORY_MICROSOFT_INTERNAL | \PhpOffice\PhpSpreadsheet\Calculation\Internal\ExcelArrayPseudoFunctions::anchorArray
1919
AND | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations::logicalAnd
2020
ARABIC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Arabic::evaluate
2121
AREAS | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented**
@@ -510,7 +510,7 @@ SHEET | CATEGORY_INFORMATION | **Not yet Implemente
510510
SHEETS | CATEGORY_INFORMATION | **Not yet Implemented**
511511
SIGN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Sign::evaluate
512512
SIN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Sine::sin
513-
SINGLE | CATEGORY_UNCATEGORISED | **Not yet Implemented**
513+
SINGLE | CATEGORY_MICROSOFT_INTERNAL | \PhpOffice\PhpSpreadsheet\Calculation\Internal\ExcelArrayPseudoFunctions::single
514514
SINH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Sine::sinh
515515
SKEW | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Deviations::skew
516516
SKEW.P | CATEGORY_STATISTICAL | **Not yet Implemented**

docs/topics/calculation-engine.md

+20-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ formula calculation capabilities. A cell can be of a value type
1010
which can be evaluated). For example, the formula `=SUM(A1:A10)`
1111
evaluates to the sum of values in A1, A2, ..., A10.
1212

13+
Calling `getValue()` on a cell that contains a formula will return the formula itself.
14+
1315
To calculate a formula, you can call the cell containing the formula’s
1416
method `getCalculatedValue()`, for example:
1517

@@ -22,7 +24,18 @@ with PhpSpreadsheet, it evaluates to the value "64":
2224

2325
![09-command-line-calculation.png](./images/09-command-line-calculation.png)
2426

25-
When writing a formula to a cell, formulae should always be set as they would appear in an English version of Microsoft Office Excel, and PhpSpreadsheet handles all formulae internally in this format. This means that the following rules hold:
27+
Calling `getCalculatedValue()` on a cell that doesn't contain a formula will simply return the value of that cell; but if the cell does contain a formula, then PhpSpreadsheet will evaluate that formula to calculate the result.
28+
29+
There are a few useful mehods to help identify whether a cell contains a formula or a simple value; and if a formula, to provide further information about it:
30+
31+
```php
32+
$spreadsheet->getActiveSheet()->getCell('E11')->isFormula();
33+
```
34+
will return a boolean true/false, telling you whether that cell contains a formula or not, so you can determine if a call to `getCalculatedVaue()` will need to perform an evaluation.
35+
36+
For more details on working with array formulas, see the [the recipes documentationn](./recipes.md/#array-formulas).
37+
38+
When writing a formula to a cell, formulas should always be set as they would appear in an English version of Microsoft Office Excel, and PhpSpreadsheet handles all formulas internally in this format. This means that the following rules hold:
2639

2740
- Decimal separator is `.` (period)
2841
- Function argument separator is `,` (comma)
@@ -91,6 +104,11 @@ formula calculation is subject to PHP's language characteristics.
91104
Not all functions are supported, for a comprehensive list, read the
92105
[function list by name](../references/function-list-by-name.md).
93106

107+
#### Array arguments for Function Calls in Formulas
108+
109+
While most of the Excel function implementations now support array arguments, there are a few that should accept arrays as arguments but don't do so.
110+
In these cases, the result may be a single value rather than an array; or it may be a `#VALUE!` error.
111+
94112
#### Operator precedence
95113

96114
In Excel `+` wins over `&`, just like `*` wins over `+` in ordinary
@@ -161,7 +179,7 @@ number of seconds from the PHP/Unix base date. The PHP/Unix base date
161179
(0) is 00:00 UST on 1st January 1970. This value can be positive or
162180
negative: so a value of -3600 would be 23:00 hrs on 31st December 1969;
163181
while a value of +3600 would be 01:00 hrs on 1st January 1970. This
164-
gives PHP a date range of between 14th December 1901 and 19th January
182+
gives 32-bit PHP a date range of between 14th December 1901 and 19th January
165183
2038.
166184

167185
#### PHP `DateTime` Objects
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

docs/topics/reading-files.md

+87-1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,87 @@ Once you have created a reader object for the workbook that you want to
168168
load, you have the opportunity to set additional options before
169169
executing the `load()` method.
170170

171+
All of these options can be set by calling the appropriate methods against the Reader (as described below), but some options (those with only two possible values) can also be set through flags, either by calling the Reader's `setFlags()` method, or passing the flags as an argument in the call to `load()`.
172+
Those options that can be set through flags are:
173+
174+
Option | Flag | Default
175+
-------------------|-------------------------------------|------------------------
176+
Empty Cells | IReader::IGNORE_EMPTY_CELLS | Load empty cells
177+
Rows with no Cells | IReader::IGNORE_ROWS_WITH_NO_CELLS | Load rows with no cells
178+
Data Only | IReader::READ_DATA_ONLY | Read data, structure and style
179+
Charts | IReader::LOAD_WITH_CHARTS | Don't read charts
180+
181+
Several flags can be combined in a single call:
182+
```php
183+
$inputFileType = 'Xlsx';
184+
$inputFileName = './sampleData/example1.xlsx';
185+
186+
/** Create a new Reader of the type defined in $inputFileType **/
187+
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
188+
/** Set additional flags before the call to load() */
189+
$reader->setFlags(IReader::IGNORE_EMPTY_CELLS | IReader::LOAD_WITH_CHARTS);
190+
$reader->load($inputFileName);
191+
```
192+
or
193+
```php
194+
$inputFileType = 'Xlsx';
195+
$inputFileName = './sampleData/example1.xlsx';
196+
197+
/** Create a new Reader of the type defined in $inputFileType **/
198+
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
199+
/** Set additional flags in the call to load() */
200+
$reader->load($inputFileName, IReader::IGNORE_EMPTY_CELLS | IReader::LOAD_WITH_CHARTS);
201+
```
202+
203+
### Ignoring Empty Cells
204+
205+
Many Excel files have empty rows or columns at the end of a worksheet, which can't easily be seen when looking at the file in Excel (Try using Ctrl-End to see the last cell in a worksheet).
206+
By default, PhpSpreadsheet will load these cells, because they are valid Excel values; but you may find that an apparently small spreadsheet requires a lot of memory for all those empty cells.
207+
If you are running into memory issues with seemingly small files, you can tell PhpSpreadsheet not to load those empty cells using the `setReadEmptyCells()` method.
208+
209+
```php
210+
$inputFileType = 'Xls';
211+
$inputFileName = './sampleData/example1.xls';
212+
213+
/** Create a new Reader of the type defined in $inputFileType **/
214+
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
215+
/** Advise the Reader that we only want to load cell's that contain actual content **/
216+
$reader->setReadEmptyCells(false);
217+
/** Load $inputFileName to a Spreadsheet Object **/
218+
$spreadsheet = $reader->load($inputFileName);
219+
```
220+
221+
Note that cells containing formulae will still be loaded, even if that formula evaluates to a NULL or an empty string.
222+
Similarly, Conditional Styling might also hide the value of a cell; but cells that contain Conditional Styling or Data Validation will always be loaded regardless of their value.
223+
224+
This option is available for the following formats:
225+
226+
Reader | Y/N |Reader | Y/N |Reader | Y/N |
227+
----------|:---:|--------|:---:|--------------|:---:|
228+
Xlsx | YES | Xls | YES | Xml | NO |
229+
Ods | NO | SYLK | NO | Gnumeric | NO |
230+
CSV | NO | HTML | NO
231+
232+
This option is also available through flags.
233+
234+
### Ignoring Rows With No Cells
235+
236+
Similar to the previous item, you can choose to ignore rows which contain no cells.
237+
This can also help with memory issues.
238+
```php
239+
$inputFileType = 'Xlsx';
240+
$inputFileName = './sampleData/example1.xlsx';
241+
242+
/** Create a new Reader of the type defined in $inputFileType **/
243+
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
244+
/** Advise the Reader that we do not want rows with no cells **/
245+
$reader->setIgnoreRowsWithNoCells(true);
246+
/** Load $inputFileName to a Spreadsheet Object **/
247+
$spreadsheet = $reader->load($inputFileName);
248+
```
249+
250+
This option is available only for Xlsx. It is also available through flags.
251+
171252
### Reading Only Data from a Spreadsheet File
172253

173254
If you're only interested in the cell values in a workbook, but don't
@@ -210,6 +291,8 @@ Xlsx | YES | Xls | YES | Xml | YES |
210291
Ods | YES | SYLK | NO | Gnumeric | YES |
211292
CSV | NO | HTML | NO
212293

294+
This option is also available through flags.
295+
213296
### Reading Only Named WorkSheets from a File
214297

215298
If your workbook contains a number of worksheets, but you are only
@@ -642,7 +725,7 @@ Xlsx | NO | Xls | NO | Xml | NO |
642725
Ods | NO | SYLK | NO | Gnumeric | NO |
643726
CSV | YES | HTML | NO
644727

645-
### A Brief Word about the Advanced Value Binder
728+
## A Brief Word about the Advanced Value Binder
646729

647730
When loading data from a file that contains no formatting information,
648731
such as a CSV file, then data is read either as strings or numbers
@@ -694,6 +777,9 @@ Xlsx | NO | Xls | NO | Xml | NO
694777
Ods | NO | SYLK | NO | Gnumeric | NO
695778
CSV | YES | HTML | YES
696779

780+
Note that you can also use the Binder to determine how PhpSpreadsheet identified datatypes for values when you set a cell value without explicitly setting a datatype.
781+
Value Binders can also be used to set formatting for a cell appropriate to the value.
782+
697783
## Error Handling
698784

699785
Of course, you should always apply some error handling to your scripts

0 commit comments

Comments
 (0)