Skip to content

Commit 0dbe154

Browse files
authored
Merge pull request #4503 from oleibman/issue4502
AutoColor for LibreOffice Dark Mode
2 parents 30369ca + b91a9ef commit 0dbe154

File tree

6 files changed

+187
-7
lines changed

6 files changed

+187
-7
lines changed

src/PhpSpreadsheet/Reader/Xlsx/Styles.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ public function readFontStyle(Font $fontStyle, SimpleXMLElement $fontStyleXml):
152152
$attr = $this->getStyleAttributes($fontStyleXml->scheme);
153153
$fontStyle->setScheme((string) $attr['val']);
154154
}
155+
if (isset($fontStyleXml->auto)) {
156+
$attr = $this->getStyleAttributes($fontStyleXml->auto);
157+
if (isset($attr['val'])) {
158+
$fontStyle->setAutoColor(self::boolean((string) $attr['val']));
159+
}
160+
}
155161
}
156162

157163
private function readNumberFormat(NumberFormat $numfmtStyle, SimpleXMLElement $numfmtStyleXml): void

src/PhpSpreadsheet/Style/Font.php

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ class Font extends Supervisor
8686
*/
8787
protected Color $color;
8888

89+
protected bool $autoColor = false;
90+
8991
public ?int $colorIndex = null;
9092

9193
protected string $scheme = '';
@@ -175,7 +177,7 @@ public function getStyleArray(array $array): array
175177
* );
176178
* </code>
177179
*
178-
* @param array{name?: string, latin?: string, eastAsian?: string, complexScript?: string, bold?: bool, italic?: bool, superscript?: bool, subscript?: bool, underline?: bool|string, strikethrough?: bool, color?: string[], size?: ?int, chartColor?: ChartColor, scheme?: string, cap?: string} $styleArray Array containing style information
180+
* @param array{name?: string, latin?: string, eastAsian?: string, complexScript?: string, bold?: bool, italic?: bool, superscript?: bool, subscript?: bool, underline?: bool|string, strikethrough?: bool, color?: string[], size?: ?int, chartColor?: ChartColor, scheme?: string, cap?: string, autoColor?: bool} $styleArray Array containing style information
179181
*
180182
* @return $this
181183
*/
@@ -194,7 +196,9 @@ public function applyFromArray(array $styleArray): static
194196
$this->setEastAsian($styleArray['eastAsian']);
195197
}
196198
if (isset($styleArray['complexScript'])) {
197-
$this->setComplexScript($styleArray['complexScript']);
199+
$this->setComplexScript(
200+
$styleArray['complexScript']
201+
);
198202
}
199203
if (isset($styleArray['bold'])) {
200204
$this->setBold($styleArray['bold']);
@@ -212,7 +216,9 @@ public function applyFromArray(array $styleArray): static
212216
$this->setUnderline($styleArray['underline']);
213217
}
214218
if (isset($styleArray['strikethrough'])) {
215-
$this->setStrikethrough($styleArray['strikethrough']);
219+
$this->setStrikethrough(
220+
$styleArray['strikethrough']
221+
);
216222
}
217223
if (isset($styleArray['color'])) {
218224
/** @var array{rgb?: string, argb?: string, theme?: int} */
@@ -232,6 +238,9 @@ public function applyFromArray(array $styleArray): static
232238
if (isset($styleArray['cap'])) {
233239
$this->setCap($styleArray['cap']);
234240
}
241+
if (isset($styleArray['autoColor'])) {
242+
$this->setAutoColor($styleArray['autoColor']);
243+
}
235244
}
236245

237246
return $this;
@@ -745,6 +754,7 @@ public function getHashCode(): string
745754
. ($this->subscript ? 't' : 'f')
746755
. $this->underline
747756
. ($this->strikethrough ? 't' : 'f')
757+
. ($this->autoColor ? 't' : 'f')
748758
. $this->color->getHashCode()
749759
. $this->scheme
750760
. implode(
@@ -786,6 +796,7 @@ protected function exportArray1(): array
786796
$this->exportArray2($exportedArray, 'superscript', $this->getSuperscript());
787797
$this->exportArray2($exportedArray, 'underline', $this->getUnderline());
788798
$this->exportArray2($exportedArray, 'underlineColor', $this->getUnderlineColor());
799+
$this->exportArray2($exportedArray, 'autoColor', $this->getAutoColor());
789800

790801
return $exportedArray;
791802
}
@@ -840,6 +851,29 @@ public function setHyperlinkTheme(): self
840851
return $this;
841852
}
842853

