Skip to content

Commit ef031e7

Browse files
authored
More Chart Fixes (#2841)
* More Chart Fixes Taking up where #2828 left off. Most of the following changes are demonstrated in 32readwriteChartWithImages1: - Adds support for "scheme" colors (because rgb, theme, and index colors just weren't enough for Excel) for DataSeriesValues. See issue #2299. - For chart titles (including axis labels), rather than a font name, Excel supplies a 3-fold series of font names for Latin, East Asian, and Complex Scripts. New properties `latin`, `eastAsian`, and `complexScript` are added to the Font class. I frankly have no idea how, or even if, you can set these in Excel; my test case (sample 32readwriteScatterChart7) is a result of manually editing the XML. - Add support for subscript/superscript to chart titles. This requires a new property `baseLine` in Font (positive=superscript negative=subscript baseline value says how high/low). - Support for underscore with different scheme color than its text, using a new string property `uSchemeClr` in Font. - Support for extra options for strikethrough, using a new string property `strikeType` in Font. - Support for extra options for underscore type, using the existing string property `underline` in Font. - I do not anticipate that any of the new Font properties will be used except for chart titles. - If no default font overrides are found for a Rich Text element in chart titles, and no explicit font overrides are found for a Run under such an element, the font element of the Run is set to null. - PhpSpreadsheet will always write a tag `a:pPr` and, underneath that, an empty tag `a:defRPr`, for default font settings for chart titles and axis labels. Combined with the previous bullet item, this will prevent PhpSpreadsheet from inadvertently overriding the Excel defaults (18 point bold Calibri for chart title, 10 point bold Calibri for axis labels). - Axis labels will now be written to XML in the same manner as chart titles. Among other considerations, this means that they can now have colors. Fix #2700. Supersedes PR #2701. Demonstrated in sample 32readwriteStockChart5. * Fix Some Chart Corruption Fix #2817, where @bridgeplayr gives an excellent description of the problem and how it should be solved. * Fix Bubble Charts Sample produced corrupt output - see issue #2763. After a lot of research, solution was just re-ordering of parameters in a single function call. Bubble 3D had not been supported at all. It is now. Surface Charts remain corrupted.
1 parent 9d36e44 commit ef031e7

File tree

11 files changed

+690
-38
lines changed

11 files changed

+690
-38
lines changed

phpstan-baseline.neon

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4792,7 +4792,7 @@ parameters:
47924792

47934793
-
47944794
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, int given\\.$#"
4795-
count: 44
4795+
count: 43
47964796
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
47974797

47984798
-
@@ -4982,7 +4982,7 @@ parameters:
49824982

49834983
-
49844984
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, string\\|null given\\.$#"
4985-
count: 5
4985+
count: 4
49864986
path: src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
49874987

49884988
-
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php
2+
3+
use PhpOffice\PhpSpreadsheet\Chart\Axis;
4+
use PhpOffice\PhpSpreadsheet\Chart\Chart;
5+
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
6+
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
7+
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
8+
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
9+
use PhpOffice\PhpSpreadsheet\Chart\Properties;
10+
use PhpOffice\PhpSpreadsheet\Chart\Title;
11+
use PhpOffice\PhpSpreadsheet\IOFactory;
12+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
13+
14+
require __DIR__ . '/../Header.php';
15+
16+
$spreadsheet = new Spreadsheet();
17+
$worksheet = $spreadsheet->getActiveSheet();
18+
// changed data to simulate a trend chart - Xaxis are dates; Yaxis are 3 meausurements from each date
19+
$worksheet->fromArray(
20+
[
21+
['', 'metric1', 'metric2', 'metric3'],
22+
['=DATEVALUE("2021-01-01")', 12.1, 15.1, 21.1],
23+
['=DATEVALUE("2021-01-04")', 56.2, 73.2, 86.2],
24+
['=DATEVALUE("2021-01-07")', 52.2, 61.2, 69.2],
25+
['=DATEVALUE("2021-01-10")', 30.2, 32.2, 0.2],
26+
]
27+
);
28+
$worksheet->getStyle('A2:A5')->getNumberFormat()->setFormatCode('yyyy-mm-dd');
29+
$worksheet->getColumnDimension('A')->setAutoSize(true);
30+
$worksheet->setSelectedCells('A1');
31+
32+
// Set the Labels for each data series we want to plot
33+
// Datatype
34+
// Cell reference for data
35+
// Format Code
36+
// Number of datapoints in series
37+
// Data values
38+
// Data Marker
39+
$dataSeriesLabels = [
40+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // was 2010
41+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // was 2011
42+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // was 2012
43+
];
44+
// Set the X-Axis Labels
45+
// changed from STRING to NUMBER
46+
// added 2 additional x-axis values associated with each of the 3 metrics
47+
// added FORMATE_CODE_NUMBER
48+
$xAxisTickValues = [
49+
//new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4
50+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4),
51+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4),
52+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4),
53+
];
54+
// Set the Data values for each data series we want to plot
55+
// Datatype
56+
// Cell reference for data
57+
// Format Code
58+
// Number of datapoints in series
59+
// Data values
60+
// Data Marker
61+
// added FORMAT_CODE_NUMBER
62+
$dataSeriesValues = [
63+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', Properties::FORMAT_CODE_NUMBER, 4),
64+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', Properties::FORMAT_CODE_NUMBER, 4),
65+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', Properties::FORMAT_CODE_NUMBER, 4),
66+
];
67+
// Added so that Xaxis shows dates instead of Excel-equivalent-year1900-numbers
68+
$xAxis = new Axis();
69+
//$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE );
70+
$xAxis->setAxisNumberProperties('yyyy-mm-dd');
71+
72+
// Build the dataseries
73+
$series = new DataSeries(
74+
DataSeries::TYPE_SCATTERCHART, // plotType
75+
null, // plotGrouping (Scatter charts don't have any grouping)
76+
range(0, count($dataSeriesValues) - 1), // plotOrder
77+
$dataSeriesLabels, // plotLabel
78+
$xAxisTickValues, // plotCategory
79+
$dataSeriesValues, // plotValues
80+
null, // plotDirection
81+
null, // smooth line
82+
//DataSeries::STYLE_LINEMARKER // plotStyle
83+
DataSeries::STYLE_MARKER // plotStyle
84+
);
85+
86+
// Set the series in the plot area
87+
$plotArea = new PlotArea(null, [$series]);
88+
// Set the chart legend
89+
$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
90+
91+
$title = new Title('Test Scatter Trend Chart');
92+
$yAxisLabel = new Title('Value ($k)');
93+
94+
// Create the chart
95+
$chart = new Chart(
96+
'chart1', // name
97+
$title, // title
98+
$legend, // legend
99+
$plotArea, // plotArea
100+
true, // plotVisibleOnly
101+
DataSeries::EMPTY_AS_GAP, // displayBlanksAs
102+
null, // xAxisLabel
103+
$yAxisLabel, // yAxisLabel
104+
// added xAxis for correct date display
105+
$xAxis, // xAxis
106+
);
107+
108+
// Set the position where the chart should appear in the worksheet
109+
$chart->setTopLeftPosition('A7');
110+
$chart->setBottomRightPosition('N20');
111+
// Add the chart to the worksheet
112+
$worksheet->addChart($chart);
113+
114+
// Save Excel 2007 file
115+
$filename = $helper->getFilename(__FILE__);
116+
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
117+
$writer->setIncludeCharts(true);
118+
$callStartTime = microtime(true);
119+
$writer->save($filename);
120+
$spreadsheet->disconnectWorksheets();
121+
$helper->logWrite($writer, $filename, $callStartTime);
30.9 KB
Binary file not shown.
30.7 KB
Binary file not shown.

src/PhpSpreadsheet/Chart/DataSeriesValues.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ class DataSeriesValues
7373
*/
7474
private $fillColor;
7575

76+
/** @var string */
77+
private $schemeClr = '';
78+
7679
/**
7780
* Line Width.
7881
*
@@ -83,6 +86,9 @@ class DataSeriesValues
8386
/** @var bool */
8487
private $scatterLines = true;
8588

89+
/** @var bool */
90+
private $bubble3D = false;
91+
8692
/**
8793
* Create a new DataSeriesValues object.
8894
*
@@ -440,4 +446,28 @@ public function setScatterLines(bool $scatterLines): self
440446

441447
return $this;
442448
}
449+
450+
public function getBubble3D(): bool
451+
{
452+
return $this->bubble3D;
453+
}
454+
455+
public function setBubble3D(bool $bubble3D): self
456+
{
457+
$this->bubble3D = $bubble3D;
458+
459+
return $this;
460+
}
461+
462+
public function getSchemeClr(): string
463+
{
464+
return $this->schemeClr;
465+
}
466+
467+
public function setSchemeClr(string $schemeClr): self
468+
{
469+
$this->schemeClr = $schemeClr;
470+
471+
return $this;
472+
}
443473
}

0 commit comments

Comments
 (0)