Repository: PHPOffice/PhpSpreadsheet (php)

Issue:
[a feature request] Can't set the pdf file direction to RTL
### What is the expected behavior?
I should be able to customize the exported pdf direction to RTL

### What is the current behavior?
The method `setRightToLeft(true)` works when generate Excel file but does not work when the exported file is PDF.

### What are the steps to reproduce?

1. Load any of the pdf packages `mpdf`, `dompdf` or `tcpdf` 
2. set the direction of the generated file by the method `setRightToLeft(true)`
3. Try to generate pdf file using phpspreadsheet

### Which versions of PhpSpreadsheet and PHP are affected?
PHP 7.3.6 
PHPSpreadsheet 1.8.1

It seems that the method that changes the pdf direction in `mpdf` is `$pdf->SetDirectionality('rtl');` but I couldn't customize it through phpspreadsheet

Pull request description:
Writer Html/Pdf Support RTL Alignment of Table
Fix #1104, which went stale over 6 years ago, and is now reopened. This PR addresses the alignment of the table, not alignment of text. Support is added for the following:

- Html. Full support.
- Mpdf. Full support, except that, when mixed LTR and RTL worksheets are output, all tables will be on the left of the page (but will be properly aligned).
- Tcpdf. Full support when all worksheets being output are RTL; no support when mixed LTR and RTL worksheets are output.
- Dompdf. No support.

This is:

- [x] a bugfix
- [ ] a new feature
- [ ] refactoring
- [ ] additional unit tests

Checklist:

- [ ] Changes are covered by unit tests
  - [ ] 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 d05bf119b..467d3ee83 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
 
 ### Fixed
 
