Skip to content

Commit 0dfeea8

Browse files
committed
Binary-value options for Reader using flag settings
1 parent e35bbb9 commit 0dfeea8

File tree

4 files changed

+191
-6
lines changed

4 files changed

+191
-6
lines changed

docs/topics/reading-files.md

+68-1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,68 @@ 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+
Ignore Empty Cells | IReader::IGNORE_EMPTY_CELLS | Load empty cells
177+
Read Data Only | IReader::READ_DATA_ONLY | Read data, structure and style
178+
Include Charts | IReader::LOAD_WITH_CHARTS | Don't read charts
179+
180+
Several flags can be combined in a single call:
181+
```php
182+
$inputFileType = 'Xlsx';
183+
$inputFileName = './sampleData/example1.xlsx';
184+
185+
/** Create a new Reader of the type defined in $inputFileType **/
186+
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
187+
/** Set additional flags before the call to load() */
188+
$reader->setFlags(IReader::IGNORE_EMPTY_CELLS | IReader::LOAD_WITH_CHARTS);
189+
$reader->load($inputFileName);
190+
```
191+
or
192+
```php
193+
$inputFileType = 'Xlsx';
194+
$inputFileName = './sampleData/example1.xlsx';
195+
196+
/** Create a new Reader of the type defined in $inputFileType **/
197+
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
198+
/** Set additional flags in the call to load() */
199+
$reader->load($inputFileName, IReader::IGNORE_EMPTY_CELLS | IReader::LOAD_WITH_CHARTS);
200+
```
201+
202+
### Ignoring Empty Cells
203+
204+
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).
205+
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.
206+
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.
207+
208+
```php
209+
$inputFileType = 'Xls';
210+
$inputFileName = './sampleData/example1.xls';
211+
212+
/** Create a new Reader of the type defined in $inputFileType **/
213+
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
214+
/** Advise the Reader that we only want to load cell's that contain actual content **/
215+
$reader->setReadEmptyCells(false);
216+
/** Load $inputFileName to a Spreadsheet Object **/
217+
$spreadsheet = $reader->load($inputFileName);
218+
```
219+
220+
Note that cells containing formulae will still be loaded, even if that formula evaluates to a NULL or an empty string.
221+
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.
222+
223+
This option is available for the following formats:
224+
225+
Reader | Y/N |Reader | Y/N |Reader | Y/N |
226+
----------|:---:|--------|:---:|--------------|:---:|
227+
Xlsx | YES | Xls | YES | Xml | NO |
228+
Ods | NO | SYLK | NO | Gnumeric | NO |
229+
CSV | NO | HTML | NO
230+
231+
This option is also available through flags.
232+
171233
### Reading Only Data from a Spreadsheet File
172234

173235
If you're only interested in the cell values in a workbook, but don't
@@ -210,6 +272,8 @@ Xlsx | YES | Xls | YES | Xml | YES |
210272
Ods | YES | SYLK | NO | Gnumeric | YES |
211273
CSV | NO | HTML | NO
212274

275+
This option is also available through flags.
276+
213277
### Reading Only Named WorkSheets from a File
214278

215279
If your workbook contains a number of worksheets, but you are only
@@ -642,7 +706,7 @@ Xlsx | NO | Xls | NO | Xml | NO |
642706
Ods | NO | SYLK | NO | Gnumeric | NO |
643707
CSV | YES | HTML | NO
644708

645-
### A Brief Word about the Advanced Value Binder
709+
## A Brief Word about the Advanced Value Binder
646710

647711
When loading data from a file that contains no formatting information,
648712
such as a CSV file, then data is read either as strings or numbers
@@ -694,6 +758,9 @@ Xlsx | NO | Xls | NO | Xml | NO
694758
Ods | NO | SYLK | NO | Gnumeric | NO
695759
CSV | YES | HTML | YES
696760

761+
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.
762+
Value Binders can also be used to set formatting for a cell appropriate to the value.
763+
697764
## Error Handling
698765

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

src/PhpSpreadsheet/Reader/BaseReader.php

+14-4
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,14 @@ public function getSecurityScanner()
140140
return $this->securityScanner;
141141
}
142142

