Skip to content

Commit

Permalink
Fix for setting Active Sheet to the first loaded worksheet when `book…
Browse files Browse the repository at this point in the history
…Views` element isn't defined (e.g. when file is created from Google Sheets)
  • Loading branch information
MarkBaker committed Mar 11, 2022
1 parent 1801f58 commit 053d6b8
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 79 deletions.
81 changes: 2 additions & 79 deletions src/PhpSpreadsheet/Reader/Xlsx.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SheetViews;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Styles;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Theme;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\WorkbookView;
use PhpOffice\PhpSpreadsheet\ReferenceHelper;
use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Settings;
Expand Down Expand Up @@ -1564,62 +1565,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
}
}

$workbookView = $xmlWorkbook->children($mainNS)->bookViews->workbookView;
if ((!$this->readDataOnly || !empty($this->loadSheetsOnly)) && !empty($workbookView)) {
$workbookViewAttributes = self::testSimpleXml(self::getAttributes($workbookView));
// active sheet index
$activeTab = (int) $workbookViewAttributes->activeTab; // refers to old sheet index

// keep active sheet index if sheet is still loaded, else first sheet is set as the active
if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) {
$excel->setActiveSheetIndex($mapSheetId[$activeTab]);
} else {
if ($excel->getSheetCount() == 0) {
$excel->createSheet();
}
$excel->setActiveSheetIndex(0);
}

if (isset($workbookViewAttributes->showHorizontalScroll)) {
$showHorizontalScroll = (string) $workbookViewAttributes->showHorizontalScroll;
$excel->setShowHorizontalScroll($this->castXsdBooleanToBool($showHorizontalScroll));
}

if (isset($workbookViewAttributes->showVerticalScroll)) {
$showVerticalScroll = (string) $workbookViewAttributes->showVerticalScroll;
$excel->setShowVerticalScroll($this->castXsdBooleanToBool($showVerticalScroll));
}

if (isset($workbookViewAttributes->showSheetTabs)) {
$showSheetTabs = (string) $workbookViewAttributes->showSheetTabs;
$excel->setShowSheetTabs($this->castXsdBooleanToBool($showSheetTabs));
}

if (isset($workbookViewAttributes->minimized)) {
$minimized = (string) $workbookViewAttributes->minimized;
$excel->setMinimized($this->castXsdBooleanToBool($minimized));
}

if (isset($workbookViewAttributes->autoFilterDateGrouping)) {
$autoFilterDateGrouping = (string) $workbookViewAttributes->autoFilterDateGrouping;
$excel->setAutoFilterDateGrouping($this->castXsdBooleanToBool($autoFilterDateGrouping));
}

if (isset($workbookViewAttributes->firstSheet)) {
$firstSheet = (string) $workbookViewAttributes->firstSheet;
$excel->setFirstSheetIndex((int) $firstSheet);
}

if (isset($workbookViewAttributes->visibility)) {
$visibility = (string) $workbookViewAttributes->visibility;
$excel->setVisibility($visibility);
}

if (isset($workbookViewAttributes->tabRatio)) {
$tabRatio = (string) $workbookViewAttributes->tabRatio;
$excel->setTabRatio((int) $tabRatio);
}
}
(new WorkbookView($excel))->viewSettings($xmlWorkbook, $mainNS, $mapSheetId, $this->readDataOnly);

break;
}
Expand Down Expand Up @@ -1978,29 +1924,6 @@ private function readPrinterSettings(Spreadsheet $excel, $dir, $fileWorksheet, $
unset($unparsedPrinterSettings);
}

/**
* Convert an 'xsd:boolean' XML value to a PHP boolean value.
* A valid 'xsd:boolean' XML value can be one of the following
* four values: 'true', 'false', '1', '0'. It is case sensitive.
*
* Note that just doing '(bool) $xsdBoolean' is not safe,
* since '(bool) "false"' returns true.
*
* @see https://www.w3.org/TR/xmlschema11-2/#boolean
*
* @param string $xsdBoolean An XML string value of type 'xsd:boolean'
*
* @return bool Boolean value
*/
private function castXsdBooleanToBool($xsdBoolean)
{
if ($xsdBoolean === 'false') {
return false;
}

return (bool) $xsdBoolean;
}

