Merge branch 'master' into feature/num_format
This commit is contained in:
commit
5388764d52
@ -8,7 +8,7 @@
|
||||
[](https://packagist.org/packages/box/spout)
|
||||
|
||||
Spout is a PHP library to read and write spreadsheet files (CSV, XLSX and ODS), 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 3MB).
|
||||
|
||||
Join the community and come discuss about Spout: [](https://gitter.im/box/spout?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
@ -301,7 +301,7 @@ For information, the performance tests take about 30 minutes to run (processing
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
#### How can Spout handle such large data sets and still use less than 10MB of memory?
|
||||
#### 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.
|
||||
|
||||
|
@ -100,11 +100,16 @@ class SharedStringsHelper
|
||||
// removes nodes that should not be read, like the pronunciation of the Kanji characters
|
||||
$cleanNode = $this->removeSuperfluousTextNodes($node);
|
||||
|
||||
// find all text nodes 't'; there can be multiple if the cell contains formatting
|
||||
// find all text nodes "t"; there can be multiple if the cell contains formatting
|
||||
$textNodes = $cleanNode->xpath('//ns:t');
|
||||
|
||||
$textValue = '';
|
||||
foreach ($textNodes as $textNode) {
|
||||
foreach ($textNodes as $nodeIndex => $textNode) {
|
||||
if ($nodeIndex !== 0) {
|
||||
// add a space between each "t" node
|
||||
$textValue .= ' ';
|
||||
}
|
||||
|
||||
if ($this->shouldPreserveWhitespace($textNode)) {
|
||||
$textValue .= $textNode->__toString();
|
||||
} else {
|
||||
@ -200,6 +205,8 @@ class SharedStringsHelper
|
||||
{
|
||||
$tagsToRemove = [
|
||||
'rPh', // Pronunciation of the text
|
||||
'pPr', // Paragraph Properties / Previous Paragraph Properties
|
||||
'rPr', // Run Properties for the Paragraph Mark / Previous Run Properties for the Paragraph Mark
|
||||
];
|
||||
|
||||
foreach ($tagsToRemove as $tagToRemove) {
|
||||
|
@ -134,6 +134,10 @@ class Worksheet implements WorksheetInterface
|
||||
*/
|
||||
public function addRow($dataRow, $style)
|
||||
{
|
||||
// $dataRow can be an associative array. We need to transform
|
||||
// it into a regular array, as we'll use the numeric indexes.
|
||||
$dataRowWithNumericIndexes = array_values($dataRow);
|
||||
|
||||
$styleIndex = ($style->getId() + 1); // 1-based
|
||||
$cellsCount = count($dataRow);
|
||||
$this->maxNumColumns = max($this->maxNumColumns, $cellsCount);
|
||||
@ -144,10 +148,12 @@ class Worksheet implements WorksheetInterface
|
||||
$nextCellIndex = 1;
|
||||
|
||||
for ($i = 0; $i < $cellsCount; $i++) {
|
||||
$currentCellValue = $dataRow[$currentCellIndex];
|
||||
$currentCellValue = $dataRowWithNumericIndexes[$currentCellIndex];
|
||||
|
||||
// Using isset here because it is way faster than array_key_exists...
|
||||
if (!isset($dataRow[$nextCellIndex]) || $currentCellValue !== $dataRow[$nextCellIndex]) {
|
||||
if (!isset($dataRowWithNumericIndexes[$nextCellIndex]) ||
|
||||
$currentCellValue !== $dataRowWithNumericIndexes[$nextCellIndex]) {
|
||||
|
||||
$numTimesValueRepeated = ($nextCellIndex - $currentCellIndex);
|
||||
$data .= $this->getCellContent($currentCellValue, $styleIndex, $numTimesValueRepeated);
|
||||
|
||||
|
@ -82,6 +82,22 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
|
||||
$sharedStringsHelper->cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testGetStringAtIndexShouldWorkWithStringsContainingTextAndHyperlinkInSameCell()
|
||||
{
|
||||
$resourcePath = $this->getResourcePath('one_sheet_with_shared_strings_containing_text_and_hyperlink_in_same_cell.xlsx');
|
||||
$sharedStringsHelper = new SharedStringsHelper($resourcePath);
|
||||
|
||||
$sharedStringsHelper->extractSharedStrings();
|
||||
|
||||
$sharedString = $sharedStringsHelper->getStringAtIndex(0);
|
||||
$this->assertEquals('go to https://github.com please', $sharedString);
|
||||
|
||||
$sharedStringsHelper->cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
|
@ -74,6 +74,20 @@ class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertContains(EncodingHelper::BOM_UTF8, $writtenContent, 'The CSV file should contain a UTF-8 BOM');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testWriteShouldSupportAssociativeArrays()
|
||||
{
|
||||
$allRows = [
|
||||
['foo' => 'csv--11', 'bar' => 'csv--12'],
|
||||
];
|
||||
$writtenContent = $this->writeToCsvFileAndReturnWrittenContent($allRows, 'csv_from_associative_arrays.csv');
|
||||
$writtenContent = $this->trimWrittenContent($writtenContent);
|
||||
|
||||
$this->assertEquals('csv--11,csv--12', $writtenContent, 'Values from associative arrays should be written');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
|
@ -23,7 +23,7 @@ class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
public function testAddRowShouldThrowExceptionIfCannotOpenAFileForWriting()
|
||||
{
|
||||
$fileName = 'file_that_wont_be_written.ods';
|
||||
$this->createUnwritableFolderIfNeeded($fileName);
|
||||
$this->createUnwritableFolderIfNeeded();
|
||||
$filePath = $this->getGeneratedUnwritableResourcePath($fileName);
|
||||
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
@ -177,6 +177,25 @@ class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldSupportAssociativeArrays()
|
||||
{
|
||||
$fileName = 'test_add_row_should_support_associative_arrays.ods';
|
||||
$dataRows = [
|
||||
['foo' => 'ods--11', 'bar' => 'ods--12'],
|
||||
];
|
||||
|
||||
$this->writeToODSFile($dataRows, $fileName);
|
||||
|
||||
foreach ($dataRows as $dataRow) {
|
||||
foreach ($dataRow as $cellValue) {
|
||||
$this->assertValueWasWritten($fileName, $cellValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
|
@ -21,7 +21,7 @@ class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
public function testAddRowShouldThrowExceptionIfCannotOpenAFileForWriting()
|
||||
{
|
||||
$fileName = 'file_that_wont_be_written.xlsx';
|
||||
$this->createUnwritableFolderIfNeeded($fileName);
|
||||
$this->createUnwritableFolderIfNeeded();
|
||||
$filePath = $this->getGeneratedUnwritableResourcePath($fileName);
|
||||
|
||||
$writer = WriterFactory::create(Type::XLSX);
|
||||
@ -232,6 +232,25 @@ class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldSupportAssociativeArrays()
|
||||
{
|
||||
$fileName = 'test_add_row_should_support_associative_arrays.xlsx';
|
||||
$dataRows = [
|
||||
['foo' => 'xlsx--11', 'bar' => 'xlsx--12'],
|
||||
];
|
||||
|
||||
$this->writeToXLSXFile($dataRows, $fileName, $shouldUseInlineStrings = true);
|
||||
|
||||
foreach ($dataRows as $dataRow) {
|
||||
foreach ($dataRow as $cellValue) {
|
||||
$this->assertInlineDataWasWrittenToSheet($fileName, 1, $cellValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user