Repository: PHPOffice/PhpSpreadsheet (php)

Issue:
Inconsistent cell styles on RichText values.
This is:
```
- [x] a bug report
- [ ] a feature request
- [ ] **not** a usage question (ask them on https://stackoverflow.com/questions/tagged/phpspreadsheet or https://gitter.im/PHPOffice/PhpSpreadsheet)
```

### What is the expected behavior?
Consistency among ```TextElement``` styles of the same ```RichText``` value after applying a cell style. Desired behavior would be one of the following:
  1) Overwrite any applicable ```TextElement``` and ```Run``` styles.
  2) Overwrite any applicable ```TextElement``` styles, and ignore all ```Run``` styles.
  3) Ignore all ```TextElement``` and ```Run``` styles.

### What is the current behavior?
Inconsistency among ```TextElement``` styles of the same ```RichText``` value after applying a cell style. Current behavior is that setting a cell style only overwrites any applicable ```TextElement``` styles found before a ```Run``` style; any ```TextElement``` styles found after a ```Run``` style are ignored.

### What are the steps to reproduce?
```php
<?php
require_once 'vendor/autoload.php';

use \PhpOffice\PhpSpreadsheet\Spreadsheet;
use \PhpOffice\PhpSpreadsheet\RichText\RichText;
use \PhpOffice\PhpSpreadsheet\Writer\Xlsx;

$workbook = new Spreadsheet();

$rtf = new RichText();

/* This segment will receive applied cell styles. */
$rtf->createText('~Cell Style~');

/* This segment ignore applied cell styles. */
$rtf->createTextRun('~RTF Style~')->getFont()->setItalic(true);

/* This segment will also ignore applied cell styles. */
$rtf->createText('~No Style~');

$sheet = $workbook->getSheet(0);
$sheet->getCell('A1')->setValue($rtf);
$sheet->getStyle('A1')->getFont()->setBold(true);

(new Xlsx($workbook))->save('output.xlsx');

$workbook->disconnectWorksheets();
unset($workbook);
```

### Which versions of PhpSpreadsheet and PHP are affected?
PhpSpreadsheet [1.9]
PHP [7.1.27]


Pull request description:
Various Writers RichText TextElement Should Inherit Cell Style
Fix #1154, which went stale over 5 years ago, and is now reopened. RichText elements can be a Run, which sets its own style, or a TextElement, which doesn't. As the issue states, TextElement handling is inconsistent. This PR forces it to inherit the style of the cell. As implemented, this will change it to a Run when it is read in, but there should be no practical difference as far as the end-user is concerned. There is no change as far as Run is concerned. The user suggested 3 options - TextElement and Run both inherit for any unspecified style elements, TextElement inherits and Run does not, neither inherits. Option 2 makes most sense to me. Option 1 may not even be possible (we can't tell if, say, the user explicityl set Italic to false, or if that was just the default choice).

Tests are added for all of Xlsx, Xls, and Html. Html reading of RichText elements is not well-supported. The tests are fairly difficult to understand. A new sample is added to demonstrate this change.

This is:

- [x] a bugfix
- [ ] a new feature
- [ ] refactoring
- [ ] additional unit tests

Checklist:

- [x] Changes are covered by unit tests
  - [x] Changes are covered by existing unit tests
  - [x] New unit tests have been added
- [x] Code style is respected
- [x] Commit message explains **why** the change is made (see https://github.com/erlang/otp/wiki/Writing-good-commit-messages)
- [ ] CHANGELOG.md contains a short summary of the change and a link to the pull request if applicable
- [ ] Documentation is updated as necessary



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 83c3c02e6..eef7960de 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org).
 
 ### Added
 
