PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.9.4
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.9.4
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
visualizer / vendor / phpoffice / phpspreadsheet / src / PhpSpreadsheet / Writer / Xlsx / Drawing.php

Drawing.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.9.4, at vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php

520 lines 19.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
4
5 use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
6 use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
7 use PhpOffice\PhpSpreadsheet\Spreadsheet;
8 use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
9 use PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing;
10 use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
11
12 class Drawing extends WriterPart
13 {
14 /**
15 * Write drawings to XML format.
16 *
17 * @param \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet
18 * @param bool $includeCharts Flag indicating if we should include drawing details for charts
19 *
20 * @throws WriterException
21 *
22 * @return string XML Output
23 */
24 public function writeDrawings(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet, $includeCharts = false)
25 {
26 // Create XML writer
27 $objWriter = null;
28 if ($this->getParentWriter()->getUseDiskCaching()) {
29 $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
30 } else {
31 $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
32 }
33
34 // XML header
35 $objWriter->startDocument('1.0', 'UTF-8', 'yes');
36
37 // xdr:wsDr
38 $objWriter->startElement('xdr:wsDr');
39 $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing');
40 $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main');
41
42 // Loop through images and write drawings
43 $i = 1;
44 $iterator = $pWorksheet->getDrawingCollection()->getIterator();
45 while ($iterator->valid()) {
46 /** @var BaseDrawing $pDrawing */
47 $pDrawing = $iterator->current();
48 $pRelationId = $i;
49 $hlinkClickId = $pDrawing->getHyperlink() === null ? null : ++$i;
50
51 $this->writeDrawing($objWriter, $pDrawing, $pRelationId, $hlinkClickId);
52
53 $iterator->next();
54 ++$i;
55 }
56
57 if ($includeCharts) {
58 $chartCount = $pWorksheet->getChartCount();
59 // Loop through charts and write the chart position
60 if ($chartCount > 0) {
61 for ($c = 0; $c < $chartCount; ++$c) {
62 $this->writeChart($objWriter, $pWorksheet->getChartByIndex($c), $c + $i);
63 }
64 }
65 }
66
67 // unparsed AlternateContent
68 $unparsedLoadedData = $pWorksheet->getParent()->getUnparsedLoadedData();
69 if (isset($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()]['drawingAlternateContents'])) {
70 foreach ($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()]['drawingAlternateContents'] as $drawingAlternateContent) {
71 $objWriter->writeRaw($drawingAlternateContent);
72 }
73 }
74
75 $objWriter->endElement();
76
77 // Return
78 return $objWriter->getData();
79 }
80
81 /**
82 * Write drawings to XML format.
83 *
84 * @param XMLWriter $objWriter XML Writer
85 * @param \PhpOffice\PhpSpreadsheet\Chart\Chart $pChart
86 * @param int $pRelationId
87 */
88 public function writeChart(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Chart\Chart $pChart, $pRelationId = -1)
89 {
90 $tl = $pChart->getTopLeftPosition();
91 $tl['colRow'] = Coordinate::coordinateFromString($tl['cell']);
92 $br = $pChart->getBottomRightPosition();
93 $br['colRow'] = Coordinate::coordinateFromString($br['cell']);
94
95 $objWriter->startElement('xdr:twoCellAnchor');
96
97 $objWriter->startElement('xdr:from');
98 $objWriter->writeElement('xdr:col', Coordinate::columnIndexFromString($tl['colRow'][0]) - 1);
99 $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['xOffset']));
100 $objWriter->writeElement('xdr:row', $tl['colRow'][1] - 1);
101 $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['yOffset']));
102 $objWriter->endElement();
103 $objWriter->startElement('xdr:to');
104 $objWriter->writeElement('xdr:col', Coordinate::columnIndexFromString($br['colRow'][0]) - 1);
105 $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($br['xOffset']));
106 $objWriter->writeElement('xdr:row', $br['colRow'][1] - 1);
107 $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($br['yOffset']));
108 $objWriter->endElement();
109
110 $objWriter->startElement('xdr:graphicFrame');
111 $objWriter->writeAttribute('macro', '');
112 $objWriter->startElement('xdr:nvGraphicFramePr');
113 $objWriter->startElement('xdr:cNvPr');
114 $objWriter->writeAttribute('name', 'Chart ' . $pRelationId);
115 $objWriter->writeAttribute('id', 1025 * $pRelationId);
116 $objWriter->endElement();
117 $objWriter->startElement('xdr:cNvGraphicFramePr');
118 $objWriter->startElement('a:graphicFrameLocks');
119 $objWriter->endElement();
120 $objWriter->endElement();
121 $objWriter->endElement();
122
123 $objWriter->startElement('xdr:xfrm');
124 $objWriter->startElement('a:off');
125 $objWriter->writeAttribute('x', '0');
126 $objWriter->writeAttribute('y', '0');
127 $objWriter->endElement();
128 $objWriter->startElement('a:ext');
129 $objWriter->writeAttribute('cx', '0');
130 $objWriter->writeAttribute('cy', '0');
131 $objWriter->endElement();
132 $objWriter->endElement();
133
134 $objWriter->startElement('a:graphic');
135 $objWriter->startElement('a:graphicData');
136 $objWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/chart');
137 $objWriter->startElement('c:chart');
138 $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart');
139 $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
140 $objWriter->writeAttribute('r:id', 'rId' . $pRelationId);
141 $objWriter->endElement();
142 $objWriter->endElement();
143 $objWriter->endElement();
144 $objWriter->endElement();
145
146 $objWriter->startElement('xdr:clientData');
147 $objWriter->endElement();
148
149 $objWriter->endElement();
150 }
151
152 /**
153 * Write drawings to XML format.
154 *
155 * @param XMLWriter $objWriter XML Writer
156 * @param BaseDrawing $pDrawing
157 * @param int $pRelationId
158 * @param null|int $hlinkClickId
159 *
160 * @throws WriterException
161 */
162 public function writeDrawing(XMLWriter $objWriter, BaseDrawing $pDrawing, $pRelationId = -1, $hlinkClickId = null)
163 {
164 if ($pRelationId >= 0) {
165 // xdr:oneCellAnchor
166 $objWriter->startElement('xdr:oneCellAnchor');
167 // Image location
168 $aCoordinates = Coordinate::coordinateFromString($pDrawing->getCoordinates());
169 $aCoordinates[0] = Coordinate::columnIndexFromString($aCoordinates[0]);
170
171 // xdr:from
172 $objWriter->startElement('xdr:from');
173 $objWriter->writeElement('xdr:col', $aCoordinates[0] - 1);
174 $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getOffsetX()));
175 $objWriter->writeElement('xdr:row', $aCoordinates[1] - 1);
176 $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getOffsetY()));
177 $objWriter->endElement();
178
179 // xdr:ext
180 $objWriter->startElement('xdr:ext');
181 $objWriter->writeAttribute('cx', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getWidth()));
182 $objWriter->writeAttribute('cy', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getHeight()));
183 $objWriter->endElement();
184
185 // xdr:pic
186 $objWriter->startElement('xdr:pic');
187
188 // xdr:nvPicPr
189 $objWriter->startElement('xdr:nvPicPr');
190
191 // xdr:cNvPr
192 $objWriter->startElement('xdr:cNvPr');
193 $objWriter->writeAttribute('id', $pRelationId);
194 $objWriter->writeAttribute('name', $pDrawing->getName());
195 $objWriter->writeAttribute('descr', $pDrawing->getDescription());
196
197 //a:hlinkClick
198 $this->writeHyperLinkDrawing($objWriter, $hlinkClickId);
199
200 $objWriter->endElement();
201
202 // xdr:cNvPicPr
203 $objWriter->startElement('xdr:cNvPicPr');
204
205 // a:picLocks
206 $objWriter->startElement('a:picLocks');
207 $objWriter->writeAttribute('noChangeAspect', '1');
208 $objWriter->endElement();
209
210 $objWriter->endElement();
211
212 $objWriter->endElement();
213
214 // xdr:blipFill
215 $objWriter->startElement('xdr:blipFill');
216
217 // a:blip
218 $objWriter->startElement('a:blip');
219 $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
220 $objWriter->writeAttribute('r:embed', 'rId' . $pRelationId);
221 $objWriter->endElement();
222
223 // a:stretch
224 $objWriter->startElement('a:stretch');
225 $objWriter->writeElement('a:fillRect', null);
226 $objWriter->endElement();
227
228 $objWriter->endElement();
229
230 // xdr:spPr
231 $objWriter->startElement('xdr:spPr');
232
233 // a:xfrm
234 $objWriter->startElement('a:xfrm');
235 $objWriter->writeAttribute('rot', \PhpOffice\PhpSpreadsheet\Shared\Drawing::degreesToAngle($pDrawing->getRotation()));
236 $objWriter->endElement();
237
238 // a:prstGeom
239 $objWriter->startElement('a:prstGeom');
240 $objWriter->writeAttribute('prst', 'rect');
241
242 // a:avLst
243 $objWriter->writeElement('a:avLst', null);
244
245 $objWriter->endElement();
246
247 if ($pDrawing->getShadow()->getVisible()) {
248 // a:effectLst
249 $objWriter->startElement('a:effectLst');
250
251 // a:outerShdw
252 $objWriter->startElement('a:outerShdw');
253 $objWriter->writeAttribute('blurRad', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getShadow()->getBlurRadius()));
254 $objWriter->writeAttribute('dist', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getShadow()->getDistance()));
255 $objWriter->writeAttribute('dir', \PhpOffice\PhpSpreadsheet\Shared\Drawing::degreesToAngle($pDrawing->getShadow()->getDirection()));
256 $objWriter->writeAttribute('algn', $pDrawing->getShadow()->getAlignment());
257 $objWriter->writeAttribute('rotWithShape', '0');
258
259 // a:srgbClr
260 $objWriter->startElement('a:srgbClr');
261 $objWriter->writeAttribute('val', $pDrawing->getShadow()->getColor()->getRGB());
262
263 // a:alpha
264 $objWriter->startElement('a:alpha');
265 $objWriter->writeAttribute('val', $pDrawing->getShadow()->getAlpha() * 1000);
266 $objWriter->endElement();
267
268 $objWriter->endElement();
269
270 $objWriter->endElement();
271
272 $objWriter->endElement();
273 }
274 $objWriter->endElement();
275
276 $objWriter->endElement();
277
278 // xdr:clientData
279 $objWriter->writeElement('xdr:clientData', null);
280
281 $objWriter->endElement();
282 } else {
283 throw new WriterException('Invalid parameters passed.');
284 }
285 }
286
287 /**
288 * Write VML header/footer images to XML format.
289 *
290 * @param \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet
291 *
292 * @throws WriterException
293 *
294 * @return string XML Output
295 */
296 public function writeVMLHeaderFooterImages(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet)
297 {
298 // Create XML writer
299 $objWriter = null;
300 if ($this->getParentWriter()->getUseDiskCaching()) {
301 $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
302 } else {
303 $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
304 }
305
306 // XML header
307 $objWriter->startDocument('1.0', 'UTF-8', 'yes');
308
309 // Header/footer images
310 $images = $pWorksheet->getHeaderFooter()->getImages();
311
312 // xml
313 $objWriter->startElement('xml');
314 $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml');
315 $objWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office');
316 $objWriter->writeAttribute('xmlns:x', 'urn:schemas-microsoft-com:office:excel');
317
318 // o:shapelayout
319 $objWriter->startElement('o:shapelayout');
320 $objWriter->writeAttribute('v:ext', 'edit');
321
322 // o:idmap
323 $objWriter->startElement('o:idmap');
324 $objWriter->writeAttribute('v:ext', 'edit');
325 $objWriter->writeAttribute('data', '1');
326 $objWriter->endElement();
327
328 $objWriter->endElement();
329
330 // v:shapetype
331 $objWriter->startElement('v:shapetype');
332 $objWriter->writeAttribute('id', '_x0000_t75');
333 $objWriter->writeAttribute('coordsize', '21600,21600');
334 $objWriter->writeAttribute('o:spt', '75');
335 $objWriter->writeAttribute('o:preferrelative', 't');
336 $objWriter->writeAttribute('path', 'm@4@5l@4@11@9@11@9@5xe');
337 $objWriter->writeAttribute('filled', 'f');
338 $objWriter->writeAttribute('stroked', 'f');
339
340 // v:stroke
341 $objWriter->startElement('v:stroke');
342 $objWriter->writeAttribute('joinstyle', 'miter');
343 $objWriter->endElement();
344
345 // v:formulas
346 $objWriter->startElement('v:formulas');
347
348 // v:f
349 $objWriter->startElement('v:f');
350 $objWriter->writeAttribute('eqn', 'if lineDrawn pixelLineWidth 0');
351 $objWriter->endElement();
352
353 // v:f
354 $objWriter->startElement('v:f');
355 $objWriter->writeAttribute('eqn', 'sum @0 1 0');
356 $objWriter->endElement();
357
358 // v:f
359 $objWriter->startElement('v:f');
360 $objWriter->writeAttribute('eqn', 'sum 0 0 @1');
361 $objWriter->endElement();
362
363 // v:f
364 $objWriter->startElement('v:f');
365 $objWriter->writeAttribute('eqn', 'prod @2 1 2');
366 $objWriter->endElement();
367
368 // v:f
369 $objWriter->startElement('v:f');
370 $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelWidth');
371 $objWriter->endElement();
372
373 // v:f
374 $objWriter->startElement('v:f');
375 $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelHeight');
376 $objWriter->endElement();
377
378 // v:f
379 $objWriter->startElement('v:f');
380 $objWriter->writeAttribute('eqn', 'sum @0 0 1');
381 $objWriter->endElement();
382
383 // v:f
384 $objWriter->startElement('v:f');
385 $objWriter->writeAttribute('eqn', 'prod @6 1 2');
386 $objWriter->endElement();
387
388 // v:f
389 $objWriter->startElement('v:f');
390 $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelWidth');
391 $objWriter->endElement();
392
393 // v:f
394 $objWriter->startElement('v:f');
395 $objWriter->writeAttribute('eqn', 'sum @8 21600 0');
396 $objWriter->endElement();
397
398 // v:f
399 $objWriter->startElement('v:f');
400 $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelHeight');
401 $objWriter->endElement();
402
403 // v:f
404 $objWriter->startElement('v:f');
405 $objWriter->writeAttribute('eqn', 'sum @10 21600 0');
406 $objWriter->endElement();
407
408 $objWriter->endElement();
409
410 // v:path
411 $objWriter->startElement('v:path');
412 $objWriter->writeAttribute('o:extrusionok', 'f');
413 $objWriter->writeAttribute('gradientshapeok', 't');
414 $objWriter->writeAttribute('o:connecttype', 'rect');
415 $objWriter->endElement();
416
417 // o:lock
418 $objWriter->startElement('o:lock');
419 $objWriter->writeAttribute('v:ext', 'edit');
420 $objWriter->writeAttribute('aspectratio', 't');
421 $objWriter->endElement();
422
423 $objWriter->endElement();
424
425 // Loop through images
426 foreach ($images as $key => $value) {
427 $this->writeVMLHeaderFooterImage($objWriter, $key, $value);
428 }
429
430 $objWriter->endElement();
431
432 // Return
433 return $objWriter->getData();
434 }
435
436 /**
437 * Write VML comment to XML format.
438 *
439 * @param XMLWriter $objWriter XML Writer
440 * @param string $pReference Reference
441 * @param HeaderFooterDrawing $pImage Image
442 */
443 private function writeVMLHeaderFooterImage(XMLWriter $objWriter, $pReference, HeaderFooterDrawing $pImage)
444 {
445 // Calculate object id
446 preg_match('{(\d+)}', md5($pReference), $m);
447 $id = 1500 + (substr($m[1], 0, 2) * 1);
448
449 // Calculate offset
450 $width = $pImage->getWidth();
451 $height = $pImage->getHeight();
452 $marginLeft = $pImage->getOffsetX();
453 $marginTop = $pImage->getOffsetY();
454
455 // v:shape
456 $objWriter->startElement('v:shape');
457 $objWriter->writeAttribute('id', $pReference);
458 $objWriter->writeAttribute('o:spid', '_x0000_s' . $id);
459 $objWriter->writeAttribute('type', '#_x0000_t75');
460 $objWriter->writeAttribute('style', "position:absolute;margin-left:{$marginLeft}px;margin-top:{$marginTop}px;width:{$width}px;height:{$height}px;z-index:1");
461
462 // v:imagedata
463 $objWriter->startElement('v:imagedata');
464 $objWriter->writeAttribute('o:relid', 'rId' . $pReference);
465 $objWriter->writeAttribute('o:title', $pImage->getName());
466 $objWriter->endElement();
467
468 // o:lock
469 $objWriter->startElement('o:lock');
470 $objWriter->writeAttribute('v:ext', 'edit');
471 $objWriter->writeAttribute('textRotation', 't');
472 $objWriter->endElement();
473
474 $objWriter->endElement();
475 }
476
477 /**
478 * Get an array of all drawings.
479 *
480 * @param Spreadsheet $spreadsheet
481 *
482 * @return \PhpOffice\PhpSpreadsheet\Worksheet\Drawing[] All drawings in PhpSpreadsheet
483 */
484 public function allDrawings(Spreadsheet $spreadsheet)
485 {
486 // Get an array of all drawings
487 $aDrawings = [];
488
489 // Loop through PhpSpreadsheet
490 $sheetCount = $spreadsheet->getSheetCount();
491 for ($i = 0; $i < $sheetCount; ++$i) {
492 // Loop through images and add to array
493 $iterator = $spreadsheet->getSheet($i)->getDrawingCollection()->getIterator();
494 while ($iterator->valid()) {
495 $aDrawings[] = $iterator->current();
496
497 $iterator->next();
498 }
499 }
500
501 return $aDrawings;
502 }
503
504 /**
505 * @param XMLWriter $objWriter
506 * @param null|int $hlinkClickId
507 */
508 private function writeHyperLinkDrawing(XMLWriter $objWriter, $hlinkClickId)
509 {
510 if ($hlinkClickId === null) {
511 return;
512 }
513
514 $objWriter->startElement('a:hlinkClick');
515 $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
516 $objWriter->writeAttribute('r:id', 'rId' . $hlinkClickId);
517 $objWriter->endElement();
518 }
519 }
520