nfTlWNl rn Ѻq$³*LJ0Y8i(?q;m ^*Ogص\`Lٔ*ܝIcQj Q@~DD]f'މb1ʖQt_Ĩ ް =-f0ZRд-,F~iY@P <ⓙ}]w&]T89!9 <I@q떊,2fZˎ n6$Mýy#|)xm0{>5ݳ],_Ng$#i*xJ| ,]YIǦKRmn+~JV *H2Hܻfqs؟=ŅGID4>Uꈋi R]-{!0ĐbnN%*40O[2uXix;7#r<]рϷwNW+,0қU1pHe:QRMџZDW/e \{ߨj_}I.2SSN8٩LpH@=+|?s"j@,Q88TBeq0xNy#eMݒ?'ްΖS:x|dŰBྖ脭輣}0hx3%^(1Aѩ1чhBappu0c 9Ay³Z.ŏ Y~-QN~vtH 8jڋ]Vy3@'_G>ZO2ËHmk޸2CܟF}^6W&,ܑQY(j=JVf"\v*;Tw@ əcB E=ǜSrBr?*)BW^X[GIlmɳnYfbǹ`V*Jo`o[q2yMiCh$9i^ d. PZt^[ܭ=܃f`pz@-9mm ;S9gLȭS,!"ͮ|mP)3{q-6\Uױ}9L{E@,fw2S>J퐪߷oov={ C9>}TG/0 OR= &I ^>_8Fga Wn񋪦ѷ>>MnZ6rr_Sj7L+7u [t]4 ĢQ$3}F7+zӕ>'9.ak\"aFk?R/TPȣ[$%uw`uOCWVm$>`x*9C+b00EMpaBDF 5q͗#kK'#`.6 Y\Tb^q~+\Tr}VH=ohBφtYa("J{h) gSO1H@*KK.h{Cxv-eIzLv]֒`γ(L 튴kxb o Dk>sAJjPbJ扥8lf7܇– Ͷ)x&y`_[E#M YYsc<篂y#A)3ԭ5rC]# ~r;/U_=] y`p9#i*#K -3YzĒ{p]_`-'ЂeLQM$du%/b}pũu _;஡lㆡ2s3N*T'.'æLI>a}~Ԃu6|eLdƫ7Z[nw=-Y ov5k L␮FHaM&634)$@`)@v ler\hXi֨qy0{f7M*lQKfV6acU 0C 9[ㅚkC"եL[D*L/#gBkE"8~jBwY6VyeɌ}=NlW4#a^?O76~@Ng/ I)8 zE`A=$f#MlQyK|rg'k>2ߨl23n8jh|'\p.Ǜʦ6&kk-@dGm҈lEЫCC=KfTH|J*vbG3OEjqź%rT x \OzFho:WՃ܋~rfid%V[PsRvڭ|6 ˆeaLo>%mntyϪ=a.z|4Gg.aٳeΏV6>]64"# #VH6%)e}[#gBkEtquP"FRi!_7)츏<8 ""ἣeD7H"cٽmnp ĢQ$3 $fontStyle->setSuperscript(true); } elseif ($verticalAlign === 'subscript') { $fontStyle->setSubscript(true); } } } if (isset($fontStyleXml->scheme)) { $attr = $this->getStyleAttributes($fontStyleXml->scheme); $fontStyle->setScheme((string) $attr['val']); } } private function readNumberFormat(NumberFormat $numfmtStyle, SimpleXMLElement $numfmtStyleXml): void { if ((string) $numfmtStyleXml['formatCode'] !== '') { $numfmtStyle->setFormatCode(self::formatGeneral((string) $numfmtStyleXml['formatCode'])); return; } $numfmt = $this->getStyleAttributes($numfmtStyleXml); if (isset($numfmt['formatCode'])) { $numfmtStyle->setFormatCode(self::formatGeneral((string) $numfmt['formatCode'])); } } public function readFillStyle(Fill $fillStyle, SimpleXMLElement $fillStyleXml): void { if ($fillStyleXml->gradientFill) { /** @var SimpleXMLElement $gradientFill */ $gradientFill = $fillStyleXml->gradientFill[0]; $attr = $this->getStyleAttributes($gradientFill); if (!empty($attr['type'])) { $fillStyle->setFillType((string) $attr['type']); } $fillStyle->setRotation((float) ($attr['degree'])); $gradientFill->registerXPathNamespace('sml', Namespaces::MAIN); $fillStyle->getStartColor()->setARGB($this->readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=0]'))->color)); $fillStyle->getEndColor()->setARGB($this->readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=1]'))->color)); } elseif ($fillStyleXml->patternFill) { $defaultFillStyle = Fill::FILL_NONE; if ($fillStyleXml->patternFill->fgColor) { $fillStyle->getStartColor()->setARGB($this->readColor($fillStyleXml->patternFill->fgColor, true)); $defaultFillStyle = Fill::FILL_SOLID; } if ($fillStyleXml->patternFill->bgColor) { $fillStyle->getEndColor()->setARGB($this->readColor($fillStyleXml->patternFill->bgColor, true)); $defaultFillStyle = Fill::FILL_SOLID; } $type = ''; if ((string) $fillStyleXml->patternFill['patternType'] !== '') { $type = (string) $fillStyleXml->patternFill['patternType']; } else { $attr = $this->getStyleAttributes($fillStyleXml->patternFill); $type = (string) $attr['patternType']; } $patternType = ($type === '') ? $defaultFillStyle : $type; $fillStyle->setFillType($patternType); } } public function readBorderStyle(Borders $borderStyle, SimpleXMLElement $borderStyleXml): void { $diagonalUp = $this->getAttribute($borderStyleXml, 'diagonalUp'); $diagonalUp = self::boolean($diagonalUp); $diagonalDown = $this->getAttribute($borderStyleXml, 'diagonalDown'); $diagonalDown = self::boolean($diagonalDown); if ($diagonalUp === false) { if ($diagonalDown === false) { $borderStyle->setDiagonalDirection(Borders::DIAGONAL_NONE); } else { $borderStyle->setDiagonalDirection(Borders::DIAGONAL_DOWN); } } elseif ($diagonalDown === false) { $borderStyle->setDiagonalDirection(Borders::DIAGONAL_UP); } else { $borderStyle->setDiagonalDirection(Borders::DIAGONAL_BOTH); } if (isset($borderStyleXml->left)) { $this->readBorder($borderStyle->getLeft(), $borderStyleXml->left); } if (isset($borderStyleXml->right)) { $this->readBorder($borderStyle->getRight(), $borderStyleXml->right); } if (isset($borderStyleXml->top)) { $this->readBorder($borderStyle->getTop(), $borderStyleXml->top); } if (isset($borderStyleXml->bottom)) { $this->readBorder($borderStyle->getBottom(), $borderStyleXml->bottom); } if (isset($borderStyleXml->diagonal)) { $this->readBorder($borderStyle->getDiagonal(), $borderStyleXml->diagonal); } } private function getAttribute(SimpleXMLElement $xml, string $attribute): string { $style = ''; if ((string) $xml[$attribute] !== '') { $style = (string) $xml[$attribute]; } else { $attr = $this->getStyleAttributes($xml); if (isset($attr[$attribute])) { $style = (string) $attr[$attribute]; } } return $style; } private function readBorder(Border $border, SimpleXMLElement $borderXml): void { $style = $this->getAttribute($borderXml, 'style'); if ($style !== '') { $border->setBorderStyle((string) $style); } else { $border->setBorderStyle(Border::BORDER_NONE); } if (isset($borderXml->color)) { $border->getColor()->setARGB($this->readColor($borderXml->color)); } } public function readAlignmentStyle(Alignment $alignment, SimpleXMLElement $alignmentXml): void { $horizontal = (string) $this->getAttribute($alignmentXml, 'horizontal'); if ($horizontal !== '') { $alignment->setHorizontal($horizontal); } $vertical = (string) $this->getAttribute($alignmentXml, 'vertical'); if ($vertical !== '') { $alignment->setVertical($vertical); } $textRotation = (int) $this->getAttribute($alignmentXml, 'textRotation'); if ($textRotation > 90) { $textRotation = 90 - $textRotation; } $alignment->setTextRotation($textRotation); $wrapText = $this->getAttribute($alignmentXml, 'wrapText'); $alignment->setWrapText(self::boolean((string) $wrapText)); $shrinkToFit = $this->getAttribute($alignmentXml, 'shrinkToFit'); $alignment->setShrinkToFit(self::boolean((string) $shrinkToFit)); $indent = (int) $this->getAttribute($alignmentXml, 'indent'); $alignment->setIndent(max($indent, 0)); $readingOrder = (int) $this->getAttribute($alignmentXml, 'readingOrder'); $alignment->setReadOrder(max($readingOrder, 0)); } private static function formatGeneral(string $formatString): string { if ($formatString === 'GENERAL') { $formatString = NumberFormat::FORMAT_GENERAL; } return $formatString; } /** * Read style. * * @param SimpleXMLElement|stdClass $style */ public function readStyle(Style $docStyle, $style): void { if ($style instanceof SimpleXMLElement) { $this->readNumberFormat($docStyle->getNumberFormat(), $style->numFmt); } else { $docStyle->getNumberFormat()->setFormatCode(self::formatGeneral((string) $style->numFmt)); } if (isset($style->font)) { $this->readFontStyle($docStyle->getFont(), $style->font); } if (isset($style->fill)) { $this->readFillStyle($docStyle->getFill(), $style->fill); } if (isset($style->border)) { $this->readBorderStyle($docStyle->getBorders(), $style->border); } if (isset($style->alignment)) { $this->readAlignmentStyle($docStyle->getAlignment(), $style->alignment); } // protection if (isset($style->protection)) { $this->readProtectionLocked($docStyle, $style->protection); $this->readProtectionHidden($docStyle, $style->protection); } // top-level style settings if (isset($style->quotePrefix)) { $docStyle->setQuotePrefix((bool) $style->quotePrefix); } } /** * Read protection locked attribute. */ public function readProtectionLocked(Style $docStyle, SimpleXMLElement $style): void { $locked = ''; if ((string) $style['locked'] !== '') { $locked = (string) $style['locked']; } else { $attr = $this->getStyleAttributes($style); if (isset($attr['locked'])) { $locked = (string) $attr['locked']; } } if ($locked !== '') { if (self::boolean($locked)) { $docStyle->getProtection()->setLocked(Protection::PROTECTION_PROTECTED); } else { $docStyle->getProtection()->setLocked(Protection::PROTECTION_UNPROTECTED); } } } /** * Read protection hidden attribute. */ public function readProtectionHidden(Style $docStyle, SimpleXMLElement $style): void { $hidden = ''; if ((string) $style['hidden'] !== '') { $hidden = (string) $style['hidden']; } else { $attr = $this->getStyleAttributes($style); if (isset($attr['hidden'])) { $hidden = (string) $attr['hidden']; } } if ($hidden !== '') { if (self::boolean((string) $hidden)) { $docStyle->getProtection()->setHidden(Protection::PROTECTION_PROTECTED); } else { $docStyle->getProtection()->setHidden(Protection::PROTECTION_UNPROTECTED); } } } public function readColor(SimpleXMLElement $color, bool $background = false): string { $attr = $this->getStyleAttributes($color); if (isset($attr['rgb'])) { return (string) $attr['rgb']; } if (isset($attr['indexed'])) { $indexedColor = (int) $attr['indexed']; if ($indexedColor >= count($this->workbookPalette)) { return Color::indexedColor($indexedColor - 7, $background)->getARGB() ?? ''; } return Color::indexedColor($indexedColor, $background, $this->workbookPalette)->getARGB() ?? ''; } if (isset($attr['theme'])) { if ($this->theme !== null) { $returnColour = $this->theme->getColourByIndex((int) $attr['theme']); if (isset($attr['tint'])) { $tintAdjust = (float) $attr['tint']; $returnColour = Color::changeBrightness($returnColour ?? '', $tintAdjust); } return 'FF' . $returnColour; } } return ($background) ? 'FFFFFFFF' : 'FF000000'; } public function dxfs(bool $readDataOnly = false): array { $dxfs = []; if (!$readDataOnly && $this->styleXml) { // Conditional Styles if ($this->styleXml->dxfs) { foreach ($this->styleXml->dxfs->dxf as $dxf) { $style = new Style(false, true); $this->readStyle($style, $dxf); $dxfs[] = $style; } } // Cell Styles if ($this->styleXml->cellStyles) { foreach ($this->styleXml->cellStyles->cellStyle as $cellStylex) { $cellStyle = Xlsx::getAttributes($cellStylex); if ((int) ($cellStyle['builtinId']) == 0) { if (isset($this->cellStyles[(int) ($cellStyle['xfId'])])) { // Set default style $style = new Style(); $this->readStyle($style, $this->cellStyles[(int) ($cellStyle['xfId'])]); // normal style, currently not using it for anything } } } } } return $dxfs; } public function styles(): array { return $this->styles; } /** * Get array item. * * @param mixed $array (usually array, in theory can be false) * * @return stdClass */ private static function getArrayItem($array, int $key = 0) { return is_array($array) ? ($array[$key] ?? null) : null; } }