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