Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
1 <?php 2 3 namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx; 4 5 use PhpOffice\PhpSpreadsheet\Chart\Axis; 6 use PhpOffice\PhpSpreadsheet\Chart\DataSeries; 7 use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; 8 use PhpOffice\PhpSpreadsheet\Chart\GridLines; 9 use PhpOffice\PhpSpreadsheet\Chart\Layout; 10 use PhpOffice\PhpSpreadsheet\Chart\Legend; 11 use PhpOffice\PhpSpreadsheet\Chart\PlotArea; 12 use PhpOffice\PhpSpreadsheet\Chart\Title; 13 use PhpOffice\PhpSpreadsheet\Shared\StringHelper; 14 use PhpOffice\PhpSpreadsheet\Shared\XMLWriter; 15 use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException; 16 17 class Chart extends WriterPart 18 { 19 protected $calculateCellValues; 20 21 /** 22 * @var int 23 */ 24 private $seriesIndex; 25 26 /** 27 * Write charts to XML format. 28 * 29 * @param mixed $calculateCellValues 30 * 31 * @return string XML Output 32 */ 33 public function writeChart(\PhpOffice\PhpSpreadsheet\Chart\Chart $pChart, $calculateCellValues = true) 34 { 35 $this->calculateCellValues = $calculateCellValues; 36 37 // Create XML writer 38 $objWriter = null; 39 if ($this->getParentWriter()->getUseDiskCaching()) { 40 $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); 41 } else { 42 $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); 43 } 44 // Ensure that data series values are up-to-date before we save 45 if ($this->calculateCellValues) { 46 $pChart->refresh(); 47 } 48 49 // XML header 50 $objWriter->startDocument('1.0', 'UTF-8', 'yes'); 51 52 // c:chartSpace 53 $objWriter->startElement('c:chartSpace'); 54 $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); 55 $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); 56 $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); 57 58 $objWriter->startElement('c:date1904'); 59 $objWriter->writeAttribute('val', 0); 60 $objWriter->endElement(); 61 $objWriter->startElement('c:lang'); 62 $objWriter->writeAttribute('val', 'en-GB'); 63 $objWriter->endElement(); 64 $objWriter->startElement('c:roundedCorners'); 65 $objWriter->writeAttribute('val', 0); 66 $objWriter->endElement(); 67 68 $this->writeAlternateContent($objWriter); 69 70 $objWriter->startElement('c:chart'); 71 72 $this->writeTitle($objWriter, $pChart->getTitle()); 73 74 $objWriter->startElement('c:autoTitleDeleted'); 75 $objWriter->writeAttribute('val', 0); 76 $objWriter->endElement(); 77 78 $this->writePlotArea($objWriter, $pChart->getWorksheet(), $pChart->getPlotArea(), $pChart->getXAxisLabel(), $pChart->getYAxisLabel(), $pChart->getChartAxisX(), $pChart->getChartAxisY(), $pChart->getMajorGridlines(), $pChart->getMinorGridlines()); 79 80 $this->writeLegend($objWriter, $pChart->getLegend()); 81 82 $objWriter->startElement('c:plotVisOnly'); 83 $objWriter->writeAttribute('val', (int) $pChart->getPlotVisibleOnly()); 84 $objWriter->endElement(); 85 86 $objWriter->startElement('c:dispBlanksAs'); 87 $objWriter->writeAttribute('val', $pChart->getDisplayBlanksAs()); 88 $objWriter->endElement(); 89 90 $objWriter->startElement('c:showDLblsOverMax'); 91 $objWriter->writeAttribute('val', 0); 92 $objWriter->endElement(); 93 94 $objWriter->endElement(); 95 96 $this->writePrintSettings($objWriter); 97 98 $objWriter->endElement(); 99 100 // Return 101 return $objWriter->getData(); 102 } 103 104 /** 105 * Write Chart Title. 106 * 107 * @param XMLWriter $objWriter XML Writer 108 * @param Title $title 109 */ 110 private function writeTitle(XMLWriter $objWriter, ?Title $title = null): void 111 { 112 if ($title === null) { 113 return; 114 } 115 116 $objWriter->startElement('c:title'); 117 $objWriter->startElement('c:tx'); 118 $objWriter->startElement('c:rich'); 119 120 $objWriter->startElement('a:bodyPr'); 121 $objWriter->endElement(); 122 123 $objWriter->startElement('a:lstStyle'); 124 $objWriter->endElement(); 125 126 $objWriter->startElement('a:p'); 127 128 $caption = $title->getCaption(); 129 if ((is_array($caption)) && (count($caption) > 0)) { 130 $caption = $caption[0]; 131 } 132 $this->getParentWriter()->getWriterPart('stringtable')->writeRichTextForCharts($objWriter, $caption, 'a'); 133 134 $objWriter->endElement(); 135 $objWriter->endElement(); 136 $objWriter->endElement(); 137 138 $this->writeLayout($objWriter, $title->getLayout()); 139 140 $objWriter->startElement('c:overlay'); 141 $objWriter->writeAttribute('val', 0); 142 $objWriter->endElement(); 143 144 $objWriter->endElement(); 145 } 146 147 /** 148 * Write Chart Legend. 149 * 150 * @param XMLWriter $objWriter XML Writer 151 * @param Legend $legend 152 */ 153 private function writeLegend(XMLWriter $objWriter, ?Legend $legend = null): void 154 { 155 if ($legend === null) { 156 return; 157 } 158 159 $objWriter->startElement('c:legend'); 160 161 $objWriter->startElement('c:legendPos'); 162 $objWriter->writeAttribute('val', $legend->getPosition()); 163 $objWriter->endElement(); 164 165 $this->writeLayout($objWriter, $legend->getLayout()); 166 167 $objWriter->startElement('c:overlay'); 168 $objWriter->writeAttribute('val', ($legend->getOverlay()) ? '1' : '0'); 169 $objWriter->endElement(); 170 171 $objWriter->startElement('c:txPr'); 172 $objWriter->startElement('a:bodyPr'); 173 $objWriter->endElement(); 174 175 $objWriter->startElement('a:lstStyle'); 176 $objWriter->endElement(); 177 178 $objWriter->startElement('a:p'); 179 $objWriter->startElement('a:pPr'); 180 $objWriter->writeAttribute('rtl', 0); 181 182 $objWriter->startElement('a:defRPr'); 183 $objWriter->endElement(); 184 $objWriter->endElement(); 185 186 $objWriter->startElement('a:endParaRPr'); 187 $objWriter->writeAttribute('lang', 'en-US'); 188 $objWriter->endElement(); 189 190 $objWriter->endElement(); 191 $objWriter->endElement(); 192 193 $objWriter->endElement(); 194 } 195 196 /** 197 * Write Chart Plot Area. 198 * 199 * @param XMLWriter $objWriter XML Writer 200 * @param Title $xAxisLabel 201 * @param Title $yAxisLabel 202 * @param Axis $xAxis 203 * @param Axis $yAxis 204 */ 205 private function writePlotArea(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pSheet, PlotArea $plotArea, ?Title $xAxisLabel = null, ?Title $yAxisLabel = null, ?Axis $xAxis = null, ?Axis $yAxis = null, ?GridLines $majorGridlines = null, ?GridLines $minorGridlines = null): void 206 { 207 if ($plotArea === null) { 208 return; 209 } 210 211 $id1 = $id2 = 0; 212 $this->seriesIndex = 0; 213 $objWriter->startElement('c:plotArea'); 214 215 $layout = $plotArea->getLayout(); 216 217 $this->writeLayout($objWriter, $layout); 218 219 $chartTypes = self::getChartType($plotArea); 220 $catIsMultiLevelSeries = $valIsMultiLevelSeries = false; 221 $plotGroupingType = ''; 222 foreach ($chartTypes as $chartType) { 223 $objWriter->startElement('c:' . $chartType); 224 225 $groupCount = $plotArea->getPlotGroupCount(); 226 for ($i = 0; $i < $groupCount; ++$i) { 227 $plotGroup = $plotArea->getPlotGroupByIndex($i); 228 $groupType = $plotGroup->getPlotType(); 229 if ($groupType == $chartType) { 230 $plotStyle = $plotGroup->getPlotStyle(); 231 if ($groupType === DataSeries::TYPE_RADARCHART) { 232 $objWriter->startElement('c:radarStyle'); 233 $objWriter->writeAttribute('val', $plotStyle); 234 $objWriter->endElement(); 235 } elseif ($groupType === DataSeries::TYPE_SCATTERCHART) { 236 $objWriter->startElement('c:scatterStyle'); 237 $objWriter->writeAttribute('val', $plotStyle); 238 $objWriter->endElement(); 239 } 240 241 $this->writePlotGroup($plotGroup, $chartType, $objWriter, $catIsMultiLevelSeries, $valIsMultiLevelSeries, $plotGroupingType); 242 } 243 } 244 245 $this->writeDataLabels($objWriter, $layout); 246 247 if ($chartType === DataSeries::TYPE_LINECHART) { 248 // Line only, Line3D can't be smoothed 249 $objWriter->startElement('c:smooth'); 250 $objWriter->writeAttribute('val', (int) $plotGroup->getSmoothLine()); 251 $objWriter->endElement(); 252 } elseif (($chartType === DataSeries::TYPE_BARCHART) || ($chartType === DataSeries::TYPE_BARCHART_3D)) { 253 $objWriter->startElement('c:gapWidth'); 254 $objWriter->writeAttribute('val', 150); 255 $objWriter->endElement(); 256 257 if ($plotGroupingType == 'percentStacked' || $plotGroupingType == 'stacked') { 258 $objWriter->startElement('c:overlap'); 259 $objWriter->writeAttribute('val', 100); 260 $objWriter->endElement(); 261 } 262 } elseif ($chartType === DataSeries::TYPE_BUBBLECHART) { 263 $objWriter->startElement('c:bubbleScale'); 264 $objWriter->writeAttribute('val', 25); 265 $objWriter->endElement(); 266 267 $objWriter->startElement('c:showNegBubbles'); 268 $objWriter->writeAttribute('val', 0); 269 $objWriter->endElement(); 270 } elseif ($chartType === DataSeries::TYPE_STOCKCHART) { 271 $objWriter->startElement('c:hiLowLines'); 272 $objWriter->endElement(); 273 274 $objWriter->startElement('c:upDownBars'); 275 276 $objWriter->startElement('c:gapWidth'); 277 $objWriter->writeAttribute('val', 300); 278 $objWriter->endElement(); 279 280 $objWriter->startElement('c:upBars'); 281 $objWriter->endElement(); 282 283 $objWriter->startElement('c:downBars'); 284 $objWriter->endElement(); 285 286 $objWriter->endElement(); 287 } 288 289 // Generate 2 unique numbers to use for axId values 290 $id1 = '75091328'; 291 $id2 = '75089408'; 292 293 if (($chartType !== DataSeries::TYPE_PIECHART) && ($chartType !== DataSeries::TYPE_PIECHART_3D) && ($chartType !== DataSeries::TYPE_DONUTCHART)) { 294 $objWriter->startElement('c:axId'); 295 $objWriter->writeAttribute('val', $id1); 296 $objWriter->endElement(); 297 $objWriter->startElement('c:axId'); 298 $objWriter->writeAttribute('val', $id2); 299 $objWriter->endElement(); 300 } else { 301 $objWriter->startElement('c:firstSliceAng'); 302 $objWriter->writeAttribute('val', 0); 303 $objWriter->endElement(); 304 305 if ($chartType === DataSeries::TYPE_DONUTCHART) { 306 $objWriter->startElement('c:holeSize'); 307 $objWriter->writeAttribute('val', 50); 308 $objWriter->endElement(); 309 } 310 } 311 312 $objWriter->endElement(); 313 } 314 315 if (($chartType !== DataSeries::TYPE_PIECHART) && ($chartType !== DataSeries::TYPE_PIECHART_3D) && ($chartType !== DataSeries::TYPE_DONUTCHART)) { 316 if ($chartType === DataSeries::TYPE_BUBBLECHART) { 317 $this->writeValueAxis($objWriter, $xAxisLabel, $chartType, $id1, $id2, $catIsMultiLevelSeries, $xAxis, $majorGridlines, $minorGridlines); 318 } else { 319 $this->writeCategoryAxis($objWriter, $xAxisLabel, $id1, $id2, $catIsMultiLevelSeries, $yAxis); 320 } 321 322 $this->writeValueAxis($objWriter, $yAxisLabel, $chartType, $id1, $id2, $valIsMultiLevelSeries, $xAxis, $majorGridlines, $minorGridlines); 323 } 324 325 $objWriter->endElement(); 326 } 327 328 /** 329 * Write Data Labels. 330 * 331 * @param XMLWriter $objWriter XML Writer 332 * @param \PhpOffice\PhpSpreadsheet\Chart\Layout $chartLayout Chart layout 333 */ 334 private function writeDataLabels(XMLWriter $objWriter, ?Layout $chartLayout = null): void 335 { 336 $objWriter->startElement('c:dLbls'); 337 338 $objWriter->startElement('c:showLegendKey'); 339 $showLegendKey = (empty($chartLayout)) ? 0 : $chartLayout->getShowLegendKey(); 340 $objWriter->writeAttribute('val', ((empty($showLegendKey)) ? 0 : 1)); 341 $objWriter->endElement(); 342 343 $objWriter->startElement('c:showVal'); 344 $showVal = (empty($chartLayout)) ? 0 : $chartLayout->getShowVal(); 345 $objWriter->writeAttribute('val', ((empty($showVal)) ? 0 : 1)); 346 $objWriter->endElement(); 347 348 $objWriter->startElement('c:showCatName'); 349 $showCatName = (empty($chartLayout)) ? 0 : $chartLayout->getShowCatName(); 350 $objWriter->writeAttribute('val', ((empty($showCatName)) ? 0 : 1)); 351 $objWriter->endElement(); 352 353 $objWriter->startElement('c:showSerName'); 354 $showSerName = (empty($chartLayout)) ? 0 : $chartLayout->getShowSerName(); 355 $objWriter->writeAttribute('val', ((empty($showSerName)) ? 0 : 1)); 356 $objWriter->endElement(); 357 358 $objWriter->startElement('c:showPercent'); 359 $showPercent = (empty($chartLayout)) ? 0 : $chartLayout->getShowPercent(); 360 $objWriter->writeAttribute('val', ((empty($showPercent)) ? 0 : 1)); 361 $objWriter->endElement(); 362 363 $objWriter->startElement('c:showBubbleSize'); 364 $showBubbleSize = (empty($chartLayout)) ? 0 : $chartLayout->getShowBubbleSize(); 365 $objWriter->writeAttribute('val', ((empty($showBubbleSize)) ? 0 : 1)); 366 $objWriter->endElement(); 367 368 $objWriter->startElement('c:showLeaderLines'); 369 $showLeaderLines = (empty($chartLayout)) ? 1 : $chartLayout->getShowLeaderLines(); 370 $objWriter->writeAttribute('val', ((empty($showLeaderLines)) ? 0 : 1)); 371 $objWriter->endElement(); 372 373 $objWriter->endElement(); 374 } 375 376 /** 377 * Write Category Axis. 378 * 379 * @param XMLWriter $objWriter XML Writer 380 * @param Title $xAxisLabel 381 * @param string $id1 382 * @param string $id2 383 * @param bool $isMultiLevelSeries 384 */ 385 private function writeCategoryAxis($objWriter, $xAxisLabel, $id1, $id2, $isMultiLevelSeries, Axis $yAxis): void 386 { 387 $objWriter->startElement('c:catAx'); 388 389 if ($id1 > 0) { 390 $objWriter->startElement('c:axId'); 391 $objWriter->writeAttribute('val', $id1); 392 $objWriter->endElement(); 393 } 394 395 $objWriter->startElement('c:scaling'); 396 $objWriter->startElement('c:orientation'); 397 $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('orientation')); 398 $objWriter->endElement(); 399 $objWriter->endElement(); 400 401 $objWriter->startElement('c:delete'); 402 $objWriter->writeAttribute('val', 0); 403 $objWriter->endElement(); 404 405 $objWriter->startElement('c:axPos'); 406 $objWriter->writeAttribute('val', 'b'); 407 $objWriter->endElement(); 408 409 if ($xAxisLabel !== null) { 410 $objWriter->startElement('c:title'); 411 $objWriter->startElement('c:tx'); 412 $objWriter->startElement('c:rich'); 413 414 $objWriter->startElement('a:bodyPr'); 415 $objWriter->endElement(); 416 417 $objWriter->startElement('a:lstStyle'); 418 $objWriter->endElement(); 419 420 $objWriter->startElement('a:p'); 421 $objWriter->startElement('a:r'); 422 423 $caption = $xAxisLabel->getCaption(); 424 if (is_array($caption)) { 425 $caption = $caption[0]; 426 } 427 $objWriter->startElement('a:t'); 428 $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($caption)); 429 $objWriter->endElement(); 430 431 $objWriter->endElement(); 432 $objWriter->endElement(); 433 $objWriter->endElement(); 434 $objWriter->endElement(); 435 436 $layout = $xAxisLabel->getLayout(); 437 $this->writeLayout($objWriter, $layout); 438 439 $objWriter->startElement('c:overlay'); 440 $objWriter->writeAttribute('val', 0); 441 $objWriter->endElement(); 442 443 $objWriter->endElement(); 444 } 445 446 $objWriter->startElement('c:numFmt'); 447 $objWriter->writeAttribute('formatCode', $yAxis->getAxisNumberFormat()); 448 $objWriter->writeAttribute('sourceLinked', $yAxis->getAxisNumberSourceLinked()); 449 $objWriter->endElement(); 450 451 $objWriter->startElement('c:majorTickMark'); 452 $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('major_tick_mark')); 453 $objWriter->endElement(); 454 455 $objWriter->startElement('c:minorTickMark'); 456 $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('minor_tick_mark')); 457 $objWriter->endElement(); 458 459 $objWriter->startElement('c:tickLblPos'); 460 $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('axis_labels')); 461 $objWriter->endElement(); 462 463 if ($id2 > 0) { 464 $objWriter->startElement('c:crossAx'); 465 $objWriter->writeAttribute('val', $id2); 466 $objWriter->endElement(); 467 468 $objWriter->startElement('c:crosses'); 469 $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('horizontal_crosses')); 470 $objWriter->endElement(); 471 } 472 473 $objWriter->startElement('c:auto'); 474 $objWriter->writeAttribute('val', 1); 475 $objWriter->endElement(); 476 477 $objWriter->startElement('c:lblAlgn'); 478 $objWriter->writeAttribute('val', 'ctr'); 479 $objWriter->endElement(); 480 481 $objWriter->startElement('c:lblOffset'); 482 $objWriter->writeAttribute('val', 100); 483 $objWriter->endElement(); 484 485 if ($isMultiLevelSeries) { 486 $objWriter->startElement('c:noMultiLvlLbl'); 487 $objWriter->writeAttribute('val', 0); 488 $objWriter->endElement(); 489 } 490 $objWriter->endElement(); 491 } 492 493 /** 494 * Write Value Axis. 495 * 496 * @param XMLWriter $objWriter XML Writer 497 * @param Title $yAxisLabel 498 * @param string $groupType Chart type 499 * @param string $id1 500 * @param string $id2 501 * @param bool $isMultiLevelSeries 502 */ 503 private function writeValueAxis($objWriter, $yAxisLabel, $groupType, $id1, $id2, $isMultiLevelSeries, Axis $xAxis, GridLines $majorGridlines, GridLines $minorGridlines): void 504 { 505 $objWriter->startElement('c:valAx'); 506 507 if ($id2 > 0) { 508 $objWriter->startElement('c:axId'); 509 $objWriter->writeAttribute('val', $id2); 510 $objWriter->endElement(); 511 } 512 513 $objWriter->startElement('c:scaling'); 514 515 if ($xAxis->getAxisOptionsProperty('maximum') !== null) { 516 $objWriter->startElement('c:max'); 517 $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('maximum')); 518 $objWriter->endElement(); 519 } 520 521 if ($xAxis->getAxisOptionsProperty('minimum') !== null) { 522 $objWriter->startElement('c:min'); 523 $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('minimum')); 524 $objWriter->endElement(); 525 } 526 527 $objWriter->startElement('c:orientation'); 528 $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('orientation')); 529 530 $objWriter->endElement(); 531 $objWriter->endElement(); 532 533 $objWriter->startElement('c:delete'); 534 $objWriter->writeAttribute('val', 0); 535 $objWriter->endElement(); 536 537 $objWriter->startElement('c:axPos'); 538 $objWriter->writeAttribute('val', 'l'); 539 $objWriter->endElement(); 540 541 $objWriter->startElement('c:majorGridlines'); 542 $objWriter->startElement('c:spPr'); 543 544 if ($majorGridlines->getLineColorProperty('value') !== null) { 545 $objWriter->startElement('a:ln'); 546 $objWriter->writeAttribute('w', $majorGridlines->getLineStyleProperty('width')); 547 $objWriter->startElement('a:solidFill'); 548 $objWriter->startElement("a:{$majorGridlines->getLineColorProperty('type')}"); 549 $objWriter->writeAttribute('val', $majorGridlines->getLineColorProperty('value')); 550 $objWriter->startElement('a:alpha'); 551 $objWriter->writeAttribute('val', $majorGridlines->getLineColorProperty('alpha')); 552 $objWriter->endElement(); //end alpha 553 $objWriter->endElement(); //end srgbClr 554 $objWriter->endElement(); //end solidFill 555 556 $objWriter->startElement('a:prstDash'); 557 $objWriter->writeAttribute('val', $majorGridlines->getLineStyleProperty('dash')); 558 $objWriter->endElement(); 559 560 if ($majorGridlines->getLineStyleProperty('join') == 'miter') { 561 $objWriter->startElement('a:miter'); 562 $objWriter->writeAttribute('lim', '800000'); 563 $objWriter->endElement(); 564 } else { 565 $objWriter->startElement('a:bevel'); 566 $objWriter->endElement(); 567 } 568 569 if ($majorGridlines->getLineStyleProperty(['arrow', 'head', 'type']) !== null) { 570 $objWriter->startElement('a:headEnd'); 571 $objWriter->writeAttribute('type', $majorGridlines->getLineStyleProperty(['arrow', 'head', 'type'])); 572 $objWriter->writeAttribute('w', $majorGridlines->getLineStyleArrowParameters('head', 'w')); 573 $objWriter->writeAttribute('len', $majorGridlines->getLineStyleArrowParameters('head', 'len')); 574 $objWriter->endElement(); 575 } 576 577 if ($majorGridlines->getLineStyleProperty(['arrow', 'end', 'type']) !== null) { 578 $objWriter->startElement('a:tailEnd'); 579 $objWriter->writeAttribute('type', $majorGridlines->getLineStyleProperty(['arrow', 'end', 'type'])); 580 $objWriter->writeAttribute('w', $majorGridlines->getLineStyleArrowParameters('end', 'w')); 581 $objWriter->writeAttribute('len', $majorGridlines->getLineStyleArrowParameters('end', 'len')); 582 $objWriter->endElement(); 583 } 584 $objWriter->endElement(); //end ln 585 } 586 $objWriter->startElement('a:effectLst'); 587 588 if ($majorGridlines->getGlowSize() !== null) { 589 $objWriter->startElement('a:glow'); 590 $objWriter->writeAttribute('rad', $majorGridlines->getGlowSize()); 591 $objWriter->startElement("a:{$majorGridlines->getGlowColor('type')}"); 592 $objWriter->writeAttribute('val', $majorGridlines->getGlowColor('value')); 593 $objWriter->startElement('a:alpha'); 594 $objWriter->writeAttribute('val', $majorGridlines->getGlowColor('alpha')); 595 $objWriter->endElement(); //end alpha 596 $objWriter->endElement(); //end schemeClr 597 $objWriter->endElement(); //end glow 598 } 599 600 if ($majorGridlines->getShadowProperty('presets') !== null) { 601 $objWriter->startElement("a:{$majorGridlines->getShadowProperty('effect')}"); 602 if ($majorGridlines->getShadowProperty('blur') !== null) { 603 $objWriter->writeAttribute('blurRad', $majorGridlines->getShadowProperty('blur')); 604 } 605 if ($majorGridlines->getShadowProperty('distance') !== null) { 606 $objWriter->writeAttribute('dist', $majorGridlines->getShadowProperty('distance')); 607 } 608 if ($majorGridlines->getShadowProperty('direction') !== null) { 609 $objWriter->writeAttribute('dir', $majorGridlines->getShadowProperty('direction')); 610 } 611 if ($majorGridlines->getShadowProperty('algn') !== null) { 612 $objWriter->writeAttribute('algn', $majorGridlines->getShadowProperty('algn')); 613 } 614 if ($majorGridlines->getShadowProperty(['size', 'sx']) !== null) { 615 $objWriter->writeAttribute('sx', $majorGridlines->getShadowProperty(['size', 'sx'])); 616 } 617 if ($majorGridlines->getShadowProperty(['size', 'sy']) !== null) { 618 $objWriter->writeAttribute('sy', $majorGridlines->getShadowProperty(['size', 'sy'])); 619 } 620 if ($majorGridlines->getShadowProperty(['size', 'kx']) !== null) { 621 $objWriter->writeAttribute('kx', $majorGridlines->getShadowProperty(['size', 'kx'])); 622 } 623 if ($majorGridlines->getShadowProperty('rotWithShape') !== null) { 624 $objWriter->writeAttribute('rotWithShape', $majorGridlines->getShadowProperty('rotWithShape')); 625 } 626 $objWriter->startElement("a:{$majorGridlines->getShadowProperty(['color', 'type'])}"); 627 $objWriter->writeAttribute('val', $majorGridlines->getShadowProperty(['color', 'value'])); 628 629 $objWriter->startElement('a:alpha'); 630 $objWriter->writeAttribute('val', $majorGridlines->getShadowProperty(['color', 'alpha'])); 631 $objWriter->endElement(); //end alpha 632 633 $objWriter->endElement(); //end color:type 634 $objWriter->endElement(); //end shadow 635 } 636 637 if ($majorGridlines->getSoftEdgesSize() !== null) { 638 $objWriter->startElement('a:softEdge'); 639 $objWriter->writeAttribute('rad', $majorGridlines->getSoftEdgesSize()); 640 $objWriter->endElement(); //end softEdge 641 } 642 643 $objWriter->endElement(); //end effectLst 644 $objWriter->endElement(); //end spPr 645 $objWriter->endElement(); //end majorGridLines 646 647 if ($minorGridlines->getObjectState()) { 648 $objWriter->startElement('c:minorGridlines'); 649 $objWriter->startElement('c:spPr'); 650 651 if ($minorGridlines->getLineColorProperty('value') !== null) { 652 $objWriter->startElement('a:ln'); 653 $objWriter->writeAttribute('w', $minorGridlines->getLineStyleProperty('width')); 654 $objWriter->startElement('a:solidFill'); 655 $objWriter->startElement("a:{$minorGridlines->getLineColorProperty('type')}"); 656 $objWriter->writeAttribute('val', $minorGridlines->getLineColorProperty('value')); 657 $objWriter->startElement('a:alpha'); 658 $objWriter->writeAttribute('val', $minorGridlines->getLineColorProperty('alpha')); 659 $objWriter->endElement(); //end alpha 660 $objWriter->endElement(); //end srgbClr 661 $objWriter->endElement(); //end solidFill 662 663 $objWriter->startElement('a:prstDash'); 664 $objWriter->writeAttribute('val', $minorGridlines->getLineStyleProperty('dash')); 665 $objWriter->endElement(); 666 667 if ($minorGridlines->getLineStyleProperty('join') == 'miter') { 668 $objWriter->startElement('a:miter'); 669 $objWriter->writeAttribute('lim', '800000'); 670 $objWriter->endElement(); 671 } else { 672 $objWriter->startElement('a:bevel'); 673 $objWriter->endElement(); 674 } 675 676 if ($minorGridlines->getLineStyleProperty(['arrow', 'head', 'type']) !== null) { 677 $objWriter->startElement('a:headEnd'); 678 $objWriter->writeAttribute('type', $minorGridlines->getLineStyleProperty(['arrow', 'head', 'type'])); 679 $objWriter->writeAttribute('w', $minorGridlines->getLineStyleArrowParameters('head', 'w')); 680 $objWriter->writeAttribute('len', $minorGridlines->getLineStyleArrowParameters('head', 'len')); 681 $objWriter->endElement(); 682 } 683 684 if ($minorGridlines->getLineStyleProperty(['arrow', 'end', 'type']) !== null) { 685 $objWriter->startElement('a:tailEnd'); 686 $objWriter->writeAttribute('type', $minorGridlines->getLineStyleProperty(['arrow', 'end', 'type'])); 687 $objWriter->writeAttribute('w', $minorGridlines->getLineStyleArrowParameters('end', 'w')); 688 $objWriter->writeAttribute('len', $minorGridlines->getLineStyleArrowParameters('end', 'len')); 689 $objWriter->endElement(); 690 } 691 $objWriter->endElement(); //end ln 692 } 693 694 $objWriter->startElement('a:effectLst'); 695 696 if ($minorGridlines->getGlowSize() !== null) { 697 $objWriter->startElement('a:glow'); 698 $objWriter->writeAttribute('rad', $minorGridlines->getGlowSize()); 699 $objWriter->startElement("a:{$minorGridlines->getGlowColor('type')}"); 700 $objWriter->writeAttribute('val', $minorGridlines->getGlowColor('value')); 701 $objWriter->startElement('a:alpha'); 702 $objWriter->writeAttribute('val', $minorGridlines->getGlowColor('alpha')); 703 $objWriter->endElement(); //end alpha 704 $objWriter->endElement(); //end schemeClr 705 $objWriter->endElement(); //end glow 706 } 707 708 if ($minorGridlines->getShadowProperty('presets') !== null) { 709 $objWriter->startElement("a:{$minorGridlines->getShadowProperty('effect')}"); 710 if ($minorGridlines->getShadowProperty('blur') !== null) { 711 $objWriter->writeAttribute('blurRad', $minorGridlines->getShadowProperty('blur')); 712 } 713 if ($minorGridlines->getShadowProperty('distance') !== null) { 714 $objWriter->writeAttribute('dist', $minorGridlines->getShadowProperty('distance')); 715 } 716 if ($minorGridlines->getShadowProperty('direction') !== null) { 717 $objWriter->writeAttribute('dir', $minorGridlines->getShadowProperty('direction')); 718 } 719 if ($minorGridlines->getShadowProperty('algn') !== null) { 720 $objWriter->writeAttribute('algn', $minorGridlines->getShadowProperty('algn')); 721 } 722 if ($minorGridlines->getShadowProperty(['size', 'sx']) !== null) { 723 $objWriter->writeAttribute('sx', $minorGridlines->getShadowProperty(['size', 'sx'])); 724 } 725 if ($minorGridlines->getShadowProperty(['size', 'sy']) !== null) { 726 $objWriter->writeAttribute('sy', $minorGridlines->getShadowProperty(['size', 'sy'])); 727 } 728 if ($minorGridlines->getShadowProperty(['size', 'kx']) !== null) { 729 $objWriter->writeAttribute('kx', $minorGridlines->getShadowProperty(['size', 'kx'])); 730 } 731 if ($minorGridlines->getShadowProperty('rotWithShape') !== null) { 732 $objWriter->writeAttribute('rotWithShape', $minorGridlines->getShadowProperty('rotWithShape')); 733 } 734 $objWriter->startElement("a:{$minorGridlines->getShadowProperty(['color', 'type'])}"); 735 $objWriter->writeAttribute('val', $minorGridlines->getShadowProperty(['color', 'value'])); 736 $objWriter->startElement('a:alpha'); 737 $objWriter->writeAttribute('val', $minorGridlines->getShadowProperty(['color', 'alpha'])); 738 $objWriter->endElement(); //end alpha 739 $objWriter->endElement(); //end color:type 740 $objWriter->endElement(); //end shadow 741 } 742 743 if ($minorGridlines->getSoftEdgesSize() !== null) { 744 $objWriter->startElement('a:softEdge'); 745 $objWriter->writeAttribute('rad', $minorGridlines->getSoftEdgesSize()); 746 $objWriter->endElement(); //end softEdge 747 } 748 749 $objWriter->endElement(); //end effectLst 750 $objWriter->endElement(); //end spPr 751 $objWriter->endElement(); //end minorGridLines 752 } 753 754 if ($yAxisLabel !== null) { 755 $objWriter->startElement('c:title'); 756 $objWriter->startElement('c:tx'); 757 $objWriter->startElement('c:rich'); 758 759 $objWriter->startElement('a:bodyPr'); 760 $objWriter->endElement(); 761 762 $objWriter->startElement('a:lstStyle'); 763 $objWriter->endElement(); 764 765 $objWriter->startElement('a:p'); 766 $objWriter->startElement('a:r'); 767 768 $caption = $yAxisLabel->getCaption(); 769 if (is_array($caption)) { 770 $caption = $caption[0]; 771 } 772 773 $objWriter->startElement('a:t'); 774 $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($caption)); 775 $objWriter->endElement(); 776 777 $objWriter->endElement(); 778 $objWriter->endElement(); 779 $objWriter->endElement(); 780 $objWriter->endElement(); 781 782 if ($groupType !== DataSeries::TYPE_BUBBLECHART) { 783 $layout = $yAxisLabel->getLayout(); 784 $this->writeLayout($objWriter, $layout); 785 } 786 787 $objWriter->startElement('c:overlay'); 788 $objWriter->writeAttribute('val', 0); 789 $objWriter->endElement(); 790 791 $objWriter->endElement(); 792 } 793 794 $objWriter->startElement('c:numFmt'); 795 $objWriter->writeAttribute('formatCode', $xAxis->getAxisNumberFormat()); 796 $objWriter->writeAttribute('sourceLinked', $xAxis->getAxisNumberSourceLinked()); 797 $objWriter->endElement(); 798 799 $objWriter->startElement('c:majorTickMark'); 800 $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('major_tick_mark')); 801 $objWriter->endElement(); 802 803 $objWriter->startElement('c:minorTickMark'); 804 $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('minor_tick_mark')); 805 $objWriter->endElement(); 806 807 $objWriter->startElement('c:tickLblPos'); 808 $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('axis_labels')); 809 $objWriter->endElement(); 810 811 $objWriter->startElement('c:spPr'); 812 813 if ($xAxis->getFillProperty('value') !== null) { 814 $objWriter->startElement('a:solidFill'); 815 $objWriter->startElement('a:' . $xAxis->getFillProperty('type')); 816 $objWriter->writeAttribute('val', $xAxis->getFillProperty('value')); 817 $objWriter->startElement('a:alpha'); 818 $objWriter->writeAttribute('val', $xAxis->getFillProperty('alpha')); 819 $objWriter->endElement(); 820 $objWriter->endElement(); 821 $objWriter->endElement(); 822 } 823 824 $objWriter->startElement('a:ln'); 825 826 $objWriter->writeAttribute('w', $xAxis->getLineStyleProperty('width')); 827 $objWriter->writeAttribute('cap', $xAxis->getLineStyleProperty('cap')); 828 $objWriter->writeAttribute('cmpd', $xAxis->getLineStyleProperty('compound')); 829 830 if ($xAxis->getLineProperty('value') !== null) { 831 $objWriter->startElement('a:solidFill'); 832 $objWriter->startElement('a:' . $xAxis->getLineProperty('type')); 833 $objWriter->writeAttribute('val', $xAxis->getLineProperty('value')); 834 $objWriter->startElement('a:alpha'); 835 $objWriter->writeAttribute('val', $xAxis->getLineProperty('alpha')); 836 $objWriter->endElement(); 837 $objWriter->endElement(); 838 $objWriter->endElement(); 839 } 840 841 $objWriter->startElement('a:prstDash'); 842 $objWriter->writeAttribute('val', $xAxis->getLineStyleProperty('dash')); 843 $objWriter->endElement(); 844 845 if ($xAxis->getLineStyleProperty('join') == 'miter') { 846 $objWriter->startElement('a:miter'); 847 $objWriter->writeAttribute('lim', '800000'); 848 $objWriter->endElement(); 849 } else { 850 $objWriter->startElement('a:bevel'); 851 $objWriter->endElement(); 852 } 853 854 if ($xAxis->getLineStyleProperty(['arrow', 'head', 'type']) !== null) { 855 $objWriter->startElement('a:headEnd'); 856 $objWriter->writeAttribute('type', $xAxis->getLineStyleProperty(['arrow', 'head', 'type'])); 857 $objWriter->writeAttribute('w', $xAxis->getLineStyleArrowWidth('head')); 858 $objWriter->writeAttribute('len', $xAxis->getLineStyleArrowLength('head')); 859 $objWriter->endElement(); 860 } 861 862 if ($xAxis->getLineStyleProperty(['arrow', 'end', 'type']) !== null) { 863 $objWriter->startElement('a:tailEnd'); 864 $objWriter->writeAttribute('type', $xAxis->getLineStyleProperty(['arrow', 'end', 'type'])); 865 $objWriter->writeAttribute('w', $xAxis->getLineStyleArrowWidth('end')); 866 $objWriter->writeAttribute('len', $xAxis->getLineStyleArrowLength('end')); 867 $objWriter->endElement(); 868 } 869 870 $objWriter->endElement(); 871 872 $objWriter->startElement('a:effectLst'); 873 874 if ($xAxis->getGlowProperty('size') !== null) { 875 $objWriter->startElement('a:glow'); 876 $objWriter->writeAttribute('rad', $xAxis->getGlowProperty('size')); 877 $objWriter->startElement("a:{$xAxis->getGlowProperty(['color', 'type'])}"); 878 $objWriter->writeAttribute('val', $xAxis->getGlowProperty(['color', 'value'])); 879 $objWriter->startElement('a:alpha'); 880 $objWriter->writeAttribute('val', $xAxis->getGlowProperty(['color', 'alpha'])); 881 $objWriter->endElement(); 882 $objWriter->endElement(); 883 $objWriter->endElement(); 884 } 885 886 if ($xAxis->getShadowProperty('presets') !== null) { 887 $objWriter->startElement("a:{$xAxis->getShadowProperty('effect')}"); 888 889 if ($xAxis->getShadowProperty('blur') !== null) { 890 $objWriter->writeAttribute('blurRad', $xAxis->getShadowProperty('blur')); 891 } 892 if ($xAxis->getShadowProperty('distance') !== null) { 893 $objWriter->writeAttribute('dist', $xAxis->getShadowProperty('distance')); 894 } 895 if ($xAxis->getShadowProperty('direction') !== null) { 896 $objWriter->writeAttribute('dir', $xAxis->getShadowProperty('direction')); 897 } 898 if ($xAxis->getShadowProperty('algn') !== null) { 899 $objWriter->writeAttribute('algn', $xAxis->getShadowProperty('algn')); 900 } 901 if ($xAxis->getShadowProperty(['size', 'sx']) !== null) { 902 $objWriter->writeAttribute('sx', $xAxis->getShadowProperty(['size', 'sx'])); 903 } 904 if ($xAxis->getShadowProperty(['size', 'sy']) !== null) { 905 $objWriter->writeAttribute('sy', $xAxis->getShadowProperty(['size', 'sy'])); 906 } 907 if ($xAxis->getShadowProperty(['size', 'kx']) !== null) { 908 $objWriter->writeAttribute('kx', $xAxis->getShadowProperty(['size', 'kx'])); 909 } 910 if ($xAxis->getShadowProperty('rotWithShape') !== null) { 911 $objWriter->writeAttribute('rotWithShape', $xAxis->getShadowProperty('rotWithShape')); 912 } 913 914 $objWriter->startElement("a:{$xAxis->getShadowProperty(['color', 'type'])}"); 915 $objWriter->writeAttribute('val', $xAxis->getShadowProperty(['color', 'value'])); 916 $objWriter->startElement('a:alpha'); 917 $objWriter->writeAttribute('val', $xAxis->getShadowProperty(['color', 'alpha'])); 918 $objWriter->endElement(); 919 $objWriter->endElement(); 920 921 $objWriter->endElement(); 922 } 923 924 if ($xAxis->getSoftEdgesSize() !== null) { 925 $objWriter->startElement('a:softEdge'); 926 $objWriter->writeAttribute('rad', $xAxis->getSoftEdgesSize()); 927 $objWriter->endElement(); 928 } 929 930 $objWriter->endElement(); //effectList 931 $objWriter->endElement(); //end spPr 932 933 if ($id1 > 0) { 934 $objWriter->startElement('c:crossAx'); 935 $objWriter->writeAttribute('val', $id2); 936 $objWriter->endElement(); 937 938 if ($xAxis->getAxisOptionsProperty('horizontal_crosses_value') !== null) { 939 $objWriter->startElement('c:crossesAt'); 940 $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('horizontal_crosses_value')); 941 $objWriter->endElement(); 942 } else { 943 $objWriter->startElement('c:crosses'); 944 $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('horizontal_crosses')); 945 $objWriter->endElement(); 946 } 947 948 $objWriter->startElement('c:crossBetween'); 949 $objWriter->writeAttribute('val', 'midCat'); 950 $objWriter->endElement(); 951 952 if ($xAxis->getAxisOptionsProperty('major_unit') !== null) { 953 $objWriter->startElement('c:majorUnit'); 954 $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('major_unit')); 955 $objWriter->endElement(); 956 } 957 958 if ($xAxis->getAxisOptionsProperty('minor_unit') !== null) { 959 $objWriter->startElement('c:minorUnit'); 960 $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('minor_unit')); 961 $objWriter->endElement(); 962 } 963 } 964 965 if ($isMultiLevelSeries) { 966 if ($groupType !== DataSeries::TYPE_BUBBLECHART) { 967 $objWriter->startElement('c:noMultiLvlLbl'); 968 $objWriter->writeAttribute('val', 0); 969 $objWriter->endElement(); 970 } 971 } 972 973 $objWriter->endElement(); 974 } 975 976 /** 977 * Get the data series type(s) for a chart plot series. 978 * 979 * @param PlotArea $plotArea 980 * 981 * @return array|string 982 */ 983 private static function getChartType($plotArea) 984 { 985 $groupCount = $plotArea->getPlotGroupCount(); 986 987 if ($groupCount == 1) { 988 $chartType = [$plotArea->getPlotGroupByIndex(0)->getPlotType()]; 989 } else { 990 $chartTypes = []; 991 for ($i = 0; $i < $groupCount; ++$i) { 992 $chartTypes[] = $plotArea->getPlotGroupByIndex($i)->getPlotType(); 993 } 994 $chartType = array_unique($chartTypes); 995 if (count($chartTypes) == 0) { 996 throw new WriterException('Chart is not yet implemented'); 997 } 998 } 999 1000 return $chartType; 1001 } 1002 1003 /** 1004 * Method writing plot series values. 1005 * 1006 * @param XMLWriter $objWriter XML Writer 1007 * @param int $val value for idx (default: 3) 1008 * @param string $fillColor hex color (default: FF9900) 1009 * 1010 * @return XMLWriter XML Writer 1011 */ 1012 private function writePlotSeriesValuesElement($objWriter, $val = 3, $fillColor = 'FF9900') 1013 { 1014 $objWriter->startElement('c:dPt'); 1015 $objWriter->startElement('c:idx'); 1016 $objWriter->writeAttribute('val', $val); 1017 $objWriter->endElement(); 1018 1019 $objWriter->startElement('c:bubble3D'); 1020 $objWriter->writeAttribute('val', 0); 1021 $objWriter->endElement(); 1022 1023 $objWriter->startElement('c:spPr'); 1024 $objWriter->startElement('a:solidFill'); 1025 $objWriter->startElement('a:srgbClr'); 1026 $objWriter->writeAttribute('val', $fillColor); 1027 $objWriter->endElement(); 1028 $objWriter->endElement(); 1029 $objWriter->endElement(); 1030 $objWriter->endElement(); 1031 1032 return $objWriter; 1033 } 1034 1035 /** 1036 * Write Plot Group (series of related plots). 1037 * 1038 * @param DataSeries $plotGroup 1039 * @param string $groupType Type of plot for dataseries 1040 * @param XMLWriter $objWriter XML Writer 1041 * @param bool &$catIsMultiLevelSeries Is category a multi-series category 1042 * @param bool &$valIsMultiLevelSeries Is value set a multi-series set 1043 * @param string &$plotGroupingType Type of grouping for multi-series values 1044 */ 1045 private function writePlotGroup($plotGroup, $groupType, $objWriter, &$catIsMultiLevelSeries, &$valIsMultiLevelSeries, &$plotGroupingType): void 1046 { 1047 if ($plotGroup === null) { 1048 return; 1049 } 1050 1051 if (($groupType == DataSeries::TYPE_BARCHART) || ($groupType == DataSeries::TYPE_BARCHART_3D)) { 1052 $objWriter->startElement('c:barDir'); 1053 $objWriter->writeAttribute('val', $plotGroup->getPlotDirection()); 1054 $objWriter->endElement(); 1055 } 1056 1057 if ($plotGroup->getPlotGrouping() !== null) { 1058 $plotGroupingType = $plotGroup->getPlotGrouping(); 1059 $objWriter->startElement('c:grouping'); 1060 $objWriter->writeAttribute('val', $plotGroupingType); 1061 $objWriter->endElement(); 1062 } 1063 1064 // Get these details before the loop, because we can use the count to check for varyColors 1065 $plotSeriesOrder = $plotGroup->getPlotOrder(); 1066 $plotSeriesCount = count($plotSeriesOrder); 1067 1068 if (($groupType !== DataSeries::TYPE_RADARCHART) && ($groupType !== DataSeries::TYPE_STOCKCHART)) { 1069 if ($groupType !== DataSeries::TYPE_LINECHART) { 1070 if (($groupType == DataSeries::TYPE_PIECHART) || ($groupType == DataSeries::TYPE_PIECHART_3D) || ($groupType == DataSeries::TYPE_DONUTCHART) || ($plotSeriesCount > 1)) { 1071 $objWriter->startElement('c:varyColors'); 1072 $objWriter->writeAttribute('val', 1); 1073 $objWriter->endElement(); 1074 } else { 1075 $objWriter->startElement('c:varyColors'); 1076 $objWriter->writeAttribute('val', 0); 1077 $objWriter->endElement(); 1078 } 1079 } 1080 } 1081 1082 foreach ($plotSeriesOrder as $plotSeriesIdx => $plotSeriesRef) { 1083 $objWriter->startElement('c:ser'); 1084 1085 $plotLabel = $plotGroup->getPlotLabelByIndex($plotSeriesIdx); 1086 if ($plotLabel) { 1087 $fillColor = $plotLabel->getFillColor(); 1088 if ($fillColor !== null && !is_array($fillColor)) { 1089 $objWriter->startElement('c:spPr'); 1090 $objWriter->startElement('a:solidFill'); 1091 $objWriter->startElement('a:srgbClr'); 1092 $objWriter->writeAttribute('val', $fillColor); 1093 $objWriter->endElement(); 1094 $objWriter->endElement(); 1095 $objWriter->endElement(); 1096 } 1097 } 1098 1099 $objWriter->startElement('c:idx'); 1100 $objWriter->writeAttribute('val', $this->seriesIndex + $plotSeriesIdx); 1101 $objWriter->endElement(); 1102 1103 $objWriter->startElement('c:order'); 1104 $objWriter->writeAttribute('val', $this->seriesIndex + $plotSeriesRef); 1105 $objWriter->endElement(); 1106 1107 // Values 1108 $plotSeriesValues = $plotGroup->getPlotValuesByIndex($plotSeriesRef); 1109 1110 if (($groupType == DataSeries::TYPE_PIECHART) || ($groupType == DataSeries::TYPE_PIECHART_3D) || ($groupType == DataSeries::TYPE_DONUTCHART)) { 1111 $fillColorValues = $plotSeriesValues->getFillColor(); 1112 if ($fillColorValues !== null && is_array($fillColorValues)) { 1113 foreach ($plotSeriesValues->getDataValues() as $dataKey => $dataValue) { 1114 $this->writePlotSeriesValuesElement($objWriter, $dataKey, ($fillColorValues[$dataKey] ?? 'FF9900')); 1115 } 1116 } else { 1117 $this->writePlotSeriesValuesElement($objWriter); 1118 } 1119 } 1120 1121 // Labels 1122 $plotSeriesLabel = $plotGroup->getPlotLabelByIndex($plotSeriesRef); 1123 if ($plotSeriesLabel && ($plotSeriesLabel->getPointCount() > 0)) { 1124 $objWriter->startElement('c:tx'); 1125 $objWriter->startElement('c:strRef'); 1126 $this->writePlotSeriesLabel($plotSeriesLabel, $objWriter); 1127 $objWriter->endElement(); 1128 $objWriter->endElement(); 1129 } 1130 1131 // Formatting for the points 1132 if (($groupType == DataSeries::TYPE_LINECHART) || ($groupType == DataSeries::TYPE_STOCKCHART)) { 1133 $plotLineWidth = 12700; 1134 if ($plotSeriesValues) { 1135 $plotLineWidth = $plotSeriesValues->getLineWidth(); 1136 } 1137 1138 $objWriter->startElement('c:spPr'); 1139 $objWriter->startElement('a:ln'); 1140 $objWriter->writeAttribute('w', $plotLineWidth); 1141 if ($groupType == DataSeries::TYPE_STOCKCHART) { 1142 $objWriter->startElement('a:noFill'); 1143 $objWriter->endElement(); 1144 } 1145 $objWriter->endElement(); 1146 $objWriter->endElement(); 1147 } 1148 1149 if ($plotSeriesValues) { 1150 $plotSeriesMarker = $plotSeriesValues->getPointMarker(); 1151 if ($plotSeriesMarker) { 1152 $objWriter->startElement('c:marker'); 1153 $objWriter->startElement('c:symbol'); 1154 $objWriter->writeAttribute('val', $plotSeriesMarker); 1155 $objWriter->endElement(); 1156 1157 if ($plotSeriesMarker !== 'none') { 1158 $objWriter->startElement('c:size'); 1159 $objWriter->writeAttribute('val', 3); 1160 $objWriter->endElement(); 1161 } 1162 1163 $objWriter->endElement(); 1164 } 1165 } 1166 1167 if (($groupType === DataSeries::TYPE_BARCHART) || ($groupType === DataSeries::TYPE_BARCHART_3D) || ($groupType === DataSeries::TYPE_BUBBLECHART)) { 1168 $objWriter->startElement('c:invertIfNegative'); 1169 $objWriter->writeAttribute('val', 0); 1170 $objWriter->endElement(); 1171 } 1172 1173 // Category Labels 1174 $plotSeriesCategory = $plotGroup->getPlotCategoryByIndex($plotSeriesRef); 1175 if ($plotSeriesCategory && ($plotSeriesCategory->getPointCount() > 0)) { 1176 $catIsMultiLevelSeries = $catIsMultiLevelSeries || $plotSeriesCategory->isMultiLevelSeries(); 1177 1178 if (($groupType == DataSeries::TYPE_PIECHART) || ($groupType == DataSeries::TYPE_PIECHART_3D) || ($groupType == DataSeries::TYPE_DONUTCHART)) { 1179 if ($plotGroup->getPlotStyle() !== null) { 1180 $plotStyle = $plotGroup->getPlotStyle(); 1181 if ($plotStyle) { 1182 $objWriter->startElement('c:explosion'); 1183 $objWriter->writeAttribute('val', 25); 1184 $objWriter->endElement(); 1185 } 1186 } 1187 } 1188 1189 if (($groupType === DataSeries::TYPE_BUBBLECHART) || ($groupType === DataSeries::TYPE_SCATTERCHART)) { 1190 $objWriter->startElement('c:xVal'); 1191 } else { 1192 $objWriter->startElement('c:cat'); 1193 } 1194 1195 $this->writePlotSeriesValues($plotSeriesCategory, $objWriter, $groupType, 'str'); 1196 $objWriter->endElement(); 1197 } 1198 1199 // Values 1200 if ($plotSeriesValues) { 1201 $valIsMultiLevelSeries = $valIsMultiLevelSeries || $plotSeriesValues->isMultiLevelSeries(); 1202 1203 if (($groupType === DataSeries::TYPE_BUBBLECHART) || ($groupType === DataSeries::TYPE_SCATTERCHART)) { 1204 $objWriter->startElement('c:yVal'); 1205 } else { 1206 $objWriter->startElement('c:val'); 1207 } 1208 1209 $this->writePlotSeriesValues($plotSeriesValues, $objWriter, $groupType, 'num'); 1210 $objWriter->endElement(); 1211 } 1212 1213 if ($groupType === DataSeries::TYPE_BUBBLECHART) { 1214 $this->writeBubbles($plotSeriesValues, $objWriter); 1215 } 1216 1217 $objWriter->endElement(); 1218 } 1219 1220 $this->seriesIndex += $plotSeriesIdx + 1; 1221 } 1222 1223 /** 1224 * Write Plot Series Label. 1225 * 1226 * @param DataSeriesValues $plotSeriesLabel 1227 * @param XMLWriter $objWriter XML Writer 1228 */ 1229 private function writePlotSeriesLabel($plotSeriesLabel, $objWriter): void 1230 { 1231 if ($plotSeriesLabel === null) { 1232 return; 1233 } 1234 1235 $objWriter->startElement('c:f'); 1236 $objWriter->writeRawData($plotSeriesLabel->getDataSource()); 1237 $objWriter->endElement(); 1238 1239 $objWriter->startElement('c:strCache'); 1240 $objWriter->startElement('c:ptCount'); 1241 $objWriter->writeAttribute('val', $plotSeriesLabel->getPointCount()); 1242 $objWriter->endElement(); 1243 1244 foreach ($plotSeriesLabel->getDataValues() as $plotLabelKey => $plotLabelValue) { 1245 $objWriter->startElement('c:pt'); 1246 $objWriter->writeAttribute('idx', $plotLabelKey); 1247 1248 $objWriter->startElement('c:v'); 1249 $objWriter->writeRawData($plotLabelValue); 1250 $objWriter->endElement(); 1251 $objWriter->endElement(); 1252 } 1253 $objWriter->endElement(); 1254 } 1255 1256 /** 1257 * Write Plot Series Values. 1258 * 1259 * @param DataSeriesValues $plotSeriesValues 1260 * @param XMLWriter $objWriter XML Writer 1261 * @param string $groupType Type of plot for dataseries 1262 * @param string $dataType Datatype of series values 1263 */ 1264 private function writePlotSeriesValues($plotSeriesValues, XMLWriter $objWriter, $groupType, $dataType = 'str'): void 1265 { 1266 if ($plotSeriesValues === null) { 1267 return; 1268 } 1269 1270 if ($plotSeriesValues->isMultiLevelSeries()) { 1271 $levelCount = $plotSeriesValues->multiLevelCount(); 1272 1273 $objWriter->startElement('c:multiLvlStrRef'); 1274 1275 $objWriter->startElement('c:f'); 1276 $objWriter->writeRawData($plotSeriesValues->getDataSource()); 1277 $objWriter->endElement(); 1278 1279 $objWriter->startElement('c:multiLvlStrCache'); 1280 1281 $objWriter->startElement('c:ptCount'); 1282 $objWriter->writeAttribute('val', $plotSeriesValues->getPointCount()); 1283 $objWriter->endElement(); 1284 1285 for ($level = 0; $level < $levelCount; ++$level) { 1286 $objWriter->startElement('c:lvl'); 1287 1288 foreach ($plotSeriesValues->getDataValues() as $plotSeriesKey => $plotSeriesValue) { 1289 if (isset($plotSeriesValue[$level])) { 1290 $objWriter->startElement('c:pt'); 1291 $objWriter->writeAttribute('idx', $plotSeriesKey); 1292 1293 $objWriter->startElement('c:v'); 1294 $objWriter->writeRawData($plotSeriesValue[$level]); 1295 $objWriter->endElement(); 1296 $objWriter->endElement(); 1297 } 1298 } 1299 1300 $objWriter->endElement(); 1301 } 1302 1303 $objWriter->endElement(); 1304 1305 $objWriter->endElement(); 1306 } else { 1307 $objWriter->startElement('c:' . $dataType . 'Ref'); 1308 1309 $objWriter->startElement('c:f'); 1310 $objWriter->writeRawData($plotSeriesValues->getDataSource()); 1311 $objWriter->endElement(); 1312 1313 $objWriter->startElement('c:' . $dataType . 'Cache'); 1314 1315 if (($groupType != DataSeries::TYPE_PIECHART) && ($groupType != DataSeries::TYPE_PIECHART_3D) && ($groupType != DataSeries::TYPE_DONUTCHART)) { 1316 if (($plotSeriesValues->getFormatCode() !== null) && ($plotSeriesValues->getFormatCode() !== '')) { 1317 $objWriter->startElement('c:formatCode'); 1318 $objWriter->writeRawData($plotSeriesValues->getFormatCode()); 1319 $objWriter->endElement(); 1320 } 1321 } 1322 1323 $objWriter->startElement('c:ptCount'); 1324 $objWriter->writeAttribute('val', $plotSeriesValues->getPointCount()); 1325 $objWriter->endElement(); 1326 1327 $dataValues = $plotSeriesValues->getDataValues(); 1328 if (!empty($dataValues)) { 1329 if (is_array($dataValues)) { 1330 foreach ($dataValues as $plotSeriesKey => $plotSeriesValue) { 1331 $objWriter->startElement('c:pt'); 1332 $objWriter->writeAttribute('idx', $plotSeriesKey); 1333 1334 $objWriter->startElement('c:v'); 1335 $objWriter->writeRawData($plotSeriesValue); 1336 $objWriter->endElement(); 1337 $objWriter->endElement(); 1338 } 1339 } 1340 } 1341 1342 $objWriter->endElement(); 1343 1344 $objWriter->endElement(); 1345 } 1346 } 1347 1348 /** 1349 * Write Bubble Chart Details. 1350 * 1351 * @param DataSeriesValues $plotSeriesValues 1352 * @param XMLWriter $objWriter XML Writer 1353 */ 1354 private function writeBubbles($plotSeriesValues, $objWriter): void 1355 { 1356 if ($plotSeriesValues === null) { 1357 return; 1358 } 1359 1360 $objWriter->startElement('c:bubbleSize'); 1361 $objWriter->startElement('c:numLit'); 1362 1363 $objWriter->startElement('c:formatCode'); 1364 $objWriter->writeRawData('General'); 1365 $objWriter->endElement(); 1366 1367 $objWriter->startElement('c:ptCount'); 1368 $objWriter->writeAttribute('val', $plotSeriesValues->getPointCount()); 1369 $objWriter->endElement(); 1370 1371 $dataValues = $plotSeriesValues->getDataValues(); 1372 if (!empty($dataValues)) { 1373 if (is_array($dataValues)) { 1374 foreach ($dataValues as $plotSeriesKey => $plotSeriesValue) { 1375 $objWriter->startElement('c:pt'); 1376 $objWriter->writeAttribute('idx', $plotSeriesKey); 1377 $objWriter->startElement('c:v'); 1378 $objWriter->writeRawData(1); 1379 $objWriter->endElement(); 1380 $objWriter->endElement(); 1381 } 1382 } 1383 } 1384 1385 $objWriter->endElement(); 1386 $objWriter->endElement(); 1387 1388 $objWriter->startElement('c:bubble3D'); 1389 $objWriter->writeAttribute('val', 0); 1390 $objWriter->endElement(); 1391 } 1392 1393 /** 1394 * Write Layout. 1395 * 1396 * @param XMLWriter $objWriter XML Writer 1397 * @param Layout $layout 1398 */ 1399 private function writeLayout(XMLWriter $objWriter, ?Layout $layout = null): void 1400 { 1401 $objWriter->startElement('c:layout'); 1402 1403 if ($layout !== null) { 1404 $objWriter->startElement('c:manualLayout'); 1405 1406 $layoutTarget = $layout->getLayoutTarget(); 1407 if ($layoutTarget !== null) { 1408 $objWriter->startElement('c:layoutTarget'); 1409 $objWriter->writeAttribute('val', $layoutTarget); 1410 $objWriter->endElement(); 1411 } 1412 1413 $xMode = $layout->getXMode(); 1414 if ($xMode !== null) { 1415 $objWriter->startElement('c:xMode'); 1416 $objWriter->writeAttribute('val', $xMode); 1417 $objWriter->endElement(); 1418 } 1419 1420 $yMode = $layout->getYMode(); 1421 if ($yMode !== null) { 1422 $objWriter->startElement('c:yMode'); 1423 $objWriter->writeAttribute('val', $yMode); 1424 $objWriter->endElement(); 1425 } 1426 1427 $x = $layout->getXPosition(); 1428 if ($x !== null) { 1429 $objWriter->startElement('c:x'); 1430 $objWriter->writeAttribute('val', $x); 1431 $objWriter->endElement(); 1432 } 1433 1434 $y = $layout->getYPosition(); 1435 if ($y !== null) { 1436 $objWriter->startElement('c:y'); 1437 $objWriter->writeAttribute('val', $y); 1438 $objWriter->endElement(); 1439 } 1440 1441 $w = $layout->getWidth(); 1442 if ($w !== null) { 1443 $objWriter->startElement('c:w'); 1444 $objWriter->writeAttribute('val', $w); 1445 $objWriter->endElement(); 1446 } 1447 1448 $h = $layout->getHeight(); 1449 if ($h !== null) { 1450 $objWriter->startElement('c:h'); 1451 $objWriter->writeAttribute('val', $h); 1452 $objWriter->endElement(); 1453 } 1454 1455 $objWriter->endElement(); 1456 } 1457 1458 $objWriter->endElement(); 1459 } 1460 1461 /** 1462 * Write Alternate Content block. 1463 * 1464 * @param XMLWriter $objWriter XML Writer 1465 */ 1466 private function writeAlternateContent($objWriter): void 1467 { 1468 $objWriter->startElement('mc:AlternateContent'); 1469 $objWriter->writeAttribute('xmlns:mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006'); 1470 1471 $objWriter->startElement('mc:Choice'); 1472 $objWriter->writeAttribute('xmlns:c14', 'http://schemas.microsoft.com/office/drawing/2007/8/2/chart'); 1473 $objWriter->writeAttribute('Requires', 'c14'); 1474 1475 $objWriter->startElement('c14:style'); 1476 $objWriter->writeAttribute('val', '102'); 1477 $objWriter->endElement(); 1478 $objWriter->endElement(); 1479 1480 $objWriter->startElement('mc:Fallback'); 1481 $objWriter->startElement('c:style'); 1482 $objWriter->writeAttribute('val', '2'); 1483 $objWriter->endElement(); 1484 $objWriter->endElement(); 1485 1486 $objWriter->endElement(); 1487 } 1488 1489 /** 1490 * Write Printer Settings. 1491 * 1492 * @param XMLWriter $objWriter XML Writer 1493 */ 1494 private function writePrintSettings($objWriter): void 1495 { 1496 $objWriter->startElement('c:printSettings'); 1497 1498 $objWriter->startElement('c:headerFooter'); 1499 $objWriter->endElement(); 1500 1501 $objWriter->startElement('c:pageMargins'); 1502 $objWriter->writeAttribute('footer', 0.3); 1503 $objWriter->writeAttribute('header', 0.3); 1504 $objWriter->writeAttribute('r', 0.7); 1505 $objWriter->writeAttribute('l', 0.7); 1506 $objWriter->writeAttribute('t', 0.75); 1507 $objWriter->writeAttribute('b', 0.75); 1508 $objWriter->endElement(); 1509 1510 $objWriter->startElement('c:pageSetup'); 1511 $objWriter->writeAttribute('orientation', 'portrait'); 1512 $objWriter->endElement(); 1513 1514 $objWriter->endElement(); 1515 } 1516 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body