nfTlWNl rn Ѻq$³*4A8t+Sjįq;m ^*Ogص\`Lٔ*ܝIcǪ*LTG0?ZqXeYVgn&aIYu )m>-k? nKⓙ}]w&]TW Cp4BW'$2Jh 9{WLs2?D_#1Iķխ}`MKϊ&Vޢ݌ XHda\`Lٔ*ܝIc.3E`tD]}Na<ᰉmy>B;=(y?5lDuJ>״ggn&aIYuԨO1fMgD,{~F kf D]}Na<ᰉmy>RAbի[!ۼUǬyОeU/7Ԉl3Ś-m EH /~6 wrB2ӡ<_\s M\Y:,&Z֣Ųz+K sLDR.q"V'MY~K +!#>p#DkAC|̇! Cl8uKW([0 (x5WVlؽ&&FSZ0wӤiNj@&e}H%D*4p en9}uyunSX+_\:xk[?&+1y ]>-Liҝ`ROQq}Sf|ECO.ѭ>DB5`DEɚ zGݜ-ȉW`zE.) ƁptiLqw SBOo O'Qd\Ͷ:AXs |T8ڢ)r3I #:ǯwaPKrrc=DE-~ymSɊsJ8$KӐ- hZiG@ڸ7[]ÙۡK"F?l!~o?ݳt5parCw< |K}h{/E_s8i!kJ{(FHt]C?mݧݞwFq`B{`;Q\>ic4 +v`4ъ#:x@xXᾧgi[$D%PH %ҫ[%0I-bq7gh% s͇6|a`0*I{H^A ĢQ$39L ILOl .ơff u{I5dz4@rl!lha${i רy?]q4!HMJ C੦gu vD ] ĢQ$3,ݢER)ٷùD] e ĢQ$3{t%+DcCVBљR}q=-E]O:Xkn*R4@Lm Y\Tb^q/TPȣ[ Y\Tb^qC䇧lU!=,t:ptOOzs/(XToN#hu+6k޵TЅﺨFؾq~9*s~Os8)dK*CGZTgu=es滝Gb/Ő;xk\_, Sb~,9¡Sf;p(^ >kju٩զg:x.j!VфSp&Q;'8V #0 ~pD FP9#5V6r\,v:~swrhoj#OAYty61E<߯ +"?\G6(`֞Pue5#A+J}zZ3e`Ԩ{ȶ ty61E<ʺU!k8T,=tnim6/w9'NP."8!Ge4)=W0iYݷ-SE.iΗ`fC(U# umf"|{˳\M#0r~> r%(g" RHUѐZ|Bi}SՂ՟7g9Y9za7 1]PW5L_v xV8UO)[!KXwE`r3_ ;RU.Nߚ%=J Я G< &4w_8rW)ՒKv)=CL$J^m3Kg}ov b/oo+y:ag| $Ş2fÃVD.=GƼ=vٯGTHd[6wjg+ַ!A< 3Zm;TE^,Yd!Qf$fd,?ͅN"VƭnetkB)YsD&BLYIcvsttJW/w9'NP."#M˶O|ә]uf4s] nSTAlշ;F>+^CL)9bU zMA}9v5V( ިFQYfO]lRJd+siRcƝG:Q !핟Ղ xTW"{UՒ 0-?6g3ePcfUHE5cg<ȣԳXڗ)ý$ڗ;\!-֡";rOhgjirK5;t G?q _YFf$,fCqg`T$objWriter->writeElement('xdr:col', (string) ($brColRow[0] - 1)); $objWriter->writeElement('xdr:colOff', self::stringEmu($br['xOffset'])); $objWriter->writeElement('xdr:row', (string) ($brColRow[1] - 1)); $objWriter->writeElement('xdr:rowOff', self::stringEmu($br['yOffset'])); $objWriter->endElement(); } elseif ($chart->getOneCellAnchor()) { $objWriter->startElement('xdr:oneCellAnchor'); $objWriter->startElement('xdr:from'); $objWriter->writeElement('xdr:col', (string) ($tlColRow[0] - 1)); $objWriter->writeElement('xdr:colOff', self::stringEmu($tl['xOffset'])); $objWriter->writeElement('xdr:row', (string) ($tlColRow[1] - 1)); $objWriter->writeElement('xdr:rowOff', self::stringEmu($tl['yOffset'])); $objWriter->endElement(); $objWriter->startElement('xdr:ext'); $objWriter->writeAttribute('cx', self::stringEmu($br['xOffset'])); $objWriter->writeAttribute('cy', self::stringEmu($br['yOffset'])); $objWriter->endElement(); } else { $objWriter->startElement('xdr:absoluteAnchor'); $objWriter->startElement('xdr:pos'); $objWriter->writeAttribute('x', '0'); $objWriter->writeAttribute('y', '0'); $objWriter->endElement(); $objWriter->startElement('xdr:ext'); $objWriter->writeAttribute('cx', self::stringEmu($br['xOffset'])); $objWriter->writeAttribute('cy', self::stringEmu($br['yOffset'])); $objWriter->endElement(); } $objWriter->startElement('xdr:graphicFrame'); $objWriter->writeAttribute('macro', ''); $objWriter->startElement('xdr:nvGraphicFramePr'); $objWriter->startElement('xdr:cNvPr'); $objWriter->writeAttribute('name', 'Chart ' . $relationId); $objWriter->writeAttribute('id', (string) (1025 * $relationId)); $objWriter->endElement(); $objWriter->startElement('xdr:cNvGraphicFramePr'); $objWriter->startElement('a:graphicFrameLocks'); $objWriter->endElement(); $objWriter->endElement(); $objWriter->endElement(); $objWriter->startElement('xdr:xfrm'); $objWriter->startElement('a:off'); $objWriter->writeAttribute('x', '0'); $objWriter->writeAttribute('y', '0'); $objWriter->endElement(); $objWriter->startElement('a:ext'); $objWriter->writeAttribute('cx', '0'); $objWriter->writeAttribute('cy', '0'); $objWriter->endElement(); $objWriter->endElement(); $objWriter->startElement('a:graphic'); $objWriter->startElement('a:graphicData'); $objWriter->writeAttribute('uri', Namespaces::CHART); $objWriter->startElement('c:chart'); $objWriter->writeAttribute('xmlns:c', Namespaces::CHART); $objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT); $objWriter->writeAttribute('r:id', 'rId' . $relationId); $objWriter->endElement(); $objWriter->endElement(); $objWriter->endElement(); $objWriter->endElement(); $objWriter->startElement('xdr:clientData'); $objWriter->endElement(); $objWriter->endElement(); } /** * Write drawings to XML format. * * @param int $relationId * @param null|int $hlinkClickId */ public function writeDrawing(XMLWriter $objWriter, BaseDrawing $drawing, $relationId = -1, $hlinkClickId = null): void { if ($relationId >= 0) { $isTwoCellAnchor = $drawing->getCoordinates2() !== ''; if ($isTwoCellAnchor) { // xdr:twoCellAnchor $objWriter->startElement('xdr:twoCellAnchor'); if ($drawing->validEditAs()) { $objWriter->writeAttribute('editAs', $drawing->getEditAs()); } // Image location $aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates()); $aCoordinates2 = Coordinate::indexesFromString($drawing->getCoordinates2()); // xdr:from $objWriter->startElement('xdr:from'); $objWriter->writeElement('xdr:col', (string) ($aCoordinates[0] - 1)); $objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX())); $objWriter->writeElement('xdr:row', (string) ($aCoordinates[1] - 1)); $objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY())); $objWriter->endElement(); // xdr:to $objWriter->startElement('xdr:to'); $objWriter->writeElement('xdr:col', (string) ($aCoordinates2[0] - 1)); $objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX2())); $objWriter->writeElement('xdr:row', (string) ($aCoordinates2[1] - 1)); $objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY2())); $objWriter->endElement(); } else { // xdr:oneCellAnchor $objWriter->startElement('xdr:oneCellAnchor'); // Image location $aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates()); // xdr:from $objWriter->startElement('xdr:from'); $objWriter->writeElement('xdr:col', (string) ($aCoordinates[0] - 1)); $objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX())); $objWriter->writeElement('xdr:row', (string) ($aCoordinates[1] - 1)); $objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY())); $objWriter->endElement(); // xdr:ext $objWriter->startElement('xdr:ext'); $objWriter->writeAttribute('cx', self::stringEmu($drawing->getWidth())); $objWriter->writeAttribute('cy', self::stringEmu($drawing->getHeight())); $objWriter->endElement(); } // xdr:pic $objWriter->startElement('xdr:pic'); // xdr:nvPicPr $objWriter->startElement('xdr:nvPicPr'); // xdr:cNvPr $objWriter->startElement('xdr:cNvPr'); $objWriter->writeAttribute('id', (string) $relationId); $objWriter->writeAttribute('name', $drawing->getName()); $objWriter->writeAttribute('descr', $drawing->getDescription()); //a:hlinkClick $this->writeHyperLinkDrawing($objWriter, $hlinkClickId); $objWriter->endElement(); // xdr:cNvPicPr $objWriter->startElement('xdr:cNvPicPr'); // a:picLocks $objWriter->startElement('a:picLocks'); $objWriter->writeAttribute('noChangeAspect', '1'); $objWriter->endElement(); $objWriter->endElement(); $objWriter->endElement(); // xdr:blipFill $objWriter->startElement('xdr:blipFill'); // a:blip $objWriter->startElement('a:blip'); $objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT); $objWriter->writeAttribute('r:embed', 'rId' . $relationId); $objWriter->endElement(); // a:stretch $objWriter->startElement('a:stretch'); $objWriter->writeElement('a:fillRect', null); $objWriter->endElement(); $objWriter->endElement(); // xdr:spPr $objWriter->startElement('xdr:spPr'); // a:xfrm $objWriter->startElement('a:xfrm'); $objWriter->writeAttribute('rot', (string) SharedDrawing::degreesToAngle($drawing->getRotation())); if ($isTwoCellAnchor) { $objWriter->startElement('a:ext'); $objWriter->writeAttribute('cx', self::stringEmu($drawing->getWidth())); $objWriter->writeAttribute('cy', self::stringEmu($drawing->getHeight())); $objWriter->endElement(); } $objWriter->endElement(); // a:prstGeom $objWriter->startElement('a:prstGeom'); $objWriter->writeAttribute('prst', 'rect'); // a:avLst $objWriter->writeElement('a:avLst', null); $objWriter->endElement(); if ($drawing->getShadow()->getVisible()) { // a:effectLst $objWriter->startElement('a:effectLst'); // a:outerShdw $objWriter->startElement('a:outerShdw'); $objWriter->writeAttribute('blurRad', self::stringEmu($drawing->getShadow()->getBlurRadius())); $objWriter->writeAttribute('dist', self::stringEmu($drawing->getShadow()->getDistance())); $objWriter->writeAttribute('dir', (string) SharedDrawing::degreesToAngle($drawing->getShadow()->getDirection())); $objWriter->writeAttribute('algn', $drawing->getShadow()->getAlignment()); $objWriter->writeAttribute('rotWithShape', '0'); // a:srgbClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', $drawing->getShadow()->getColor()->getRGB()); // a:alpha $objWriter->startElement('a:alpha'); $objWriter->writeAttribute('val', (string) ($drawing->getShadow()->getAlpha() * 1000)); $objWriter->endElement(); $objWriter->endElement(); $objWriter->endElement(); $objWriter->endElement(); } $objWriter->endElement(); $objWriter->endElement(); // xdr:clientData $objWriter->writeElement('xdr:clientData', null); $objWriter->endElement(); } else { throw new WriterException('Invalid parameters passed.'); } } /** * Write VML header/footer images to XML format. * * @return string XML Output */ public function writeVMLHeaderFooterImages(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet) { // Create XML writer $objWriter = null; if ($this->getParentWriter()->getUseDiskCaching()) { $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); } else { $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); } // XML header $objWriter->startDocument('1.0', 'UTF-8', 'yes'); // Header/footer images $images = $worksheet->getHeaderFooter()->getImages(); // xml $objWriter->startElement('xml'); $objWriter->writeAttribute('xmlns:v', Namespaces::URN_VML); $objWriter->writeAttribute('xmlns:o', Namespaces::URN_MSOFFICE); $objWriter->writeAttribute('xmlns:x', Namespaces::URN_EXCEL); // o:shapelayout $objWriter->startElement('o:shapelayout'); $objWriter->writeAttribute('v:ext', 'edit'); // o:idmap $objWriter->startElement('o:idmap'); $objWriter->writeAttribute('v:ext', 'edit'); $objWriter->writeAttribute('data', '1'); $objWriter->endElement(); $objWriter->endElement(); // v:shapetype $objWriter->startElement('v:shapetype'); $objWriter->writeAttribute('id', '_x0000_t75'); $objWriter->writeAttribute('coordsize', '21600,21600'); $objWriter->writeAttribute('o:spt', '75'); $objWriter->writeAttribute('o:preferrelative', 't'); $objWriter->writeAttribute('path', 'm@4@5l@4@11@9@11@9@5xe'); $objWriter->writeAttribute('filled', 'f'); $objWriter->writeAttribute('stroked', 'f'); // v:stroke $objWriter->startElement('v:stroke'); $objWriter->writeAttribute('joinstyle', 'miter'); $objWriter->endElement(); // v:formulas $objWriter->startElement('v:formulas'); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'if lineDrawn pixelLineWidth 0'); $objWriter->endElement(); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'sum @0 1 0'); $objWriter->endElement(); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'sum 0 0 @1'); $objWriter->endElement(); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'prod @2 1 2'); $objWriter->endElement(); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelWidth'); $objWriter->endElement(); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelHeight'); $objWriter->endElement(); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'sum @0 0 1'); $objWriter->endElement(); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'prod @6 1 2'); $objWriter->endElement(); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelWidth'); $objWriter->endElement(); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'sum @8 21600 0'); $objWriter->endElement(); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelHeight'); $objWriter->endElement(); // v:f $objWriter->startElement('v:f'); $objWriter->writeAttribute('eqn', 'sum @10 21600 0'); $objWriter->endElement(); $objWriter->endElement(); // v:path $objWriter->startElement('v:path'); $objWriter->writeAttribute('o:extrusionok', 'f'); $objWriter->writeAttribute('gradientshapeok', 't'); $objWriter->writeAttribute('o:connecttype', 'rect'); $objWriter->endElement(); // o:lock $objWriter->startElement('o:lock'); $objWriter->writeAttribute('v:ext', 'edit'); $objWriter->writeAttribute('aspectratio', 't'); $objWriter->endElement(); $objWriter->endElement(); // Loop through images foreach ($images as $key => $value) { $this->writeVMLHeaderFooterImage($objWriter, $key, $value); } $objWriter->endElement(); // Return return $objWriter->getData(); } /** * Write VML comment to XML format. * * @param string $reference Reference */ private function writeVMLHeaderFooterImage(XMLWriter $objWriter, $reference, HeaderFooterDrawing $image): void { // Calculate object id preg_match('{(\d+)}', md5($reference), $m); $id = 1500 + ((int) substr($m[1], 0, 2) * 1); // Calculate offset $width = $image->getWidth(); $height = $image->getHeight(); $marginLeft = $image->getOffsetX(); $marginTop = $image->getOffsetY(); // v:shape $objWriter->startElement('v:shape'); $objWriter->writeAttribute('id', $reference); $objWriter->writeAttribute('o:spid', '_x0000_s' . $id); $objWriter->writeAttribute('type', '#_x0000_t75'); $objWriter->writeAttribute('style', "position:absolute;margin-left:{$marginLeft}px;margin-top:{$marginTop}px;width:{$width}px;height:{$height}px;z-index:1"); // v:imagedata $objWriter->startElement('v:imagedata'); $objWriter->writeAttribute('o:relid', 'rId' . $reference); $objWriter->writeAttribute('o:title', $image->getName()); $objWriter->endElement(); // o:lock $objWriter->startElement('o:lock'); $objWriter->writeAttribute('v:ext', 'edit'); $objWriter->writeAttribute('textRotation', 't'); $objWriter->endElement(); $objWriter->endElement(); } /** * Get an array of all drawings. * * @return BaseDrawing[] All drawings in PhpSpreadsheet */ public function allDrawings(Spreadsheet $spreadsheet) { // Get an array of all drawings $aDrawings = []; // Loop through PhpSpreadsheet $sheetCount = $spreadsheet->getSheetCount(); for ($i = 0; $i < $sheetCount; ++$i) { // Loop through images and add to array $iterator = $spreadsheet->getSheet($i)->getDrawingCollection()->getIterator(); while ($iterator->valid()) { $aDrawings[] = $iterator->current(); $iterator->next(); } } return $aDrawings; } /** * @param null|int $hlinkClickId */ private function writeHyperLinkDrawing(XMLWriter $objWriter, $hlinkClickId): void { if ($hlinkClickId === null) { return; } $objWriter->startElement('a:hlinkClick'); $objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT); $objWriter->writeAttribute('r:id', 'rId' . $hlinkClickId); $objWriter->endElement(); } private static function stringEmu(int $pixelValue): string { return (string) SharedDrawing::pixelsToEMU($pixelValue); } }