diff --git a/src/PhpSpreadsheet/Cell/Cell.php b/src/PhpSpreadsheet/Cell/Cell.php index 543574e84..a6be2f8ce 100644 --- a/src/PhpSpreadsheet/Cell/Cell.php +++ b/src/PhpSpreadsheet/Cell/Cell.php @@ -361,6 +361,18 @@ class Cell implements Stringable $result = array_shift($result); } } + // if return_as_array for formula like '=sheet!cell' + if (is_array($result) && count($result) === 1) { + $resultKey = array_keys($result)[0]; + $resultValue = $result[$resultKey]; + if (is_int($resultKey) && is_array($resultValue) && count($resultValue) === 1) { + $resultKey2 = array_keys($resultValue)[0]; + $resultValue2 = $resultValue[$resultKey2]; + if (is_string($resultKey2) && !is_array($resultValue2) && preg_match('/[a-zA-Z]{1,3}/', $resultKey2) === 1) { + $result = $resultValue2; + } + } + } } catch (SpreadsheetException $ex) { if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->calculatedValue !== null)) { return $this->calculatedValue; // Fallback for calculations referencing external files. diff --git a/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php b/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php index 984aa174e..c394a0ee2 100644 --- a/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php +++ b/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php @@ -107,7 +107,7 @@ class Formatter extends BaseFormatter /** * Convert a value in a pre-defined format to a PHP string. * - * @param null|bool|float|int|RichText|string $value Value to format + * @param null|array|bool|float|int|RichText|string $value Value to format * @param string $format Format code: see = self::FORMAT_* for predefined values; * or can be any valid MS Excel custom format string * @param ?array $callBack Callback function for additional formatting of string @@ -116,6 +116,9 @@ class Formatter extends BaseFormatter */ public static function toFormattedString($value, string $format, ?array $callBack = null): string { + while (is_array($value)) { + $value = array_shift($value); + } if (is_bool($value)) { return $value ? Calculation::getTRUE() : Calculation::getFALSE(); } diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php index 1b149c833..56efed67d 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php @@ -1402,7 +1402,12 @@ class Worksheet extends WriterPart } $attributes = $cell->getFormulaAttributes() ?? []; - $ref = array_key_exists('ref', $attributes) ? $attributes['ref'] : $cell->getCoordinate(); + $coordinate = $cell->getCoordinate(); + if (isset($attributes['ref'])) { + $ref = $this->parseRef($coordinate, $attributes['ref']); + } else { + $ref = $coordinate; + } if (is_array($calculatedValue)) { $attributes['t'] = 'array'; $rows = max(1, count($calculatedValue)); @@ -1410,11 +1415,11 @@ class Worksheet extends WriterPart foreach ($calculatedValue as $row) { $cols = max($cols, is_array($row) ? count($row) : 1); } - $firstCellArray = Coordinate::indexesFromString($ref); + $firstCellArray = Coordinate::indexesFromString($coordinate); $lastRow = $firstCellArray[1] + $rows - 1; $lastColumn = $firstCellArray[0] + $cols - 1; $lastColumnString = Coordinate::stringFromColumnIndex($lastColumn); - $ref .= ":$lastColumnString$lastRow"; + $ref = "$coordinate:$lastColumnString$lastRow"; } if (($attributes['t'] ?? null) === 'array') { $objWriter->startElement('f'); @@ -1449,6 +1454,28 @@ class Worksheet extends WriterPart } } + private function parseRef(string $coordinate, string $ref): string + { + if (preg_match('/^([A-Z]{1,3})([0-9]{1,7})(:([A-Z]{1,3})([0-9]{1,7}))?$/', $ref, $matches) !== 1) { + return $ref; + } + if (!isset($matches[3])) { // single cell, not range + return $coordinate; + } + $minRow = (int) $matches[2]; + $maxRow = (int) $matches[5]; + $rows = $maxRow - $minRow + 1; + $minCol = Coordinate::columnIndexFromString($matches[1]); + $maxCol = Coordinate::columnIndexFromString($matches[4]); + $cols = $maxCol - $minCol + 1; + $firstCellArray = Coordinate::indexesFromString($coordinate); + $lastRow = $firstCellArray[1] + $rows - 1; + $lastColumn = $firstCellArray[0] + $cols - 1; + $lastColumnString = Coordinate::stringFromColumnIndex($lastColumn); + + return "$coordinate:$lastColumnString$lastRow"; + } + /** * Write Cell. *