Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Font/Effects/Theme Support for Chart Data Labels and Axis #3476

Merged
merged 6 commits into from
Mar 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).

### Changed

- Xlsx Color schemes read in will be written out (previously Excel 2007-2010 Color scheme was always written); manipulation of those schemes before write, including restoring prior behavior, is provided [PR #3476](https://github.com/PHPOffice/PhpSpreadsheet/pull/3476)
- Memory and speed optimisations for Read Filters with Xlsx Files and Shared Formulae. [PR #3474](https://github.com/PHPOffice/PhpSpreadsheet/pull/3474)

### Deprecated
Expand Down
107 changes: 107 additions & 0 deletions samples/Chart/33_Chart_create_area_2.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

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\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Theme as SpreadsheetTheme;

require __DIR__ . '/../Header.php';

$spreadsheet = new Spreadsheet();
// same as 33_Chart_create_area, but with 2013+ schemes
$spreadsheet->getTheme()->setThemeColorName(SpreadsheetTheme::COLOR_SCHEME_2013_PLUS_NAME);
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray(
[
['', 2010, 2011, 2012],
['Q1', 12, 15, 21],
['Q2', 56, 73, 86],
['Q3', 52, 61, 69],
['Q4', 30, 32, 0],
]
);

// 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), // 2010
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012
];
// 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$5', null, 4), // Q1 to Q4
];
// 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$5', null, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4),
];

// Build the dataseries
$series = new DataSeries(
DataSeries::TYPE_AREACHART, // plotType
DataSeries::GROUPING_PERCENT_STACKED, // plotGrouping
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_TOPRIGHT, null, false);

$title = new Title('Test %age-Stacked Area Chart');
$yAxisLabel = new Title('Value ($k)');