854+
public function setAutoColor(bool $autoColor): self
855+
{
856+
if ($this->isSupervisor) {
857+
$styleArray = $this->getStyleArray(['autoColor' => $autoColor]);
858+
$this->getActiveSheet()
859+
->getStyle($this->getSelectedCells())
860+
->applyFromArray($styleArray);
861+
} else {
862+
$this->autoColor = $autoColor;
863+
}
864+
865+
return $this;
866+
}
867+
868+
public function getAutoColor(): bool
869+
{
870+
if ($this->isSupervisor) {
871+
return $this->getSharedComponent()->getAutoColor();
872+
}
873+
874+
return $this->autoColor;
875+
}
876+
843877
/**
844878
* Implement PHP __clone to create a deep clone, not just a shallow copy.
845879
*/

src/PhpSpreadsheet/Writer/Ods/Cell/Style.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,15 +204,26 @@ protected function writeTextProperties(CellStyle $style): void
204204

205205
if ($font->getBold()) {
206206
$this->writer->writeAttribute('fo:font-weight', 'bold');
207-
$this->writer->writeAttribute('style:font-weight-complex', 'bold');
208-
$this->writer->writeAttribute('style:font-weight-asian', 'bold');
207+
$this->writer->writeAttribute(
208+
'style:font-weight-complex',
209+
'bold'
210+
);
211+
$this->writer->writeAttribute(
212+
'style:font-weight-asian',
213+
'bold'
214+
);
209215
}
210216

211217
if ($font->getItalic()) {
212218
$this->writer->writeAttribute('fo:font-style', 'italic');
213219
}
214220

215-
$this->writer->writeAttribute('fo:color', sprintf('#%s', $font->getColor()->getRGB()));
221+
if ($font->getAutoColor()) {
222+
$this->writer
223+
->writeAttribute('style:use-window-font-color', 'true');
224+
} else {
225+
$this->writer->writeAttribute('fo:color', sprintf('#%s', $font->getColor()->getRGB()));
226+
}
216227

