diff --git a/samples/Chart/33_Chart_create_stock2.php b/samples/Chart/33_Chart_create_stock2.php new file mode 100644 index 000000000..0d5ebf2c0 --- /dev/null +++ b/samples/Chart/33_Chart_create_stock2.php @@ -0,0 +1,127 @@ +getActiveSheet(); +$worksheet->fromArray( + [ + ['Counts', 'Max', 'Min', 'Min Threshold', 'Max Threshold'], + [10, 10, 5, 0, 50], + [30, 20, 10, 0, 50], + [20, 30, 15, 0, 50], + [40, 10, 0, 0, 50], + [100, 40, 5, 0, 50], + ], + null, + 'A1', + true +); +$worksheet->getStyle('B2:E6')->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_NUMBER_00); + +// Set the Labels for each data series we want to plot +// Datatype +// Cell reference for data +// Format Code +// Number of datapoints in series +// Data values +// Data Marker +$dataSeriesLabels = [ + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), //Max / Open + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), //Min / Close + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), //Min Threshold / Min + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$E$1', null, 1), //Max Threshold / Max +]; +// Set the X-Axis Labels +// Datatype +// Cell reference for data +// Format Code +// Number of datapoints in series +// Data values +// Data Marker +$xAxisTickValues = [ + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$6', null, 5), // Counts +]; +// Set the Data values for each data series we want to plot +// Datatype +// Cell reference for data +// Format Code +// Number of datapoints in series +// Data values +// Data Marker +$dataSeriesValues = [ + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$6', null, 5), + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$6', null, 5), + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$6', null, 5), + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$E$2:$E$6', null, 5), +]; + +// Build the dataseries +$series = new DataSeries( + DataSeries::TYPE_STOCKCHART, // plotType + null, // plotGrouping - if we set this to not null, then xlsx throws error + range(0, count($dataSeriesValues) - 1), // plotOrder + $dataSeriesLabels, // plotLabel + $xAxisTickValues, // plotCategory + $dataSeriesValues // plotValues +); + +// Set the series in the plot area +$plotArea = new PlotArea(null, [$series]); +// Set the chart legend +$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); +$legend->getBorderLines()->setLineColorProperties('ffc000', null, ChartColor::EXCEL_COLOR_TYPE_RGB); +$legend->getFillColor()->setColorProperties('cccccc'); +$legendText = new AxisText(); +$legendText->getFillColorObject()->setValue('008080')->setType(ChartColor::EXCEL_COLOR_TYPE_RGB); +$legendText->setShadowProperties(1); +$legend->setLegendText($legendText); + +$title = new Title('Test Stock Chart'); +$xAxisLabel = new Title('Counts'); +$yAxisLabel = new Title('Values'); + +// 3 stmts below are only difference from 33_chart_create_stock.php +$plotArea->setGapWidth(300); +$plotArea->setUseUpBars(true); +$plotArea->setUseDownBars(true); + +// Create the chart +$chart = new Chart( + 'stock-chart', // name + $title, // title + $legend, // legend + $plotArea, // plotArea + true, // plotVisibleOnly + DataSeries::EMPTY_AS_GAP, // displayBlanksAs + $xAxisLabel, // xAxisLabel + $yAxisLabel // yAxisLabel +); + +// Set the position where the chart should appear in the worksheet +$chart->setTopLeftPosition('A7'); +$chart->setBottomRightPosition('H20'); + +// Add the chart to the worksheet +$worksheet->addChart($chart); +$worksheet->setSelectedCells('G2'); + +// Save Excel 2007 file +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/templates/32readwriteStockChart2.xlsx b/samples/templates/32readwriteStockChart2.xlsx index 1e6d1fff6..d5d1a99b7 100644 Binary files a/samples/templates/32readwriteStockChart2.xlsx and b/samples/templates/32readwriteStockChart2.xlsx differ diff --git a/src/PhpSpreadsheet/Chart/PlotArea.php b/src/PhpSpreadsheet/Chart/PlotArea.php index ccde4bb2a..2b78d9a4e 100644 --- a/src/PhpSpreadsheet/Chart/PlotArea.php +++ b/src/PhpSpreadsheet/Chart/PlotArea.php @@ -163,4 +163,49 @@ class PlotArea { return $this->gradientFillStops; } + + /** @var ?int */ + private $gapWidth; + + /** @var bool */ + private $useUpBars = false; + + /** @var bool */ + private $useDownBars = false; + + public function getGapWidth(): ?int + { + return $this->gapWidth; + } + + public function setGapWidth(?int $gapWidth): self + { + $this->gapWidth = $gapWidth; + + return $this; + } + + public function getUseUpBars(): bool + { + return $this->useUpBars; + } + + public function setUseUpBars(bool $useUpBars): self + { + $this->useUpBars = $useUpBars; + + return $this; + } + + public function getUseDownBars(): bool + { + return $this->useDownBars; + } + + public function setUseDownBars(bool $useDownBars): self + { + $this->useDownBars = $useDownBars; + + return $this; + } } diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php index 7d33c6eba..c5a59f558 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php @@ -82,6 +82,9 @@ class Chart $gradientArray = []; $gradientLin = null; $roundedCorners = false; + $gapWidth = null; + $useUpBars = null; + $useDownBars = null; foreach ($chartElementsC as $chartElementKey => $chartElement) { switch ($chartElementKey) { case 'spPr': @@ -332,6 +335,15 @@ class Chart break; case 'stockChart': $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); + if (isset($chartDetail->upDownBars->gapWidth)) { + $gapWidth = self::getAttribute($chartDetail->upDownBars->gapWidth, 'val', 'integer'); + } + if (isset($chartDetail->upDownBars->upBars)) { + $useUpBars = true; + } + if (isset($chartDetail->upDownBars->downBars)) { + $useDownBars = true; + } $plotAttributes = $this->readChartAttributes($chartDetail); break; @@ -348,6 +360,15 @@ class Chart if (!empty($gradientArray)) { $plotArea->setGradientFillProperties($gradientArray, $gradientLin); } + if (is_int($gapWidth)) { + $plotArea->setGapWidth($gapWidth); + } + if ($useUpBars === true) { + $plotArea->setUseUpBars(true); + } + if ($useDownBars === true) { + $plotArea->setUseDownBars(true); + } break; case 'plotVisOnly': diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php index 6200159a7..6d302aac4 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php @@ -331,19 +331,26 @@ class Chart extends WriterPart $objWriter->startElement('c:hiLowLines'); $objWriter->endElement(); - $objWriter->startElement('c:upDownBars'); - - $objWriter->startElement('c:gapWidth'); - $objWriter->writeAttribute('val', '300'); - $objWriter->endElement(); - - $objWriter->startElement('c:upBars'); - $objWriter->endElement(); - - $objWriter->startElement('c:downBars'); - $objWriter->endElement(); - - $objWriter->endElement(); + $gapWidth = $plotArea->getGapWidth(); + $upBars = $plotArea->getUseUpBars(); + $downBars = $plotArea->getUseDownBars(); + if ($gapWidth !== null || $upBars || $downBars) { + $objWriter->startElement('c:upDownBars'); + if ($gapWidth !== null) { + $objWriter->startElement('c:gapWidth'); + $objWriter->writeAttribute('val', "$gapWidth"); + $objWriter->endElement(); + } + if ($upBars) { + $objWriter->startElement('c:upBars'); + $objWriter->endElement(); + } + if ($downBars) { + $objWriter->startElement('c:downBars'); + $objWriter->endElement(); + } + $objWriter->endElement(); // c:upDownBars + } } // Generate 3 unique numbers to use for axId values