Skip to main content
PhpSpreadsheet is the next version of PHPExcel. It breaks compatibility to dramatically improve the code base quality through namespaces, PSR compliance, and use of latest PHP language features.
All efforts have shifted to PhpSpreadsheet. PHPExcel is no longer maintained. All contributions, patches, and new features should target PhpSpreadsheet.

Automated Migration Tool

RectorPHP can automatically migrate your codebase. Note that this support has been dropped from current releases of Rector, so you need to require an earlier release.

Installation

Assuming your files to be migrated live in src/, install the required packages:
composer require rector/rector:0.15.10 rector/rector-phpoffice phpoffice/phpspreadsheet --dev

Configuration

Initialize Rector configuration:
vendor/bin/rector init
Add PHPOfficeSetList to your rector.php config:
declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\PHPOffice\Set\PHPOfficeSetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->sets([
        PHPOfficeSetList::PHPEXCEL_TO_PHPSPREADSHEET
    ]);
};

Run Migration

Execute Rector on your codebase:
vendor/bin/rector process src
For more details, see rector-phpoffice.

Manual Changes

RectorPHP should handle most changes, but you may need to apply some manual updates:

Renamed Readers and Writers

When using IOFactory::createReader(), IOFactory::createWriter(), and IOFactory::identify(), the reader/writer short names have changed:
BeforeAfter
'CSV''Csv'
'Excel2003XML''Xml'
'Excel2007''Xlsx'
'Excel5''Xls'
'Gnumeric''Gnumeric'
'HTML''Html'
'OOCalc''Ods'
'OpenDocument''Ods'
'PDF''Pdf'
'SYLK''Slk'

Simplified IOFactory

The following methods have been replaced:
  • PHPExcel_IOFactory::getSearchLocations()
  • PHPExcel_IOFactory::setSearchLocations()
  • PHPExcel_IOFactory::addSearchLocation()
Use IOFactory::registerReader() and IOFactory::registerWriter() instead. IOFactory now relies on class autoloading.
// Before
\PHPExcel_IOFactory::addSearchLocation($type, $location, $classname);

// After
\PhpOffice\PhpSpreadsheet\IOFactory::registerReader($type, $classname);

Removed Deprecated Methods

Worksheet::duplicateStyleArray()

// Before
$worksheet->duplicateStyleArray($styles, $range, $advanced);

// After
$worksheet->getStyle($range)->applyFromArray($styles, $advanced);

DataType::dataTypeForValue()

// Before
DataType::dataTypeForValue($value);

// After
DefaultValueBinder::dataTypeForValue($value);

Conditional::getCondition()

// Before
$conditional->getCondition();

// After
$conditional->getConditions()[0];

Conditional::setCondition()

// Before
$conditional->setCondition($value);

// After
$conditional->setConditions($value);

Worksheet::getDefaultStyle()

// Before
$worksheet->getDefaultStyle();

// After
$worksheet->getParent()->getDefaultStyle();

Worksheet::setDefaultStyle()

// Before
$worksheet->setDefaultStyle($value);

// After
$worksheet->getParent()->getDefaultStyle()->applyFromArray([
    'font' => [
        'name' => $pValue->getFont()->getName(),
        'size' => $pValue->getFont()->getSize(),
    ],
]);

Worksheet::setSharedStyle()

// Before
$worksheet->setSharedStyle($sharedStyle, $range);

// After
$worksheet->duplicateStyle($sharedStyle, $range);

Worksheet::getSelectedCell()

// Before
$worksheet->getSelectedCell();

// After
$worksheet->getSelectedCells();

Writer\Xls::setTempDir()

// Before
$writer->setTempDir();

// After - no replacement available
// Temporary storage directory can no longer be set

Autoloader

The class PHPExcel_Autoloader has been removed entirely and is replaced by Composer’s autoloading mechanism.

Writing PDF

PDF libraries must be installed via Composer. The following methods have been removed:
  • PHPExcel_Settings::getPdfRenderer()
  • PHPExcel_Settings::setPdfRenderer()
  • PHPExcel_Settings::getPdfRendererName()
  • PHPExcel_Settings::setPdfRendererName()
