Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69190cd855 | ||
|
|
13a53fb43f | ||
|
|
a848be52de | ||
|
|
52faef0168 | ||
|
|
3b4dfba38e | ||
|
|
cfd3e0ffa3 | ||
|
|
c6e943041e | ||
|
|
502dd54c81 | ||
|
|
c6cfc4c80f | ||
|
|
d02013c82e | ||
|
|
71d9c18a81 | ||
|
|
e9ec4e745c | ||
|
|
e58284d27b | ||
|
|
27a47f509f | ||
|
|
8aeb883ebc | ||
|
|
05c504e72c | ||
|
|
abbc158877 | ||
|
|
3f3461b002 | ||
|
|
2074781852 | ||
|
|
fd5cfc5440 | ||
|
|
a538813827 | ||
|
|
3e5ef284a5 |
No files matched your search
@@ -1,4 +1,5 @@
|
|||||||
/tests/resources/generated
|
/tests/resources/generated
|
||||||
|
/tests/coverage
|
||||||
/vendor
|
/vendor
|
||||||
composer.lock
|
composer.lock
|
||||||
/.idea
|
/.idea
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ php:
|
|||||||
- 5.4
|
- 5.4
|
||||||
- 5.5
|
- 5.5
|
||||||
- 5.6
|
- 5.6
|
||||||
|
- nightly
|
||||||
|
- hhvm
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- composer self-update
|
- composer self-update
|
||||||
|
|||||||
@@ -180,6 +180,23 @@ It is also possible to retrieve all the sheets currently created:
|
|||||||
$sheets = $writer->getSheets();
|
$sheets = $writer->getSheets();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you rely on the sheet's name in your application, you can access it and customize it this way:
|
||||||
|
```php
|
||||||
|
// Accessing the sheet name when reading
|
||||||
|
while ($reader->hasNextSheet()) {
|
||||||
|
$sheet = $reader->nextSheet();
|
||||||
|
$sheetName = $sheet->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessing the sheet name when writing
|
||||||
|
$sheet = $writer->getCurrentSheet();
|
||||||
|
$sheetName = $sheet->getName();
|
||||||
|
|
||||||
|
// Customizing the sheet name when writing
|
||||||
|
$sheet = $writer->getCurrentSheet();
|
||||||
|
$sheetName = $sheet->setName('My custom name');
|
||||||
|
```
|
||||||
|
|
||||||
### Fluent interface
|
### Fluent interface
|
||||||
|
|
||||||
Because fluent interfaces are great, you can use them with Spout:
|
Because fluent interfaces are great, you can use them with Spout:
|
||||||
|
|||||||
+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.3",
|
"version": "1.0.7",
|
||||||
"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",
|
||||||
|
|||||||
+10
@@ -14,4 +14,14 @@
|
|||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
|
|
||||||
|
<logging>
|
||||||
|
<log type="coverage-html" target="tests/coverage/"/>
|
||||||
|
</logging>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<whitelist>
|
||||||
|
<directory suffix=".php">src/</directory>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
|
|
||||||
</phpunit>
|
</phpunit>
|
||||||
@@ -13,6 +13,8 @@ class CSV implements EscaperInterface
|
|||||||
/**
|
/**
|
||||||
* Escapes the given string to make it compatible with CSV
|
* Escapes the given string to make it compatible with CSV
|
||||||
*
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
* @param string $string The string to escape
|
* @param string $string The string to escape
|
||||||
* @return string The escaped string
|
* @return string The escaped string
|
||||||
*/
|
*/
|
||||||
@@ -24,6 +26,8 @@ class CSV implements EscaperInterface
|
|||||||
/**
|
/**
|
||||||
* Unescapes the given string to make it compatible with CSV
|
* Unescapes the given string to make it compatible with CSV
|
||||||
*
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
* @param string $string The string to unescape
|
* @param string $string The string to unescape
|
||||||
* @return string The unescaped string
|
* @return string The unescaped string
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ namespace Box\Spout\Common\Helper;
|
|||||||
* Class GlobalFunctionsHelper
|
* Class GlobalFunctionsHelper
|
||||||
* This class wraps global functions to facilitate testing
|
* This class wraps global functions to facilitate testing
|
||||||
*
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
* @package Box\Spout\Common\Helper
|
* @package Box\Spout\Common\Helper
|
||||||
*/
|
*/
|
||||||
class GlobalFunctionsHelper
|
class GlobalFunctionsHelper
|
||||||
@@ -89,6 +91,21 @@ class GlobalFunctionsHelper
|
|||||||
return fgetcsv($handle, $length, $delimiter, $enclosure);
|
return fgetcsv($handle, $length, $delimiter, $enclosure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around global function fputcsv()
|
||||||
|
* @see fputcsv()
|
||||||
|
*
|
||||||
|
* @param resource $handle
|
||||||
|
* @param array $fields
|
||||||
|
* @param string|void $delimiter
|
||||||
|
* @param string|void $enclosure
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function fputcsv($handle, array $fields, $delimiter = null, $enclosure = null)
|
||||||
|
{
|
||||||
|
return fputcsv($handle, $fields, $delimiter, $enclosure);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around global function fclose()
|
* Wrapper around global function fclose()
|
||||||
* @see fclose()
|
* @see fclose()
|
||||||
@@ -117,7 +134,7 @@ class GlobalFunctionsHelper
|
|||||||
* Wrapper around global function file_exists()
|
* Wrapper around global function file_exists()
|
||||||
* @see file_exists()
|
* @see file_exists()
|
||||||
*
|
*
|
||||||
* @param string $filename
|
* @param string $fileName
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function file_exists($fileName)
|
public function file_exists($fileName)
|
||||||
@@ -125,11 +142,23 @@ class GlobalFunctionsHelper
|
|||||||
return file_exists($fileName);
|
return file_exists($fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around global function file_get_contents()
|
||||||
|
* @see file_get_contents()
|
||||||
|
*
|
||||||
|
* @param string $filePath
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function file_get_contents($filePath)
|
||||||
|
{
|
||||||
|
return file_get_contents($filePath);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around global function is_readable()
|
* Wrapper around global function is_readable()
|
||||||
* @see is_readable()
|
* @see is_readable()
|
||||||
*
|
*
|
||||||
* @param string $filename
|
* @param string $fileName
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function is_readable($fileName)
|
public function is_readable($fileName)
|
||||||
@@ -142,11 +171,12 @@ class GlobalFunctionsHelper
|
|||||||
* @see basename()
|
* @see basename()
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
|
* @param string|void $suffix
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function basename($path)
|
public function basename($path, $suffix = null)
|
||||||
{
|
{
|
||||||
return basename($path);
|
return basename($path, $suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use Box\Spout\Reader\Exception\EndOfFileReachedException;
|
|||||||
*/
|
*/
|
||||||
abstract class AbstractReader implements ReaderInterface
|
abstract class AbstractReader implements ReaderInterface
|
||||||
{
|
{
|
||||||
/** @var int Used to keep track of the row number */
|
/** @var int Used to keep track of the row index */
|
||||||
protected $currentRowIndex = 0;
|
protected $currentRowIndex = 0;
|
||||||
|
|
||||||
/** @var bool Indicates whether the stream is currently open */
|
/** @var bool Indicates whether the stream is currently open */
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class CellHelper
|
|||||||
{
|
{
|
||||||
$existingIndexes = array_keys($dataArray);
|
$existingIndexes = array_keys($dataArray);
|
||||||
|
|
||||||
$newIndexes = array_fill_keys(range(min($existingIndexes), max($existingIndexes)), $fillValue);
|
$newIndexes = array_fill_keys(range(0, max($existingIndexes)), $fillValue);
|
||||||
$dataArray += $newIndexes;
|
$dataArray += $newIndexes;
|
||||||
|
|
||||||
ksort($dataArray);
|
ksort($dataArray);
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ class SharedStringsHelper
|
|||||||
$sharedString = $this->unescapeLineFeed($escapedSharedString);
|
$sharedString = $this->unescapeLineFeed($escapedSharedString);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$sharedString) {
|
if ($sharedString === null) {
|
||||||
throw new SharedStringNotFoundException("Shared string not found for index: $sharedStringIndex");
|
throw new SharedStringNotFoundException("Shared string not found for index: $sharedStringIndex");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace Box\Spout\Reader\Helper\XLSX;
|
namespace Box\Spout\Reader\Helper\XLSX;
|
||||||
|
|
||||||
use Box\Spout\Reader\Internal\XLSX\Worksheet;
|
use Box\Spout\Reader\Internal\XLSX\Worksheet;
|
||||||
|
use Box\Spout\Reader\Sheet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class WorksheetHelper
|
* Class WorksheetHelper
|
||||||
@@ -12,11 +13,18 @@ use Box\Spout\Reader\Internal\XLSX\Worksheet;
|
|||||||
*/
|
*/
|
||||||
class WorksheetHelper
|
class WorksheetHelper
|
||||||
{
|
{
|
||||||
/** Path of Content_Types XML file inside the XLSX file */
|
/** Extension for XML files */
|
||||||
const CONTENT_TYPES_XML_FILE_PATH = '[Content_Types].xml';
|
const XML_EXTENSION = '.xml';
|
||||||
|
|
||||||
/** Main namespace for the [Content_Types].xml file */
|
/** Paths of XML files relative to the XLSX file root */
|
||||||
|
const CONTENT_TYPES_XML_FILE_PATH = '[Content_Types].xml';
|
||||||
|
const WORKBOOK_XML_RELS_FILE_PATH = 'xl/_rels/workbook.xml.rels';
|
||||||
|
const WORKBOOK_XML_FILE_PATH = 'xl/workbook.xml';
|
||||||
|
|
||||||
|
/** Namespaces for the XML files */
|
||||||
const MAIN_NAMESPACE_FOR_CONTENT_TYPES_XML = 'http://schemas.openxmlformats.org/package/2006/content-types';
|
const MAIN_NAMESPACE_FOR_CONTENT_TYPES_XML = 'http://schemas.openxmlformats.org/package/2006/content-types';
|
||||||
|
const MAIN_NAMESPACE_FOR_WORKBOOK_XML_RELS = 'http://schemas.openxmlformats.org/package/2006/relationships';
|
||||||
|
const MAIN_NAMESPACE_FOR_WORKBOOK_XML = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main';
|
||||||
|
|
||||||
/** Value of the Override attribute used in [Content_Types].xml to define worksheets */
|
/** Value of the Override attribute used in [Content_Types].xml to define worksheets */
|
||||||
const OVERRIDE_CONTENT_TYPES_ATTRIBUTE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml';
|
const OVERRIDE_CONTENT_TYPES_ATTRIBUTE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml';
|
||||||
@@ -24,12 +32,23 @@ class WorksheetHelper
|
|||||||
/** @var string Path of the XLSX file being read */
|
/** @var string Path of the XLSX file being read */
|
||||||
protected $filePath;
|
protected $filePath;
|
||||||
|
|
||||||
|
/** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */
|
||||||
|
protected $globalFunctionsHelper;
|
||||||
|
|
||||||
|
/** @var \SimpleXMLElement XML element representing the workbook.xml.rels file */
|
||||||
|
protected $workbookXMLRelsAsXMLElement;
|
||||||
|
|
||||||
|
/** @var \SimpleXMLElement XML element representing the workbook.xml file */
|
||||||
|
protected $workbookXMLAsXMLElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $filePath Path of the XLSX file being read
|
* @param string $filePath Path of the XLSX file being read
|
||||||
|
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
|
||||||
*/
|
*/
|
||||||
public function __construct($filePath)
|
public function __construct($filePath, $globalFunctionsHelper)
|
||||||
{
|
{
|
||||||
$this->filePath = $filePath;
|
$this->filePath = $filePath;
|
||||||
|
$this->globalFunctionsHelper = $globalFunctionsHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,23 +61,139 @@ class WorksheetHelper
|
|||||||
{
|
{
|
||||||
$worksheets = [];
|
$worksheets = [];
|
||||||
|
|
||||||
$xmlContents = file_get_contents('zip://' . $this->filePath . '#' . self::CONTENT_TYPES_XML_FILE_PATH);
|
$contentTypesAsXMLElement = $this->getFileAsXMLElementWithNamespace(
|
||||||
|
self::CONTENT_TYPES_XML_FILE_PATH,
|
||||||
$contentTypes = new \SimpleXMLElement($xmlContents);
|
self::MAIN_NAMESPACE_FOR_CONTENT_TYPES_XML
|
||||||
$contentTypes->registerXPathNamespace('ns', self::MAIN_NAMESPACE_FOR_CONTENT_TYPES_XML);
|
);
|
||||||
|
|
||||||
// find all nodes defining a worksheet
|
// find all nodes defining a worksheet
|
||||||
$sheetNodes = $contentTypes->xpath('//ns:Override[@ContentType="' . self::OVERRIDE_CONTENT_TYPES_ATTRIBUTE . '"]');
|
$sheetNodes = $contentTypesAsXMLElement->xpath('//ns:Override[@ContentType="' . self::OVERRIDE_CONTENT_TYPES_ATTRIBUTE . '"]');
|
||||||
|
|
||||||
for ($i = 0; $i < count($sheetNodes); $i++) {
|
for ($i = 0; $i < count($sheetNodes); $i++) {
|
||||||
$sheetNode = $sheetNodes[$i];
|
$sheetNode = $sheetNodes[$i];
|
||||||
$sheetDataXMLFilePath = (string) $sheetNode->attributes()->PartName;
|
$sheetDataXMLFilePath = (string) $sheetNode->attributes()->PartName;
|
||||||
$worksheets[] = new Worksheet($i, $sheetDataXMLFilePath);
|
|
||||||
|
$sheet = $this->getSheet($sheetDataXMLFilePath, $i);
|
||||||
|
$worksheets[] = new Worksheet($sheet, $i, $sheetDataXMLFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $worksheets;
|
return $worksheets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an instance of a sheet, given the path of its data XML file.
|
||||||
|
* We first look at "xl/_rels/workbook.xml.rels" to find the relationship ID of the sheet.
|
||||||
|
* Then we look at "xl/worbook.xml" to find the sheet entry associated to the found ID.
|
||||||
|
* The entry contains the ID and name of the sheet.
|
||||||
|
*
|
||||||
|
* If this piece of data can't be found by parsing the different XML files, the ID will default
|
||||||
|
* to the sheet index, based on order in [Content_Types].xml. Similarly, the sheet's name will
|
||||||
|
* default to the data sheet XML file name ("xl/worksheets/sheet2.xml" => "sheet2").
|
||||||
|
*
|
||||||
|
* @param string $sheetDataXMLFilePath Path of the sheet data XML file as in [Content_Types].xml
|
||||||
|
* @param int $sheetIndexZeroBased Index of the sheet, based on order in [Content_Types].xml (zero-based)
|
||||||
|
* @return \Box\Spout\Reader\Sheet Sheet instance
|
||||||
|
*/
|
||||||
|
protected function getSheet($sheetDataXMLFilePath, $sheetIndexZeroBased)
|
||||||
|
{
|
||||||
|
$sheetId = $sheetIndexZeroBased + 1;
|
||||||
|
$sheetName = $this->getDefaultSheetName($sheetDataXMLFilePath);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In [Content_Types].xml, the path is "/xl/worksheets/sheet1.xml"
|
||||||
|
* In workbook.xml.rels, it is only "worksheets/sheet1.xml"
|
||||||
|
*/
|
||||||
|
$sheetDataXMLFilePathInWorkbookXMLRels = ltrim($sheetDataXMLFilePath, '/xl/');
|
||||||
|
|
||||||
|
// find the node associated to the given file path
|
||||||
|
$workbookXMLResElement = $this->getWorkbookXMLRelsAsXMLElement();
|
||||||
|
$relationshipNodes = $workbookXMLResElement->xpath('//ns:Relationship[@Target="' . $sheetDataXMLFilePathInWorkbookXMLRels . '"]');
|
||||||
|
|
||||||
|
if (count($relationshipNodes) === 1) {
|
||||||
|
$relationshipNode = $relationshipNodes[0];
|
||||||
|
$sheetId = (string) $relationshipNode->attributes()->Id;
|
||||||
|
|
||||||
|
$workbookXMLElement = $this->getWorkbookXMLAsXMLElement();
|
||||||
|
$sheetNodes = $workbookXMLElement->xpath('//ns:sheet[@r:id="' . $sheetId . '"]');
|
||||||
|
|
||||||
|
if (count($sheetNodes) === 1) {
|
||||||
|
$sheetNode = $sheetNodes[0];
|
||||||
|
$sheetId = (int) $sheetNode->attributes()->sheetId;
|
||||||
|
$escapedSheetName = (string) $sheetNode->attributes()->name;
|
||||||
|
|
||||||
|
$escaper = new \Box\Spout\Common\Escaper\XLSX();
|
||||||
|
$sheetName = $escaper->unescape($escapedSheetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Sheet($sheetId, $sheetIndexZeroBased, $sheetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default name of the sheet whose data is located
|
||||||
|
* at the given path.
|
||||||
|
*
|
||||||
|
* @param $sheetDataXMLFilePath
|
||||||
|
* @return string The default sheet name
|
||||||
|
*/
|
||||||
|
protected function getDefaultSheetName($sheetDataXMLFilePath)
|
||||||
|
{
|
||||||
|
return $this->globalFunctionsHelper->basename($sheetDataXMLFilePath, self::XML_EXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a representation of the workbook.xml.rels file, ready to be parsed.
|
||||||
|
* The returned value is cached.
|
||||||
|
*
|
||||||
|
* @return \SimpleXMLElement XML element representating the workbook.xml.rels file
|
||||||
|
*/
|
||||||
|
protected function getWorkbookXMLRelsAsXMLElement()
|
||||||
|
{
|
||||||
|
if (!$this->workbookXMLRelsAsXMLElement) {
|
||||||
|
$this->workbookXMLRelsAsXMLElement = $this->getFileAsXMLElementWithNamespace(
|
||||||
|
self::WORKBOOK_XML_RELS_FILE_PATH,
|
||||||
|
self::MAIN_NAMESPACE_FOR_WORKBOOK_XML_RELS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->workbookXMLRelsAsXMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a representation of the workbook.xml file, ready to be parsed.
|
||||||
|
* The returned value is cached.
|
||||||
|
*
|
||||||
|
* @return \SimpleXMLElement XML element representating the workbook.xml.rels file
|
||||||
|
*/
|
||||||
|
protected function getWorkbookXMLAsXMLElement()
|
||||||
|
{
|
||||||
|
if (!$this->workbookXMLAsXMLElement) {
|
||||||
|
$this->workbookXMLAsXMLElement = $this->getFileAsXMLElementWithNamespace(
|
||||||
|
self::WORKBOOK_XML_FILE_PATH,
|
||||||
|
self::MAIN_NAMESPACE_FOR_WORKBOOK_XML
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->workbookXMLAsXMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the contents of the given file in an XML parser and register the given XPath namespace.
|
||||||
|
*
|
||||||
|
* @param string $xmlFilePath The path of the XML file inside the XLSX file
|
||||||
|
* @param string $mainNamespace The main XPath namespace to register
|
||||||
|
* @return \SimpleXMLElement The XML element representing the file
|
||||||
|
*/
|
||||||
|
protected function getFileAsXMLElementWithNamespace($xmlFilePath, $mainNamespace)
|
||||||
|
{
|
||||||
|
$xmlContents = $this->globalFunctionsHelper->file_get_contents('zip://' . $this->filePath . '#' . $xmlFilePath);
|
||||||
|
|
||||||
|
$xmlElement = new \SimpleXMLElement($xmlContents);
|
||||||
|
$xmlElement->registerXPathNamespace('ns', $mainNamespace);
|
||||||
|
|
||||||
|
return $xmlElement;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether another worksheet exists after the current worksheet.
|
* Returns whether another worksheet exists after the current worksheet.
|
||||||
* The order is determined by the order of appearance in the [Content_Types].xml file.
|
* The order is determined by the order of appearance in the [Content_Types].xml file.
|
||||||
@@ -69,6 +204,6 @@ class WorksheetHelper
|
|||||||
*/
|
*/
|
||||||
public function hasNextWorksheet($currentWorksheet, $allWorksheets)
|
public function hasNextWorksheet($currentWorksheet, $allWorksheets)
|
||||||
{
|
{
|
||||||
return ($currentWorksheet === null || ($currentWorksheet->getWorksheetNumber() + 1 < count($allWorksheets)));
|
return ($currentWorksheet === null || ($currentWorksheet->getWorksheetIndex() + 1 < count($allWorksheets)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,19 +10,24 @@ namespace Box\Spout\Reader\Internal\XLSX;
|
|||||||
*/
|
*/
|
||||||
class Worksheet
|
class Worksheet
|
||||||
{
|
{
|
||||||
/** @var int Worksheet number, based on the order of appareance in [Content_Types].xml (zero-based) */
|
/** @var \Box\Spout\Reader\Sheet The "external" sheet */
|
||||||
protected $worksheetNumber;
|
protected $externalSheet;
|
||||||
|
|
||||||
|
/** @var int Worksheet index, based on the order of appareance in [Content_Types].xml (zero-based) */
|
||||||
|
protected $worksheetIndex;
|
||||||
|
|
||||||
/** @var string Path of the XML file containing the worksheet data */
|
/** @var string Path of the XML file containing the worksheet data */
|
||||||
protected $dataXmlFilePath;
|
protected $dataXmlFilePath;
|
||||||
|
|
||||||
/**
|
/**\
|
||||||
* @param int $worksheetNumber Worksheet number, based on the order of appareance in [Content_Types].xml (zero-based)
|
* @param \Box\Spout\Reader\Sheet $externalSheet The associated "external" sheet
|
||||||
|
* @param int $worksheetIndex Worksheet index, based on the order of appareance in [Content_Types].xml (zero-based)
|
||||||
* @param string $dataXmlFilePath Path of the XML file containing the worksheet data
|
* @param string $dataXmlFilePath Path of the XML file containing the worksheet data
|
||||||
*/
|
*/
|
||||||
public function __construct($worksheetNumber, $dataXmlFilePath)
|
public function __construct($externalSheet, $worksheetIndex, $dataXmlFilePath)
|
||||||
{
|
{
|
||||||
$this->worksheetNumber = $worksheetNumber;
|
$this->externalSheet = $externalSheet;
|
||||||
|
$this->worksheetIndex = $worksheetIndex;
|
||||||
$this->dataXmlFilePath = $dataXmlFilePath;
|
$this->dataXmlFilePath = $dataXmlFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,11 +39,19 @@ class Worksheet
|
|||||||
return ltrim($this->dataXmlFilePath, '/');
|
return ltrim($this->dataXmlFilePath, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Box\Spout\Reader\Sheet The "external" sheet
|
||||||
|
*/
|
||||||
|
public function getExternalSheet()
|
||||||
|
{
|
||||||
|
return $this->externalSheet;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getWorksheetNumber()
|
public function getWorksheetIndex()
|
||||||
{
|
{
|
||||||
return $this->worksheetNumber;
|
return $this->worksheetIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Box\Spout\Reader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Sheet
|
||||||
|
* Represents a worksheet within a XLSX file
|
||||||
|
*
|
||||||
|
* @package Box\Spout\Reader
|
||||||
|
*/
|
||||||
|
class Sheet
|
||||||
|
{
|
||||||
|
/** @var int ID of the sheet */
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
/** @var int Index of the sheet, based on order of creation (zero-based) */
|
||||||
|
protected $index;
|
||||||
|
|
||||||
|
/** @var string Name of the sheet */
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $sheetId ID of the sheet
|
||||||
|
* @param int $sheetIndex Index of the sheet, based on order of creation (zero-based)
|
||||||
|
* @param string $sheetName Name of the sheet
|
||||||
|
*/
|
||||||
|
function __construct($sheetId, $sheetIndex, $sheetName)
|
||||||
|
{
|
||||||
|
$this->id = $sheetId;
|
||||||
|
$this->index = $sheetIndex;
|
||||||
|
$this->name = $sheetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int ID of the sheet
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int Index of the sheet, based on order of creation (zero-based)
|
||||||
|
*/
|
||||||
|
public function getIndex()
|
||||||
|
{
|
||||||
|
return $this->index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string Name of the sheet
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -76,7 +76,7 @@ class XLSX extends AbstractReader
|
|||||||
$this->extractSharedStrings($filePath);
|
$this->extractSharedStrings($filePath);
|
||||||
|
|
||||||
// Fetch all available worksheets
|
// Fetch all available worksheets
|
||||||
$this->worksheetHelper = new WorksheetHelper($filePath);
|
$this->worksheetHelper = new WorksheetHelper($filePath, $this->globalFunctionsHelper);
|
||||||
$this->worksheets = $this->worksheetHelper->getWorksheets($filePath);
|
$this->worksheets = $this->worksheetHelper->getWorksheets($filePath);
|
||||||
|
|
||||||
if (count($this->worksheets) === 0) {
|
if (count($this->worksheets) === 0) {
|
||||||
@@ -119,18 +119,21 @@ class XLSX extends AbstractReader
|
|||||||
* Moves the pointer to the current worksheet.
|
* Moves the pointer to the current worksheet.
|
||||||
* Moving to another worksheet will stop the reading in the current worksheet.
|
* Moving to another worksheet will stop the reading in the current worksheet.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return \Box\Spout\Reader\Sheet The next sheet
|
||||||
* @throws Exception\ReaderNotOpenedException If the stream was not opened first
|
* @throws Exception\ReaderNotOpenedException If the stream was not opened first
|
||||||
* @throws Exception\EndOfWorksheetsReachedException If there is no more worksheets to read
|
* @throws Exception\EndOfWorksheetsReachedException If there is no more worksheets to read
|
||||||
*/
|
*/
|
||||||
public function nextSheet()
|
public function nextSheet()
|
||||||
{
|
{
|
||||||
if ($this->hasNextSheet()) {
|
if (!$this->hasNextSheet()) {
|
||||||
|
throw new EndOfWorksheetsReachedException('End of worksheets was reached. Cannot read more worksheets.');
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->currentWorksheet === null) {
|
if ($this->currentWorksheet === null) {
|
||||||
$nextWorksheet = $this->worksheets[0];
|
$nextWorksheet = $this->worksheets[0];
|
||||||
} else {
|
} else {
|
||||||
$currentWorksheetNumber = $this->currentWorksheet->getWorksheetNumber();
|
$currentWorksheetIndex = $this->currentWorksheet->getWorksheetIndex();
|
||||||
$nextWorksheet = $this->worksheets[$currentWorksheetNumber + 1];
|
$nextWorksheet = $this->worksheets[$currentWorksheetIndex + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->initXmlReaderForWorksheetData($nextWorksheet);
|
$this->initXmlReaderForWorksheetData($nextWorksheet);
|
||||||
@@ -139,9 +142,8 @@ class XLSX extends AbstractReader
|
|||||||
// make sure that we are ready to read more rows
|
// make sure that we are ready to read more rows
|
||||||
$this->hasReachedEndOfFile = false;
|
$this->hasReachedEndOfFile = false;
|
||||||
$this->emptyRowDataBuffer();
|
$this->emptyRowDataBuffer();
|
||||||
} else {
|
|
||||||
throw new EndOfWorksheetsReachedException('End of worksheets was reached. Cannot read more worksheets.');
|
return $this->currentWorksheet->getExternalSheet();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ abstract class AbstractWriter implements WriterInterface
|
|||||||
* Inits the writer and opens it to accept data.
|
* Inits the writer and opens it to accept data.
|
||||||
* By using this method, the data will be outputted directly to the browser.
|
* By using this method, the data will be outputted directly to the browser.
|
||||||
*
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
* @param string $outputFileName Name of the output file that will contain the data. If a path is passed in, only the file name will be kept
|
* @param string $outputFileName Name of the output file that will contain the data. If a path is passed in, only the file name will be kept
|
||||||
* @return \Box\Spout\Writer\AbstractWriter
|
* @return \Box\Spout\Writer\AbstractWriter
|
||||||
* @throws \Box\Spout\Common\Exception\IOException If the writer cannot be opened
|
* @throws \Box\Spout\Common\Exception\IOException If the writer cannot be opened
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class CSV extends AbstractWriter
|
|||||||
*/
|
*/
|
||||||
protected function addRowToWriter(array $dataRow)
|
protected function addRowToWriter(array $dataRow)
|
||||||
{
|
{
|
||||||
$wasWriteSuccessful = fputcsv($this->filePointer, $dataRow, $this->fieldDelimiter, $this->fieldEnclosure);
|
$wasWriteSuccessful = $this->globalFunctionsHelper->fputcsv($this->filePointer, $dataRow, $this->fieldDelimiter, $this->fieldEnclosure);
|
||||||
if ($wasWriteSuccessful === false) {
|
if ($wasWriteSuccessful === false) {
|
||||||
throw new IOException('Unable to write data');
|
throw new IOException('Unable to write data');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ class Workbook
|
|||||||
*/
|
*/
|
||||||
public function addNewSheet()
|
public function addNewSheet()
|
||||||
{
|
{
|
||||||
$newSheetNumber = count($this->worksheets);
|
$newSheetIndex = count($this->worksheets);
|
||||||
$sheet = new Sheet($newSheetNumber);
|
$sheet = new Sheet($newSheetIndex);
|
||||||
|
|
||||||
$worksheetFilesFolder = $this->fileSystemHelper->getXlWorksheetsFolder();
|
$worksheetFilesFolder = $this->fileSystemHelper->getXlWorksheetsFolder();
|
||||||
$worksheet = new Worksheet($sheet, $worksheetFilesFolder, $this->sharedStringsHelper, $this->shouldUseInlineStrings);
|
$worksheet = new Worksheet($sheet, $worksheetFilesFolder, $this->sharedStringsHelper, $this->shouldUseInlineStrings);
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ EOD;
|
|||||||
*/
|
*/
|
||||||
public function getId()
|
public function getId()
|
||||||
{
|
{
|
||||||
// sheet number is zero-based, while ID is 1-based
|
// sheet index is zero-based, while ID is 1-based
|
||||||
return $this->externalSheet->getSheetNumber() + 1;
|
return $this->externalSheet->getIndex() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,27 +12,27 @@ class Sheet
|
|||||||
{
|
{
|
||||||
const DEFAULT_SHEET_NAME_PREFIX = 'Sheet';
|
const DEFAULT_SHEET_NAME_PREFIX = 'Sheet';
|
||||||
|
|
||||||
/** @var int Number of the sheet, based on order of creation (zero-based) */
|
/** @var int Index of the sheet, based on order of creation (zero-based) */
|
||||||
protected $sheetNumber;
|
protected $index;
|
||||||
|
|
||||||
/** @var string Name of the sheet */
|
/** @var string Name of the sheet */
|
||||||
protected $name;
|
protected $name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $sheetNumber Number of the sheet, based on order of creation (zero-based)
|
* @param int $sheetIndex Index of the sheet, based on order of creation (zero-based)
|
||||||
*/
|
*/
|
||||||
function __construct($sheetNumber)
|
function __construct($sheetIndex)
|
||||||
{
|
{
|
||||||
$this->sheetNumber = $sheetNumber;
|
$this->index = $sheetIndex;
|
||||||
$this->name = self::DEFAULT_SHEET_NAME_PREFIX . ($sheetNumber + 1);
|
$this->name = self::DEFAULT_SHEET_NAME_PREFIX . ($sheetIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int Number of the sheet, based on order of creation (zero-based)
|
* @return int Index of the sheet, based on order of creation (zero-based)
|
||||||
*/
|
*/
|
||||||
public function getSheetNumber()
|
public function getIndex()
|
||||||
{
|
{
|
||||||
return $this->sheetNumber;
|
return $this->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,4 +42,14 @@ class Sheet
|
|||||||
{
|
{
|
||||||
return $this->name;
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name Name of the sheet
|
||||||
|
* @return \Box\Spout\Writer\Sheet
|
||||||
|
*/
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Box\Spout\Reader\Helper\XLSX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CellHelperTest
|
||||||
|
*
|
||||||
|
* @package Box\Spout\Reader\Helper\XLSX
|
||||||
|
*/
|
||||||
|
class CellHelperTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testFillMissingArrayIndexes()
|
||||||
|
{
|
||||||
|
$arrayToFill = [1 => 1, 3 => 3];
|
||||||
|
$filledArray = CellHelper::fillMissingArrayIndexes($arrayToFill, 'FILL');
|
||||||
|
|
||||||
|
$expectedFilledArray = ['FILL', 1, 'FILL', 3];
|
||||||
|
$this->assertEquals($expectedFilledArray, $filledArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function dataProviderForTestGetColumnIndexFromCellIndex()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['A1', 0],
|
||||||
|
['Z3', 25],
|
||||||
|
['AA5', 26],
|
||||||
|
['AB24', 27],
|
||||||
|
['BC5', 54],
|
||||||
|
['BCZ99', 1455],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataProviderForTestGetColumnIndexFromCellIndex
|
||||||
|
*
|
||||||
|
* @param string $cellIndex
|
||||||
|
* @param int $expectedColumnIndex
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testGetColumnIndexFromCellIndex($cellIndex, $expectedColumnIndex)
|
||||||
|
{
|
||||||
|
$this->assertEquals($expectedColumnIndex, CellHelper::getColumnIndexFromCellIndex($cellIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Box\Spout\Common\Exception\InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testGetColumnIndexFromCellIndexShouldThrowIfInvalidCellIndex()
|
||||||
|
{
|
||||||
|
CellHelper::getColumnIndexFromCellIndex('InvalidCellIndex');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Box\Spout\Reader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ReaderFactoryTest
|
||||||
|
*
|
||||||
|
* @package Box\Spout\Writer
|
||||||
|
*/
|
||||||
|
class ReaderFactoryTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @expectedException \Box\Spout\Common\Exception\UnsupportedTypeException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testCreateReaderShouldThrowWithUnsupportedType()
|
||||||
|
{
|
||||||
|
ReaderFactory::create('unsupportedType');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Box\Spout\Reader;
|
||||||
|
|
||||||
|
use Box\Spout\Common\Type;
|
||||||
|
use Box\Spout\TestUsingResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SheetTest
|
||||||
|
*
|
||||||
|
* @package Box\Spout\Reader
|
||||||
|
*/
|
||||||
|
class SheetTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
use TestUsingResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testNextSheetShouldReturnCorrectSheetInfos()
|
||||||
|
{
|
||||||
|
$sheets = $this->openFileAndReturnSheets('two_sheets_with_custom_names.xlsx');
|
||||||
|
|
||||||
|
$this->assertEquals('CustomName1', $sheets[0]->getName());
|
||||||
|
$this->assertEquals(0, $sheets[0]->getIndex());
|
||||||
|
$this->assertEquals(1, $sheets[0]->getId());
|
||||||
|
|
||||||
|
$this->assertEquals('CustomName2', $sheets[1]->getName());
|
||||||
|
$this->assertEquals(1, $sheets[1]->getIndex());
|
||||||
|
$this->assertEquals(2, $sheets[1]->getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $fileName
|
||||||
|
* @return Sheet[]
|
||||||
|
*/
|
||||||
|
private function openFileAndReturnSheets($fileName)
|
||||||
|
{
|
||||||
|
$resourcePath = $this->getResourcePath($fileName);
|
||||||
|
$reader = ReaderFactory::create(Type::XLSX);
|
||||||
|
$reader->open($resourcePath);
|
||||||
|
|
||||||
|
$sheets = [];
|
||||||
|
while ($reader->hasNextSheet()) {
|
||||||
|
$sheets[] = $reader->nextSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
$reader->close();
|
||||||
|
|
||||||
|
return $sheets;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,6 +38,37 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->getAllRowsForFile($filePath);
|
$this->getAllRowsForFile($filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Box\Spout\Reader\Exception\ReaderNotOpenedException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testHasNextSheetShouldThrowExceptionIfReaderNotOpened()
|
||||||
|
{
|
||||||
|
$reader = ReaderFactory::create(Type::XLSX);
|
||||||
|
$reader->hasNextSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Box\Spout\Reader\Exception\EndOfWorksheetsReachedException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testNextSheetShouldThrowExceptionIfNoMoreSheetsToRead()
|
||||||
|
{
|
||||||
|
$fileName = 'one_sheet_with_shared_strings.xlsx';
|
||||||
|
$resourcePath = $this->getResourcePath($fileName);
|
||||||
|
|
||||||
|
$reader = ReaderFactory::create(Type::XLSX);
|
||||||
|
$reader->open($resourcePath);
|
||||||
|
|
||||||
|
while ($reader->hasNextSheet()) {
|
||||||
|
$reader->nextSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
$reader->nextSheet();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
@@ -140,6 +171,32 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals($expectedRows, $allRows);
|
$this->assertEquals($expectedRows, $allRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testReadShouldSupportEmptySharedString()
|
||||||
|
{
|
||||||
|
$allRows = $this->getAllRowsForFile('sheet_with_empty_shared_string.xlsx');
|
||||||
|
|
||||||
|
$expectedRows = [
|
||||||
|
['s1--A1', '', 's1--C1'],
|
||||||
|
];
|
||||||
|
$this->assertEquals($expectedRows, $allRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testReadShouldPreserveSpaceIfSpecified()
|
||||||
|
{
|
||||||
|
$allRows = $this->getAllRowsForFile('sheet_with_preserve_space_shared_strings.xlsx');
|
||||||
|
|
||||||
|
$expectedRows = [
|
||||||
|
[' s1--A1', 's1--B1 ', ' s1--C1 '],
|
||||||
|
];
|
||||||
|
$this->assertEquals($expectedRows, $allRows);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@@ -158,7 +215,7 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$allRows = $this->getAllRowsForFile('billion_laughs_test_file.xlsx');
|
$allRows = $this->getAllRowsForFile('billion_laughs_test_file.xlsx');
|
||||||
|
|
||||||
$expectedMaxMemoryUsage = 10 * 1024 * 1024; // 10MB
|
$expectedMaxMemoryUsage = 20 * 1024 * 1024; // 20MB
|
||||||
$this->assertLessThan($expectedMaxMemoryUsage, memory_get_peak_usage(true), 'Entities should not be expanded and therefore consume all the memory.');
|
$this->assertLessThan($expectedMaxMemoryUsage, memory_get_peak_usage(true), 'Entities should not be expanded and therefore consume all the memory.');
|
||||||
|
|
||||||
$expectedFirstRow = ['s1--A1', 's1--B1', 's1--C1', 's1--D1', 's1--E1'];
|
$expectedFirstRow = ['s1--A1', 's1--B1', 's1--C1', 's1--D1', 's1--E1'];
|
||||||
|
|||||||
@@ -49,6 +49,16 @@ class CSVTest extends \PHPUnit_Framework_TestCase
|
|||||||
$writer->close();
|
$writer->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Box\Spout\Common\Exception\InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testAddRowsShouldThrowExceptionIfRowsAreNotArrayOfArrays()
|
||||||
|
{
|
||||||
|
$writer = WriterFactory::create(Type::CSV);
|
||||||
|
$writer->addRows(['csv--11', 'csv--12']);
|
||||||
|
$writer->close();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ class SheetTest extends \PHPUnit_Framework_TestCase
|
|||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function testGetSheetNumber()
|
public function testGetSheetIndex()
|
||||||
{
|
{
|
||||||
$sheets = $this->writeDataAndReturnSheets('test_get_sheet_number.xlsx');
|
$sheets = $this->writeDataAndReturnSheets('test_get_sheet_index.xlsx');
|
||||||
|
|
||||||
$this->assertEquals(2, count($sheets), '2 sheets should have been created');
|
$this->assertEquals(2, count($sheets), '2 sheets should have been created');
|
||||||
$this->assertEquals(0, $sheets[0]->getSheetNumber(), 'The first sheet should be number 0');
|
$this->assertEquals(0, $sheets[0]->getIndex(), 'The first sheet should be index 0');
|
||||||
$this->assertEquals(1, $sheets[1]->getSheetNumber(), 'The second sheet should be number 1');
|
$this->assertEquals(1, $sheets[1]->getIndex(), 'The second sheet should be index 1');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,6 +38,28 @@ class SheetTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals('Sheet2', $sheets[1]->getName(), 'Invalid name for the second sheet');
|
$this->assertEquals('Sheet2', $sheets[1]->getName(), 'Invalid name for the second sheet');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testSetSheetNameShouldCreateSheetWithCustomName()
|
||||||
|
{
|
||||||
|
$fileName = 'test_set_name_should_create_sheet_with_custom_name.xlsx';
|
||||||
|
$this->createGeneratedFolderIfNeeded($fileName);
|
||||||
|
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||||
|
|
||||||
|
$writer = WriterFactory::create(Type::XLSX);
|
||||||
|
$writer->openToFile($resourcePath);
|
||||||
|
|
||||||
|
$customSheetName = 'CustomName';
|
||||||
|
$sheet = $writer->getCurrentSheet();
|
||||||
|
$sheet->setName($customSheetName);
|
||||||
|
|
||||||
|
$writer->addRow(['xlsx--11', 'xlsx--12']);
|
||||||
|
$writer->close();
|
||||||
|
|
||||||
|
$this->assertSheetNameEquals($customSheetName, $resourcePath, "The sheet name should have been changed to '$customSheetName'");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $fileName
|
* @param string $fileName
|
||||||
* @return Sheet[]
|
* @return Sheet[]
|
||||||
@@ -59,4 +81,18 @@ class SheetTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
return $writer->getSheets();
|
return $writer->getSheets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $expectedName
|
||||||
|
* @param string $resourcePath
|
||||||
|
* @param string $message
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function assertSheetNameEquals($expectedName, $resourcePath, $message = '')
|
||||||
|
{
|
||||||
|
$pathToWorkbookFile = $resourcePath . '#xl/workbook.xml';
|
||||||
|
$xmlContents = file_get_contents('zip://' . $pathToWorkbookFile);
|
||||||
|
|
||||||
|
$this->assertContains('<sheet name="' . $expectedName . '"', $xmlContents, $message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Box\Spout\Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class WriterFactoryTest
|
||||||
|
*
|
||||||
|
* @package Box\Spout\Writer
|
||||||
|
*/
|
||||||
|
class WriterFactoryTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @expectedException \Box\Spout\Common\Exception\UnsupportedTypeException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testCreateWriterShouldThrowWithUnsupportedType()
|
||||||
|
{
|
||||||
|
WriterFactory::create('unsupportedType');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -343,7 +343,6 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertInlineDataWasWrittenToSheet($fileName, 1, 'control's _x0015_ "character"');
|
$this->assertInlineDataWasWrittenToSheet($fileName, 1, 'control's _x0015_ "character"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $allRows
|
* @param array $allRows
|
||||||
* @param string $fileName
|
* @param string $fileName
|
||||||
@@ -401,15 +400,15 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $fileName
|
* @param string $fileName
|
||||||
* @param int $sheetNumber
|
* @param int $sheetIndex
|
||||||
* @param mixed $inlineData
|
* @param mixed $inlineData
|
||||||
* @param string $message
|
* @param string $message
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function assertInlineDataWasWrittenToSheet($fileName, $sheetNumber, $inlineData, $message = '')
|
private function assertInlineDataWasWrittenToSheet($fileName, $sheetIndex, $inlineData, $message = '')
|
||||||
{
|
{
|
||||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||||
$pathToSheetFile = $resourcePath . '#xl/worksheets/sheet' . $sheetNumber . '.xml';
|
$pathToSheetFile = $resourcePath . '#xl/worksheets/sheet' . $sheetIndex . '.xml';
|
||||||
$xmlContents = file_get_contents('zip://' . $pathToSheetFile);
|
$xmlContents = file_get_contents('zip://' . $pathToSheetFile);
|
||||||
|
|
||||||
$this->assertContains((string)$inlineData, $xmlContents, $message);
|
$this->assertContains((string)$inlineData, $xmlContents, $message);
|
||||||
@@ -417,15 +416,15 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $fileName
|
* @param string $fileName
|
||||||
* @param int $sheetNumber
|
* @param int $sheetIndex
|
||||||
* @param mixed $inlineData
|
* @param mixed $inlineData
|
||||||
* @param string $message
|
* @param string $message
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function assertInlineDataWasNotWrittenToSheet($fileName, $sheetNumber, $inlineData, $message = '')
|
private function assertInlineDataWasNotWrittenToSheet($fileName, $sheetIndex, $inlineData, $message = '')
|
||||||
{
|
{
|
||||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||||
$pathToSheetFile = $resourcePath . '#xl/worksheets/sheet' . $sheetNumber . '.xml';
|
$pathToSheetFile = $resourcePath . '#xl/worksheets/sheet' . $sheetIndex . '.xml';
|
||||||
$xmlContents = file_get_contents('zip://' . $pathToSheetFile);
|
$xmlContents = file_get_contents('zip://' . $pathToSheetFile);
|
||||||
|
|
||||||
$this->assertNotContains((string)$inlineData, $xmlContents, $message);
|
$this->assertNotContains((string)$inlineData, $xmlContents, $message);
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in new issue
Block a user