Move documentation from gh-pages branch to 'docs' folder
To prepare the migration to 3.0, we need to change the location where the documentation is generated from. Having a gh-pages branch makes it hard to synchronize the code and the docs. Having a "docs" folder in the repo itself simplifies this.
This commit is contained in:
1 parent
a420e3fffa
commit
c62177f0e4
285 files changed
+46165
No files matched your search
Executable
+245
@@ -0,0 +1,245 @@
|
||||
---
|
||||
layout: doc
|
||||
title: Documentation
|
||||
permalink: /docs/
|
||||
---
|
||||
|
||||
## Configuring for CSV
|
||||
|
||||
It is possible to configure both the CSV reader and writer to adapt them to your requirements:
|
||||
```php?start_inline=1
|
||||
use Box\Spout\Reader\ReaderFactory;
|
||||
use Box\Spout\Common\Type;
|
||||
|
||||
$reader = ReaderFactory::create(Type::CSV);
|
||||
$reader->setFieldDelimiter('|');
|
||||
$reader->setFieldEnclosure('@');
|
||||
$reader->setEndOfLineCharacter("\r");
|
||||
```
|
||||
|
||||
Additionally, if you need to read non UTF-8 files, you can specify the encoding of your file this way:
|
||||
```php?start_inline=1
|
||||
$reader->setEncoding('UTF-16LE');
|
||||
```
|
||||
|
||||
By default, the writer generates CSV files encoded in UTF-8, with a BOM.
|
||||
It is however possible to not include the BOM:
|
||||
```php?start_inline=1
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
use Box\Spout\Common\Type;
|
||||
|
||||
$writer = WriterFactory::create(Type::CSV);
|
||||
$writer->setShouldAddBOM(false);
|
||||
```
|
||||
|
||||
|
||||
## Configuring for XLSX and ODS
|
||||
|
||||
### New sheet creation
|
||||
|
||||
It is possible to change the behavior of the writers when the maximum number of rows (*1,048,576*) has been written in the current sheet. By default, a new sheet is automatically created so that writing can keep going but that may not always be preferable.
|
||||
```php?start_inline=1
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
use Box\Spout\Common\Type;
|
||||
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->setShouldCreateNewSheetsAutomatically(true); // default value
|
||||
$writer->setShouldCreateNewSheetsAutomatically(false); // will stop writing new data when limit is reached
|
||||
```
|
||||
|
||||
### Using custom temporary folder
|
||||
|
||||
Processing XLSX and ODS files requires temporary files to be created. By default, {{ site.spout_html }} will use the system default temporary folder (as returned by `sys_get_temp_dir()`). It is possible to override this by explicitly setting it on the reader or writer:
|
||||
```php?start_inline=1
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
use Box\Spout\Common\Type;
|
||||
|
||||
$writer = WriterFactory::create(Type::XLSX);
|
||||
$writer->setTempFolder($customTempFolderPath);
|
||||
```
|
||||
|
||||
### Strings storage (XLSX writer)
|
||||
|
||||
XLSX files support different ways to store the string values:
|
||||
* Shared strings are meant to optimize file size by separating strings from the sheet representation and ignoring strings duplicates (if a string is used three times, only one string will be stored)
|
||||
* Inline strings are less optimized (as duplicate strings are all stored) but is faster to process
|
||||
|
||||
In order to keep the memory usage really low, {{ site.spout_html }} does not de-duplicate strings when using shared strings. It is nevertheless possible to use this mode.
|
||||
```php?start_inline=1
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
use Box\Spout\Common\Type;
|
||||
|
||||
$writer = WriterFactory::create(Type::XLSX);
|
||||
$writer->setShouldUseInlineStrings(true); // default (and recommended) value
|
||||
$writer->setShouldUseInlineStrings(false); // will use shared strings
|
||||
```
|
||||
|
||||
> #### Note on Apple Numbers and iOS support
|
||||
>
|
||||
> Apple's products (Numbers and the iOS previewer) don't support inline strings and display empty cells instead. Therefore, if these platforms need to be supported, make sure to use shared strings!
|
||||
|
||||
### Date/Time formatting
|
||||
|
||||
When reading a spreadsheet containing dates or times, {{ site.spout_html }} returns the values by default as DateTime objects.
|
||||
It is possible to change this behavior and have a formatted date returned instead (e.g. "2016-11-29 1:22 AM"). The format of the date corresponds to what is specified in the spreadsheet.
|
||||
|
||||
```php?start_inline=1
|
||||
use Box\Spout\Reader\ReaderFactory;
|
||||
use Box\Spout\Common\Type;
|
||||
|
||||
$reader = ReaderFactory::create(Type::XLSX);
|
||||
$reader->setShouldFormatDates(false); // default value
|
||||
$reader->setShouldFormatDates(true); // will return formatted dates
|
||||
```
|
||||
|
||||
|
||||
## Styling rows
|
||||
|
||||
It is possible to apply some formatting options to a row. {{ site.spout_html }} supports fonts, background, borders as well as alignment styles.
|
||||
|
||||
```php?start_inline=1
|
||||
use Box\Spout\Common\Type;
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
use Box\Spout\Writer\Style\StyleBuilder;
|
||||
use Box\Spout\Writer\Style\Color;
|
||||
|
||||
$style = (new StyleBuilder())
|
||||
->setFontBold()
|
||||
->setFontSize(15)
|
||||
->setFontColor(Color::BLUE)
|
||||
->setShouldWrapText()
|
||||
->setBackgroundColor(Color::YELLOW)
|
||||
->build();
|
||||
|
||||
$writer = WriterFactory::create(Type::XLSX);
|
||||
$writer->openToFile($filePath);
|
||||
|
||||
$writer->addRowWithStyle($singleRow, $style); // style will only be applied to this row
|
||||
$writer->addRow($otherSingleRow); // no style will be applied
|
||||
$writer->addRowsWithStyle($multipleRows, $style); // style will be applied to all given rows
|
||||
|
||||
$writer->close();
|
||||
```
|
||||
|
||||
Adding borders to a row requires a ```Border``` object.
|
||||
|
||||
```php?start_inline=1
|
||||
use Box\Spout\Common\Type;
|
||||
use Box\Spout\Writer\Style\Border;
|
||||
use Box\Spout\Writer\Style\BorderBuilder;
|
||||
use Box\Spout\Writer\Style\Color;
|
||||
use Box\Spout\Writer\Style\StyleBuilder;
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
|
||||
$border = (new BorderBuilder())
|
||||
->setBorderBottom(Color::GREEN, Border::WIDTH_THIN, Border::STYLE_DASHED)
|
||||
->build();
|
||||
|
||||
$style = (new StyleBuilder())
|
||||
->setBorder($border)
|
||||
->build();
|
||||
|
||||
$writer = WriterFactory::create(Type::XLSX);
|
||||
$writer->openToFile($filePath);
|
||||
|
||||
$writer->addRowWithStyle(['Border Bottom Green Thin Dashed'], $style);
|
||||
|
||||
$writer->close();
|
||||
```
|
||||
|
||||
{{ site.spout_html }} will use a default style for all created rows. This style can be overridden this way:
|
||||
|
||||
```php?start_inline=1
|
||||
$defaultStyle = (new StyleBuilder())
|
||||
->setFontName('Arial')
|
||||
->setFontSize(11)
|
||||
->build();
|
||||
|
||||
$writer = WriterFactory::create(Type::XLSX);
|
||||
$writer->setDefaultRowStyle($defaultStyle)
|
||||
->openToFile($filePath);
|
||||
```
|
||||
|
||||
Unfortunately, {{ site.spout_html }} does not support all the possible formatting options yet. But you can find the most important ones:
|
||||
|
||||
| Category | Property | API
|
||||
|:----------|:--------------|:--------------------------------------
|
||||
| Font | Bold | `StyleBuilder::setFontBold()`
|
||||
| | Italic | `StyleBuilder::setFontItalic()`
|
||||
| | Underline | `StyleBuilder::setFontUnderline()`
|
||||
| | Strikethrough | `StyleBuilder::setFontStrikethrough()`
|
||||
| | Font name | `StyleBuilder::setFontName('Arial')`
|
||||
| | Font size | `StyleBuilder::setFontSize(14)`
|
||||
| | Font color | `StyleBuilder::setFontColor(Color::BLUE)`<br>`StyleBuilder::setFontColor(Color::rgb(0, 128, 255))`
|
||||
| Alignment | Wrap text | `StyleBuilder::setShouldWrapText(true|false)`
|
||||
|
||||
|
||||
## Playing with sheets
|
||||
|
||||
When creating a XLSX or ODS file, it is possible to control which sheet the data will be written into. At any time, you can retrieve or set the current sheet:
|
||||
```php?start_inline=1
|
||||
$firstSheet = $writer->getCurrentSheet();
|
||||
$writer->addRow($rowForSheet1); // writes the row to the first sheet
|
||||
|
||||
$newSheet = $writer->addNewSheetAndMakeItCurrent();
|
||||
$writer->addRow($rowForSheet2); // writes the row to the new sheet
|
||||
|
||||
$writer->setCurrentSheet($firstSheet);
|
||||
$writer->addRow($anotherRowForSheet1); // append the row to the first sheet
|
||||
```
|
||||
|
||||
It is also possible to retrieve all the sheets currently created:
|
||||
```php?start_inline=1
|
||||
$sheets = $writer->getSheets();
|
||||
```
|
||||
|
||||
If you rely on the sheet's name in your application, you can access it and customize it this way:
|
||||
```php?start_inline=1
|
||||
// Accessing the sheet name when reading
|
||||
foreach ($reader->getSheetIterator() as $sheet) {
|
||||
$sheetName = $sheet->getName();
|
||||
}
|
||||
|
||||
// Accessing the sheet name when writing
|
||||
$sheet = $writer->getCurrentSheet();
|
||||
$sheetName = $sheet->getName();
|
||||
|
||||
// Customizing the sheet name when writing
|
||||
$sheet = $writer->getCurrentSheet();
|
||||
$sheet->setName('My custom name');
|
||||
```
|
||||
|
||||
> Please note that Excel has some restrictions on the sheet's name:
|
||||
> * it must not be blank
|
||||
> * it must not exceed 31 characters
|
||||
> * it must not contain these characters: \ / ? * : [ or ]
|
||||
> * it must not start or end with a single quote
|
||||
> * it must be unique
|
||||
>
|
||||
> Handling these restrictions is the developer's responsibility. {{ site.spout_html }} does not try to automatically change the sheet's name, as one may rely on this name to be exactly what was passed in.
|
||||
|
||||
Finally, it is possible to know which sheet was active when the spreadsheet was last saved. This can be useful if you are only interested in processing the one sheet that was last focused.
|
||||
```php?start_inline=1
|
||||
foreach ($reader->getSheetIterator() as $sheet) {
|
||||
// only process data for the active sheet
|
||||
if ($sheet->isActive()) {
|
||||
// do something...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Fluent interface
|
||||
|
||||
Because fluent interfaces are great, you can use them with {{ site.spout_html }}:
|
||||
```php?start_inline=1
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
use Box\Spout\Common\Type;
|
||||
|
||||
$writer = WriterFactory::create(Type::XLSX);
|
||||
$writer->setTempFolder($customTempFolderPath)
|
||||
->setShouldUseInlineStrings(true)
|
||||
->openToFile($filePath)
|
||||
->addRow($headerRow)
|
||||
->addRows($dataRows)
|
||||
->close();
|
||||
```
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
layout: page
|
||||
title: Frequently Asked Questions
|
||||
permalink: /faq/
|
||||
---
|
||||
|
||||
### How can Spout handle such large data sets and still use less than 3MB of memory?
|
||||
|
||||
When writing data, Spout is streaming the data to files, one or few lines at a time. That means that it only keeps in memory the few rows that it needs to write. Once written, the memory is freed.
|
||||
|
||||
Same goes with reading. Only one row at a time is stored in memory. A special technique is used to handle shared strings in XLSX, storing them - if needed - into several small temporary files that allows fast access.
|
||||
|
||||
### How long does it take to generate a file with X rows?
|
||||
|
||||
Here are a few numbers regarding the performance of Spout:
|
||||
|
||||
| Type | Action | 2,000 rows (6,000 cells) | 200,000 rows (600,000 cells) | 2,000,000 rows (6,000,000 cells) |
|
||||
|------|-------------------------------|--------------------------|------------------------------|----------------------------------|
|
||||
| CSV | Read | < 1 second | 4 seconds | 2-3 minutes |
|
||||
| | Write | < 1 second | 2 seconds | 2-3 minutes |
|
||||
| XLSX | Read<br>*inline strings* | < 1 second | 35-40 seconds | 18-20 minutes |
|
||||
| | Read<br>*shared strings* | 1 second | 1-2 minutes | 35-40 minutes |
|
||||
| | Write | 1 second | 20-25 seconds | 8-10 minutes |
|
||||
| ODS | Read | 1 second | 1-2 minutes | 5-6 minutes |
|
||||
| | Write | < 1 second | 35-40 seconds | 5-6 minutes |
|
||||
|
||||
### Does Spout support charts or formulas?
|
||||
|
||||
No. This is a compromise to keep memory usage low. Charts and formulas requires data to be kept in memory in order to be used.
|
||||
So the larger the file would be, the more memory would be consumed, preventing your code to scale well.
|
||||
Executable
+96
@@ -0,0 +1,96 @@
|
||||
---
|
||||
layout: doc
|
||||
title: Getting Started
|
||||
permalink: /getting-started/
|
||||
---
|
||||
|
||||
This guide will help you install {{ site.spout_html }} and teach you how to use it.
|
||||
|
||||
## Requirements
|
||||
|
||||
* PHP version 5.4.0 or higher
|
||||
* PHP extension `php_zip` enabled
|
||||
* PHP extension `php_xmlreader` enabled
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
### Composer (recommended)
|
||||
|
||||
{{ site.spout_html }} can be installed directly from [Composer](https://getcomposer.org/).
|
||||
|
||||
Run the following command:
|
||||
```powershell
|
||||
$ composer require box/spout
|
||||
```
|
||||
|
||||
### Manual installation
|
||||
|
||||
If you can't use Composer, no worries! You can still install {{ site.spout_html }} manually.
|
||||
|
||||
> Before starting, make sure your system meets the [requirements](#requirements).
|
||||
|
||||
1. Download the source code from the [Releases page](https://github.com/box/spout/releases)
|
||||
2. Extract the downloaded content into your project.
|
||||
3. Add this code to the top controller (e.g. index.php) or wherever it may be more appropriate:
|
||||
|
||||
```php?start_inline=1
|
||||
// don't forget to change the path!
|
||||
require_once '[PATH/TO]/src/Spout/Autoloader/autoload.php';
|
||||
```
|
||||
|
||||
|
||||
## Basic usage
|
||||
|
||||
### Reader
|
||||
|
||||
Regardless of the file type, the interface to read a file is always the same:
|
||||
|
||||
```php?start_inline=1
|
||||
use Box\Spout\Reader\ReaderFactory;
|
||||
use Box\Spout\Common\Type;
|
||||
|
||||
$reader = ReaderFactory::create(Type::XLSX); // for XLSX files
|
||||
//$reader = ReaderFactory::create(Type::CSV); // for CSV files
|
||||
//$reader = ReaderFactory::create(Type::ODS); // for ODS files
|
||||
|
||||
$reader->open($filePath);
|
||||
|
||||
foreach ($reader->getSheetIterator() as $sheet) {
|
||||
foreach ($sheet->getRowIterator() as $row) {
|
||||
// do stuff with the row
|
||||
}
|
||||
}
|
||||
|
||||
$reader->close();
|
||||
```
|
||||
|
||||
If there are multiple sheets in the file, the reader will read all of them sequentially.
|
||||
|
||||
### Writer
|
||||
|
||||
As with the reader, there is one common interface to write data to a file:
|
||||
|
||||
```php?start_inline=1
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
use Box\Spout\Common\Type;
|
||||
|
||||
$writer = WriterFactory::create(Type::XLSX); // for XLSX files
|
||||
//$writer = WriterFactory::create(Type::CSV); // for CSV files
|
||||
//$writer = WriterFactory::create(Type::ODS); // for ODS files
|
||||
|
||||
$writer->openToFile($filePath); // write data to a file or to a PHP stream
|
||||
//$writer->openToBrowser($fileName); // stream data directly to the browser
|
||||
|
||||
$writer->addRow($singleRow); // add a row at a time
|
||||
$writer->addRows($multipleRows); // add multiple rows at a time
|
||||
|
||||
$writer->close();
|
||||
```
|
||||
|
||||
For XLSX and ODS files, the number of rows per sheet is limited to *1,048,576*. By default, once this limit is reached, the writer will automatically create a new sheet and continue writing data into it.
|
||||
|
||||
|
||||
## Advanced usage
|
||||
|
||||
You can do a lot more with {{ site.spout_html }}! Check out the [full documentation]({{ site.github.url }}/docs/) to learn about all the features.
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
layout: page
|
||||
title: Guides
|
||||
permalink: /guides/
|
||||
---
|
||||
|
||||
These guides focus on common and more advanced usages of {{ site.spout_html }}.<br>
|
||||
If you are just starting with {{ site.spout_html }}, check out the [Getting Started page]({{ site.github.url }}/getting-started/) and the [Documentation]({{ site.github.url }}/docs/) first.
|
||||
|
||||
{% assign pages=site.pages | sort: 'path' %}
|
||||
<ul>
|
||||
{% for page in pages %}
|
||||
{% if page.title and page.category contains 'guide' %}
|
||||
<li>
|
||||
<a class="page-link" href="{{ page.url | prepend: site.github.url }}">{{ page.title }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,61 @@
|
||||
---
|
||||
layout: page
|
||||
title: "Add data to an existing spreadsheet"
|
||||
category: guide
|
||||
permalink: /guides/add-data-to-existing-spreadsheet/
|
||||
---
|
||||
|
||||
A common use case when using spreadsheets is to add data to an existing spreadsheet. For instance, let's assume you built a spreadsheet containing the last orders on your favorite website and want to update it as you make a new order.
|
||||
|
||||
We'll start with a file called "orders.xlsx" and add a new row, containing the last order's info, at the end.
|
||||
|
||||
In order to avoid memory issues when dealing with large spreadsheets, {{ site.spout_html }} does not hold the whole representation of the spreadsheet in memory. So to alter an existing spreadsheet, we'll have to create a new one that is similar to the existing one and add the new data in the new one.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Box\Spout\Reader\ReaderFactory;
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
use Box\Spout\Common\Type;
|
||||
|
||||
$existingFilePath = 'path/to/orders.xlsx';
|
||||
$newFilePath = 'path/to/new-orders.xlsx';
|
||||
|
||||
// we need a reader to read the existing file...
|
||||
$reader = ReaderFactory::create(Type::XLSX);
|
||||
$reader->open($existingFilePath);
|
||||
$reader->setShouldFormatDates(true); // this is to be able to copy dates
|
||||
|
||||
// ... and a writer to create the new file
|
||||
$writer = WriterFactory::create(Type::XLSX);
|
||||
$writer->openToFile($newFilePath);
|
||||
|
||||
// let's read the entire spreadsheet...
|
||||
foreach ($reader->getSheetIterator() as $sheetIndex => $sheet) {
|
||||
// Add sheets in the new file, as we read new sheets in the existing one
|
||||
if ($sheetIndex !== 1) {
|
||||
$writer->addNewSheetAndMakeItCurrent();
|
||||
}
|
||||
|
||||
foreach ($sheet->getRowIterator() as $row) {
|
||||
// ... and copy each row into the new spreadsheet
|
||||
$writer->addRow($row);
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, the new spreadsheet contains the same data as the existing one.
|
||||
// So let's add the new data:
|
||||
$writer->addRow(['2015-12-25', 'Christmas gift', 29, 'USD']);
|
||||
|
||||
$reader->close();
|
||||
$writer->close();
|
||||
```
|
||||
|
||||
Optionally, if you rely on the file name or want to keep only one file, simple remove the old file and rename the new one:
|
||||
|
||||
```php?start_inline=1
|
||||
unlink($existingFilePath);
|
||||
rename($newFilePath, $existingFilePath);
|
||||
```
|
||||
|
||||
That's it! The created file now contains the updated data and is ready to be used.
|
||||
@@ -0,0 +1,88 @@
|
||||
---
|
||||
layout: page
|
||||
title: "Edit an existing spreadsheet"
|
||||
category: guide
|
||||
permalink: /guides/edit-existing-spreadsheet/
|
||||
---
|
||||
|
||||
Editing an existing spreadsheet is a pretty common task that {{ site.spout_html }} is totally capable of doing.
|
||||
|
||||
With {{ site.spout_html }}, it is not possible to do things like `deleteRow(3)` or `insertRowAfter(5, $newRow)`. This is because {{ site.spout_html }} does not keep an in-memory representation of the entire spreadsheet, to avoid consuming all the memory available with large spreadsheets. This means, {{ site.spout_html }} does not know how to jump to the 3rd row directly and has especially no way of moving backwards (changing row 3 after having changed row 5). So let's see how this can be done, in a scalable way.
|
||||
|
||||
For this example, let's assume we have an existing ODS spreadsheet called "my-music.ods" that looks like this:
|
||||
|
||||
| Song title | Artist | Album | Year |
|
||||
| ---------------- | --------------- | --------------- | ---- |
|
||||
| Yesterday | The Beatles | The White Album | 1968 |
|
||||
| Yellow Submarine | The Beatles | Unknown | 1968 |
|
||||
| Space Oddity | David Bowie | David Bowie | 1969 |
|
||||
| Thriller | Michael Jackson | Thriller | 1982 |
|
||||
| No Woman No Cry | Bob Marley | Legend | 1984 |
|
||||
| Buffalo Soldier | Bob Marley | Legend | 1984 |
|
||||
|
||||
> Note that the album for "Yellow Submarine" is "Unknown" and that the songs are ordered by year (most recent last).
|
||||
|
||||
We'd like to update the missing album for "Yellow Submarine", remove the Bob Marley's songs and add a new song: "Hotel California" from "The Eagles", released in 1976. Here is how this can be done:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Box\Spout\Reader\ReaderFactory;
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
use Box\Spout\Common\Type;
|
||||
|
||||
$existingFilePath = '/path/to/my-music.ods';
|
||||
$newFilePath = '/path/to/my-new-music.ods';
|
||||
|
||||
// we need a reader to read the existing file...
|
||||
$reader = ReaderFactory::create(Type::ODS);
|
||||
$reader->open($existingFilePath);
|
||||
$reader->setShouldFormatDates(true); // this is to be able to copy dates
|
||||
|
||||
// ... and a writer to create the new file
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->openToFile($newFilePath);
|
||||
|
||||
// let's read the entire spreadsheet
|
||||
foreach ($reader->getSheetIterator() as $sheetIndex => $sheet) {
|
||||
// Add sheets in the new file, as you read new sheets in the existing one
|
||||
if ($sheetIndex !== 1) {
|
||||
$writer->addNewSheetAndMakeItCurrent();
|
||||
}
|
||||
|
||||
foreach ($sheet->getRowIterator() as $rowIndex => $row) {
|
||||
$songTitle = $row[0];
|
||||
$artist = $row[1];
|
||||
|
||||
// Change the album name for "Yellow Submarine"
|
||||
if ($songTitle === 'Yellow Submarine') {
|
||||
$row[2] = 'The White Album';
|
||||
}
|
||||
|
||||
// skip Bob Marley's songs
|
||||
if ($artist === 'Bob Marley') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// write the edited row to the new file
|
||||
$writer->addRow($row);
|
||||
|
||||
// insert new song at the right position, between the 3rd and 4th rows
|
||||
if ($rowIndex === 3) {
|
||||
$writer->addRow(['Hotel California', 'The Eagles', 'Hotel California', 1976]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$reader->close();
|
||||
$writer->close();
|
||||
```
|
||||
|
||||
Optionally, if you rely on the file name or want to keep only one file, simple remove the old file and rename the new one:
|
||||
|
||||
```php?start_inline=1
|
||||
unlink($existingFilePath);
|
||||
rename($newFilePath, $existingFilePath);
|
||||
```
|
||||
|
||||
That's it! The created file now contains the updated data and is ready to be used.
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
layout: page
|
||||
title: "Read data from a specific sheet only"
|
||||
category: guide
|
||||
permalink: /guides/read-data-from-specific-sheet/
|
||||
---
|
||||
|
||||
Even though a spreadsheet contains multiple sheets, you may be interested in reading only one of them and skip the other ones. Here is how you can do it with Spout:
|
||||
|
||||
* If you know the name of the sheet
|
||||
|
||||
```php?start_inline=1
|
||||
$reader = ReaderFactory::create(Type:XLSX);
|
||||
$reader->open($filePath);
|
||||
|
||||
foreach ($reader->getSheetIterator() as $sheet) {
|
||||
// only read data from "summary" sheet
|
||||
if ($sheet->getName() === 'summary') {
|
||||
foreach ($sheet->getRowIterator() as $row) {
|
||||
// do something with the row
|
||||
}
|
||||
break; // no need to read more sheets
|
||||
}
|
||||
}
|
||||
|
||||
$reader->close();
|
||||
```
|
||||
|
||||
* If you know the position of the sheet
|
||||
|
||||
```php?start_inline=1
|
||||
$reader = ReaderFactory::create(Type:XLSX);
|
||||
$reader->open($filePath);
|
||||
|
||||
foreach ($reader->getSheetIterator() as $sheet) {
|
||||
// only read data from 3rd sheet
|
||||
if ($sheet->getIndex() === 2) { // index is 0-based
|
||||
foreach ($sheet->getRowIterator() as $row) {
|
||||
// do something with the row
|
||||
}
|
||||
break; // no need to read more sheets
|
||||
}
|
||||
}
|
||||
|
||||
$reader->close();
|
||||
```
|
||||
@@ -0,0 +1,110 @@
|
||||
---
|
||||
layout: page
|
||||
title: "[Symfony] Stream content of a large spreadsheet"
|
||||
category: guide
|
||||
permalink: /guides/symfony-stream-content-large-spreadsheet/
|
||||
---
|
||||
|
||||
> This tutorial is for the PHP framework [Symfony](http://symfony.com/).
|
||||
|
||||
The main benefit of streaming content is that this content can be rendered as soon as it is available. No matter how big the content is, the browser will be able to start rendering it as soon as the first byte is sent.
|
||||
|
||||
Reading a static spreadsheet to display its content to a user is a great use case for streaming. The spreadsheet can contain from a few rows to thousands of them and we don't want to wait until the whole file has been read (which can take a long time) before showing something to the user. Let's see how [Symfony's StreamedResponse](http://symfony.com/doc/current/components/http_foundation/introduction.html#streaming-a-response) let us easily stream the content of the spreadsheet.
|
||||
|
||||
A regular controller usually builds the content to be displayed and encapsulate it into a `Response` object. Everything happens synchronously. Such a controller may look like this:
|
||||
|
||||
```php?start_inline=1
|
||||
class MyRegularController extends Controller
|
||||
{
|
||||
/**
|
||||
* @Route("/spreadsheet/read")
|
||||
*/
|
||||
public function readAction()
|
||||
{
|
||||
$filePath = '/path/to/static/file.xlsx';
|
||||
|
||||
// The content to be displayed has to be built entirely
|
||||
// before it can be sent to the browser.
|
||||
$content = '';
|
||||
|
||||
$reader = ReaderFactory::create(Type::XLSX);
|
||||
$reader->open($filePath);
|
||||
|
||||
foreach ($reader->getSheetIterator() as $sheet) {
|
||||
$content .= '<table>';
|
||||
foreach ($sheet->getRowIterator() as $row) {
|
||||
$content .= '<tr>';
|
||||
$content .= implode(array_map(function($cell) {
|
||||
return '<td>' . $cell . '</td>';
|
||||
}, $row));
|
||||
$content .= '</tr>';
|
||||
}
|
||||
$content .= '</table><br>';
|
||||
}
|
||||
|
||||
$reader->close();
|
||||
|
||||
// The response is sent to the browser
|
||||
// once the entire file has been read.
|
||||
$response = new Response($content);
|
||||
$response->headers->set('Content-Type', 'text/html');
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Converting a regular controller to return a `StreamedResponse` is super easy! This is what it looks like after conversion:
|
||||
|
||||
```php?start_inline=1
|
||||
class MyStreamController extends Controller
|
||||
{
|
||||
// See below how it is used.
|
||||
const FLUSH_THRESHOLD = 100;
|
||||
|
||||
/**
|
||||
* @Route("/spreadsheet/stream")
|
||||
*/
|
||||
public function readAction()
|
||||
{
|
||||
$filePath = '/path/to/static/file.xlsx';
|
||||
|
||||
// We'll now return a StreamedResponse.
|
||||
$response = new StreamedResponse();
|
||||
$response->headers->set('Content-Type', 'text/html');
|
||||
|
||||
// Instead of a string, the streamed response will execute
|
||||
// a callback function to retrieve data chunks.
|
||||
$response->setCallback(function() use ($filePath) {
|
||||
// Same code goes inside the callback.
|
||||
$reader = ReaderFactory::create(Type::XLSX);
|
||||
$reader->open($filePath);
|
||||
|
||||
$i = 0;
|
||||
foreach ($reader->getSheetIterator() as $sheet) {
|
||||
// The main difference with the regular response is
|
||||
// that the content is now echo'ed, not appended.
|
||||
echo '<table>';
|
||||
foreach ($sheet->getRowIterator() as $row) {
|
||||
echo '<tr>';
|
||||
echo implode(array_map(function($cell) {
|
||||
return '<td>' . $cell . '</td>';
|
||||
}, $row));
|
||||
echo '</tr>';
|
||||
|
||||
$i++;
|
||||
// Flushing the buffer every N rows to stream echo'ed content.
|
||||
if ($i % FLUSH_THRESHOLD === 0) {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
echo '</table><br>';
|
||||
}
|
||||
|
||||
$reader->close();
|
||||
});
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
layout: default
|
||||
banner: true
|
||||
title: Spout - Read and write spreadsheets, quickly and at scale
|
||||
permalink: /
|
||||
---
|
||||
|
||||
{% include section-supported-spreadsheet-types.html %}
|
||||
{% include section-fast-and-scalable.html %}
|
||||
{% include section-why-use-spout.html %}
|
||||
Reference in new issue
Block a user