diff --git a/src/Spout/Reader/XLSX/Creator/EntityFactory.php b/src/Spout/Reader/XLSX/Creator/EntityFactory.php
index 8699529..8ef648a 100644
--- a/src/Spout/Reader/XLSX/Creator/EntityFactory.php
+++ b/src/Spout/Reader/XLSX/Creator/EntityFactory.php
@@ -53,6 +53,7 @@ class EntityFactory implements EntityFactoryInterface
* @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
* @param string $sheetName Name of the sheet
* @param bool $isSheetActive Whether the sheet was defined as active
+ * @param bool $isSheetVisible Whether the sheet is visible
* @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param SharedStringsManager $sharedStringsManager Manages shared strings
* @return Sheet
@@ -63,12 +64,13 @@ class EntityFactory implements EntityFactoryInterface
$sheetIndex,
$sheetName,
$isSheetActive,
+ $isSheetVisible,
$optionsManager,
$sharedStringsManager
) {
$rowIterator = $this->createRowIterator($filePath, $sheetDataXMLFilePath, $optionsManager, $sharedStringsManager);
- return new Sheet($rowIterator, $sheetIndex, $sheetName, $isSheetActive);
+ return new Sheet($rowIterator, $sheetIndex, $sheetName, $isSheetActive, $isSheetVisible);
}
/**
diff --git a/src/Spout/Reader/XLSX/Manager/SheetManager.php b/src/Spout/Reader/XLSX/Manager/SheetManager.php
index 1dbcc95..ac400e3 100644
--- a/src/Spout/Reader/XLSX/Manager/SheetManager.php
+++ b/src/Spout/Reader/XLSX/Manager/SheetManager.php
@@ -29,9 +29,13 @@ class SheetManager
const XML_ATTRIBUTE_ACTIVE_TAB = 'activeTab';
const XML_ATTRIBUTE_R_ID = 'r:id';
const XML_ATTRIBUTE_NAME = 'name';
+ const XML_ATTRIBUTE_STATE = 'state';
const XML_ATTRIBUTE_ID = 'Id';
const XML_ATTRIBUTE_TARGET = 'Target';
+ /** State value to represent a hidden sheet */
+ const SHEET_STATE_HIDDEN = 'hidden';
+
/** @var string Path of the XLSX file being read */
protected $filePath;
@@ -163,6 +167,10 @@ class SheetManager
protected function getSheetFromSheetXMLNode($xmlReaderOnSheetNode, $sheetIndexZeroBased, $isSheetActive)
{
$sheetId = $xmlReaderOnSheetNode->getAttribute(self::XML_ATTRIBUTE_R_ID);
+
+ $sheetState = $xmlReaderOnSheetNode->getAttribute(self::XML_ATTRIBUTE_STATE);
+ $isSheetVisible = ($sheetState !== self::SHEET_STATE_HIDDEN);
+
$escapedSheetName = $xmlReaderOnSheetNode->getAttribute(self::XML_ATTRIBUTE_NAME);
$sheetName = $this->escaper->unescape($escapedSheetName);
@@ -174,6 +182,7 @@ class SheetManager
$sheetIndexZeroBased,
$sheetName,
$isSheetActive,
+ $isSheetVisible,
$this->optionsManager,
$this->sharedStringsManager
);
diff --git a/src/Spout/Reader/XLSX/Sheet.php b/src/Spout/Reader/XLSX/Sheet.php
index 592c7c3..575af2d 100644
--- a/src/Spout/Reader/XLSX/Sheet.php
+++ b/src/Spout/Reader/XLSX/Sheet.php
@@ -22,18 +22,23 @@ class Sheet implements SheetInterface
/** @var bool Whether the sheet was the active one */
protected $isActive;
+ /** @var bool Whether the sheet is visible */
+ protected $isVisible;
+
/**
* @param RowIterator $rowIterator The corresponding row iterator
* @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
* @param string $sheetName Name of the sheet
* @param bool $isSheetActive Whether the sheet was defined as active
+ * @param bool $isSheetVisible Whether the sheet is visible
*/
- public function __construct($rowIterator, $sheetIndex, $sheetName, $isSheetActive)
+ public function __construct($rowIterator, $sheetIndex, $sheetName, $isSheetActive, $isSheetVisible)
{
$this->rowIterator = $rowIterator;
$this->index = $sheetIndex;
$this->name = $sheetName;
$this->isActive = $isSheetActive;
+ $this->isVisible = $isSheetVisible;
}
/**
@@ -67,4 +72,12 @@ class Sheet implements SheetInterface
{
return $this->isActive;
}
+
+ /**
+ * @return bool Whether the sheet is visible
+ */
+ public function isVisible()
+ {
+ return $this->isVisible;
+ }
}
diff --git a/src/Spout/Writer/Common/Entity/Sheet.php b/src/Spout/Writer/Common/Entity/Sheet.php
index 5713175..c2f5366 100644
--- a/src/Spout/Writer/Common/Entity/Sheet.php
+++ b/src/Spout/Writer/Common/Entity/Sheet.php
@@ -21,6 +21,9 @@ class Sheet
/** @var string Name of the sheet */
private $name;
+ /** @var bool Visibility of the sheet */
+ private $isVisible;
+
/** @var SheetManager Sheet manager */
private $sheetManager;
@@ -38,6 +41,7 @@ class Sheet
$this->sheetManager->markWorkbookIdAsUsed($associatedWorkbookId);
$this->setName(self::DEFAULT_SHEET_NAME_PREFIX . ($sheetIndex + 1));
+ $this->setIsVisible(true);
}
/**
@@ -85,4 +89,23 @@ class Sheet
return $this;
}
+
+ /**
+ * @return bool isVisible Visibility of the sheet
+ */
+ public function isVisible()
+ {
+ return $this->isVisible;
+ }
+
+ /**
+ * @param bool $isVisible Visibility of the sheet
+ * @return Sheet
+ */
+ public function setIsVisible($isVisible)
+ {
+ $this->isVisible = $isVisible;
+
+ return $this;
+ }
}
diff --git a/src/Spout/Writer/XLSX/Helper/FileSystemHelper.php b/src/Spout/Writer/XLSX/Helper/FileSystemHelper.php
index 8bba670..06d5481 100644
--- a/src/Spout/Writer/XLSX/Helper/FileSystemHelper.php
+++ b/src/Spout/Writer/XLSX/Helper/FileSystemHelper.php
@@ -307,8 +307,9 @@ EOD;
/** @var Worksheet $worksheet */
foreach ($worksheets as $worksheet) {
$worksheetName = $worksheet->getExternalSheet()->getName();
+ $worksheetVisibility = $worksheet->getExternalSheet()->isVisible() ? 'visible' : 'hidden';
$worksheetId = $worksheet->getId();
- $workbookXmlFileContents .= '';
+ $workbookXmlFileContents .= '';
}
$workbookXmlFileContents .= <<<'EOD'
diff --git a/tests/Spout/Reader/XLSX/SheetTest.php b/tests/Spout/Reader/XLSX/SheetTest.php
index b4291fb..96eee4a 100644
--- a/tests/Spout/Reader/XLSX/SheetTest.php
+++ b/tests/Spout/Reader/XLSX/SheetTest.php
@@ -30,6 +30,17 @@ class SheetTest extends \PHPUnit_Framework_TestCase
$this->assertTrue($sheets[1]->isActive());
}
+ /**
+ * @return void
+ */
+ public function testReaderShouldReturnCorrectSheetVisibility()
+ {
+ $sheets = $this->openFileAndReturnSheets('two_sheets_one_hidden_one_not.xlsx');
+
+ $this->assertFalse($sheets[0]->isVisible());
+ $this->assertTrue($sheets[1]->isVisible());
+ }
+
/**
* @param string $fileName
* @return Sheet[]
diff --git a/tests/Spout/Writer/XLSX/SheetTest.php b/tests/Spout/Writer/XLSX/SheetTest.php
index ec636ad..64b276b 100644
--- a/tests/Spout/Writer/XLSX/SheetTest.php
+++ b/tests/Spout/Writer/XLSX/SheetTest.php
@@ -22,7 +22,7 @@ class SheetTest extends \PHPUnit_Framework_TestCase
*/
public function testGetSheetIndex()
{
- $sheets = $this->writeDataToMulitpleSheetsAndReturnSheets('test_get_sheet_index.xlsx');
+ $sheets = $this->writeDataToMultipleSheetsAndReturnSheets('test_get_sheet_index.xlsx');
$this->assertEquals(2, count($sheets), '2 sheets should have been created');
$this->assertEquals(0, $sheets[0]->getIndex(), 'The first sheet should be index 0');
@@ -34,7 +34,7 @@ class SheetTest extends \PHPUnit_Framework_TestCase
*/
public function testGetSheetName()
{
- $sheets = $this->writeDataToMulitpleSheetsAndReturnSheets('test_get_sheet_name.xlsx');
+ $sheets = $this->writeDataToMultipleSheetsAndReturnSheets('test_get_sheet_name.xlsx');
$this->assertEquals(2, count($sheets), '2 sheets should have been created');
$this->assertEquals('Sheet1', $sheets[0]->getName(), 'Invalid name for the first sheet');
@@ -48,7 +48,7 @@ class SheetTest extends \PHPUnit_Framework_TestCase
{
$fileName = 'test_set_name_should_create_sheet_with_custom_name.xlsx';
$customSheetName = 'CustomName';
- $this->writeDataAndReturnSheetWithCustomName($fileName, $customSheetName);
+ $this->writeDataToSheetWithCustomName($fileName, $customSheetName);
$this->assertSheetNameEquals($customSheetName, $fileName, "The sheet name should have been changed to '$customSheetName'");
}
@@ -78,12 +78,27 @@ class SheetTest extends \PHPUnit_Framework_TestCase
$sheet->setName($customSheetName);
}
+ /**
+ * @return void
+ */
+ public function testSetSheetVisibilityShouldCreateSheetHidden()
+ {
+ $fileName = 'test_set_visibility_should_create_sheet_hidden.xlsx';
+ $this->writeDataToHiddenSheet($fileName);
+
+ $resourcePath = $this->getGeneratedResourcePath($fileName);
+ $pathToWorkbookFile = $resourcePath . '#xl/workbook.xml';
+ $xmlContents = file_get_contents('zip://' . $pathToWorkbookFile);
+
+ $this->assertContains(" state=\"hidden\"", $xmlContents, 'The sheet visibility should have been changed to "hidden"');
+ }
+
/**
* @param string $fileName
* @param string $sheetName
* @return Sheet
*/
- private function writeDataAndReturnSheetWithCustomName($fileName, $sheetName)
+ private function writeDataToSheetWithCustomName($fileName, $sheetName)
{
$this->createGeneratedFolderIfNeeded($fileName);
$resourcePath = $this->getGeneratedResourcePath($fileName);
@@ -105,7 +120,7 @@ class SheetTest extends \PHPUnit_Framework_TestCase
* @param string $fileName
* @return Sheet[]
*/
- private function writeDataToMulitpleSheetsAndReturnSheets($fileName)
+ private function writeDataToMultipleSheetsAndReturnSheets($fileName)
{
$this->createGeneratedFolderIfNeeded($fileName);
$resourcePath = $this->getGeneratedResourcePath($fileName);
@@ -123,6 +138,26 @@ class SheetTest extends \PHPUnit_Framework_TestCase
return $writer->getSheets();
}
+ /**
+ * @param string $fileName
+ * @return void
+ */
+ private function writeDataToHiddenSheet($fileName)
+ {
+ $this->createGeneratedFolderIfNeeded($fileName);
+ $resourcePath = $this->getGeneratedResourcePath($fileName);
+
+ /** @var \Box\Spout\Writer\XLSX\Writer $writer */
+ $writer = EntityFactory::createWriter(Type::XLSX);
+ $writer->openToFile($resourcePath);
+
+ $sheet = $writer->getCurrentSheet();
+ $sheet->setIsVisible(false);
+
+ $writer->addRow($this->createRowFromValues(['xlsx--11', 'xlsx--12']));
+ $writer->close();
+ }
+
/**
* @param string $expectedName
* @param string $fileName
diff --git a/tests/resources/xlsx/two_sheets_one_hidden_one_not.xlsx b/tests/resources/xlsx/two_sheets_one_hidden_one_not.xlsx
new file mode 100644
index 0000000..f6d571f
Binary files /dev/null and b/tests/resources/xlsx/two_sheets_one_hidden_one_not.xlsx differ