Skip to content

Support Current Office Theme #4500

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

Merged
merged 1 commit into from
Jun 18, 2025
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
2 changes: 1 addition & 1 deletion samples/Chart33a/33_Chart_create_area_2.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */
$spreadsheet = new Spreadsheet();
// same as 33_Chart_create_area, but with 2013+ schemes
$spreadsheet->getTheme()->setThemeColorName(SpreadsheetTheme::COLOR_SCHEME_2013_PLUS_NAME);
$spreadsheet->getTheme()->setThemeColorName(SpreadsheetTheme::COLOR_SCHEME_2013_2022_NAME);
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray(
[
Expand Down
9 changes: 9 additions & 0 deletions src/PhpSpreadsheet/Style/Font.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace PhpOffice\PhpSpreadsheet\Style;

use PhpOffice\PhpSpreadsheet\Chart\ChartColor;
use PhpOffice\PhpSpreadsheet\Theme;

class Font extends Supervisor
{
Expand Down Expand Up @@ -124,6 +125,14 @@ public function __construct(bool $isSupervisor = false, bool $isConditional = fa
}
}

public function applyThemeFonts(Theme $theme): void
{
$this->setName($theme->getMinorFontLatin());
$this->setLatin($theme->getMinorFontLatin());
$this->setEastAsian($theme->getMinorFontEastAsian());
$this->setComplexScript($theme->getMinorFontComplexScript());
}

/**
* Get the shared style component for the currently active cell in currently active sheet.
* Only used for style supervisor.
Expand Down
47 changes: 42 additions & 5 deletions src/PhpSpreadsheet/Theme.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ class Theme
private string $themeFontName = 'Office';

public const HYPERLINK_THEME = 10;
public const COLOR_SCHEME_2013_PLUS_NAME = 'Office 2013+';
public const COLOR_SCHEME_2013_PLUS = [
public const COLOR_SCHEME_2013_2022_NAME = 'Office 2013-2022';
public const COLOR_SCHEME_2013_2022 = [
'dk1' => '000000',
'lt1' => 'FFFFFF',
'dk2' => '44546A',
Expand All @@ -24,6 +24,10 @@ class Theme
'hlink' => '0563C1',
'folHlink' => '954F72',
];
/** @deprecated 4.4.0 Use COLOR_SCHEME_2013_2022_NAME */
public const COLOR_SCHEME_2013_PLUS_NAME = 'Office 2013+';
/** @deprecated 4.4.0 Use COLOR_SCHEME_2013_2022 */
public const COLOR_SCHEME_2013_PLUS = self::COLOR_SCHEME_2013_2022;

public const COLOR_SCHEME_2007_2010_NAME = 'Office 2007-2010';
public const COLOR_SCHEME_2007_2010 = [
Expand All @@ -41,6 +45,22 @@ class Theme
'folHlink' => '800080',
];

public const COLOR_SCHEME_2023_PLUS_NAME = 'Office 2023+';
public const COLOR_SCHEME_2023_PLUS = [
'dk1' => '000000',
'lt1' => 'FFFFFF',
'dk2' => '0E2841',
'lt2' => 'E8E8E8',
'accent1' => '156082',
'accent2' => 'E97132',
'accent3' => '196B24',
'accent4' => '0F9ED5',
'accent5' => 'A02B93',
'accent6' => '4EA72E',
'hlink' => '467886',
'folHlink' => '96607D',
];

/** @var string[] */
private array $themeColors = self::COLOR_SCHEME_2007_2010;

Expand Down Expand Up @@ -155,17 +175,34 @@ public function getThemeColorName(): string
}

/** @param null|string[] $themeColors */
public function setThemeColorName(string $name, ?array $themeColors = null): self
public function setThemeColorName(string $name, ?array $themeColors = null, ?Spreadsheet $spreadsheet = null): self
{
$this->themeColorName = $name;
if ($name === self::COLOR_SCHEME_2007_2010_NAME) {
$themeColors = $themeColors ?? self::COLOR_SCHEME_2007_2010;
} elseif ($name === self::COLOR_SCHEME_2013_PLUS_NAME) {
$themeColors = $themeColors ?? self::COLOR_SCHEME_2013_PLUS;
$this->majorFontLatin = 'Cambria';
$this->minorFontLatin = 'Calibri';
} elseif ($name === self::COLOR_SCHEME_2013_PLUS_NAME) { //* @phpstan-ignore-line
// delete this block when deprecated constants removed
$themeColors = $themeColors ?? self::COLOR_SCHEME_2013_PLUS; //* @phpstan-ignore-line
$this->majorFontLatin = 'Calibri Light';
$this->minorFontLatin = 'Calibri';
} elseif ($name === self::COLOR_SCHEME_2013_2022_NAME) {
$themeColors = $themeColors ?? self::COLOR_SCHEME_2013_2022;
$this->majorFontLatin = 'Calibri Light';
$this->minorFontLatin = 'Calibri';
} elseif ($name === self::COLOR_SCHEME_2023_PLUS_NAME) {
$themeColors = $themeColors ?? self::COLOR_SCHEME_2023_PLUS;
$this->majorFontLatin = 'Aptos Display';
$this->minorFontLatin = 'Aptos Narrow';
}
if ($themeColors !== null) {
$this->themeColors = $themeColors;
}
if ($spreadsheet !== null) {
$spreadsheet->getDefaultStyle()->getFont()
->applyThemeFonts($this);
}

return $this;
}
Expand Down
89 changes: 87 additions & 2 deletions tests/PhpSpreadsheetTests/Writer/Xlsx/ThemeColorsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Style;
use PhpOffice\PhpSpreadsheet\Theme as SpreadsheetTheme;
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;

Expand All @@ -14,11 +15,48 @@ class ThemeColorsTest extends AbstractFunctional
public function testOffice2013Theme(): void
{
$spreadsheet = new Spreadsheet();
$spreadsheet->getTheme()->setThemeColorName(SpreadsheetTheme::COLOR_SCHEME_2013_PLUS_NAME);
$spreadsheet->getTheme()
->setThemeColorName(
SpreadsheetTheme::COLOR_SCHEME_2013_PLUS_NAME //* @phpstan-ignore-line
);
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
$spreadsheet->disconnectWorksheets();
self::assertSame('Office 2013+', $reloadedSpreadsheet->getTheme()->getThemeColorName());
self::assertSame(
SpreadsheetTheme::COLOR_SCHEME_2013_PLUS_NAME, //* @phpstan-ignore-line
$reloadedSpreadsheet->getTheme()->getThemeColorName()
);
self::assertSame('FFC000', $reloadedSpreadsheet->getTheme()->getThemeColors()['accent4']);
self::assertSame('Calibri Light', $reloadedSpreadsheet->getTheme()->getMajorFontLatin());
self::assertSame('Calibri', $reloadedSpreadsheet->getTheme()->getMinorFontLatin());
$defaultFont2 = $reloadedSpreadsheet->getDefaultStyle()->getFont()->getName();
self::assertSame('Calibri', $defaultFont2);
$font3 = $reloadedSpreadsheet->getActiveSheet()
->getStyle('Z10')->getFont()->getName();
self::assertSame('Calibri', $font3);
$reloadedSpreadsheet->disconnectWorksheets();
}

public function testOffice2013Theme2(): void
{
$spreadsheet = new Spreadsheet();
$spreadsheet->getTheme()
->setThemeColorName(
SpreadsheetTheme::COLOR_SCHEME_2013_2022_NAME
);
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
$spreadsheet->disconnectWorksheets();
self::assertSame(
SpreadsheetTheme::COLOR_SCHEME_2013_2022_NAME,
$reloadedSpreadsheet->getTheme()->getThemeColorName()
);
self::assertSame('FFC000', $reloadedSpreadsheet->getTheme()->getThemeColors()['accent4']);
self::assertSame('Calibri Light', $reloadedSpreadsheet->getTheme()->getMajorFontLatin());
self::assertSame('Calibri', $reloadedSpreadsheet->getTheme()->getMinorFontLatin());
$defaultFont2 = $reloadedSpreadsheet->getDefaultStyle()->getFont()->getName();
self::assertSame('Calibri', $defaultFont2);
$font3 = $reloadedSpreadsheet->getActiveSheet()
->getStyle('Z10')->getFont()->getName();
self::assertSame('Calibri', $font3);
$reloadedSpreadsheet->disconnectWorksheets();
}

Expand All @@ -30,6 +68,13 @@ public function testOffice2007Theme(): void
$spreadsheet->disconnectWorksheets();
self::assertSame('Office 2007-2010', $reloadedSpreadsheet->getTheme()->getThemeColorName());
self::assertSame('8064A2', $reloadedSpreadsheet->getTheme()->getThemeColors()['accent4']);
self::assertSame('Cambria', $reloadedSpreadsheet->getTheme()->getMajorFontLatin());
self::assertSame('Calibri', $reloadedSpreadsheet->getTheme()->getMinorFontLatin());
$defaultFont2 = $reloadedSpreadsheet->getDefaultStyle()->getFont()->getName();
self::assertSame('Calibri', $defaultFont2);
$font3 = $reloadedSpreadsheet->getActiveSheet()
->getStyle('Z10')->getFont()->getName();
self::assertSame('Calibri', $font3);
$reloadedSpreadsheet->disconnectWorksheets();
}