217228
if ($family = $font->getName()) {
218229
$this->writer->writeAttribute('fo:font-family', $family);

src/PhpSpreadsheet/Writer/Xlsx/Style.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,12 @@ private function writeFont(XMLWriter $objWriter, Font $font, Spreadsheet $spread
347347
}
348348

349349
// Foreground color
350-
if ($font->getColor()->getTheme() >= 0) {
350+
if ($font->getAutoColor()) {
351+
$this->startFont($objWriter, $fontStarted);
352+
$objWriter->startElement('auto');
353+
$objWriter->writeAttribute('val', '1');
354+
$objWriter->endElement();
355+
} elseif ($font->getColor()->getTheme() >= 0) {
351356
$this->startFont($objWriter, $fontStarted);
352357
$objWriter->startElement('color');
353358
$objWriter->writeAttribute('theme', (string) $font->getColor()->getTheme());
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Writer\ODS;
6+
7+
use PhpOffice\PhpSpreadsheet\Shared\File;
8+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
9+
use PhpOffice\PhpSpreadsheet\Writer\Ods as OdsWriter;
10+
use PHPUnit\Framework\TestCase;
11+
12+
class AutoColorTest extends TestCase
13+
{
14+
private string $outputFile = '';
15+
16+
protected function tearDown(): void
17+
{
18+
if ($this->outputFile !== '') {
19+
unlink($this->outputFile);
20+
$this->outputFile = '';
21+
}
22+
}
23+
24+
public function testAutoColor(): void
25+
{
26+
// It's not clear to me what AutoColor does in Excel.
27+
// However, LibreOffice Dark Mode
28+
// can make use of a spreadsheet which uses it.
29+
$spreadsheet = new Spreadsheet();
30+
$spreadsheet->getDefaultStyle()->getFont()
31+
->setAutoColor(true);
32+
$sheet = $spreadsheet->getActiveSheet();
33+
$sheet->setCellValue('A1', 'Hello World!');
34+
$sheet->setCellValue('A2', 'Hello World!');
35+
$sheet->getStyle('A2')->getFont()
36+
->setBold(true);
37+
$sheet->setCellValue('A3', 'Hello World!');
38+
$sheet->getStyle('A3')->getFont()
39+
->setItalic(true);
40+
$sheet->setCellValue('B1', 'Hello World!');
41+
42+
$writer = new OdsWriter($spreadsheet);
43+
$outputFile = $this->outputFile = File::temporaryFilename();
44+
$writer->save($outputFile);
45+
$spreadsheet->disconnectWorksheets();
46+
$zipfile = "zip://$outputFile#content.xml";
47+
$contents = file_get_contents($zipfile);
48+
if ($contents === false) {
49+
self::fail('Unable to open file');
50+
} else {
51+
self::assertStringContainsString('<style:text-properties style:use-window-font-color="true" fo:font-family="Calibri" fo:font-size="11.0pt"/>', $contents);
52+
self::assertStringContainsString('<style:text-properties fo:font-weight="bold" style:font-weight-complex="bold" style:font-weight-asian="bold" style:use-window-font-color="true" fo:font-family="Calibri" fo:font-size="11.0pt"/>', $contents);
53+
self::assertStringContainsString('<style:text-properties fo:font-style="italic" style:use-window-font-color="true" fo:font-family="Calibri" fo:font-size="11.0pt"/>', $contents);
54+
}
55+
}
56+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
6+
7+
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
8+
use PhpOffice\PhpSpreadsheet\Shared\File;
9+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
10+
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
11+
use PHPUnit\Framework\TestCase;
12+
13+
class AutoColorTest extends TestCase
14+
{
15+
private string $outputFile = '';
16+
17+
protected function tearDown(): void
18+
{
19+
if ($this->outputFile !== '') {
20+
unlink($this->outputFile);
21+
$this->outputFile = '';
22+
}
23+
}
24+
25+
public function testAutoColor(): void
26+
{
27+
// It's not clear to me what AutoColor does in Excel.
28+
// However, LibreOffice Dark Mode
29+
// can make use of a spreadsheet which uses it.
30+
$spreadsheet = new Spreadsheet();
31+
$spreadsheet->getDefaultStyle()->getFont()
32+
->setAutoColor(true);
33+
$sheet = $spreadsheet->getActiveSheet();
34+
$sheet->setCellValue('A1', 'Hello World!');
35+
$sheet->setCellValue('A2', 'Hello World!');
36+
$sheet->getStyle('A2')->getFont()
37+
->setBold(true);
38+
$sheet->setCellValue('A3', 'Hello World!');
39+
$sheet->getStyle('A3')->getFont()
40+
->setItalic(true);
41+
$sheet->setCellValue('B1', 'Hello World!');
42+
43+
$writer = new XlsxWriter($spreadsheet);
44+
$outputFile = $this->outputFile = File::temporaryFilename();
45+
$writer->save($outputFile);
46+
$spreadsheet->disconnectWorksheets();
47+
$zipfile = "zip://$outputFile#xl/styles.xml";
48+
$contents = file_get_contents($zipfile);
49+
if ($contents === false) {
50+
self::fail('Unable to open file');
51+
} else {
52+
self::assertStringContainsString('<fonts count="3">', $contents);
53+
self::assertStringContainsString('<font><b val="0"/><i val="0"/><strike val="0"/><u val="none"/><sz val="11"/><auto val="1"/><name val="Calibri"/></font>', $contents);
54+
self::assertStringContainsString('<font><b val="1"/><i val="0"/><strike val="0"/><u val="none"/><sz val="11"/><auto val="1"/><name val="Calibri"/></font>', $contents);
55+
self::assertStringContainsString('<font><b val="0"/><i val="1"/><strike val="0"/><u val="none"/><sz val="11"/><auto val="1"/><name val="Calibri"/></font>', $contents);
56+
}
57+
58+
$reader = new XlsxReader();
59+
$spreadsheet2 = $reader->load($outputFile);
60+
$sheet2 = $spreadsheet2->getActiveSheet();
61+
self::assertTrue(
62+
$sheet2->getStyle('A1')
63+
->getFont()
64+
->getAutoColor()
65+
);
66+
$spreadsheet2->disconnectWorksheets();
67+
}
68+
}

0 commit comments

Comments
 (0)