Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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