diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index c8b2de2a9..2daa2dc07 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -891,9 +891,16 @@ class Xlsx extends BaseReader } else { // Formula $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToString'); - if (isset($c->f['t'])) { - $attributes = $c->f['t']; - $docSheet->getCell($r)->setFormulaAttributes(['t' => (string) $attributes]); + $formulaAttributes = []; + $attributes = $c->f->attributes(); + if (isset($attributes['t'])) { + $formulaAttributes['t'] = (string) $attributes['t']; + } + if (isset($attributes['ref'])) { + $formulaAttributes['ref'] = (string) $attributes['ref']; + } + if (!empty($formulaAttributes)) { + $docSheet->getCell($r)->setFormulaAttributes($formulaAttributes); } } diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php index 301d988ab..1b149c833 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php @@ -1401,8 +1401,8 @@ class Worksheet extends WriterPart $calculatedValue = (int) $calculatedValue; } - $attributes = $cell->getFormulaAttributes(); - $ref = $cell->getCoordinate(); + $attributes = $cell->getFormulaAttributes() ?? []; + $ref = array_key_exists('ref', $attributes) ? $attributes['ref'] : $cell->getCoordinate(); if (is_array($calculatedValue)) { $attributes['t'] = 'array'; $rows = max(1, count($calculatedValue)); @@ -1424,6 +1424,17 @@ class Worksheet extends WriterPart $objWriter->writeAttribute('ca', '1'); $objWriter->text(FunctionPrefix::addFunctionPrefixStripEquals($cellValue)); $objWriter->endElement(); + $result = $calculatedValue; + while (is_array($result)) { + $result = array_shift($result); + } + if ( + is_scalar($result) + && $this->getParentWriter()->getOffice2003Compatibility() === false + && $this->getParentWriter()->getPreCalculateFormulas() + ) { + $objWriter->writeElement('v', (string) $result); + } } else { $objWriter->writeElement('f', FunctionPrefix::addFunctionPrefixStripEquals($cellValue)); self::writeElementIf( diff --git a/tests/PhpSpreadsheetTests/Writer/Xlsx/ArrayFunctionsTest.php b/tests/PhpSpreadsheetTests/Writer/Xlsx/ArrayFunctionsTest.php index 39cc72ff7..fc26beb54 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xlsx/ArrayFunctionsTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xlsx/ArrayFunctionsTest.php @@ -120,8 +120,44 @@ class ArrayFunctionsTest extends TestCase 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'); + self::assertStringContainsString('_xlfn.UNIQUE(A1:A19)41', $data, '15 results for UNIQUE'); + self::assertStringContainsString('_xlfn._xlws.SORT(A1:A19)26', $data, '19 results for SORT'); + } + } + + public function testUnimplementedArrayOutput(): void + { + //Calculation::setArrayReturnType(Calculation::RETURN_ARRAY_AS_ARRAY); // not required for this test + $reader = new XlsxReader(); + $spreadsheet = $reader->load('tests/data/Reader/XLSX/atsign.choosecols.xlsx'); + $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(); + self::assertSame('=_xlfn.CHOOSECOLS(A1:C5,3,1)', $sheet2->getCell('F1')->getValue()); + $expectedFG = [ + ['11', '1'], + ['12', '2'], + ['13', '3'], + ['14', '4'], + ['15', '5'], + ]; + $actualFG = $sheet2->rangeToArray('F1:G5'); + self::assertSame($expectedFG, $actualFG); + $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.CHOOSECOLS(A1:C5,3,1)11', $data); } } } diff --git a/tests/data/Reader/XLSX/atsign.choosecols.xlsx b/tests/data/Reader/XLSX/atsign.choosecols.xlsx new file mode 100644 index 000000000..45ea6ca2a Binary files /dev/null and b/tests/data/Reader/XLSX/atsign.choosecols.xlsx differ