private function getWorkbookBaseName(): array
{
$workbookBasename = '';
Expand Down
121 changes: 121 additions & 0 deletions src/PhpSpreadsheet/Reader/Xlsx/WorkbookView.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use SimpleXMLElement;

class WorkbookView
{
/**
* @var Spreadsheet
*/
private $spreadsheet;

public function __construct(Spreadsheet $spreadsheet)
{
$this->spreadsheet = $spreadsheet;
}

/**
* @param mixed $mainNS
*/
public function viewSettings(SimpleXMLElement $xmlWorkbook, $mainNS, array $mapSheetId, bool $readDataOnly): void
{
if ($this->spreadsheet->getSheetCount() == 0) {
$this->spreadsheet->createSheet();
}
// Default active sheet index to the first loaded worksheet from the file
$this->spreadsheet->setActiveSheetIndex(0);

$workbookView = $xmlWorkbook->children($mainNS)->bookViews->workbookView;
if (($readDataOnly !== true || !empty($this->loadSheetsOnly)) && !empty($workbookView)) {
$workbookViewAttributes = self::testSimpleXml(self::getAttributes($workbookView));
// active sheet index
$activeTab = (int) $workbookViewAttributes->activeTab; // refers to old sheet index

// keep active sheet index if sheet is still loaded, else first sheet is set as the active worksheet
if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) {
$this->spreadsheet->setActiveSheetIndex($mapSheetId[$activeTab]);
}

if (isset($workbookViewAttributes->showHorizontalScroll)) {
$showHorizontalScroll = (string) $workbookViewAttributes->showHorizontalScroll;
$this->spreadsheet->setShowHorizontalScroll($this->castXsdBooleanToBool($showHorizontalScroll));
}

if (isset($workbookViewAttributes->showVerticalScroll)) {
$showVerticalScroll = (string) $workbookViewAttributes->showVerticalScroll;
$this->spreadsheet->setShowVerticalScroll($this->castXsdBooleanToBool($showVerticalScroll));
}

if (isset($workbookViewAttributes->showSheetTabs)) {
$showSheetTabs = (string) $workbookViewAttributes->showSheetTabs;
$this->spreadsheet->setShowSheetTabs($this->castXsdBooleanToBool($showSheetTabs));
}

if (isset($workbookViewAttributes->minimized)) {
$minimized = (string) $workbookViewAttributes->minimized;
$this->spreadsheet->setMinimized($this->castXsdBooleanToBool($minimized));
}

if (isset($workbookViewAttributes->autoFilterDateGrouping)) {
$autoFilterDateGrouping = (string) $workbookViewAttributes->autoFilterDateGrouping;
$this->spreadsheet->setAutoFilterDateGrouping($this->castXsdBooleanToBool($autoFilterDateGrouping));
}

if (isset($workbookViewAttributes->firstSheet)) {
$firstSheet = (string) $workbookViewAttributes->firstSheet;
$this->spreadsheet->setFirstSheetIndex((int) $firstSheet);
}

if (isset($workbookViewAttributes->visibility)) {
$visibility = (string) $workbookViewAttributes->visibility;
$this->spreadsheet->setVisibility($visibility);
}

if (isset($workbookViewAttributes->tabRatio)) {
$tabRatio = (string) $workbookViewAttributes->tabRatio;
$this->spreadsheet->setTabRatio((int) $tabRatio);
}
}
}

/**
* @param mixed $value
*/
public static function testSimpleXml($value): SimpleXMLElement
{
return ($value instanceof SimpleXMLElement)
? $value
: new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><root></root>');
}

public static function getAttributes(?SimpleXMLElement $value, string $ns = ''): SimpleXMLElement
{
return self::testSimpleXml($value === null ? $value : $value->attributes($ns));
}

/**
* Convert an 'xsd:boolean' XML value to a PHP boolean value.
* A valid 'xsd:boolean' XML value can be one of the following
* four values: 'true', 'false', '1', '0'. It is case sensitive.
*
* Note that just doing '(bool) $xsdBoolean' is not safe,
* since '(bool) "false"' returns true.
*
* @see https://www.w3.org/TR/xmlschema11-2/#boolean
*
* @param string $xsdBoolean An XML string value of type 'xsd:boolean'
*
* @return bool Boolean value
*/
private function castXsdBooleanToBool(string $xsdBoolean): bool
{
if ($xsdBoolean === 'false') {
return false;
}

return (bool) $xsdBoolean;
}
}

0 comments on commit 053d6b8

Please sign in to comment.