143-
protected function processFlags(int $flags): void
143+
public function setFlags(int $flags): void
144144
{
145+
if (((bool) ($flags & self::IGNORE_EMPTY_CELLS)) === true) {
146+
$this->setReadEmptyCells(false);
147+
}
148+
if (((bool) ($flags & self::READ_DATA_ONLY)) === true) {
149+
$this->setReadDataOnly(true);
150+
}
145151
if (((bool) ($flags & self::LOAD_WITH_CHARTS)) === true) {
146152
$this->setIncludeCharts(true);
147153
}
@@ -155,13 +161,17 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
155161
/**
156162
* Loads Spreadsheet from file.
157163
*
158-
* @param int $flags the optional second parameter flags may be used to identify specific elements
164+
* @param ?int $flags the optional second parameter flags may be used to identify specific elements
159165
* that should be loaded, but which won't be loaded by default, using these values:
166+
* IReader::IGNORE_EMPTY_CELLS - Don't create empty cells (those containing a null or an empty string)
167+
* IReader::READ_DATA_ONLY - Only read data from the file, not structure or styling
160168
* IReader::LOAD_WITH_CHARTS - Include any charts that are defined in the loaded file
161169
*/
162-
public function load(string $filename, int $flags = 0): Spreadsheet
170+
public function load(string $filename, ?int $flags = null): Spreadsheet
163171
{
164-
$this->processFlags($flags);
172+
if ($flags !== null) {
173+
$this->setFlags($flags);
174+
}
165175

166176
IOFactory::setLoading(true);
167177

src/PhpSpreadsheet/Reader/IReader.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
interface IReader
88
{
9-
public const LOAD_WITH_CHARTS = 1;
9+
public const IGNORE_EMPTY_CELLS = 1;
10+
public const READ_DATA_ONLY = 2;
11+
public const LOAD_WITH_CHARTS = 4;
1012

1113
/**
1214
* Can the current IReader read the file?
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Reader;
4+
5+
use PhpOffice\PhpSpreadsheet\Reader\IReader;
6+
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
7+
use PHPUnit\Framework\TestCase;
8+
9+
class ReaderFlagsTest extends TestCase
10+
{
11+
private const EMPTY_CELLS = 'Empty Cells';
12+
private const DATA_ONLY = 'Data only';
13+
private const WITH_CHARTS = 'with Charts';
14+
15+
/**
16+
* @var Xlsx
17+
*/
18+
private $reader;
19+
20+
protected function setup(): void
21+
{
22+
$this->reader = new Xlsx();
23+
}
24+
25+
/**
26+
* @dataProvider flagsProvider
27+
*/
28+
public function testFlags(int $flags, array $settings): void
29+
{
30+
$this->reader->setFlags($flags);
31+
32+
self::assertSame($settings[self::EMPTY_CELLS], $this->reader->getReadEmptyCells());
33+
self::assertSame($settings[self::DATA_ONLY], $this->reader->getReadDataOnly());
34+
self::assertSame($settings[self::WITH_CHARTS], $this->reader->getIncludeCharts());
35+
}
36+
37+
public function flagsProvider(): array
38+
{
39+
return [
40+
[
41+
0,
42+
[
43+
self::EMPTY_CELLS => true,
44+
self::DATA_ONLY => false,
45+
self::WITH_CHARTS => false,
46+
],
47+
],
48+
[
49+
IReader::IGNORE_EMPTY_CELLS,
50+
[
51+
self::EMPTY_CELLS => false,
52+
self::DATA_ONLY => false,
53+
self::WITH_CHARTS => false,
54+
],
55+
],
56+
[
57+
IReader::READ_DATA_ONLY,
58+
[
59+
self::EMPTY_CELLS => true,
60+
self::DATA_ONLY => true,
61+
self::WITH_CHARTS => false,
62+
],
63+
],
64+
[
65+
IReader::IGNORE_EMPTY_CELLS | IReader::READ_DATA_ONLY,
66+
[
67+
self::EMPTY_CELLS => false,
68+
self::DATA_ONLY => true,
69+
self::WITH_CHARTS => false,
70+
],
71+
],
72+
[
73+
IReader::LOAD_WITH_CHARTS,
74+
[
75+
self::EMPTY_CELLS => true,
76+
self::DATA_ONLY => false,
77+
self::WITH_CHARTS => true,
78+
],
79+
],
80+
[
81+
IReader::IGNORE_EMPTY_CELLS | IReader::LOAD_WITH_CHARTS,
82+
[
83+
self::EMPTY_CELLS => false,
84+
self::DATA_ONLY => false,
85+
self::WITH_CHARTS => true,
86+
],
87+
],
88+
[
89+
IReader::READ_DATA_ONLY | IReader::LOAD_WITH_CHARTS,
90+
[
91+
self::EMPTY_CELLS => true,
92+
self::DATA_ONLY => true,
93+
self::WITH_CHARTS => true,
94+
],
95+
],
96+
[
97+
IReader::IGNORE_EMPTY_CELLS | IReader::READ_DATA_ONLY | IReader::LOAD_WITH_CHARTS,
98+
[
99+
self::EMPTY_CELLS => false,
100+
self::DATA_ONLY => true,
101+
self::WITH_CHARTS => true,
102+
],
103+
],
104+
];
105+
}
106+
}

0 commit comments

Comments
 (0)