// Create the chart
$chart = new Chart(
'chart1', // name
$title, // title
$legend, // legend
$plotArea, // plotArea
true, // plotVisibleOnly
DataSeries::EMPTY_AS_GAP, // displayBlanksAs
null, // 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);

// 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);
Binary file added samples/templates/32readwriteLineChart6.xlsx
Binary file not shown.
29 changes: 25 additions & 4 deletions src/PhpSpreadsheet/Chart/AxisText.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,21 @@

namespace PhpOffice\PhpSpreadsheet\Chart;

use PhpOffice\PhpSpreadsheet\Style\Font;

class AxisText extends Properties
{
/** @var ?int */
private $rotation;

/** @var ChartColor */
private $fillColor;
/** @var Font */
private $font;

public function __construct()
{
parent::__construct();
$this->fillColor = new ChartColor();
$this->font = new Font();
$this->font->setSize(null, true);
}

public function setRotation(?int $rotation): self
Expand All @@ -30,6 +33,24 @@ public function getRotation(): ?int

public function getFillColorObject(): ChartColor
{
return $this->fillColor;
$fillColor = $this->font->getChartColor();
if ($fillColor === null) {
$fillColor = new ChartColor();
$this->font->setChartColorFromObject($fillColor);
}

return $fillColor;
}

public function getFont(): Font
{
return $this->font;
}

public function setFont(Font $font): self
{
$this->font = $font;

return $this;
}
}
44 changes: 39 additions & 5 deletions src/PhpSpreadsheet/Chart/Layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace PhpOffice\PhpSpreadsheet\Chart;

use PhpOffice\PhpSpreadsheet\Style\Font;

class Layout
{
/**
Expand Down Expand Up @@ -127,8 +129,11 @@ class Layout
/** @var ?ChartColor */
private $labelBorderColor;

/** @var ?ChartColor */
private $labelFontColor;
/** @var ?Font */
private $labelFont;

/** @var Properties */
private $labelEffects;

/**
* Create a new Layout.
Expand Down Expand Up @@ -172,7 +177,18 @@ public function __construct(array $layout = [])
$this->initBoolean($layout, 'numFmtLinked');
$this->initColor($layout, 'labelFillColor');
$this->initColor($layout, 'labelBorderColor');
$this->initColor($layout, 'labelFontColor');
$labelFont = $layout['labelFont'] ?? null;
if ($labelFont instanceof Font) {
$this->labelFont = $labelFont;
}
$labelFontColor = $layout['labelFontColor'] ?? null;
if ($labelFontColor instanceof ChartColor) {
$this->setLabelFontColor($labelFontColor);
}
$labelEffects = $layout['labelEffects'] ?? null;
if ($labelEffects instanceof Properties) {
$this->labelEffects = $labelEffects;
}
}

private function initBoolean(array $layout, string $name): void
Expand Down Expand Up @@ -493,14 +509,32 @@ public function setLabelBorderColor(?ChartColor $chartColor): self
return $this;
}

public function getLabelFont(): ?Font
{
return $this->labelFont;
}

public function getLabelEffects(): ?Properties
{
return $this->labelEffects;
}

public function getLabelFontColor(): ?ChartColor
{
return $this->labelFontColor;
if ($this->labelFont === null) {
return null;
}

return $this->labelFont->getChartColor();
}

public function setLabelFontColor(?ChartColor $chartColor): self
{
$this->labelFontColor = $chartColor;
if ($this->labelFont === null) {
$this->labelFont = new Font();
$this->labelFont->setSize(null, true);
}
$this->labelFont->setChartColorFromObject($chartColor);

return $this;
}
Expand Down
3 changes: 3 additions & 0 deletions src/PhpSpreadsheet/Reader/Xlsx.php
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet

$colourScheme = self::getAttributes($xmlTheme->themeElements->clrScheme);
$colourSchemeName = (string) $colourScheme['name'];
$excel->getTheme()->setThemeColorName($colourSchemeName);
$colourScheme = $xmlTheme->themeElements->clrScheme->children($drawingNS);

$themeColours = [];
Expand All @@ -466,9 +467,11 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
if (isset($xmlColour->sysClr)) {
$xmlColourData = self::getAttributes($xmlColour->sysClr);
$themeColours[$themePos] = (string) $xmlColourData['lastClr'];
$excel->getTheme()->setThemeColor($k, (string) $xmlColourData['lastClr']);
} elseif (isset($xmlColour->srgbClr)) {
$xmlColourData = self::getAttributes($xmlColour->srgbClr);
$themeColours[$themePos] = (string) $xmlColourData['val'];
$excel->getTheme()->setThemeColor($k, (string) $xmlColourData['val']);
}
}
$theme = new Theme($themeName, $colourSchemeName, $themeColours);
Expand Down
50 changes: 44 additions & 6 deletions src/PhpSpreadsheet/Reader/Xlsx/Chart.php
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,37 @@ private function parseRichText(SimpleXMLElement $titleDetailPart): RichText
return $value;
}

private function parseFont(SimpleXMLElement $titleDetailPart): ?Font
{
if (!isset($titleDetailPart->pPr->defRPr)) {
return null;
}
$fontArray = [];
$fontArray['size'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'sz', 'integer');
$fontArray['bold'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'b', 'boolean');
$fontArray['italic'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'i', 'boolean');
$fontArray['underscore'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'u', 'string');
$fontArray['strikethrough'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'strike', 'string');

if (isset($titleDetailPart->pPr->defRPr->latin)) {
$fontArray['latin'] = self::getAttribute($titleDetailPart->pPr->defRPr->latin, 'typeface', 'string');
}
if (isset($titleDetailPart->pPr->defRPr->ea)) {
$fontArray['eastAsian'] = self::getAttribute($titleDetailPart->pPr->defRPr->ea, 'typeface', 'string');
}
if (isset($titleDetailPart->pPr->defRPr->cs)) {
$fontArray['complexScript'] = self::getAttribute($titleDetailPart->pPr->defRPr->cs, 'typeface', 'string');
}
if (isset($titleDetailPart->pPr->defRPr->solidFill)) {
$fontArray['chartColor'] = new ChartColor($this->readColor($titleDetailPart->pPr->defRPr->solidFill));
}
$font = new Font();
$font->setSize(null, true);
$font->applyFromArray($fontArray);

return $font;
}

/**
* @param ?SimpleXMLElement $chartDetail
*/
Expand Down Expand Up @@ -1189,8 +1220,13 @@ private function readChartAttributes($chartDetail): array
}
if (isset($chartDetail->dLbls->txPr)) {
$txpr = $chartDetail->dLbls->txPr->children($this->aNamespace);
if (isset($txpr->p->pPr->defRPr->solidFill)) {
$plotAttributes['labelFontColor'] = new ChartColor($this->readColor($txpr->p->pPr->defRPr->solidFill));
if (isset($txpr->p)) {
$plotAttributes['labelFont'] = $this->parseFont($txpr->p);
if (isset($txpr->p->pPr->defRPr->effectLst)) {
$labelEffects = new GridLines();
$this->readEffects($txpr->p->pPr->defRPr, $labelEffects, false);
$plotAttributes['labelEffects'] = $labelEffects;
}
}
}
}
Expand Down Expand Up @@ -1489,10 +1525,12 @@ private function setAxisProperties(SimpleXMLElement $chartDetail, ?Axis $whichAx
$addAxisText = true;
}
}
if (isset($children->p->pPr->defRPr->solidFill)) {
$colorArray = $this->readColor($children->p->pPr->defRPr->solidFill);
$axisText->getFillColorObject()->setColorPropertiesArray($colorArray);
$addAxisText = true;
if (isset($children->p->pPr->defRPr)) {
$font = $this->parseFont($children->p);
if ($font !== null) {
$axisText->setFont($font);
$addAxisText = true;
}
}
if (isset($children->p->pPr->defRPr->effectLst)) {
$this->readEffects($children->p->pPr->defRPr, $axisText, false);
Expand Down
9 changes: 9 additions & 0 deletions src/PhpSpreadsheet/Spreadsheet.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,14 @@ class Spreadsheet implements JsonSerializable
*/
private $tabRatio = 600;

/** @var Theme */
private $theme;

public function getTheme(): Theme
{
return $this->theme;
}

/**
* The workbook has macros ?
*
Expand Down Expand Up @@ -476,6 +484,7 @@ public function __construct()
{
$this->uniqueID = uniqid('', true);
$this->calculationEngine = new Calculation($this);
$this->theme = new Theme();

// Initialise worksheet collection and add one worksheet
$this->workSheetCollection = [];
Expand Down
10 changes: 10 additions & 0 deletions src/PhpSpreadsheet/Style/Font.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ public function applyFromArray(array $styleArray)
if (isset($styleArray['size'])) {
$this->setSize($styleArray['size']);
}
if (isset($styleArray['chartColor'])) {
$this->chartColor = $styleArray['chartColor'];
}
}

return $this;
Expand Down Expand Up @@ -634,6 +637,13 @@ public function setChartColor(array $colorArray): self
return $this;
}

public function setChartColorFromObject(?ChartColor $chartColor): self
{
$this->chartColor = $chartColor;

return $this;
}

/**
* Get Underline.
*
Expand Down
Loading