+- Writer Html/Pdf support RTL alignment of tables. [Issue #1104](https://github.com/PHPOffice/PhpSpreadsheet/issues/1104) [PR #4535](https://github.com/PHPOffice/PhpSpreadsheet/pull/4535)
 - Xlsx Reader use dynamic arrays if spreadsheet did so. [PR #4533](https://github.com/PHPOffice/PhpSpreadsheet/pull/4533)
 - Ods Reader Nested table-row. [Issue #4528](https://github.com/PHPOffice/PhpSpreadsheet/issues/4528) [Issue #2507](https://github.com/PHPOffice/PhpSpreadsheet/issues/2507) [PR #4531](https://github.com/PHPOffice/PhpSpreadsheet/pull/4531)
 - Recognize application/x-empty mimetype. [Issue #4521](https://github.com/PHPOffice/PhpSpreadsheet/issues/4521) [PR #4524](https://github.com/PHPOffice/PhpSpreadsheet/pull/4524)
diff --git a/samples/Pdf/21f_Drawing_mpdf.php b/samples/Pdf/21f_Drawing.php
similarity index 78%
rename from samples/Pdf/21f_Drawing_mpdf.php
rename to samples/Pdf/21f_Drawing.php
index 357b4690a..489914c3a 100644
--- a/samples/Pdf/21f_Drawing_mpdf.php
+++ b/samples/Pdf/21f_Drawing.php
@@ -2,12 +2,10 @@
 
 use PhpOffice\PhpSpreadsheet\Spreadsheet;
 use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
-use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
 
 require __DIR__ . '/../Header.php';
-/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */
-require_once __DIR__ . '/Mpdf2.php';
 
+/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */
 $spreadsheet = new Spreadsheet();
 $sheet = $spreadsheet->getActiveSheet();
 
@@ -41,11 +39,6 @@ $helper->log('Merge drawing cells for Pdf');
 $spreadsheet->mergeDrawingCellsForPdf();
 
 $helper->log('Write to Mpdf');
-$writer = new Mpdf($spreadsheet);
-$filename = $helper->getFileName(__FILE__, 'pdf');
-$writer->save($filename);
-$helper->log("Saved $filename");
-if (PHP_SAPI !== 'cli') {
-    echo '<a href="/download.php?type=pdf&name=' . basename($filename) . '">Download ' . basename($filename) . '</a><br />';
-}
+$helper->write($spreadsheet, __FILE__, ['Mpdf']);
+
 $spreadsheet->disconnectWorksheets();
diff --git a/samples/Pdf/21g_Direction.php b/samples/Pdf/21g_Direction.php
new file mode 100644
index 000000000..180fad1a3
--- /dev/null
+++ b/samples/Pdf/21g_Direction.php
@@ -0,0 +1,28 @@
+<?php
+
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+
+require __DIR__ . '/../Header.php';
+
+/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */
+$spreadsheet = new Spreadsheet();
+$sheet = $spreadsheet->getActiveSheet();
+
+$sheet1 = $spreadsheet->getActiveSheet();
+$sheet2 = $spreadsheet->createSheet();
+$sheet3 = $spreadsheet->createSheet();
+$cells = [
+    ['a1', 'b1', 'c1'],
+    ['a2', 'b2', 'c2'],
+];
+$sheet1->fromArray($cells);
+$sheet1->setRightToLeft(true);
+$sheet2->fromArray($cells);
+$sheet3->fromArray($cells);
+$sheet3->setRightToLeft(true);
+
+$helper->log('Write to html, mpdf, tcpdf');
+// Save
+$helper->write($spreadsheet, __FILE__, ['Html', 'Mpdf', 'Tcpdf']);
+
+$spreadsheet->disconnectWorksheets();
diff --git a/samples/Pdf/21h_DirectionMultiple.php b/samples/Pdf/21h_DirectionMultiple.php
new file mode 100644
index 000000000..894dfa3f6
--- /dev/null
+++ b/samples/Pdf/21h_DirectionMultiple.php
@@ -0,0 +1,36 @@
+<?php
+
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Writer\Html as HtmlWriter;
+
+require __DIR__ . '/../Header.php';
+
+/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */
+$spreadsheet = new Spreadsheet();
+$sheet = $spreadsheet->getActiveSheet();
+
+$sheet1 = $spreadsheet->getActiveSheet();
+$sheet2 = $spreadsheet->createSheet();
+$sheet3 = $spreadsheet->createSheet();
+$cells = [
+    ['a1', 'b1', 'c1'],
+    ['a2', 'b2', 'c2'],
+];
+$sheet1->fromArray($cells);
+$sheet1->setRightToLeft(true);
+$sheet2->fromArray($cells);
+$sheet3->fromArray($cells);
+$sheet3->setRightToLeft(true);
+
+$helper->log('Write to html, mpdf');
+// Save
+$helper->write(
+    $spreadsheet,
+    __FILE__,
+    ['Html', 'Mpdf'],
+    writerCallback: function (HtmlWriter $writer): void {
+            $writer->writeAllSheets();
+    }
+);
+
+$spreadsheet->disconnectWorksheets();
diff --git a/src/PhpSpreadsheet/Reader/Html.php b/src/PhpSpreadsheet/Reader/Html.php
index af831cf46..e63c05327 100644
--- a/src/PhpSpreadsheet/Reader/Html.php
+++ b/src/PhpSpreadsheet/Reader/Html.php
@@ -532,6 +532,9 @@ class Html extends BaseReader
                 $sheet->setShowGridlines(in_array('gridlines', $classes, true));
                 $sheet->setPrintGridlines(in_array('gridlinesp', $classes, true));
             }
+            if ('rtl' === ($attributeArray['dir'] ?? '')) {
+                $sheet->setRightToLeft(true);
+            }
             $this->currentColumn = 'A';
             $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray);
             $column = $this->setTableStartColumn($column);
diff --git a/src/PhpSpreadsheet/Writer/Html.php b/src/PhpSpreadsheet/Writer/Html.php
index 8d7e45b0b..c79b5737a 100644
--- a/src/PhpSpreadsheet/Writer/Html.php
+++ b/src/PhpSpreadsheet/Writer/Html.php
@@ -158,6 +158,10 @@ class Html extends BaseWriter
 
     private string $getFalse = 'FALSE';
 
+    protected bool $rtlSheets = false;
+
+    protected bool $ltrSheets = false;
+
     /**
      * Create a new HTML.
      */
@@ -186,11 +190,31 @@ class Html extends BaseWriter
         $this->maybeCloseFileHandle();
     }
 
+    protected function checkRtlAndLtr(): void
+    {
+        $this->rtlSheets = false;
+        $this->ltrSheets = false;
+        if ($this->sheetIndex === null) {
+            foreach ($this->spreadsheet->getAllSheets() as $sheet) {
+                if ($sheet->getRightToLeft()) {
+                    $this->rtlSheets = true;
+                } else {
+                    $this->ltrSheets = true;
+                }
+            }
+        } else {
+            if ($this->spreadsheet->getSheet($this->sheetIndex)->getRightToLeft()) {
+                $this->rtlSheets = true;
+            }
+        }
+    }
+
     /**
      * Save Spreadsheet as html to variable.
      */
     public function generateHtmlAll(): string
     {
+        $this->checkRtlAndLtr();
         $sheets = $this->generateSheetPrep();
         foreach ($sheets as $sheet) {
             $sheet->calculateArrays($this->preCalculateFormulas);
@@ -369,7 +393,8 @@ class Html extends BaseWriter
         // Construct HTML
         $properties = $this->spreadsheet->getProperties();
         $html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' . PHP_EOL;
-        $html .= '<html xmlns="http://www.w3.org/1999/xhtml">' . PHP_EOL;
+        $rtl = ($this->rtlSheets && !$this->ltrSheets) ? " dir='rtl'" : '';
+        $html .= '<html xmlns="http://www.w3.org/1999/xhtml"' . $rtl . '>' . PHP_EOL;
         $html .= '  <head>' . PHP_EOL;
         $html .= '      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . PHP_EOL;
         $html .= '      <meta name="generator" content="PhpSpreadsheet, https://github.com/PHPOffice/PhpSpreadsheet" />' . PHP_EOL;
@@ -1013,6 +1038,9 @@ class Html extends BaseWriter
         // .s {}
         $css['.s']['text-align'] = 'left'; // STRING
 
+        $css['.floatright']['float'] = 'right';
+        $css['.floatleft']['float'] = 'left';
+
         // Calculate cell style hashes
         foreach ($this->spreadsheet->getCellXfCollection() as $index => $style) {
             $css['td.style' . $index . ', th.style' . $index] = $this->createCSSStyle($style);
@@ -1221,21 +1249,52 @@ class Html extends BaseWriter
         return $html;
     }
 
+    private function getDir(Worksheet $worksheet): string
+    {
+        if ($worksheet->getRightToLeft()) {
+            return " dir='rtl'";
+        }
+        if ($this->rtlSheets) {
+            return " dir='ltr'";
+        }
+
+        return '';
+    }
+
+    private function getFloat(Worksheet $worksheet): string
+    {
+        $float = '';
+        if ($worksheet->getRightToLeft()) {
+            if ($this->ltrSheets) {
+                $float = ' floatright';
+            }
+        } else {
+            if ($this->rtlSheets) {
+                $float = ' floatleft';
+            }
+        }
+
+        return $float;
+    }
+
     private function generateTableTagInline(Worksheet $worksheet, string $id): string
     {
         $style = isset($this->cssStyles['table'])
             ? $this->assembleCSS($this->cssStyles['table']) : '';
-
+        $rtl = $this->getDir($worksheet);
+        $float = $this->getFloat($worksheet);
         $prntgrid = $worksheet->getPrintGridlines();
         $viewgrid = $this->isPdf ? $prntgrid : $worksheet->getShowGridlines();
         if ($viewgrid && $prntgrid) {
-            $html = "    <table border='1' cellpadding='1' $id cellspacing='1' style='$style' class='gridlines gridlinesp'>" . PHP_EOL;
+            $html = "    <table border='1' cellpadding='1'$rtl $id cellspacing='1' style='$style' class='gridlines gridlinesp$float'>" . PHP_EOL;
         } elseif ($viewgrid) {
-            $html = "    <table border='0' cellpadding='0' $id cellspacing='0' style='$style' class='gridlines'>" . PHP_EOL;
+            $html = "    <table border='0' cellpadding='0'$rtl $id cellspacing='0' style='$style' class='gridlines$float'>" . PHP_EOL;
         } elseif ($prntgrid) {
-            $html = "    <table border='0' cellpadding='0' $id cellspacing='0' style='$style' class='gridlinesp'>" . PHP_EOL;
+            $html = "    <table border='0' cellpadding='0'$rtl $id cellspacing='0' style='$style' class='gridlinesp$float'>" . PHP_EOL;
+        } elseif ($float === '') {
+            $html = "    <table border='0' cellpadding='1'$rtl $id cellspacing='0' style='$style'>" . PHP_EOL;
         } else {
-            $html = "    <table border='0' cellpadding='1' $id cellspacing='0' style='$style'>" . PHP_EOL;
+            $html = "    <table border='0' cellpadding='1'$rtl $id cellspacing='0' style='$style' class='$float'>" . PHP_EOL;
         }
 
         return $html;
@@ -1244,9 +1303,11 @@ class Html extends BaseWriter
     private function generateTableTag(Worksheet $worksheet, string $id, string &$html, int $sheetIndex): void
     {
         if (!$this->useInlineCss) {
+            $rtl = $this->getDir($worksheet);
+            $float = $this->getFloat($worksheet);
             $gridlines = $worksheet->getShowGridlines() ? ' gridlines' : '';
             $gridlinesp = $worksheet->getPrintGridlines() ? ' gridlinesp' : '';
-            $html .= "    <table border='0' cellpadding='0' cellspacing='0' $id class='sheet$sheetIndex$gridlines$gridlinesp'>" . PHP_EOL;
+            $html .= "    <table border='0' cellpadding='0' cellspacing='0'$rtl $id class='sheet$sheetIndex$gridlines$gridlinesp$float'>" . PHP_EOL;
         } else {
             $html .= $this->generateTableTagInline($worksheet, $id);
         }
@@ -1265,10 +1326,12 @@ class Html extends BaseWriter
         // Construct HTML
         $html = '';
         $id = $showid ? "id='sheet$sheetIndex'" : '';
+        $clear = ($this->rtlSheets && $this->ltrSheets) ? '; clear:both' : '';
+
         if ($showid) {
-            $html .= "<div style='page: page$sheetIndex'>" . PHP_EOL;
+            $html .= "<div style='page: page$sheetIndex$clear'>" . PHP_EOL;
         } else {
-            $html .= "<div style='page: page$sheetIndex' class='scrpgbrk'>" . PHP_EOL;
+            $html .= "<div style='page: page$sheetIndex$clear' class='scrpgbrk'>" . PHP_EOL;
         }
 
         $this->generateTableTag($worksheet, $id, $html, $sheetIndex);
diff --git a/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php b/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php
index 540882708..fe5cfe25c 100644
--- a/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php
+++ b/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php
@@ -67,14 +67,28 @@ class Tcpdf extends Pdf
 
         //  Set the appropriate font
         $pdf->SetFont($this->getFont());
+        $this->checkRtlAndLtr();
+        if ($this->rtlSheets && !$this->ltrSheets) {
+            $pdf->setRTL(true);
+        }
         $pdf->writeHTML($this->generateHTMLAll());
 
         //  Document info
-        $pdf->SetTitle($this->spreadsheet->getProperties()->getTitle());
-        $pdf->SetAuthor($this->spreadsheet->getProperties()->getCreator());
-        $pdf->SetSubject($this->spreadsheet->getProperties()->getSubject());
-        $pdf->SetKeywords($this->spreadsheet->getProperties()->getKeywords());
-        $pdf->SetCreator($this->spreadsheet->getProperties()->getCreator());
+        $pdf->SetTitle(
+            $this->spreadsheet->getProperties()->getTitle()
+        );
+        $pdf->SetAuthor(
+            $this->spreadsheet->getProperties()->getCreator()
+        );
+        $pdf->SetSubject(
+            $this->spreadsheet->getProperties()->getSubject()
+        );
+        $pdf->SetKeywords(
+            $this->spreadsheet->getProperties()->getKeywords()
+        );
+        $pdf->SetCreator(
+            $this->spreadsheet->getProperties()->getCreator()
+        );
 
         //  Write to file
         fwrite($fileHandle, $pdf->output('', 'S'));


Test patch:
diff --git a/tests/PhpSpreadsheetTests/Reader/Html/DirectionTest.php b/tests/PhpSpreadsheetTests/Reader/Html/DirectionTest.php
new file mode 100644
index 000000000..5021a54f3
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Reader/Html/DirectionTest.php
@@ -0,0 +1,92 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PhpOffice\PhpSpreadsheetTests\Reader\Html;
+
+use PhpOffice\PhpSpreadsheet\Reader\Html as HtmlReader;
+use PHPUnit\Framework\TestCase;
+
+class DirectionTest extends TestCase
+{
+    public function testRtl(): void
+    {
+        $inlines = [
+            "<table border='0' cellpadding='0' cellspacing='0' dir='rtl' id='sheet0' class='sheet0 gridlines'>",
+            '<tbody>',
+            '<tr class="row0">',
+            '<td class="column0 style0 s">a1</td>',
+            '<td class="column1 style0 s">b1</td>',
+            '<td class="column2 style0 s">c1</td>',
+            '</tr>',
+            '<tr class="row1">',
+            '<td class="column0 style0 s">a2</td>',
+            '<td class="column1 style0 s">b2</td>',
+            '<td class="column2 style0 s">c2</td>',
+            '</tr>',
+            '</tbody></table>',
+        ];
+        $html = implode("\n", $inlines);
+        $reader = new HtmlReader();
+        $spreadsheet = $reader->loadFromString($html);
+        $sheet = $spreadsheet->getActiveSheet();
+        self::assertTrue($sheet->getRightToLeft());
+        self::assertSame('a1', $sheet->getCell('A1')->getValue());
+        self::assertSame('c2', $sheet->getCell('C2')->getValue());
+        $spreadsheet->disconnectWorksheets();
+    }
+
+    public function testLtr(): void
+    {
+        $inlines = [
+            "<table border='0' cellpadding='0' cellspacing='0' dir='ltr' id='sheet0' class='sheet0 gridlines'>",
+            '<tbody>',
+            '<tr class="row0">',
+            '<td class="column0 style0 s">a1</td>',
+            '<td class="column1 style0 s">b1</td>',
+            '<td class="column2 style0 s">c1</td>',
+            '</tr>',
+            '<tr class="row1">',
+            '<td class="column0 style0 s">a2</td>',
+            '<td class="column1 style0 s">b2</td>',
+            '<td class="column2 style0 s">c2</td>',
+            '</tr>',
+            '</tbody></table>',
+        ];
+        $html = implode("\n", $inlines);
+        $reader = new HtmlReader();
+        $spreadsheet = $reader->loadFromString($html);
+        $sheet = $spreadsheet->getActiveSheet();
+        self::assertFalse($sheet->getRightToLeft());
+        self::assertSame('a1', $sheet->getCell('A1')->getValue());
+        self::assertSame('c2', $sheet->getCell('C2')->getValue());
+        $spreadsheet->disconnectWorksheets();
+    }
+
+    public function testDefault(): void
+    {
+        $inlines = [
+            "<table border='0' cellpadding='0' cellspacing='0' id='sheet0' class='sheet0 gridlines'>",
+            '<tbody>',
+            '<tr class="row0">',
+            '<td class="column0 style0 s">a1</td>',
+            '<td class="column1 style0 s">b1</td>',
+            '<td class="column2 style0 s">c1</td>',
+            '</tr>',
+            '<tr class="row1">',
+            '<td class="column0 style0 s">a2</td>',
+            '<td class="column1 style0 s">b2</td>',
+            '<td class="column2 style0 s">c2</td>',
+            '</tr>',
+            '</tbody></table>',
+        ];
+        $html = implode("\n", $inlines);
+        $reader = new HtmlReader();
+        $spreadsheet = $reader->loadFromString($html);
+        $sheet = $spreadsheet->getActiveSheet();
+        self::assertFalse($sheet->getRightToLeft());
+        self::assertSame('a1', $sheet->getCell('A1')->getValue());
+        self::assertSame('c2', $sheet->getCell('C2')->getValue());
+        $spreadsheet->disconnectWorksheets();
+    }
+}
diff --git a/tests/PhpSpreadsheetTests/Writer/Html/DirectionTest.php b/tests/PhpSpreadsheetTests/Writer/Html/DirectionTest.php
new file mode 100644
index 000000000..9a406bc32
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Writer/Html/DirectionTest.php
@@ -0,0 +1,86 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PhpOffice\PhpSpreadsheetTests\Writer\Html;
+
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Writer\Html;
+use PHPUnit\Framework\TestCase;
+
+class DirectionTest extends TestCase
+{
+    public function testMixedRtlAndLtr(): void
+    {
+        $spreadsheet = new Spreadsheet();
+        $sheet1 = $spreadsheet->getActiveSheet();
+        $sheet1->setRightToLeft(true);
+        $sheet2 = $spreadsheet->createSheet();
+        $sheet3 = $spreadsheet->createSheet();
+        $sheet3->setRightToLeft(true);
+        $cells = [
+            ['a1', 'b1', 'c1'],
+            ['a2', 'b2', 'c2'],
+        ];
+        $sheet1->fromArray($cells);
+        $sheet2->fromArray($cells);
+        $sheet3->fromArray($cells);
+        $writer = new Html($spreadsheet);
+        $writer->writeAllSheets();
+        $html = $writer->generateHTMLall();
+        $rtlCount = substr_count($html, "dir='rtl'");
+        self::assertSame(2, $rtlCount);
+        $ltrCount = substr_count($html, "dir='ltr'");
+        self::assertSame(1, $ltrCount);
+        $spreadsheet->disconnectWorksheets();
+    }
+
+    public function testNoRtl(): void
+    {
+        $spreadsheet = new Spreadsheet();
+        $sheet1 = $spreadsheet->getActiveSheet();
+        $sheet2 = $spreadsheet->createSheet();
+        $sheet3 = $spreadsheet->createSheet();
+        $cells = [
+            ['a1', 'b1', 'c1'],
+            ['a2', 'b2', 'c2'],
+        ];
+        $sheet1->fromArray($cells);
+        $sheet2->fromArray($cells);
+        $sheet3->fromArray($cells);
+        $writer = new Html($spreadsheet);
+        $writer->writeAllSheets();
+        $html = $writer->generateHTMLall();
+        $rtlCount = substr_count($html, "dir='rtl'");
+        self::assertSame(0, $rtlCount);
+        $ltrCount = substr_count($html, "dir='ltr'");
+        self::assertSame(0, $ltrCount);
+        $spreadsheet->disconnectWorksheets();
+    }
+
+    public function testOnlyRtl(): void
+    {
+        $spreadsheet = new Spreadsheet();
+        $sheet1 = $spreadsheet->getActiveSheet();
+        $sheet2 = $spreadsheet->createSheet();
+        $sheet3 = $spreadsheet->createSheet();
+        $cells = [
+            ['a1', 'b1', 'c1'],
+            ['a2', 'b2', 'c2'],
+        ];
+        $sheet1->fromArray($cells);
+        $sheet1->setRightToLeft(true);
+        $sheet2->fromArray($cells);
+        $sheet2->setRightToLeft(true);
+        $sheet3->fromArray($cells);
+        $sheet3->setRightToLeft(true);
+        $writer = new Html($spreadsheet);
+        $writer->writeAllSheets();
+        $html = $writer->generateHTMLall();
+        $rtlCount = substr_count($html, "dir='rtl'");
+        self::assertSame(4, $rtlCount, '3 sheets plus html tag');
+        $ltrCount = substr_count($html, "dir='ltr'");
+        self::assertSame(0, $ltrCount);
+        $spreadsheet->disconnectWorksheets();
+    }
+}