-- Nothing yet.
+- VSTACK and HSTACK. [Issue #4485](https://github.com/PHPOffice/PhpSpreadsheet/issues/4485) [PR #4492](https://github.com/PHPOffice/PhpSpreadsheet/pull/4492)
+- TOCOL and TOROW. [PR #4493](https://github.com/PHPOffice/PhpSpreadsheet/pull/4493)
 
 ### Removed
 
@@ -29,7 +30,8 @@ and this project adheres to [Semantic Versioning](https://semver.org).
 
 ### Fixed
 
-- Nothing yet.
+- Various Writers RichText TextElement Should Inherit Cell Style. [Issue #1154](https://github.com/PHPOffice/PhpSpreadsheet/issues/1154) [PR #4487](https://github.com/PHPOffice/PhpSpreadsheet/pull/4487)
+- Minor Changes to FILTER function. [PR #4491](https://github.com/PHPOffice/PhpSpreadsheet/pull/4491)
 
 ## 2025-05-26 - 4.3.1
 
diff --git a/samples/Basic4/42b_RichText.php b/samples/Basic4/42b_RichText.php
new file mode 100644
index 000000000..936975dec
--- /dev/null
+++ b/samples/Basic4/42b_RichText.php
@@ -0,0 +1,22 @@
+<?php
+
+use PhpOffice\PhpSpreadsheet\RichText\RichText;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+
+require __DIR__ . '/../Header.php';
+
+/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */
+$helper->log('Create new Spreadsheet object');
+$spreadsheet = new Spreadsheet();
+$sheet = $spreadsheet->getActiveSheet();
+
+$rtf = new RichText();
+$rtf->createText('~Cell Style~');
+$rtf->createTextRun('~RTF Style~')->getFont()?->setItalic(true);
+$rtf->createText('~No Style~');
+
+$sheet->getCell('A1')->setValue($rtf);
+$sheet->getStyle('A1')->getFont()->setBold(true);
+
+// Save
+$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Xls', 'Html']);
diff --git a/src/PhpSpreadsheet/Writer/Html.php b/src/PhpSpreadsheet/Writer/Html.php
index 01a35f4d1..8d7e45b0b 100644
--- a/src/PhpSpreadsheet/Writer/Html.php
+++ b/src/PhpSpreadsheet/Writer/Html.php
@@ -1096,7 +1096,7 @@ class Html extends BaseWriter
      *
      * @return string[]
      */
-    private function createCSSStyleFont(Font $font): array
+    private function createCSSStyleFont(Font $font, bool $useDefaults = false): array
     {
         // Construct CSS
         $css = [];
@@ -1104,6 +1104,8 @@ class Html extends BaseWriter
         // Create CSS
         if ($font->getBold()) {
             $css['font-weight'] = 'bold';
+        } elseif ($useDefaults) {
+            $css['font-weight'] = 'normal';
         }
         if ($font->getUnderline() != Font::UNDERLINE_NONE && $font->getStrikethrough()) {
             $css['text-decoration'] = 'underline line-through';
@@ -1111,9 +1113,13 @@ class Html extends BaseWriter
             $css['text-decoration'] = 'underline';
         } elseif ($font->getStrikethrough()) {
             $css['text-decoration'] = 'line-through';
+        } elseif ($useDefaults) {
+            $css['text-decoration'] = 'normal';
         }
         if ($font->getItalic()) {
             $css['font-style'] = 'italic';
+        } elseif ($useDefaults) {
+            $css['font-style'] = 'normal';
         }
 
         $css['color'] = '#' . $font->getColor()->getRGB();
@@ -1344,22 +1350,23 @@ class Html extends BaseWriter
         return [$cell, $cssClass, $coordinate];
     }
 
-    private function generateRowCellDataValueRich(RichText $richText): string
+    private function generateRowCellDataValueRich(RichText $richText, ?Font $defaultFont = null): string
     {
         $cellData = '';
         // Loop through rich text elements
         $elements = $richText->getRichTextElements();
         foreach ($elements as $element) {
             // Rich text start?
-            if ($element instanceof Run) {
+            $font = ($element instanceof Run) ? $element->getFont() : $defaultFont;
+            if ($element instanceof Run || $font !== null) {
                 $cellEnd = '';
-                if ($element->getFont() !== null) {
-                    $cellData .= '<span style="' . $this->assembleCSS($this->createCSSStyleFont($element->getFont())) . '">';
+                if ($font !== null) {
+                    $cellData .= '<span style="' . $this->assembleCSS($this->createCSSStyleFont($font, true)) . '">';
 
-                    if ($element->getFont()->getSuperscript()) {
+                    if ($font->getSuperscript()) {
                         $cellData .= '<sup>';
                         $cellEnd = '</sup>';
-                    } elseif ($element->getFont()->getSubscript()) {
+                    } elseif ($font->getSubscript()) {
                         $cellData .= '<sub>';
                         $cellEnd = '</sub>';
                     }
@@ -1387,7 +1394,7 @@ class Html extends BaseWriter
     private function generateRowCellDataValue(Worksheet $worksheet, Cell $cell, string &$cellData): void
     {
         if ($cell->getValue() instanceof RichText) {
-            $cellData .= $this->generateRowCellDataValueRich($cell->getValue());
+            $cellData .= $this->generateRowCellDataValueRich($cell->getValue(), $cell->getStyle()->getFont());
         } else {
             if ($this->preCalculateFormulas) {
                 try {
diff --git a/src/PhpSpreadsheet/Writer/Xls.php b/src/PhpSpreadsheet/Writer/Xls.php
index 7573d7701..3ef9bec9b 100644
--- a/src/PhpSpreadsheet/Writer/Xls.php
+++ b/src/PhpSpreadsheet/Writer/Xls.php
@@ -151,12 +151,26 @@ class Xls extends BaseWriter
                 $cell = $this->writerWorksheets[$i]->phpSheet->getCellCollection()->get($coordinate);
                 $cVal = $cell->getValue();
                 if ($cVal instanceof RichText) {
+                    $active = $this->spreadsheet->getActiveSheetIndex();
+                    $sheet = $cell->getWorksheet();
+                    $selected = $sheet->getSelectedCells();
+                    $font = $cell->getStyle()->getFont();
+                    $this->writerWorksheets[$i]
+                        ->fontHashIndex[$font->getHashCode()] = $this->writerWorkbook->addFont($font);
+                    $sheet->setSelectedCells($selected);
+                    if ($active > -1) {
+                        $this->spreadsheet
+                            ->setActiveSheetIndex($active);
+                    }
                     $elements = $cVal->getRichTextElements();
                     foreach ($elements as $element) {
                         if ($element instanceof Run) {
                             $font = $element->getFont();
                             if ($font !== null) {
-                                $this->writerWorksheets[$i]->fontHashIndex[$font->getHashCode()] = $this->writerWorkbook->addFont($font);
+                                $this->writerWorksheets[$i]
+                                    ->fontHashIndex[
+                                        $font->getHashCode()
+                                    ] = $this->writerWorkbook->addFont($font);
                             }
                         }
                     }
diff --git a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php
index 8744f9fee..a72aeac67 100644
--- a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php
+++ b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php
@@ -381,6 +381,19 @@ class Worksheet extends BIFFwriter
                         if ($getFont !== null) {
                             $str_fontidx = $this->fontHashIndex[$getFont->getHashCode()];
                         }
+                    } else {
+                        $styleArray = $this->phpSheet
+                            ->getParent()
+                            ?->getCellXfCollection();
+                        if ($styleArray !== null) {
+                            $font = $styleArray[$xfIndex - 15] ?? null;
+                            if ($font !== null) {
+                                $font = $font->getFont();
+                            }
+                            if ($font !== null) {
+                                $str_fontidx = $this->fontHashIndex[$font->getHashCode()];
+                            }
+                        }
                     }
                     $arrcRun[] = ['strlen' => $str_pos, 'fontidx' => $str_fontidx];
                     // Position FROM
diff --git a/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php b/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
index 3dd50abee..09ce162ca 100644
--- a/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
+++ b/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
@@ -10,6 +10,7 @@ use PhpOffice\PhpSpreadsheet\RichText\RichText;
 use PhpOffice\PhpSpreadsheet\RichText\Run;
 use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
 use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Style\Font;
 use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet as ActualWorksheet;
 
 class StringTable extends WriterPart
@@ -111,7 +112,7 @@ class StringTable extends WriterPart
      *
      * @param ?string $prefix Optional Namespace prefix
      */
-    public function writeRichText(XMLWriter $objWriter, RichText $richText, ?string $prefix = null): void
+    public function writeRichText(XMLWriter $objWriter, RichText $richText, ?string $prefix = null, ?Font $defaultFont = null): void
     {
         if ($prefix !== null) {
             $prefix .= ':';
@@ -122,35 +123,36 @@ class StringTable extends WriterPart
         foreach ($elements as $element) {
             // r
             $objWriter->startElement($prefix . 'r');
+            $font = ($element instanceof Run) ? $element->getFont() : $defaultFont;
 
             // rPr
-            if ($element instanceof Run && $element->getFont() !== null) {
+            if ($font !== null) {
                 // rPr
                 $objWriter->startElement($prefix . 'rPr');
 
                 // rFont
-                if ($element->getFont()->getName() !== null) {
+                if ($font->getName() !== null) {
                     $objWriter->startElement($prefix . 'rFont');
-                    $objWriter->writeAttribute('val', $element->getFont()->getName());
+                    $objWriter->writeAttribute('val', $font->getName());
                     $objWriter->endElement();
                 }
 
                 // Bold
                 $objWriter->startElement($prefix . 'b');
-                $objWriter->writeAttribute('val', ($element->getFont()->getBold() ? 'true' : 'false'));
+                $objWriter->writeAttribute('val', ($font->getBold() ? 'true' : 'false'));
                 $objWriter->endElement();
 
                 // Italic
                 $objWriter->startElement($prefix . 'i');
-                $objWriter->writeAttribute('val', ($element->getFont()->getItalic() ? 'true' : 'false'));
+                $objWriter->writeAttribute('val', ($font->getItalic() ? 'true' : 'false'));
                 $objWriter->endElement();
 
                 // Superscript / subscript
-                if ($element->getFont()->getSuperscript() || $element->getFont()->getSubscript()) {
+                if ($font->getSuperscript() || $font->getSubscript()) {
                     $objWriter->startElement($prefix . 'vertAlign');
-                    if ($element->getFont()->getSuperscript()) {
+                    if ($font->getSuperscript()) {
                         $objWriter->writeAttribute('val', 'superscript');
-                    } elseif ($element->getFont()->getSubscript()) {
+                    } elseif ($font->getSubscript()) {
                         $objWriter->writeAttribute('val', 'subscript');
                     }
                     $objWriter->endElement();
@@ -158,27 +160,27 @@ class StringTable extends WriterPart
 
                 // Strikethrough
                 $objWriter->startElement($prefix . 'strike');
-                $objWriter->writeAttribute('val', ($element->getFont()->getStrikethrough() ? 'true' : 'false'));
+                $objWriter->writeAttribute('val', ($font->getStrikethrough() ? 'true' : 'false'));
                 $objWriter->endElement();
 
                 // Color
-                if ($element->getFont()->getColor()->getARGB() !== null) {
+                if ($font->getColor()->getARGB() !== null) {
                     $objWriter->startElement($prefix . 'color');
-                    $objWriter->writeAttribute('rgb', $element->getFont()->getColor()->getARGB());
+                    $objWriter->writeAttribute('rgb', $font->getColor()->getARGB());
                     $objWriter->endElement();
                 }
 
                 // Size
-                if ($element->getFont()->getSize() !== null) {
+                if ($font->getSize() !== null) {
                     $objWriter->startElement($prefix . 'sz');
-                    $objWriter->writeAttribute('val', (string) $element->getFont()->getSize());
+                    $objWriter->writeAttribute('val', (string) $font->getSize());
                     $objWriter->endElement();
                 }
 
                 // Underline
-                if ($element->getFont()->getUnderline() !== null) {
+                if ($font->getUnderline() !== null) {
                     $objWriter->startElement($prefix . 'u');
-                    $objWriter->writeAttribute('val', $element->getFont()->getUnderline());
+                    $objWriter->writeAttribute('val', $font->getUnderline());
                     $objWriter->endElement();
                 }
 
diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
index d8e64ad4d..6437e2c19 100644
--- a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
+++ b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
@@ -17,6 +17,7 @@ use PhpOffice\PhpSpreadsheet\Style\Conditional;
 use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalColorScale;
 use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalDataBar;
 use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalFormattingRuleExtension;
+use PhpOffice\PhpSpreadsheet\Style\Font;
 use PhpOffice\PhpSpreadsheet\Worksheet\RowDimension;
 use PhpOffice\PhpSpreadsheet\Worksheet\SheetView;
 use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet as PhpspreadsheetWorksheet;
@@ -1431,19 +1432,26 @@ class Worksheet extends WriterPart
         $objWriter->endElement();
     }
 
-    private function writeCellInlineStr(XMLWriter $objWriter, string $mappedType, RichText|string $cellValue): void
+    private function writeCellInlineStr(XMLWriter $objWriter, string $mappedType, RichText|string $cellValue, ?Font $font): void
     {
         $objWriter->writeAttribute('t', $mappedType);
         if (!$cellValue instanceof RichText) {
             $objWriter->startElement('is');
             $objWriter->writeElement(
                 't',
-                StringHelper::controlCharacterPHP2OOXML(htmlspecialchars($cellValue, Settings::htmlEntityFlags()))
+                StringHelper::controlCharacterPHP2OOXML(
+                    htmlspecialchars(
+                        $cellValue,
+                        Settings::htmlEntityFlags()
+                    )
+                )
             );
             $objWriter->endElement();
         } else {
             $objWriter->startElement('is');
-            $this->getParentWriter()->getWriterPartstringtable()->writeRichText($objWriter, $cellValue);
+            $this->getParentWriter()
+                ->getWriterPartstringtable()
+                ->writeRichText($objWriter, $cellValue, null, $font);
             $objWriter->endElement();
         }
     }
@@ -1608,6 +1616,13 @@ class Worksheet extends WriterPart
         if (empty($xfi) && !$writeValue) {
             return;
         }
+        $styleArray = $this->getParentWriter()
+            ->getSpreadsheet()
+            ->getCellXfCollection();
+        $font = $styleArray[$xfi] ?? null;
+        if ($font !== null) {
+            $font = $font->getFont();
+        }
         $objWriter->startElement('c');
         $objWriter->writeAttribute('r', $cellAddress);
         $mappedType = $pCell->getDataType();
@@ -1638,7 +1653,7 @@ class Worksheet extends WriterPart
                 case 'inlinestr':    // Inline string
                     /** @var RichText|string */
                     $richText = $cellValue;
-                    $this->writeCellInlineStr($objWriter, $mappedType, $richText);
+                    $this->writeCellInlineStr($objWriter, $mappedType, $richText, $font);
 
                     break;
                 case 's':            // String


Test patch:
diff --git a/tests/PhpSpreadsheetTests/Writer/Html/HtmlCommentsTest.php b/tests/PhpSpreadsheetTests/Writer/Html/HtmlCommentsTest.php
index 45d151594..ff1e54a14 100644
--- a/tests/PhpSpreadsheetTests/Writer/Html/HtmlCommentsTest.php
+++ b/tests/PhpSpreadsheetTests/Writer/Html/HtmlCommentsTest.php
@@ -8,6 +8,7 @@ use PhpOffice\PhpSpreadsheet\RichText\RichText;
 use PhpOffice\PhpSpreadsheet\Spreadsheet;
 use PhpOffice\PhpSpreadsheet\Writer\Html;
 use PhpOffice\PhpSpreadsheetTests\Functional;
+use PHPUnit\Framework\Attributes\DataProvider;
 
 class HtmlCommentsTest extends Functional\AbstractFunctional
 {
@@ -60,15 +61,15 @@ class HtmlCommentsTest extends Functional\AbstractFunctional
                 . 'comment.</div>' . PHP_EOL
                 . 'Comment</td>'],
             'single line simple rich text' => [$richSingle, '<td class="column0 style0 s"><a class="comment-indicator"></a><div class="comment">'
-                . "<span style=\"font-weight:bold; color:#000000; font-family:'Calibri'; font-size:11pt\">I am comment.</span></div>" . PHP_EOL
+                . "<span style=\"font-weight:bold; text-decoration:normal; font-style:normal; color:#000000; font-family:'Calibri'; font-size:11pt\">I am comment.</span></div>" . PHP_EOL
                 . 'Comment</td>'],
             'multi-line simple rich text' => [$richMultiSimple, '<td class="column0 style0 s"><a class="comment-indicator"></a><div class="comment">'
-                . "<span style=\"font-weight:bold; color:#000000; font-family:'Calibri'; font-size:11pt\">I am <br />" . PHP_EOL
+                . "<span style=\"font-weight:bold; text-decoration:normal; font-style:normal; color:#000000; font-family:'Calibri'; font-size:11pt\">I am <br />" . PHP_EOL
                 . 'multi-line<br />' . PHP_EOL
                 . 'comment.</span></div>' . PHP_EOL
                 . 'Comment</td>'],
             'multi-line mixed rich text' => [$richMultiMixed, '<td class="column0 style0 s"><a class="comment-indicator"></a><div class="comment">I am<br />' . PHP_EOL
-                . "<span style=\"font-weight:bold; color:#000000; font-family:'Calibri'; font-size:11pt\">multi-line</span><br />" . PHP_EOL
+                . "<span style=\"font-weight:bold; text-decoration:normal; font-style:normal; color:#000000; font-family:'Calibri'; font-size:11pt\">multi-line</span><br />" . PHP_EOL
                 . 'comment!</div>' . PHP_EOL
                 . 'Comment</td>'],
             'script single' => [$scriptSingle, '<td class="column0 style0 s"><a class="comment-indicator"></a><div class="comment">'
@@ -77,12 +78,14 @@ class HtmlCommentsTest extends Functional\AbstractFunctional
         ];
     }
 
-    #[\PHPUnit\Framework\Attributes\DataProvider('providerCommentRichText')]
+    #[DataProvider('providerCommentRichText')]
     public function testComments(RichText $richText, string $expected): void
     {
         $spreadsheet = new Spreadsheet();
 
-        $spreadsheet->getActiveSheet()->getCell('A1')->setValue('Comment');
+        $spreadsheet->getActiveSheet()
+            ->getCell('A1')
+            ->setValue('Comment');
 
         $spreadsheet->getActiveSheet()
             ->getComment('A1')
diff --git a/tests/PhpSpreadsheetTests/Writer/Html/RichTextTest.php b/tests/PhpSpreadsheetTests/Writer/Html/RichTextTest.php
new file mode 100644
index 000000000..800f349b7
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Writer/Html/RichTextTest.php
@@ -0,0 +1,52 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PhpOffice\PhpSpreadsheetTests\Writer\Html;
+
+use PhpOffice\PhpSpreadsheet\RichText\RichText;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Writer\Html as HtmlWriter;
+use PHPUnit\Framework\TestCase;
+
+class RichTextTest extends TestCase
+{
+    public function testRichText(): void
+    {
+        $spreadsheet = new Spreadsheet();
+        $sheet = $spreadsheet->getActiveSheet();
+        $rtf = new RichText();
+        $rtf->createText('~Cell Style~');
+        $rtf->createTextRun('~RTF Style~')->getFont()?->setItalic(true);
+        $rtf->createText('~No Style~');
+        $sheet->getCell('A1')->setValue($rtf);
+        $sheet->getStyle('A1')->getFont()->setBold(true);
+
+        $fontStyle = $sheet->getStyle('A1')->getFont();
+        self::assertTrue($fontStyle->getBold());
+        self::assertFalse($fontStyle->getItalic());
+
+        $a1Value = $sheet->getCell('A1')->getValue();
+        self::assertInstanceOf(RichText::class, $a1Value);
+        $elements = $a1Value->getRichTextElements();
+        self::assertCount(3, $elements);
+        self::assertNull($elements[0]->getFont());
+        $fontStyle = $elements[1]->getFont();
+        self::assertNotNull($fontStyle);
+        self::assertFalse($fontStyle->getBold());
+        self::assertTrue($fontStyle->getItalic());
+        self::assertNull($elements[0]->getFont());
+
+        $writer = new HtmlWriter($spreadsheet);
+        $html = $writer->generateHtmlAll();
+        self::assertStringContainsString('td.style1, th.style1 { vertical-align:bottom; border-bottom:none #000000; border-top:none #000000; border-left:none #000000; border-right:none #000000; font-weight:bold; color:#000000; font-family:\'Calibri\'; font-size:11pt }', $html, 'cell style');
+
+        self::assertStringContainsString('<td class="column0 style1 inlineStr"><span style="font-weight:bold; text-decoration:normal; font-style:normal; color:#000000; font-family:\'Calibri\'; font-size:11pt">~Cell Style~</span>', $html, 'cell style and first text element');
+
+        self::assertStringContainsString('<span style="font-weight:normal; text-decoration:normal; font-style:italic; color:#000000; font-family:\'Calibri\'; font-size:11pt">~RTF Style~</span>', $html, 'second text element');
+
+        self::assertStringContainsString('<span style="font-weight:bold; text-decoration:normal; font-style:normal; color:#000000; font-family:\'Calibri\'; font-size:11pt">~No Style~</span></td>', $html, 'third text element');
+
+        $spreadsheet->disconnectWorksheets();
+    }
+}
diff --git a/tests/PhpSpreadsheetTests/Writer/Xls/RichTextTest.php b/tests/PhpSpreadsheetTests/Writer/Xls/RichTextTest.php
new file mode 100644
index 000000000..c13aa2b47
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Writer/Xls/RichTextTest.php
@@ -0,0 +1,89 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PhpOffice\PhpSpreadsheetTests\Writer\Xls;
+
+use PhpOffice\PhpSpreadsheet\Reader\Xls as XlsReader;
+use PhpOffice\PhpSpreadsheet\RichText\RichText;
+use PhpOffice\PhpSpreadsheet\Shared\File;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Writer\Xls as XlsWriter;
+use PHPUnit\Framework\TestCase;
+
+class RichTextTest extends TestCase
+{
+    private string $filename = '';
+
+    protected function teardown(): void
+    {
+        if ($this->filename !== '') {
+            unlink($this->filename);
+        }
+    }
+
+    public function testRichText(): void
+    {
+        $spreadsheet = new Spreadsheet();
+        $sheet = $spreadsheet->getActiveSheet();
+        $rtf = new RichText();
+        $rtf->createText('~Cell Style~');
+        $rtf->createTextRun('~RTF Style~')->getFont()?->setItalic(true);
+        $rtf->createText('~No Style~');
+        $sheet->getCell('A1')->setValue($rtf);
+        $sheet->getStyle('A1')->getFont()->setBold(true);
+
+        $fontStyle = $sheet->getStyle('A1')->getFont();
+        self::assertTrue($fontStyle->getBold());
+        self::assertFalse($fontStyle->getItalic());
+
+        $a1Value = $sheet->getCell('A1')->getValue();
+        self::assertInstanceOf(RichText::class, $a1Value);
+        $elements = $a1Value->getRichTextElements();
+        self::assertCount(3, $elements);
+        self::assertNull($elements[0]->getFont());
+        $fontStyle = $elements[1]->getFont();
+        self::assertNotNull($fontStyle);
+        self::assertFalse($fontStyle->getBold());
+        self::assertTrue($fontStyle->getItalic());
+        self::assertNull($elements[0]->getFont());
+
+        $this->filename = File::temporaryFilename();
+        $writer = new XlsWriter($spreadsheet);
+        $writer->save($this->filename);
+        $spreadsheet->disconnectWorksheets();
+
+        $this->readfile();
+    }
+
+    private function readfile(): void
+    {
+        $reader = new XlsReader();
+        $spreadsheet = $reader->load($this->filename);
+        $sheet = $spreadsheet->getActiveSheet();
+        $fontStyle = $sheet->getStyle('A1')->getFont();
+        self::assertTrue($fontStyle->getBold());
+        self::assertFalse($fontStyle->getItalic());
+
+        $a1Value = $sheet->getCell('A1')->getValue();
+        self::assertInstanceOf(RichText::class, $a1Value);
+        $elements = $a1Value->getRichTextElements();
+        self::assertCount(3, $elements);
+        // write/read has changed text to run but no real difference
+        $fontStyle = $elements[0]->getFont();
+        self::assertNotNull($fontStyle);
+        self::assertTrue($fontStyle->getBold());
+        self::assertFalse($fontStyle->getItalic());
+        $fontStyle = $elements[1]->getFont();
+        self::assertNotNull($fontStyle);
+        self::assertFalse($fontStyle->getBold());
+        self::assertTrue($fontStyle->getItalic());
+        // write/read has changed text to run but no real difference
+        $fontStyle = $elements[2]->getFont();
+        self::assertNotNull($fontStyle);
+        self::assertTrue($fontStyle->getBold());
+        self::assertFalse($fontStyle->getItalic());
+
+        $spreadsheet->disconnectWorksheets();
+    }
+}
diff --git a/tests/PhpSpreadsheetTests/Writer/Xlsx/RichTextTest.php b/tests/PhpSpreadsheetTests/Writer/Xlsx/RichTextTest.php
new file mode 100644
index 000000000..71dacbbad
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Writer/Xlsx/RichTextTest.php
@@ -0,0 +1,89 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
+use PhpOffice\PhpSpreadsheet\RichText\RichText;
+use PhpOffice\PhpSpreadsheet\Shared\File;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
+use PHPUnit\Framework\TestCase;
+
+class RichTextTest extends TestCase
+{
+    private string $filename = '';
+
+    protected function teardown(): void
+    {
+        if ($this->filename !== '') {
+            unlink($this->filename);
+        }
+    }
+
+    public function testRichText(): void
+    {
+        $spreadsheet = new Spreadsheet();
+        $sheet = $spreadsheet->getActiveSheet();
+        $rtf = new RichText();
+        $rtf->createText('~Cell Style~');
+        $rtf->createTextRun('~RTF Style~')->getFont()?->setItalic(true);
+        $rtf->createText('~No Style~');
+        $sheet->getCell('A1')->setValue($rtf);
+        $sheet->getStyle('A1')->getFont()->setBold(true);
+
+        $fontStyle = $sheet->getStyle('A1')->getFont();
+        self::assertTrue($fontStyle->getBold());
+        self::assertFalse($fontStyle->getItalic());
+
+        $a1Value = $sheet->getCell('A1')->getValue();
+        self::assertInstanceOf(RichText::class, $a1Value);
+        $elements = $a1Value->getRichTextElements();
+        self::assertCount(3, $elements);
+        self::assertNull($elements[0]->getFont());
+        $fontStyle = $elements[1]->getFont();
+        self::assertNotNull($fontStyle);
+        self::assertFalse($fontStyle->getBold());
+        self::assertTrue($fontStyle->getItalic());
+        self::assertNull($elements[0]->getFont());
+
+        $this->filename = File::temporaryFilename();
+        $writer = new XlsxWriter($spreadsheet);
+        $writer->save($this->filename);
+        $spreadsheet->disconnectWorksheets();
+
+        $this->readfile();
+    }
+
+    private function readfile(): void
+    {
+        $reader = new XlsxReader();
+        $spreadsheet = $reader->load($this->filename);
+        $sheet = $spreadsheet->getActiveSheet();
+        $fontStyle = $sheet->getStyle('A1')->getFont();
+        self::assertTrue($fontStyle->getBold());
+        self::assertFalse($fontStyle->getItalic());
+
+        $a1Value = $sheet->getCell('A1')->getValue();
+        self::assertInstanceOf(RichText::class, $a1Value);
+        $elements = $a1Value->getRichTextElements();
+        self::assertCount(3, $elements);
+        // write/read has changed text to run but no real difference
+        $fontStyle = $elements[0]->getFont();
+        self::assertNotNull($fontStyle);
+        self::assertTrue($fontStyle->getBold());
+        self::assertFalse($fontStyle->getItalic());
+        $fontStyle = $elements[1]->getFont();
+        self::assertNotNull($fontStyle);
+        self::assertFalse($fontStyle->getBold());
+        self::assertTrue($fontStyle->getItalic());
+        // write/read has changed text to run but no real difference
+        $fontStyle = $elements[2]->getFont();
+        self::assertNotNull($fontStyle);
+        self::assertTrue($fontStyle->getBold());
+        self::assertFalse($fontStyle->getItalic());
+
+        $spreadsheet->disconnectWorksheets();
+    }
+}