diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index 368d4ddeaa..9ffe1c4f10 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -832,6 +832,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet ->load($this->getReadFilter(), $this->getReadDataOnly()); } + $holdSelectedCells = $docSheet->getSelectedCells(); if ($xmlSheetNS && $xmlSheetNS->sheetData && $xmlSheetNS->sheetData->row) { $cIndex = 1; // Cell Start from 1 foreach ($xmlSheetNS->sheetData->row as $row) { @@ -968,6 +969,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet ++$cIndex; } } + $docSheet->setSelectedCells($holdSelectedCells); if ($xmlSheetNS && $xmlSheetNS->ignoredErrors) { foreach ($xmlSheetNS->ignoredErrors->ignoredError as $ignoredErrorx) { $ignoredError = self::testSimpleXml($ignoredErrorx); @@ -1007,23 +1009,30 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet $unparsedLoadedData = (new PageSetup($docSheet, $xmlSheet))->load($unparsedLoadedData); } - if ($xmlSheet !== false && isset($xmlSheet->extLst, $xmlSheet->extLst->ext, $xmlSheet->extLst->ext['uri']) && ($xmlSheet->extLst->ext['uri'] == '{CCE6A557-97BC-4b89-ADB6-D9C93CAAB3DF}')) { - // Create dataValidations node if does not exists, maybe is better inside the foreach ? - if (!$xmlSheet->dataValidations) { - $xmlSheet->addChild('dataValidations'); - } - - foreach ($xmlSheet->extLst->ext->children(Namespaces::DATA_VALIDATIONS1)->dataValidations->dataValidation as $item) { - $item = self::testSimpleXml($item); - $node = self::testSimpleXml($xmlSheet->dataValidations)->addChild('dataValidation'); - foreach ($item->attributes() ?? [] as $attr) { - $node->addAttribute($attr->getName(), $attr); + if ($xmlSheet !== false && isset($xmlSheet->extLst->ext)) { + foreach ($xmlSheet->extLst->ext as $extlst) { + $extAttrs = $extlst->/** @scrutinizer ignore-call */ attributes() ?? []; + $extUri = (string) ($extAttrs['uri'] ?? ''); + if ($extUri !== '{CCE6A557-97BC-4b89-ADB6-D9C93CAAB3DF}') { + continue; } - $node->addAttribute('sqref', $item->children(Namespaces::DATA_VALIDATIONS2)->sqref); - if (isset($item->formula1)) { - $childNode = $node->addChild('formula1'); - if ($childNode !== null) { // null should never happen - $childNode[0] = (string) $item->formula1->children(Namespaces::DATA_VALIDATIONS2)->f; // @phpstan-ignore-line + // Create dataValidations node if does not exists, maybe is better inside the foreach ? + if (!$xmlSheet->dataValidations) { + $xmlSheet->addChild('dataValidations'); + } + + foreach ($extlst->children(Namespaces::DATA_VALIDATIONS1)->dataValidations->dataValidation as $item) { + $item = self::testSimpleXml($item); + $node = self::testSimpleXml($xmlSheet->dataValidations)->addChild('dataValidation'); + foreach ($item->attributes() ?? [] as $attr) { + $node->addAttribute($attr->getName(), $attr); + } + $node->addAttribute('sqref', $item->children(Namespaces::DATA_VALIDATIONS2)->sqref); + if (isset($item->formula1)) { + $childNode = $node->addChild('formula1'); + if ($childNode !== null) { // null should never happen + $childNode[0] = (string) $item->formula1->children(Namespaces::DATA_VALIDATIONS2)->f; // @phpstan-ignore-line + } } } } @@ -1475,10 +1484,13 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet foreach ($xmlDrawingChildren->twoCellAnchor as $twoCellAnchor) { $twoCellAnchor = self::testSimpleXml($twoCellAnchor); if ($twoCellAnchor->pic->blipFill) { + $objDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing(); $blip = $twoCellAnchor->pic->blipFill->children(Namespaces::DRAWINGML)->blip; + if (isset($twoCellAnchor->pic->blipFill->children(Namespaces::DRAWINGML)->srcRect)) { + $objDrawing->setSrcRect($twoCellAnchor->pic->blipFill->children(Namespaces::DRAWINGML)->srcRect->attributes()); + } $xfrm = $twoCellAnchor->pic->spPr->children(Namespaces::DRAWINGML)->xfrm; $outerShdw = $twoCellAnchor->pic->spPr->children(Namespaces::DRAWINGML)->effectLst->outerShdw; - $objDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing(); /** @scrutinizer ignore-call */ $editAs = $twoCellAnchor->attributes(); if (isset($editAs, $editAs['editAs'])) { diff --git a/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php b/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php index 59bf5b84eb..ca1cf978fd 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php @@ -74,9 +74,17 @@ private function setConditionalsFromExt(array $conditionals): void private function readConditionalsFromExt(SimpleXMLElement $extLst, StyleReader $styleReader): array { $conditionals = []; + if (!isset($extLst->ext)) { + return $conditionals; + } - if (isset($extLst->ext['uri']) && (string) $extLst->ext['uri'] === '{78C0D931-6437-407d-A8EE-F0AAD7539E65}') { - $conditionalFormattingRuleXml = $extLst->ext->children($this->ns['x14']); + foreach ($extLst->ext as $extlstcond) { + $extAttrs = $extlstcond->/** @scrutinizer ignore-call */ attributes() ?? []; + $extUri = (string) ($extAttrs['uri'] ?? ''); + if ($extUri !== '{78C0D931-6437-407d-A8EE-F0AAD7539E65}') { + continue; + } + $conditionalFormattingRuleXml = $extlstcond->children($this->ns['x14']); if (!$conditionalFormattingRuleXml->conditionalFormattings) { return []; } diff --git a/src/PhpSpreadsheet/Worksheet/BaseDrawing.php b/src/PhpSpreadsheet/Worksheet/BaseDrawing.php index 5001346ad5..0226e6852b 100644 --- a/src/PhpSpreadsheet/Worksheet/BaseDrawing.php +++ b/src/PhpSpreadsheet/Worksheet/BaseDrawing.php @@ -5,6 +5,7 @@ use PhpOffice\PhpSpreadsheet\Cell\Hyperlink; use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException; use PhpOffice\PhpSpreadsheet\IComparable; +use SimpleXMLElement; class BaseDrawing implements IComparable { @@ -164,6 +165,9 @@ class BaseDrawing implements IComparable */ protected $type = IMAGETYPE_UNKNOWN; + /** @var null|SimpleXMLElement|string[] */ + protected $srcRect = []; + /** * Create a new BaseDrawing. */ @@ -532,4 +536,22 @@ public function validEditAs(): bool { return in_array($this->editAs, self::VALID_EDIT_AS, true); } + + /** + * @return null|SimpleXMLElement|string[] + */ + public function getSrcRect() + { + return $this->srcRect; + } + + /** + * @param null|SimpleXMLElement|string[] $srcRect + */ + public function setSrcRect($srcRect): self + { + $this->srcRect = $srcRect; + + return $this; + } } diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php b/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php index f5f5eeeb45..5a5775882c 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php @@ -270,10 +270,21 @@ public function writeDrawing(XMLWriter $objWriter, BaseDrawing $drawing, $relati $objWriter->writeAttribute('r:embed', 'rId' . $relationId); $objWriter->endElement(); - // a:stretch - $objWriter->startElement('a:stretch'); - $objWriter->writeElement('a:fillRect', null); - $objWriter->endElement(); + $srcRect = $drawing->getSrcRect(); + if (!empty($srcRect)) { + $objWriter->startElement('a:srcRect'); + foreach ($srcRect as $key => $value) { + $objWriter->writeAttribute($key, (string) $value); + } + $objWriter->endElement(); // a:srcRect + $objWriter->startElement('a:stretch'); + $objWriter->endElement(); // a:stretch + } else { + // a:stretch + $objWriter->startElement('a:stretch'); + $objWriter->writeElement('a:fillRect', null); + $objWriter->endElement(); + } $objWriter->endElement(); diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue3679ImgTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue3679ImgTest.php new file mode 100644 index 0000000000..2b9559073f --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue3679ImgTest.php @@ -0,0 +1,31 @@ +load($file); + + $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx'); + $spreadsheet->disconnectWorksheets(); + $sheet = $reloadedSpreadsheet->getActiveSheet(); + $drawings = $sheet->getDrawingCollection(); + self::assertCount(1, $drawings); + if ($drawings[0] === null) { + self::fail('Unexpected null drawing'); + } else { + $srcRect = $drawings[0]->getSrcRect(); + self::assertSame('448', (string) ($srcRect['r'] ?? '')); + self::assertSame('65769', (string) ($srcRect['b'] ?? '')); + } + + $reloadedSpreadsheet->disconnectWorksheets(); + } +} diff --git a/tests/data/Reader/XLSX/issue.3679.img.xlsx b/tests/data/Reader/XLSX/issue.3679.img.xlsx new file mode 100644 index 0000000000..e63da0a32f Binary files /dev/null and b/tests/data/Reader/XLSX/issue.3679.img.xlsx differ