Use IOFactory::registerWriter() instead:
// Before
\PHPExcel_Settings::setPdfRendererName(PHPExcel_Settings::PDF_RENDERER_MPDF);
\PHPExcel_Settings::setPdfRenderer($somePath);
$writer = \PHPExcel_IOFactory::createWriter($spreadsheet, 'PDF');

// After
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Mpdf');

// Or alternatively
\PhpOffice\PhpSpreadsheet\IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class);
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Pdf');

// Or alternatively
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet);

Rendering Charts

Chart rendering for HTML or PDF outputs has been simplified. While JpGraph support is still available, the version distributed via Composer is no longer maintained.
The package mitoteam/jpgraph is distributed via Composer and is fully compatible with JpGraph. We recommend using it for chart rendering.
Install the dependency:
composer require mitoteam/jpgraph
Then configure it:
// Before
$rendererName = \PHPExcel_Settings::CHART_RENDERER_JPGRAPH;
$rendererLibrary = 'jpgraph3.5.0b1/src/';
$rendererLibraryPath = '/php/libraries/Charts/' . $rendererLibrary;

\PHPExcel_Settings::setChartRenderer($rendererName, $rendererLibraryPath);

// After
Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class);

PclZip and ZipArchive

Support for PclZip has been dropped in favor of the more complete PHP extension ZipArchive. The following have been removed:
  • PclZip
  • PHPExcel_Settings::setZipClass()
  • PHPExcel_Settings::getZipClass()
  • PHPExcel_Shared_ZipArchive
  • PHPExcel_Shared_ZipStreamWrapper

Cell Caching

Cell caching was heavily refactored to leverage PSR-16. Most classes related to this feature were removed:
  • PHPExcel_CachedObjectStorage_APC
  • PHPExcel_CachedObjectStorage_DiscISAM
  • PHPExcel_CachedObjectStorage_ICache
  • PHPExcel_CachedObjectStorage_Igbinary
  • PHPExcel_CachedObjectStorage_Memcache
  • PHPExcel_CachedObjectStorage_Memory
  • PHPExcel_CachedObjectStorage_MemoryGZip
  • PHPExcel_CachedObjectStorage_MemorySerialized
  • PHPExcel_CachedObjectStorage_PHPTemp
  • PHPExcel_CachedObjectStorage_SQLite
  • PHPExcel_CachedObjectStorage_SQLite3
  • PHPExcel_CachedObjectStorage_Wincache
Additionally:
  • \PhpOffice\PhpSpreadsheet::getCellCollection() was renamed to \PhpOffice\PhpSpreadsheet::getCoordinates()
  • \PhpOffice\PhpSpreadsheet::getCellCacheController() was renamed to \PhpOffice\PhpSpreadsheet::getCellCollection()
Refer to the memory saving documentation for migration guidance.

Dropped Conditionally Returned Cell

The following methods will always return the Worksheet, never the Cell or Rule:
  • Worksheet::setCellValue()
  • Worksheet::setCellValueByColumnAndRow() (deprecated)
  • Worksheet::setCellValueExplicit()
  • Worksheet::setCellValueExplicitByColumnAndRow() (deprecated)
  • Worksheet::addRule()
Migration example:
// Before
$cell = $worksheet->setCellValue('A1', 'value', true);

// After
$cell = $worksheet->getCell('A1')->setValue('value');

Standardized Keys for Styling

Array keys used for styling have been standardized to use the same wording and casing as getter and setter methods:
// Before
$style = [
    'numberformat' => [
        'code' => NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE,
    ],
    'font' => [
        'strike' => true,
        'superScript' => true,
        'subScript' => true,
    ],
    'alignment' => [
        'rotation' => 90,
        'readorder' => Alignment::READORDER_RTL,
        'wrap' => true,
    ],
    'borders' => [
        'diagonaldirection' => Borders::DIAGONAL_BOTH,
        'allborders' => [
            'style' => Border::BORDER_THIN,
        ],
    ],
    'fill' => [
        'type' => Fill::FILL_GRADIENT_LINEAR,
        'startcolor' => [
            'argb' => 'FFA0A0A0',
        ],
        'endcolor' => [
            'argb' => 'FFFFFFFF',
        ],
    ],
];

