SpreadSheet-Coding.com

PhpSpreadsheet

Set The Worksheet Tab Color In Excel Files In PHP Using PHPSpreadSheet

Once a workbook holds more than three or four sheets the tab strip becomes the navigation, and coloring it is one call per sheet with getTabColor()->setRGB(). Two things around that call are less obvious: a color set as RGB reads back as ARGB, so a naive string comparison fails, and getTabColor() is not a passive getter, so a loop that only meant to report the colors can quietly color every tab in the workbook.

August 8, 2026

This article shows how to set the worksheet tab color in PHP with the latest version of PhpSpreadsheet. Once a workbook holds more than three or four sheets, the tab strip along the bottom becomes the navigation. Coloring them is the cheapest way to make it readable. For example, green for the quarters that hit target, amber for a near miss, red for a failure. It is one call per sheet: getTabColor()->setRGB().

The call is simple, so this article spends its time on the two things around it that are not. First, the color object takes plain RGB here. However, it reads back as ARGB, with an alpha channel bolted on the front. So a naive string comparison against the value you set will fail. Second, and more surprising, getTabColor() is not a passive getter. Calling it on a sheet that has no tab color gives that sheet one. In fact the method creates the color object on demand. Therefore a loop that only meant to report the colors can quietly color every tab in the workbook.

Below we build a workbook of five sheets and color four of them. Then we prove both behaviours by reading the saved file back.

Requirements to set the tab color in PHP:

Step 1.

First, set up the dependencies. Here we pin the latest major release of PhpSpreadsheet (the 5.x line, tested with 5.9).

composer.json
{
    "require": {
        "phpoffice/phpspreadsheet": "^5.0"
    }
}

Step 2.

Next, install phpspreadsheet.

command line
$ composer install

Step 3.

Then create a new PHP file and load the autoloader. Tab colors need nothing extra. The color lives on the worksheet itself rather than in the Style namespace.

tab-color.php
<?php

require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

Step 4.

Next, create the sheets and color them as you go. Note the shape of the loop. A new Spreadsheet already contains one sheet. So the first pass takes that one with getActiveSheet(), and every later pass calls createSheet(). Skip that and you ship a workbook with an empty Worksheet tab in front of your data.

tab-color.php
$spreadsheet = new Spreadsheet();

// One sheet per quarter, each with a colour that says how it went.
$quarters = [
    'Q1' => '2E7D32',   // green  - target met
    'Q2' => '2E7D32',   // green  - target met
    'Q3' => 'F9A825',   // amber  - close
    'Q4' => 'C62828',   // red    - missed
];

$first = true;
foreach ($quarters as $name => $rgb) {
    $worksheet = $first ? $spreadsheet->getActiveSheet() : $spreadsheet->createSheet();
    $first = false;

    $worksheet->setTitle($name);
    $worksheet->getTabColor()->setRGB($rgb);
    $worksheet->setCellValue('A1', "$name summary");
}

Step 5.

Then add one sheet with no color at all, so the comparison later is real rather than assumed. Also set the active sheet explicitly. This matters more than it sounds. Excel draws the selected tab as a pale wash of its color, not the solid block you get elsewhere. So if your one colored tab is also the one that opens, it can look as though nothing happened.

tab-color.php
// A fifth sheet deliberately left with no colour.
$notes = $spreadsheet->createSheet();
$notes->setTitle('Notes');
$notes->setCellValue('A1', 'No tab colour on this one.');

$spreadsheet->setActiveSheetIndexByName('Q1');
(new Xlsx($spreadsheet))->save('year.xlsx');
echo "Wrote year.xlsx\n\n";

Step 6.

Next, read the colors back from the saved file. Here isTabColorSet() does the real work. It is the only safe way to ask whether a sheet has a color. So we test it before touching getTabColor(). Consequently the Notes sheet still reports honestly. Also notice the two getters. getRGB() returns the six digits you set, while getARGB() returns the same value with an FF alpha prefix.

tab-color.php
// Read the colours back out of the saved file.
$reloaded = IOFactory::load('year.xlsx');

printf("%-7s %-9s %s\n", 'Sheet', 'Set?', 'RGB / ARGB');
foreach ($reloaded->getAllSheets() as $sheet) {
    if ($sheet->isTabColorSet()) {
        printf("%-7s %-9s %s / %s\n", $sheet->getTitle(), 'yes',
            $sheet->getTabColor()->getRGB(), $sheet->getTabColor()->getARGB());
    } else {
        printf("%-7s %-9s %s\n", $sheet->getTitle(), 'no', '-');
    }
}

Step 7.

