Fixes for Surface Charts (#2933)
Fix #2931. If surface charts are written with c:grouping tag, Excel will treat them as corrupt. Also, some 3D-ish Xml tags are required when 2D surface charts are written, else they will be treated as 3D. Also eliminate a duplicate line identified by #2932.
This commit is contained in:
parent
5de82981d8
commit
a062521a18
|
|
@ -144,7 +144,6 @@ class Axis extends Properties
|
|||
$this->setAxisOption('orientation', $axisOrientation);
|
||||
$this->setAxisOption('major_tick_mark', $majorTmt);
|
||||
$this->setAxisOption('minor_tick_mark', $minorTmt);
|
||||
$this->setAxisOption('minor_tick_mark', $minorTmt);
|
||||
$this->setAxisOption('minimum', $minimum);
|
||||
$this->setAxisOption('maximum', $maximum);
|
||||
$this->setAxisOption('major_unit', $majorUnit);
|
||||
|
|
|
|||
|
|
@ -72,30 +72,22 @@ class Chart extends WriterPart
|
|||
$objWriter->endElement();
|
||||
|
||||
$objWriter->startElement('c:view3D');
|
||||
$rotX = $chart->getRotX();
|
||||
if (is_int($rotX)) {
|
||||
$objWriter->startElement('c:rotX');
|
||||
$objWriter->writeAttribute('val', "$rotX");
|
||||
$objWriter->endElement();
|
||||
$surface2D = false;
|
||||
$plotArea = $chart->getPlotArea();
|
||||
if ($plotArea !== null) {
|
||||
$seriesArray = $plotArea->getPlotGroup();
|
||||
foreach ($seriesArray as $series) {
|
||||
if ($series->getPlotType() === DataSeries::TYPE_SURFACECHART) {
|
||||
$surface2D = true;
|
||||
|
||||
break;
|
||||
}
|
||||
$rotY = $chart->getRotY();
|
||||
if (is_int($rotY)) {
|
||||
$objWriter->startElement('c:rotY');
|
||||
$objWriter->writeAttribute('val', "$rotY");
|
||||
$objWriter->endElement();
|
||||
}
|
||||
$rAngAx = $chart->getRAngAx();
|
||||
if (is_int($rAngAx)) {
|
||||
$objWriter->startElement('c:rAngAx');
|
||||
$objWriter->writeAttribute('val', "$rAngAx");
|
||||
$objWriter->endElement();
|
||||
}
|
||||
$perspective = $chart->getPerspective();
|
||||
if (is_int($perspective)) {
|
||||
$objWriter->startElement('c:perspective');
|
||||
$objWriter->writeAttribute('val', "$perspective");
|
||||
$objWriter->endElement();
|
||||
}
|
||||
$this->writeView3D($objWriter, $chart->getRotX(), 'c:rotX', $surface2D, 90);
|
||||
$this->writeView3D($objWriter, $chart->getRotY(), 'c:rotY', $surface2D);
|
||||
$this->writeView3D($objWriter, $chart->getRAngAx(), 'c:rAngAx', $surface2D);
|
||||
$this->writeView3D($objWriter, $chart->getPerspective(), 'c:perspective', $surface2D);
|
||||
$objWriter->endElement(); // view3D
|
||||
|
||||
$this->writePlotArea($objWriter, $chart->getPlotArea(), $chart->getXAxisLabel(), $chart->getYAxisLabel(), $chart->getChartAxisX(), $chart->getChartAxisY());
|
||||
|
|
@ -124,6 +116,18 @@ class Chart extends WriterPart
|
|||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
private function writeView3D(XMLWriter $objWriter, ?int $value, string $tag, bool $surface2D, int $default = 0): void
|
||||
{
|
||||
if ($value === null && $surface2D) {
|
||||
$value = $default;
|
||||
}
|
||||
if ($value !== null) {
|
||||
$objWriter->startElement($tag);
|
||||
$objWriter->writeAttribute('val', "$value");
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Chart Title.
|
||||
*/
|
||||
|
|
@ -913,8 +917,8 @@ class Chart extends WriterPart
|
|||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
if ($plotGroup->getPlotGrouping() !== null) {
|
||||
$plotGroupingType = $plotGroup->getPlotGrouping();
|
||||
if ($plotGroupingType !== null && $groupType !== DataSeries::TYPE_SURFACECHART && $groupType !== DataSeries::TYPE_SURFACECHART_3D) {
|
||||
$objWriter->startElement('c:grouping');
|
||||
$objWriter->writeAttribute('val', $plotGroupingType);
|
||||
$objWriter->endElement();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Chart;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class Issue2931Test extends TestCase
|
||||
{
|
||||
public function testSurface(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$dataSeriesLabels = [
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, null, null, 1, ['5-6']),
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, null, null, 1, ['6-7']),
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, null, null, 1, ['7-8']),
|
||||
];
|
||||
|
||||
$xAxisTickValues = [
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, null, null, 9, [1, 2, 3, 4, 5, 6, 7, 8, 9]),
|
||||
];
|
||||
|
||||
$dataSeriesValues = [
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, null, null, 9, [6, 6, 6, 6, 6, 6, 5.9, 6, 6]),
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, null, null, 9, [6, 6, 6, 6.5, 7, 7, 7, 7, 7]),
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, null, null, 9, [6, 6, 6, 7, 8, 8, 8, 8, 7.9]),
|
||||
];
|
||||
|
||||
$series = new DataSeries(
|
||||
DataSeries::TYPE_SURFACECHART,
|
||||
DataSeries::GROUPING_STANDARD, // grouping should not be written for surface chart
|
||||
range(0, count($dataSeriesValues) - 1),
|
||||
$dataSeriesLabels,
|
||||
$xAxisTickValues,
|
||||
$dataSeriesValues,
|
||||
null, // plotDirection
|
||||
false, // smooth line
|
||||
DataSeries::STYLE_LINEMARKER // plotStyle
|
||||
);
|
||||
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
$legend = new ChartLegend(ChartLegend::POSITION_BOTTOM, null, false);
|
||||
|
||||
$title = new Title('График распредления температур в пределах кр');
|
||||
|
||||
$chart = new Chart(
|
||||
'chart2',
|
||||
$title,
|
||||
$legend,
|
||||
$plotArea,
|
||||
true,
|
||||
DataSeries::EMPTY_AS_GAP,
|
||||
);
|
||||
|
||||
$chart->setTopLeftPosition('$A$1');
|
||||
$chart->setBottomRightPosition('$P$20');
|
||||
|
||||
$sheet->addChart($chart);
|
||||
|
||||
$writer = new XlsxWriter($spreadsheet);
|
||||
$writer->setIncludeCharts(true);
|
||||
$writer = new XlsxWriter($spreadsheet);
|
||||
$writer->setIncludeCharts(true);
|
||||
$writerChart = new XlsxWriter\Chart($writer);
|
||||
$data = $writerChart->writeChart($chart);
|
||||
|
||||
// rotX etc. should be generated for surfaceChart 2D
|
||||
// even when unspecified.
|
||||
$expectedXml2D = [
|
||||
'<c:view3D><c:rotX val="90"/><c:rotY val="0"/><c:rAngAx val="0"/><c:perspective val="0"/></c:view3D>',
|
||||
];
|
||||
$expectedXml3D = [
|
||||
'<c:view3D/>',
|
||||
];
|
||||
$expectedXmlNoX = [
|
||||
'c:grouping',
|
||||
];
|
||||
|
||||
// confirm that file contains expected tags
|
||||
foreach ($expectedXml2D as $expected) {
|
||||
self::assertSame(1, substr_count($data, $expected), $expected);
|
||||
}
|
||||
foreach ($expectedXmlNoX as $expected) {
|
||||
self::assertSame(0, substr_count($data, $expected), $expected);
|
||||
}
|
||||
|
||||
$series->setPlotType(DataSeries::TYPE_SURFACECHART_3D);
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
$chart->setPlotArea($plotArea);
|
||||
$writerChart = new XlsxWriter\Chart($writer);
|
||||
$data = $writerChart->writeChart($chart);
|
||||
// confirm that file contains expected tags
|
||||
foreach ($expectedXml3D as $expected) {
|
||||
self::assertSame(1, substr_count($data, $expected), $expected);
|
||||
}
|
||||
foreach ($expectedXmlNoX as $expected) {
|
||||
self::assertSame(0, substr_count($data, $expected), $expected);
|
||||
}
|
||||
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue