Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ This makes it easier to see exactly what is being tested when reviewing the PR.
4. By default, Github removes markdown headings in the Release Notes. You can either edit to restore these, or, probably preferably, change the default comment character on your system - `git config core.commentChar ";"`.

> **Note:** Tagged releases are made from the `master` branch. Only in an emergency should a tagged release be made from the `release` branch. (i.e. cherry-picked hot-fixes.) However, there are 4 branches which have been updated to apply security patches, and those may be tagged if future security updates are needed.
- release1291
- release210
- release1291 (no further updates aside from security patches, including code changes needed for Php 8.5 compatibility)
- release210 (no further updates aside from security patches, including code changes needed for Php 8.5 compatibility)
- release222
- release390
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# PhpSpreadsheet

[![Build Status](https://github.com/PHPOffice/PhpSpreadsheet/workflows/main/badge.svg)](https://github.com/PHPOffice/PhpSpreadsheet/actions)
[![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/?branch=master)
[![Code Coverage](https://coveralls.io/repos/github/PHPOffice/PhpSpreadsheet/badge.svg?branch=master)](https://coveralls.io/github/PHPOffice/PhpSpreadsheet?branch=master)
[![Total Downloads](https://img.shields.io/packagist/dt/PHPOffice/PhpSpreadsheet)](https://packagist.org/packages/phpoffice/phpspreadsheet)
[![Latest Stable Version](https://img.shields.io/github/v/release/PHPOffice/PhpSpreadsheet)](https://packagist.org/packages/phpoffice/phpspreadsheet)
[![License](https://img.shields.io/github/license/PHPOffice/PhpSpreadsheet)](https://packagist.org/packages/phpoffice/phpspreadsheet)
Expand All @@ -11,6 +10,17 @@
PhpSpreadsheet is a library written in pure PHP and offers a set of classes that
allow you to read and write various spreadsheet file formats such as Excel and LibreOffice Calc.

This is the master branch, and is maintained for security and bug fixes.

## PHP Version Support

LTS: For maintained branches, support for PHP versions will only be maintained for a period of six months beyond the
[end of life](https://www.php.net/supported-versions) of that PHP version.

Currently the required PHP minimum version is PHP __8.1__, and we [will support that version](https://www.php.net/supported-versions.php) until 30th June 2026.

See the `composer.json` for other requirements.

## Installation

See the [install instructions](https://phpspreadsheet.readthedocs.io/en/latest/#installation).
Expand Down
4 changes: 3 additions & 1 deletion docs/topics/accessing-cells.md
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ $highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFrom
echo '<table>' . "\n";
for ($row = 1; $row <= $highestRow; ++$row) {
echo '<tr>' . PHP_EOL;
// Use StringHelper::stringIncrement($col) rather than ++$col if using Php8.5+.
for ($col = 1; $col <= $highestColumnIndex; ++$col) {
$value = $worksheet->getCell([$col, $row])->getValue();
echo '<td>' . $value . '</td>' . PHP_EOL;
Expand All @@ -494,11 +495,12 @@ $worksheet = $spreadsheet->getActiveSheet();
$highestRow = $worksheet->getHighestDataRow(); // e.g. 10
$highestColumn = $worksheet->getHighestDataColumn(); // e.g 'F'
// Increment the highest column letter
++$highestColumn;
++$highestColumn; // StringHelper::stringIncrement($highestColumn); if using Php8.5+.

echo '<table>' . "\n";
for ($row = 1; $row <= $highestRow; ++$row) {
echo '<tr>' . PHP_EOL;
// Use StringHelper::stringIncrement($col) rather than ++$col if using Php8.5+.
for ($col = 'A'; $col != $highestColumn; ++$col) {
echo '<td>' .
$worksheet->getCell($col . $row)
Expand Down
2 changes: 2 additions & 0 deletions docs/topics/migration-from-PHPExcel.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,13 +418,15 @@ So the code must be adapted with something like:
// Before
$cell = $worksheet->getCellByColumnAndRow($column, $row);

// Use StringHelper::stringIncrement($column) rather than ++$column if using Php8.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 Php8.5+.
for ($column = 1; $column <= $max; ++$column) {
$worksheet->setCellValue([$column, $row], 'value');
}
Expand Down
3 changes: 2 additions & 1 deletion infra/LocaleGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Exception;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

Expand Down Expand Up @@ -283,7 +284,7 @@ protected function mapLanguageColumns(Worksheet $translationWorksheet): array
$this->log("Mapping Languages for {$sheetName}:");

$baseColumn = self::ENGLISH_REFERENCE_COLUMN;
$languagesList = $translationWorksheet->getColumnIterator(++$baseColumn);
$languagesList = $translationWorksheet->getColumnIterator(StringHelper::stringIncrement($baseColumn));

$languageNameMap = [];
foreach ($languagesList as $languageColumn) {
Expand Down
3 changes: 2 additions & 1 deletion samples/Basic1/13_Calculation.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;

mt_srand(1234567890);
Expand Down Expand Up @@ -156,7 +157,7 @@

// Calculated data
$helper->log('Calculated data');
for ($col = 'B'; $col != 'G'; ++$col) {
for ($col = 'B'; $col != 'G'; StringHelper::stringIncrement($col)) {
for ($row = 14; $row <= 41; ++$row) {
$formula = $spreadsheet->getActiveSheet()->getCell($col . $row)->getValue();
if (
Expand Down
3 changes: 2 additions & 1 deletion samples/Basic1/13_CalculationCyclicFormulae.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;

require __DIR__ . '/../Header.php';
Expand All @@ -22,7 +23,7 @@
// Calculated data
$helper->log('Calculated data');
for ($row = 1; $row <= 2; ++$row) {
for ($col = 'A'; $col != 'C'; ++$col) {
for ($col = 'A'; $col != 'C'; StringHelper::stringIncrement($col)) {
$formula = $spreadsheet->getActiveSheet()->getCell($col . $row)->getValue();
if (
is_string($formula)
Expand Down
3 changes: 2 additions & 1 deletion samples/Basic3/39_Dropdown.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
use PhpOffice\PhpSpreadsheet\NamedRange;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;

require __DIR__ . '/../Header.php';
Expand Down Expand Up @@ -59,7 +60,7 @@ function transpose(string $value): array
$spreadsheet->getActiveSheet()
->setCellValue($continentColumn . ($key + 1), $continent);

++$column;
StringHelper::stringIncrement($column);
}

// Hide the dropdown data
Expand Down
7 changes: 4 additions & 3 deletions samples/ConditionalFormatting/05_Date_Comparisons.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Color;
Expand Down Expand Up @@ -97,7 +98,7 @@
->fromArray($dateFunctionArray, null, 'B1', true);
$spreadsheet->getActiveSheet()
->fromArray($dateTitleArray, null, 'A2', true);
for ($column = 'B'; $column !== 'L'; ++$column) {
for ($column = 'B'; $column !== 'L'; StringHelper::stringIncrement($column)) {
$spreadsheet->getActiveSheet()
->fromArray($dataArray, null, "{$column}2", true);
}
Expand All @@ -117,7 +118,7 @@

// Set conditional formatting rules and styles
$helper->log('Define conditional formatting and set styles');
for ($column = 'B'; $column !== 'L'; ++$column) {
for ($column = 'B'; $column !== 'L'; StringHelper::stringIncrement($column)) {
$wizardFactory = new Wizard("{$column}2:{$column}19");
/** @var Wizard\DateValue $dateWizard */
$dateWizard = $wizardFactory->newRule(Wizard::DATES_OCCURRING);
Expand All @@ -141,7 +142,7 @@
$helper->log('Set some additional styling for date formats');

$spreadsheet->getActiveSheet()->getStyle('B:B')->getNumberFormat()->setFormatCode('ddd dd-mmm-yyyy');
for ($column = 'A'; $column !== 'L'; ++$column) {
for ($column = 'A'; $column !== 'L'; StringHelper::stringIncrement($column)) {
if ($column !== 'A') {
$spreadsheet->getActiveSheet()->getStyle("{$column}:{$column}")
->getNumberFormat()->setFormatCode('ddd dd-mmm-yyyy');
Expand Down
3 changes: 2 additions & 1 deletion samples/LookupRef/VLOOKUP.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;

require __DIR__ . '/../Header.php';
Expand Down Expand Up @@ -40,7 +41,7 @@
$worksheet->getCell('I5')->setValue('=VLOOKUP(I3, B3:E9, 4, FALSE)');
$worksheet->getCell('J5')->setValue('=VLOOKUP(J3, B3:E9, 4, FALSE)');

for ($column = 'H'; $column !== 'K'; ++$column) {
for ($column = 'H'; $column !== 'K'; StringHelper::stringIncrement($column)) {
for ($row = 4; $row <= 5; ++$row) {
$cell = $worksheet->getCell("{$column}{$row}");
$helper->log("{$column}{$row}: " . $cell->getValueString() . ' => ' . $cell->getCalculatedValueString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
use Stringable;

Expand Down Expand Up @@ -174,7 +175,7 @@ private function getTableByName(Cell $cell): Table
}

/**
* @param array<array<int|string>> $tableRange
* @param array{array{string, int}, array{string, int}} $tableRange
*
* @return mixed[]
*/
Expand All @@ -184,8 +185,8 @@ private function getColumns(Cell $cell, array $tableRange): array
$cellReference = $cell->getCoordinate();

$columns = [];
$lastColumn = ++$tableRange[1][0];
for ($column = $tableRange[0][0]; $column !== $lastColumn; ++$column) {
$lastColumn = StringHelper::stringIncrement($tableRange[1][0]);
for ($column = $tableRange[0][0]; $column !== $lastColumn; StringHelper::stringIncrement($column)) {
/** @var string $column */
$columns[$column] = $worksheet
->getCell($column . ($this->headersRow ?? ($this->firstDataRow - 1)))
Expand Down
13 changes: 6 additions & 7 deletions src/PhpSpreadsheet/Cell/Cell.php
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ public function getCalculatedValue(bool $resetLog = true): mixed
}
}
/** @var string $newColumn */
++$newColumn;
StringHelper::stringIncrement($newColumn);
}
++$newRow;
} else {
Expand All @@ -484,7 +484,7 @@ public function getCalculatedValue(bool $resetLog = true): mixed
}
}
}
++$newColumn;
StringHelper::stringIncrement($newColumn);
}
if ($spill) {
break;
Expand All @@ -506,10 +506,10 @@ public function getCalculatedValue(bool $resetLog = true): mixed
$minCol = $matches[1];
$minRow = (int) $matches[2];
$maxCol = $matches[4];
++$maxCol;
StringHelper::stringIncrement($maxCol);
$maxRow = (int) $matches[5];
for ($row = $minRow; $row <= $maxRow; ++$row) {
for ($col = $minCol; $col !== $maxCol; ++$col) {
for ($col = $minCol; $col !== $maxCol; StringHelper::stringIncrement($col)) {
/** @var string $col */
if ("$col$row" !== $coordinate) {
$thisworksheet->getCell("$col$row")->setValue(null);
Expand Down Expand Up @@ -537,15 +537,14 @@ public function getCalculatedValue(bool $resetLog = true): mixed
->getCell($newColumn . $newRow)
->setValue($resultValue);
}
/** @var string $newColumn */
++$newColumn;
StringHelper::stringIncrement($newColumn);
}
++$newRow;
} else {
if ($row !== $newRow || $column !== $newColumn) {
$thisworksheet->getCell($newColumn . $newRow)->setValue($resultRow);
}
++$newColumn;
StringHelper::stringIncrement($newColumn);
}
}
$thisworksheet->getCell($column . $row);
Expand Down
2 changes: 1 addition & 1 deletion src/PhpSpreadsheet/Reader/Csv.php
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ private function loadStringOrFile2(string $filename, Spreadsheet $spreadsheet, b
// Set cell value
$sheet->getCell($columnLetter . $outRow)->setValue($rowDatum);
}
++$columnLetter;
StringHelper::stringIncrement($columnLetter);
}
$rowData = self::getCsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
++$currentRow;
Expand Down
29 changes: 11 additions & 18 deletions src/PhpSpreadsheet/Reader/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ private function processDomElementTable(Worksheet $sheet, int &$row, string &$co
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
$column = $this->releaseTableStartColumn();
if ($this->tableLevel > 1) {
++$column; //* @phpstan-ignore-line
StringHelper::stringIncrement($column);
} else {
++$row;
}
Expand All @@ -558,7 +558,7 @@ private function processDomElementTr(Worksheet $sheet, int &$row, string &$colum
{
if ($child->nodeName === 'col') {
$this->applyInlineStyle($sheet, -1, $this->currentColumn, $attributeArray);
++$this->currentColumn;
StringHelper::stringIncrement($this->currentColumn);
} elseif ($child->nodeName === 'tr') {
$column = $this->getTableStartColumn();
$cellContent = '';
Expand Down Expand Up @@ -644,10 +644,9 @@ private function processDomElementThTd(Worksheet $sheet, int &$row, string &$col
{
while (isset($this->rowspan[$column . $row])) {
$temp = (string) $column;
++$temp;
$column = (string) $temp;
$column = StringHelper::stringIncrement($temp);
}
$this->processDomElement($child, $sheet, $row, $column, $cellContent); // ++$column above confuses Phpstan
$this->processDomElement($child, $sheet, $row, $column, $cellContent);

// apply inline style
$this->applyInlineStyle($sheet, $row, $column, $attributeArray);
Expand All @@ -666,16 +665,14 @@ private function processDomElementThTd(Worksheet $sheet, int &$row, string &$col
//create merging rowspan and colspan
$columnTo = $column;
for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) {
/** @var string $columnTo */
++$columnTo;
StringHelper::stringIncrement($columnTo);
}
$range = $column . $row . ':' . $columnTo . ($row + (int) $attributeArray['rowspan'] - 1);
foreach (Coordinate::extractAllCellReferencesInRange($range) as $value) {
$this->rowspan[$value] = true;
}
$sheet->mergeCells($range);
//* @phpstan-ignore-next-line
$column = $columnTo; // ++$columnTo above confuses phpstan
$column = $columnTo;
} elseif (isset($attributeArray['rowspan'])) {
//create merging rowspan
$range = $column . $row . ':' . $column . ($row + (int) $attributeArray['rowspan'] - 1);
Expand All @@ -687,15 +684,13 @@ private function processDomElementThTd(Worksheet $sheet, int &$row, string &$col
//create merging colspan
$columnTo = $column;
for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) {
/** @var string $columnTo */
++$columnTo;
StringHelper::stringIncrement($columnTo);
}
$sheet->mergeCells($column . $row . ':' . $columnTo . $row);
//* @phpstan-ignore-next-line
$column = $columnTo; // ++$columnTo above confuses phpstan
$column = $columnTo;
}

++$column; //* @phpstan-ignore-line
StringHelper::stringIncrement($column);
}

protected function processDomElement(DOMNode $element, Worksheet $sheet, int &$row, string &$column, string &$cellContent): void
Expand Down Expand Up @@ -934,8 +929,7 @@ private function applyInlineStyle(Worksheet &$sheet, int $row, string $column, a
} elseif (isset($attributeArray['rowspan'], $attributeArray['colspan'])) {
$columnTo = $column;
for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) {
/** @var string $columnTo */
++$columnTo;
StringHelper::stringIncrement($columnTo);
}
$range = $column . $row . ':' . $columnTo . ($row + (int) $attributeArray['rowspan'] - 1);
$cellStyle = $sheet->getStyle($range);
Expand All @@ -945,8 +939,7 @@ private function applyInlineStyle(Worksheet &$sheet, int $row, string $column, a
} elseif (isset($attributeArray['colspan'])) {
$columnTo = $column;
for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) {
/** @var string $columnTo */
++$columnTo;
StringHelper::stringIncrement($columnTo);
}
$range = $column . $row . ':' . $columnTo . $row;
$cellStyle = $sheet->getStyle($range);
Expand Down
Loading