Expand All @@ -40,6 +85,13 @@ public function testDefaultTheme(): void
$spreadsheet->disconnectWorksheets();
self::assertSame('Office', $reloadedSpreadsheet->getTheme()->getThemeColorName());
self::assertSame('8064A2', $reloadedSpreadsheet->getTheme()->getThemeColors()['accent4']);
self::assertSame('Cambria', $reloadedSpreadsheet->getTheme()->getMajorFontLatin());
self::assertSame('Calibri', $reloadedSpreadsheet->getTheme()->getMinorFontLatin());
$defaultFont2 = $reloadedSpreadsheet->getDefaultStyle()->getFont()->getName();
self::assertSame('Calibri', $defaultFont2);
$font3 = $reloadedSpreadsheet->getActiveSheet()
->getStyle('Z10')->getFont()->getName();
self::assertSame('Calibri', $font3);
$reloadedSpreadsheet->disconnectWorksheets();
}

Expand All @@ -53,4 +105,37 @@ public function testGalleryTheme(): void
self::assertSame('795FAF', $reloadedSpreadsheet->getTheme()->getThemeColors()['accent4']);
$reloadedSpreadsheet->disconnectWorksheets();
}

public function testOffice2023Theme(): void
{
$spreadsheet = new Spreadsheet();
$spreadsheet->getTheme()
->setThemeColorName(
SpreadsheetTheme::COLOR_SCHEME_2023_PLUS_NAME,
null,
$spreadsheet
);
self::assertSame('Aptos Narrow', $spreadsheet->getDefaultStyle()->getFont()->getName(), 'default style is attached to spreadsheet');
$style = new Style();
self::assertSame('Calibri', $style->getFont()->getName(), 'style not attached to spreadsheet');
$style2 = $spreadsheet->getActiveSheet()->getStyle('A7');
self::assertSame('Aptos Narrow', $style2->getFont()->getName(), 'font is attached to spreadsheet');
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
$spreadsheet->disconnectWorksheets();
self::assertSame(
SpreadsheetTheme::COLOR_SCHEME_2023_PLUS_NAME,
$reloadedSpreadsheet->getTheme()->getThemeColorName()
);
self::assertSame('0F9ED5', $reloadedSpreadsheet->getTheme()->getThemeColors()['accent4']);
self::assertSame('Aptos Display', $reloadedSpreadsheet->getTheme()->getMajorFontLatin());
self::assertSame('Aptos Narrow', $reloadedSpreadsheet->getTheme()->getMinorFontLatin());
$defaultFont = $reloadedSpreadsheet->getDefaultStyle()->getFont()->getName();
self::assertSame('Aptos Narrow', $defaultFont);
$defaultFont2 = $reloadedSpreadsheet->getDefaultStyle()->getFont()->getName();
self::assertSame('Aptos Narrow', $defaultFont2);
$font3 = $reloadedSpreadsheet->getActiveSheet()
->getStyle('Z10')->getFont()->getName();
self::assertSame('Aptos Narrow', $font3);
$reloadedSpreadsheet->disconnectWorksheets();
}
}