diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php
index 6028a9d72..7a2137dc0 100644
--- a/src/PhpSpreadsheet/Calculation/Calculation.php
+++ b/src/PhpSpreadsheet/Calculation/Calculation.php
@@ -3489,6 +3489,7 @@ class Calculation
$testSheet->getCell($cellAddress['cell']);
}
}
+ self::$returnArrayAsType = $returnArrayAsType;
throw new Exception($e->getMessage(), $e->getCode(), $e);
}
diff --git a/src/PhpSpreadsheet/Cell/Cell.php b/src/PhpSpreadsheet/Cell/Cell.php
index 987e1a361..543574e84 100644
--- a/src/PhpSpreadsheet/Cell/Cell.php
+++ b/src/PhpSpreadsheet/Cell/Cell.php
@@ -356,7 +356,7 @@ class Cell implements Stringable
$this->getWorksheet()->setSelectedCells($selected);
$this->getWorksheet()->getParentOrThrow()->setActiveSheetIndex($index);
// We don't yet handle array returns
- if (is_array($result)) {
+ if (is_array($result) && Calculation::getArrayReturnType() !== Calculation::RETURN_ARRAY_AS_ARRAY) {
while (is_array($result)) {
$result = array_shift($result);
}
diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
index a14ff2812..301d988ab 100644
--- a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
+++ b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
@@ -1402,10 +1402,24 @@ class Worksheet extends WriterPart
}
$attributes = $cell->getFormulaAttributes();
+ $ref = $cell->getCoordinate();
+ if (is_array($calculatedValue)) {
+ $attributes['t'] = 'array';
+ $rows = max(1, count($calculatedValue));
+ $cols = 1;
+ foreach ($calculatedValue as $row) {
+ $cols = max($cols, is_array($row) ? count($row) : 1);
+ }
+ $firstCellArray = Coordinate::indexesFromString($ref);
+ $lastRow = $firstCellArray[1] + $rows - 1;
+ $lastColumn = $firstCellArray[0] + $cols - 1;
+ $lastColumnString = Coordinate::stringFromColumnIndex($lastColumn);
+ $ref .= ":$lastColumnString$lastRow";
+ }
if (($attributes['t'] ?? null) === 'array') {
$objWriter->startElement('f');
$objWriter->writeAttribute('t', 'array');
- $objWriter->writeAttribute('ref', $cell->getCoordinate());
+ $objWriter->writeAttribute('ref', $ref);
$objWriter->writeAttribute('aca', '1');
$objWriter->writeAttribute('ca', '1');
$objWriter->text(FunctionPrefix::addFunctionPrefixStripEquals($cellValue));
diff --git a/tests/PhpSpreadsheetTests/Worksheet/Table/Issue3659Test.php b/tests/PhpSpreadsheetTests/Worksheet/Table/Issue3659Test.php
index 3ec7c6bd5..ff1108fe8 100644
--- a/tests/PhpSpreadsheetTests/Worksheet/Table/Issue3659Test.php
+++ b/tests/PhpSpreadsheetTests/Worksheet/Table/Issue3659Test.php
@@ -4,10 +4,24 @@ declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Worksheet\Table;
+use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
class Issue3659Test extends SetupTeardown
{
+ private string $arrayReturnType;
+
+ protected function setUp(): void
+ {
+ $this->arrayReturnType = Calculation::getArrayReturnType();
+ }
+
+ protected function tearDown(): void
+ {
+ parent::tearDown();
+ Calculation::setArrayReturnType($this->arrayReturnType);
+ }
+
public function testTableOnOtherSheet(): void
{
$spreadsheet = $this->getSpreadsheet();
@@ -44,4 +58,51 @@ class Issue3659Test extends SetupTeardown
self::assertSame('F8', $tableSheet->getSelectedCells());
self::assertSame($sheet, $spreadsheet->getActiveSheet());
}
+
+ public function testTableAsArray(): void
+ {
+ Calculation::setArrayReturnType(Calculation::RETURN_ARRAY_AS_ARRAY);
+ $spreadsheet = $this->getSpreadsheet();
+ $sheet = $this->getSheet();
+ $sheet->setTitle('Feuil1');
+ $tableSheet = $spreadsheet->createSheet();
+ $tableSheet->setTitle('sheet_with_table');
+ $tableSheet->fromArray(
+ [
+ ['MyCol', 'Colonne2', 'Colonne3'],
+ [10, 20],
+ [2],
+ [3],
+ [4],
+ ],
+ null,
+ 'B1',
+ true
+ );
+ $table = new Table('B1:D5', 'Tableau1');
+ $tableSheet->addTable($table);
+ $sheet->setSelectedCells('F7');
+ $tableSheet->setSelectedCells('F8');
+ self::assertSame($sheet, $spreadsheet->getActiveSheet());
+ $sheet->getCell('F1')->setValue('=Tableau1[MyCol]');
+ $sheet->getCell('H1')->setValue('=Tableau1[]');
+ $sheet->getCell('F9')->setValue('=Tableau1');
+ $sheet->getCell('J9')->setValue('=CONCAT(Tableau1)');
+ $sheet->getCell('J11')->setValue('=SUM(Tableau1[])');
+ $expectedResult = [2 => ['B' => 10], ['B' => 2], ['B' => 3], ['B' => 4]];
+ self::assertSame($expectedResult, $sheet->getCell('F1')->getCalculatedValue());
+ $expectedResult = [
+ 2 => ['B' => 10, 'C' => 20, 'D' => null],
+ ['B' => 2, 'C' => null, 'D' => null],
+ ['B' => 3, 'C' => null, 'D' => null],
+ ['B' => 4, 'C' => null, 'D' => null],
+ ];
+ self::assertSame($expectedResult, $sheet->getCell('H1')->getCalculatedValue());
+ self::assertSame($expectedResult, $sheet->getCell('F9')->getCalculatedValue());
+ self::assertSame('1020234', $sheet->getCell('J9')->getCalculatedValue(), 'Header row not included');
+ self::assertSame(39, $sheet->getCell('J11')->getCalculatedValue(), 'Header row not included');
+ self::assertSame('F7', $sheet->getSelectedCells());
+ self::assertSame('F8', $tableSheet->getSelectedCells());
+ self::assertSame($sheet, $spreadsheet->getActiveSheet());
+ }
}
diff --git a/tests/PhpSpreadsheetTests/Writer/Xlsx/ArrayFunctionsTest.php b/tests/PhpSpreadsheetTests/Writer/Xlsx/ArrayFunctionsTest.php
new file mode 100644
index 000000000..39cc72ff7
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Writer/Xlsx/ArrayFunctionsTest.php
@@ -0,0 +1,127 @@
+arrayReturnType = Calculation::getArrayReturnType();
+ }
+
+ protected function tearDown(): void
+ {
+ Calculation::setArrayReturnType($this->arrayReturnType);
+ if ($this->outputFile !== '') {
+ unlink($this->outputFile);
+ $this->outputFile = '';
+ }
+ }
+
+ public function testArrayOutput(): void
+ {
+ Calculation::setArrayReturnType(Calculation::RETURN_ARRAY_AS_ARRAY);
+ $spreadsheet = new Spreadsheet();
+ $sheet = $spreadsheet->getActiveSheet();
+ $columnArray = [
+ [41],
+ [57],
+ [51],
+ [54],
+ [49],
+ [43],
+ [35],
+ [35],
+ [44],
+ [47],
+ [48],
+ [26],
+ [57],
+ [34],
+ [61],
+ [34],
+ [28],
+ [29],
+ [41],
+ ];
+ $sheet->fromArray($columnArray, 'A1');
+ $sheet->setCellValue('C1', '=UNIQUE(A1:A19)');
+ $sheet->setCellValue('D1', '=SORT(A1:A19)');
+ $writer = new XlsxWriter($spreadsheet);
+ $this->outputFile = File::temporaryFilename();
+ $writer->save($this->outputFile);
+ $spreadsheet->disconnectWorksheets();
+
+ $reader = new XlsxReader();
+ $spreadsheet2 = $reader->load($this->outputFile);
+ $sheet2 = $spreadsheet2->getActiveSheet();
+ $expectedUnique = [
+ ['41'],
+ ['57'],
+ ['51'],
+ ['54'],
+ ['49'],
+ ['43'],
+ ['35'],
+ ['44'],
+ ['47'],
+ ['48'],
+ ['26'],
+ ['34'],
+ ['61'],
+ ['28'],
+ ['29'],
+ ];
+ self::assertCount(15, $expectedUnique);
+ self::assertSame($expectedUnique, $sheet2->getCell('C1')->getCalculatedValue());
+ $expectedSort = [
+ [26],
+ [28],
+ [29],
+ [34],
+ [34],
+ [35],
+ [35],
+ [41],
+ [41],
+ [43],
+ [44],
+ [47],
+ [48],
+ [49],
+ [51],
+ [54],
+ [57],
+ [57],
+ [61],
+ ];
+ self::assertCount(19, $expectedSort);
+ self::assertCount(19, $columnArray);
+ self::assertSame($expectedSort, $sheet2->getCell('D1')->getCalculatedValue());
+ $spreadsheet2->disconnectWorksheets();
+
+ $file = 'zip://';
+ $file .= $this->outputFile;
+ $file .= '#xl/worksheets/sheet1.xml';
+ $data = file_get_contents($file);
+ if ($data === false) {
+ self::fail('Unable to read file');
+ } else {
+ self::assertStringContainsString('_xlfn.UNIQUE(A1:A19)', $data, '15 results for UNIQUE');
+ self::assertStringContainsString('_xlfn._xlws.SORT(A1:A19)', $data, '19 results for SORT');
+ }
+ }
+}