Finally, remove a color and then demonstrate the trap. resetTabColor() clears one properly. However, the very next block asks Notes for a tab color it does not have. That single read is enough to give it one. No assignment, no setter, just the getter. So when you want to know whether a sheet carries a tab color, always ask isTabColorSet() first.

tab-color.php
// resetTabColor() removes it again; the getter alone would re-create it.
$reloaded->getSheetByName('Q4')->resetTabColor();
printf("\nAfter resetTabColor() on Q4: %s\n",
    $reloaded->getSheetByName('Q4')->isTabColorSet() ? 'still set' : 'cleared');

// Careful: merely ASKING for the colour counts as setting it.
$reloaded->getSheetByName('Notes')->getTabColor();
printf("After calling getTabColor() on Notes: %s\n",
    $reloaded->getSheetByName('Notes')->isTabColorSet() ? 'now set' : 'still unset');

Complete code to set the tab color in PHP.

tab-color.php
<?php

require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

$spreadsheet = new Spreadsheet();

// One sheet per quarter, each with a colour that says how it went.
$quarters = [
    'Q1' => '2E7D32',   // green  - target met
    'Q2' => '2E7D32',   // green  - target met
    'Q3' => 'F9A825',   // amber  - close
    'Q4' => 'C62828',   // red    - missed
];

$first = true;
foreach ($quarters as $name => $rgb) {
    $worksheet = $first ? $spreadsheet->getActiveSheet() : $spreadsheet->createSheet();
    $first = false;

    $worksheet->setTitle($name);
    $worksheet->getTabColor()->setRGB($rgb);
    $worksheet->setCellValue('A1', "$name summary");
}

// A fifth sheet deliberately left with no colour.
$notes = $spreadsheet->createSheet();
$notes->setTitle('Notes');
$notes->setCellValue('A1', 'No tab colour on this one.');

$spreadsheet->setActiveSheetIndexByName('Q1');
(new Xlsx($spreadsheet))->save('year.xlsx');
echo "Wrote year.xlsx\n\n";

// Read the colours back out of the saved file.
$reloaded = IOFactory::load('year.xlsx');

printf("%-7s %-9s %s\n", 'Sheet', 'Set?', 'RGB / ARGB');
foreach ($reloaded->getAllSheets() as $sheet) {
    if ($sheet->isTabColorSet()) {
        printf("%-7s %-9s %s / %s\n", $sheet->getTitle(), 'yes',
            $sheet->getTabColor()->getRGB(), $sheet->getTabColor()->getARGB());
    } else {
        printf("%-7s %-9s %s\n", $sheet->getTitle(), 'no', '-');
    }
}

// resetTabColor() removes it again; the getter alone would re-create it.
$reloaded->getSheetByName('Q4')->resetTabColor();
printf("\nAfter resetTabColor() on Q4: %s\n",
    $reloaded->getSheetByName('Q4')->isTabColorSet() ? 'still set' : 'cleared');

// Careful: merely ASKING for the colour counts as setting it.
$reloaded->getSheetByName('Notes')->getTabColor();
printf("After calling getTabColor() on Notes: %s\n",
    $reloaded->getSheetByName('Notes')->isTabColorSet() ? 'now set' : 'still unset');

Test setting the tab color in PHP.

Command line testing.

command line
$ php tab-color.php

Result of setting the tab color in PHP.

First, all four quarters survive the round trip with the exact hex you gave them. Also, Notes correctly reports no color. Next, see the two getters side by side. 2E7D32 becomes FF2E7D32. That is why you compare with getRGB() and not with the ARGB form. Then resetTabColor() clears Q4 cleanly. Finally the last line is the one to remember. A single read of getTabColor() turned an uncolored sheet into a colored one:

command line
Wrote year.xlsx

Sheet   Set?      RGB / ARGB
Q1      yes       2E7D32 / FF2E7D32
Q2      yes       2E7D32 / FF2E7D32
Q3      yes       F9A825 / FFF9A825
Q4      yes       C62828 / FFC62828
Notes   no        -

After resetTabColor() on Q4: cleared
After calling getTabColor() on Notes: now set
Terminal output of setting the tab color in PHP: four quarter sheets reporting their RGB and ARGB values, a Notes sheet with none, Q4 cleared by resetTabColor, and Notes becoming set merely by calling getTabColor

So open year.xlsx and the tab strip reads at a glance. Two green quarters, one amber, one red, and a plain Notes tab at the end. Consequently it is worth the one line per sheet. Set the tab color in PHP whenever a workbook already carries several sheets. It also pairs naturally with working with multiple worksheets.

The finished year.xlsx: the tab strip reading Q1 washed pale green because it is the open sheet, then solid green Q2, amber Q3 and red Q4, and a plain white Notes tab at the end, with Q1 summary spilling out of cell A1

References for setting the tab color in PHP: