Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d617a50b85 | ||
|
|
92981fa80b | ||
|
|
766c733466 | ||
|
|
46cae76546 | ||
|
|
03be58b84d | ||
|
|
b21bb86682 | ||
|
|
8a45cec220 | ||
|
|
04d41d7c9f |
No files matched your search
@@ -1,11 +1,13 @@
|
|||||||
# Spout
|
# Spout
|
||||||
|
|
||||||
|
[](https://packagist.org/packages/box/spout)
|
||||||
|
[](http://opensource.box.com/badges)
|
||||||
|
[](http://travis-ci.org/box/spout)
|
||||||
|
[](https://packagist.org/packages/box/spout) [](https://packagist.org/packages/box/spout)
|
||||||
|
|
||||||
Spout is a PHP library to read and write CSV and XLSX files, in a fast and scalable way.
|
Spout is a PHP library to read and write CSV and XLSX files, in a fast and scalable way.
|
||||||
Contrary to other file readers or writers, it is capable of processing very large files while keeping the memory usage really low (less than 10MB).
|
Contrary to other file readers or writers, it is capable of processing very large files while keeping the memory usage really low (less than 10MB).
|
||||||
|
|
||||||
[](http://travis-ci.org/box/spout)
|
|
||||||
[](http://opensource.box.com/badges)
|
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -248,6 +250,11 @@ Here are a few numbers regarding the performance of Spout:
|
|||||||
| Read XLSX (using shared strings) | 1 second | 1-2 minutes | 35-40 minutes |
|
| Read XLSX (using shared strings) | 1 second | 1-2 minutes | 35-40 minutes |
|
||||||
| Write XLSX | 1 second | 20-25 seconds | 8-10 minutes |
|
| Write XLSX | 1 second | 20-25 seconds | 8-10 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.
|
||||||
|
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
"name": "box/spout",
|
"name": "box/spout",
|
||||||
"description": "PHP Library to read and write CSV and XLSX files, in a fast and scalable way",
|
"description": "PHP Library to read and write CSV and XLSX files, in a fast and scalable way",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"version": "1.0.8",
|
"version": "1.0.9",
|
||||||
"keywords": ["php","read","write","csv","xlsx","excel","spreadsheet","scale","memory","stream","ooxml"],
|
"keywords": ["php","read","write","csv","xlsx","excel","spreadsheet","scale","memory","stream","ooxml"],
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"homepage": "https://www.github.com/box/spout",
|
"homepage": "https://www.github.com/box/spout",
|
||||||
|
|||||||
@@ -71,6 +71,24 @@ class SharedStringsHelper
|
|||||||
$this->tempFolder = $this->fileSystemHelper->createFolder($rootTempFolder, uniqid('sharedstrings'));
|
$this->tempFolder = $this->fileSystemHelper->createFolder($rootTempFolder, uniqid('sharedstrings'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the XLSX file contains a shared strings XML file
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasSharedStrings()
|
||||||
|
{
|
||||||
|
$hasSharedStrings = false;
|
||||||
|
$zip = new \ZipArchive();
|
||||||
|
|
||||||
|
if ($zip->open($this->filePath) === true) {
|
||||||
|
$hasSharedStrings = ($zip->locateName(self::SHARED_STRINGS_XML_FILE_PATH) !== false);
|
||||||
|
$zip->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hasSharedStrings;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an in-memory array containing all the shared strings of the worksheet.
|
* Builds an in-memory array containing all the shared strings of the worksheet.
|
||||||
* All the strings are stored in a XML file, located at 'xl/sharedStrings.xml'.
|
* All the strings are stored in a XML file, located at 'xl/sharedStrings.xml'.
|
||||||
|
|||||||
+22
-19
@@ -72,8 +72,12 @@ class XLSX extends AbstractReader
|
|||||||
$this->zip = new \ZipArchive();
|
$this->zip = new \ZipArchive();
|
||||||
|
|
||||||
if ($this->zip->open($filePath) === true) {
|
if ($this->zip->open($filePath) === true) {
|
||||||
// Extracts all the strings from the worksheets for easy access in the future
|
$this->sharedStringsHelper = new SharedStringsHelper($filePath, $this->tempFolder);
|
||||||
$this->extractSharedStrings($filePath);
|
|
||||||
|
if ($this->sharedStringsHelper->hasSharedStrings()) {
|
||||||
|
// Extracts all the strings from the worksheets for easy access in the future
|
||||||
|
$this->sharedStringsHelper->extractSharedStrings();
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch all available worksheets
|
// Fetch all available worksheets
|
||||||
$this->worksheetHelper = new WorksheetHelper($filePath, $this->globalFunctionsHelper);
|
$this->worksheetHelper = new WorksheetHelper($filePath, $this->globalFunctionsHelper);
|
||||||
@@ -87,19 +91,6 @@ class XLSX extends AbstractReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds an in-memory array containing all the shared strings of the worksheets.
|
|
||||||
*
|
|
||||||
* @param string $filePath Path of the XLSX file to be read
|
|
||||||
* @return void
|
|
||||||
* @throws \Box\Spout\Common\Exception\IOException If sharedStrings XML file can't be read
|
|
||||||
*/
|
|
||||||
protected function extractSharedStrings($filePath)
|
|
||||||
{
|
|
||||||
$this->sharedStringsHelper = new SharedStringsHelper($filePath, $this->tempFolder);
|
|
||||||
$this->sharedStringsHelper->extractSharedStrings();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether another worksheet exists after the current worksheet.
|
* Returns whether another worksheet exists after the current worksheet.
|
||||||
*
|
*
|
||||||
@@ -215,13 +206,25 @@ class XLSX extends AbstractReader
|
|||||||
$currentColumnIndex = CellHelper::getColumnIndexFromCellIndex($currentCellIndex);
|
$currentColumnIndex = CellHelper::getColumnIndexFromCellIndex($currentCellIndex);
|
||||||
$node = $this->xmlReader->expand();
|
$node = $this->xmlReader->expand();
|
||||||
|
|
||||||
|
$hasInlineString = ($this->xmlReader->getAttribute('t') === 'inlineStr');
|
||||||
$hasSharedString = ($this->xmlReader->getAttribute('t') === 's');
|
$hasSharedString = ($this->xmlReader->getAttribute('t') === 's');
|
||||||
if ($hasSharedString) {
|
|
||||||
$sharedStringIndex = intval($node->nodeValue);
|
if ($hasInlineString) {
|
||||||
|
// inline strings are formatted this way:
|
||||||
|
// <c r="A1" t="inlineStr"><is><t>[INLINE_STRING]</t></is></c>
|
||||||
|
$tNode = $node->getElementsByTagName('t')->item(0);
|
||||||
|
$rowData[$currentColumnIndex] = trim($tNode->nodeValue);
|
||||||
|
} else if ($hasSharedString) {
|
||||||
|
// shared strings are formatted this way:
|
||||||
|
// <c r="A1" t="s"><v>[SHARED_STRING_INDEX]</v></c>
|
||||||
|
$vNode = $node->getElementsByTagName('v')->item(0);
|
||||||
|
$sharedStringIndex = intval($vNode->nodeValue);
|
||||||
$rowData[$currentColumnIndex] = $this->sharedStringsHelper->getStringAtIndex($sharedStringIndex);
|
$rowData[$currentColumnIndex] = $this->sharedStringsHelper->getStringAtIndex($sharedStringIndex);
|
||||||
} else {
|
} else {
|
||||||
// for inline strings or numbers, just get the value
|
// other values are formatted this way:
|
||||||
$rowData[$currentColumnIndex] = trim($node->nodeValue);
|
// <c r="A1"><v>[VALUE]</v></c>
|
||||||
|
$vNode = $node->getElementsByTagName('v')->item(0);
|
||||||
|
$rowData[$currentColumnIndex] = intval($vNode->nodeValue);
|
||||||
}
|
}
|
||||||
} else if ($this->xmlReader->nodeType == \XMLReader::END_ELEMENT && $this->xmlReader->name === 'row') {
|
} else if ($this->xmlReader->nodeType == \XMLReader::END_ELEMENT && $this->xmlReader->name === 'row') {
|
||||||
// End of the row description
|
// End of the row description
|
||||||
|
|||||||
@@ -100,6 +100,20 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testReadShouldSupportFilesWithoutSharedStringsFile()
|
||||||
|
{
|
||||||
|
$allRows = $this->getAllRowsForFile('sheet_with_no_shared_strings_file.xlsx');
|
||||||
|
|
||||||
|
$expectedRows = [
|
||||||
|
[10, 11],
|
||||||
|
[20, 21],
|
||||||
|
];
|
||||||
|
$this->assertEquals($expectedRows, $allRows);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@@ -231,6 +245,21 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals([], $allRows, 'Sheet with no cells should be correctly processed.');
|
$this->assertEquals([], $allRows, 'Sheet with no cells should be correctly processed.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testReadShouldSkipFormulas()
|
||||||
|
{
|
||||||
|
$allRows = $this->getAllRowsForFile('sheet_with_formulas.xlsx');
|
||||||
|
|
||||||
|
$expectedRows = [
|
||||||
|
['val1', 'val2', 'total1', 'total2'],
|
||||||
|
[10, 20, 30, 21],
|
||||||
|
[11, 21, 32, 41],
|
||||||
|
];
|
||||||
|
$this->assertEquals($expectedRows, $allRows);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $fileName
|
* @param string $fileName
|
||||||
* @return array All the read rows the given file
|
* @return array All the read rows the given file
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Reference in new issue
Block a user