Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 2216 resolve office365 auto filter structure move #2218

Merged
Prev Previous commit
Next Next commit
Refactor AutoFilter Reader logic into separate methods; preparatory w…
…ork toward the eventual goal of moving it into its own dedicated AutoFilterTables class
  • Loading branch information
MarkBaker committed Jul 9, 2021
commit 0bcceab0e8778db401347198616b28a967400bab
74 changes: 62 additions & 12 deletions src/PhpSpreadsheet/Reader/Xlsx.php
Original file line number Diff line number Diff line change
Expand Up @@ -847,18 +847,7 @@ public function load(string $pFilename, int $flags = 0): Spreadsheet
}

if ($this->readDataOnly === false) {
if ($xmlSheet && $xmlSheet->autoFilter) {
(new AutoFilter($docSheet, $xmlSheet))->load();
} elseif ($xmlSheet && $xmlSheet->tableParts && $xmlSheet->tableParts['count'] > 0) {
foreach ($xmlSheet->tableParts->children('') as $tablePart) {
$ele = self::getAttributes($tablePart, 'r');
var_dump($ele);
if ($this->fileExistsInArchive($this->zip, "xl/tables/table1.xml")) {
$autoFilter = $this->loadZip("xl/tables/table1.xml");
(new AutoFilter($docSheet, $autoFilter))->load();
}
}
}
$this->readAutoFilterTables($xmlSheet, $docSheet, $dir, $fileWorksheet, $zip);
}

if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->readDataOnly) {
Expand Down Expand Up @@ -2013,4 +2002,65 @@ private function readSheetProtection(Worksheet $docSheet, SimpleXMLElement $xmlS
}
}
}

/**
* @param SimpleXMLElement $xmlSheet
* @param Worksheet $docSheet
* @param string $dir
* @param $fileWorksheet
* @param ZipArchive $zip
* @return string
*/
private function readAutoFilterTables(
SimpleXMLElement $xmlSheet,
Worksheet $docSheet,
string $dir,
string $fileWorksheet,
ZipArchive $zip
): void {
if ($xmlSheet && $xmlSheet->autoFilter) {
// In older files, autofilter structure is defined in the worksheet file
(new AutoFilter($docSheet, $xmlSheet))->load();
} elseif ($xmlSheet && $xmlSheet->tableParts && $xmlSheet->tableParts['count'] > 0) {
// But for Office365, MS decided to make it all just a bit more complicated
$this->readAutoFilterTablesInTablesFile($xmlSheet, $dir, $fileWorksheet, $zip, $docSheet);
}
}

/**
* @param SimpleXMLElement $xmlSheet
* @param string $dir
* @param string $fileWorksheet
* @param ZipArchive $zip
* @param Worksheet $docSheet
*/
private function readAutoFilterTablesInTablesFile(
SimpleXMLElement $xmlSheet,
string $dir,
string $fileWorksheet,
ZipArchive $zip,
Worksheet $docSheet
): void {
foreach ($xmlSheet->tableParts->tablePart as $tablePart) {
$relation = self::getAttributes($tablePart, Namespaces::SCHEMA_OFFICE_DOCUMENT);
$tablePartRel = (string)$relation['id'];
$relationsFileName = dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels';
if ($zip->locateName($relationsFileName)) {
$relsTableReferences = $this->loadZip($relationsFileName, Namespaces::RELATIONSHIPS);
foreach ($relsTableReferences->Relationship as $relationship) {
$relationshipAttributes = self::getAttributes($relationship, '');
if ((string)$relationshipAttributes['Id'] === $tablePartRel) {
$relationshipFileName = (string)$relationshipAttributes['Target'];

$relationshipFilePath = dirname("$dir/$fileWorksheet") . '/' . $relationshipFileName;
$relationshipFilePath = File::realpath($relationshipFilePath);
if ($this->fileExistsInArchive($this->zip, $relationshipFilePath)) {
$autoFilter = $this->loadZip($relationshipFilePath);
(new AutoFilter($docSheet, $autoFilter))->load();
}
}
}
}
}
}
}