diff --git a/docs/topics/accessing-cells.md b/docs/topics/accessing-cells.md index a9fe3695d..919834739 100644 --- a/docs/topics/accessing-cells.md +++ b/docs/topics/accessing-cells.md @@ -42,6 +42,19 @@ $spreadsheet->getActiveSheet() If you make a call to `getCell()`, and the cell doesn't already exist, then PhpSpreadsheet will create that cell for you. +### Copying a Cell's Value And Style Adjusting Formulas + +If cell A1 contains `5`, cell A2 contains `10`, and cell `B1` contains `=A1`, the formula in B1 will be evaluated as `5`. In Excel, if you copy B1 to B2, B2 will wind up with the adjusted formula `=A2` and will be evaluated as 10. Until release 5.1.0, PhpSpreadsheet requires the program to perform its own formula adjustment. In 5.1.0, a new method is introduced to handle formula adjustments: +```php +$worksheet->copyformula($fromCell, $toCell); +``` +This will behave as Excel does. If $fromCell does not contain a formula, its contents will be copied as-is. + +If you also want to copy $fromCell's style, as Excel does, you can use the following (available in all supported releases): +```php +$worksheet->duplicateStyle($fromCell->getStyle(), $toCell); +``` + ### BEWARE: Cells and Styles assigned to variables as a Detached Reference As an "in-memory" model, PHPSpreadsheet can be very demanding of memory, diff --git a/src/PhpSpreadsheet/Worksheet/Worksheet.php b/src/PhpSpreadsheet/Worksheet/Worksheet.php index 525513b25..137d2b4b6 100644 --- a/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -3984,4 +3984,22 @@ class Worksheet return true; } + + public function copyFormula(string $fromCell, string $toCell): void + { + $formula = $this->getCell($fromCell)->getValue(); + $newFormula = $formula; + if (is_string($formula) && $this->getCell($fromCell)->getDataType() === DataType::TYPE_FORMULA) { + [$fromColInt, $fromRow] = Coordinate::indexesFromString($fromCell); + [$toColInt, $toRow] = Coordinate::indexesFromString($toCell); + $helper = ReferenceHelper::getInstance(); + $newFormula = $helper->updateFormulaReferences( + $formula, + 'A1', + $toColInt - $fromColInt, + $toRow - $fromRow + ); + } + $this->setCellValue($toCell, $newFormula); + } } diff --git a/tests/PhpSpreadsheetTests/Worksheet/Issue1203Test.php b/tests/PhpSpreadsheetTests/Worksheet/Issue1203Test.php new file mode 100644 index 000000000..01ddf4482 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Worksheet/Issue1203Test.php @@ -0,0 +1,31 @@ +getActiveSheet(); + $sheet->setCellValue('A1', 1); + $sheet->setCellValue('A5', 5); + $sheet->setCellValue('E5', '=A5+$A$1'); + $sheet->insertNewRowBefore(5, 1); + $e5 = $sheet->getCell('E5')->getValue(); + self::assertNull($e5); + self::assertSame('=A6+$A$1', $sheet->getCell('E6')->getValue()); + $sheet->copyFormula('E6', 'E5'); + self::assertSame('=A5+$A$1', $sheet->getCell('E5')->getValue()); + $sheet->copyFormula('E6', 'H9'); + self::assertSame('=D9+$A$1', $sheet->getCell('H9')->getValue()); + $sheet->copyFormula('A6', 'Z9'); + self::assertSame(5, $sheet->getCell('Z9')->getValue()); + $spreadsheet->disconnectWorksheets(); + } +}