// After
$style = [
    'numberFormat' => [
        'formatCode' => NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE,
    ],
    'font' => [
        'strikethrough' => true,
        'superscript' => true,
        'subscript' => true,
    ],
    'alignment' => [
        'textRotation' => 90,
        'readOrder' => Alignment::READORDER_RTL,
        'wrapText' => true,
    ],
    'borders' => [
        'diagonalDirection' => Borders::DIAGONAL_BOTH,
        'allBorders' => [
            'borderStyle' => Border::BORDER_THIN,
        ],
    ],
    'fill' => [
        'fillType' => Fill::FILL_GRADIENT_LINEAR,
        'startColor' => [
            'argb' => 'FFA0A0A0',
        ],
        'endColor' => [
            'argb' => 'FFFFFFFF',
        ],
    ],
];

Dedicated Class for Coordinate Manipulation

Methods to manipulate coordinates that previously existed in PHPExcel_Cell have been extracted to \PhpOffice\PhpSpreadsheet\Cell\Coordinate:
  • absoluteCoordinate()
  • absoluteReference()
  • buildRange()
  • columnIndexFromString()
  • coordinateFromString()
  • extractAllCellReferencesInRange()
  • getRangeBoundaries()
  • mergeRangesInCollection()
  • rangeBoundaries()
  • rangeDimension()
  • splitRange()
  • stringFromColumnIndex()

Column Index Based on 1

Column indexes are now based on 1, not 0. Column A is index 1, consistent with rows starting at 1 and Excel’s COLUMN() function.
// Before
$cell = $worksheet->getCellByColumnAndRow($column, $row);

// Use StringHelper::stringIncrement($column) rather than ++$column if using PHP 8.5+
for ($column = 0; $column < $max; ++$column) {
    $worksheet->setCellValueByColumnAndRow($column, $row, 'value');
}

// After
$cell = $worksheet->getCell([$column + 1, $row]);

// Use StringHelper::stringIncrement($column) rather than ++$column if using PHP 8.5+
for ($column = 1; $column <= $max; ++$column) {
    $worksheet->setCellValue([$column, $row], 'value');
}
All the following methods are affected and now deprecated:
  • PHPExcel_Worksheet::cellExistsByColumnAndRow()
  • PHPExcel_Worksheet::freezePaneByColumnAndRow()
  • PHPExcel_Worksheet::getCellByColumnAndRow()
  • PHPExcel_Worksheet::getColumnDimensionByColumn()
  • PHPExcel_Worksheet::getCommentByColumnAndRow()
  • PHPExcel_Worksheet::getStyleByColumnAndRow()
  • PHPExcel_Worksheet::insertNewColumnBeforeByIndex()
  • PHPExcel_Worksheet::mergeCellsByColumnAndRow()
  • PHPExcel_Worksheet::protectCellsByColumnAndRow()
  • PHPExcel_Worksheet::removeColumnByIndex()
  • PHPExcel_Worksheet::setAutoFilterByColumnAndRow()
  • PHPExcel_Worksheet::setBreakByColumnAndRow()
  • PHPExcel_Worksheet::setCellValueByColumnAndRow()
  • PHPExcel_Worksheet::setCellValueExplicitByColumnAndRow()
  • PHPExcel_Worksheet::setSelectedCellByColumnAndRow()
  • PHPExcel_Worksheet::stringFromColumnIndex()
  • PHPExcel_Worksheet::unmergeCellsByColumnAndRow()
  • PHPExcel_Worksheet::unprotectCellsByColumnAndRow()
  • PHPExcel_Worksheet_PageSetup::addPrintAreaByColumnAndRow()
  • PHPExcel_Worksheet_PageSetup::setPrintAreaByColumnAndRow()

Removed Default Values

Default values for many methods were removed when they didn’t make sense. Setter methods should not have default values. For a complete list of methods and their original default values, see this commit.

Build docs developers (and LLMs) love