Skip to content

Commit 363705c

Browse files
authored
Merge pull request #4203 from oleibman/issue4197
Allow ANCHORARRAY as Valid DataValidation List
2 parents c28abd8 + 67dad06 commit 363705c

File tree

6 files changed

+102
-12
lines changed

6 files changed

+102
-12
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ and this project adheres to [Semantic Versioning](https://semver.org).
1919

2020
### Deprecated
2121

22-
- IREADER::SKIP_EMPTY_CELLS - use its alias IGNORE_EMPTY_CELLS instead.
22+
- IReader::SKIP_EMPTY_CELLS - use its alias IGNORE_EMPTY_CELLS instead.
23+
- Worksheet::getProtectedCells was deprecated in release 2, but was not properly documented, and not removed in release 3. Use getProtectedCellRanges instead.
24+
- Writer/Html::isMpdf property was deprecated in release 2, but was not properly documented, and not removed in release 3. Use instanceof Mpdf instead.
2325

2426
### Moved
2527

@@ -35,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
3537
- Option to Write Hyperlink Rather Than Label to Csv. [Issue #1412](https://github.com/PHPOffice/PhpSpreadsheet/issues/1412) [PR #4151](https://github.com/PHPOffice/PhpSpreadsheet/pull/4151)
3638
- Invalid Html Due to Cached Filesize. [Issue #1107](https://github.com/PHPOffice/PhpSpreadsheet/issues/1107) [PR #4184](https://github.com/PHPOffice/PhpSpreadsheet/pull/4184)
3739
- Excel 2003 Allows Html Entities. [Issue #2157](https://github.com/PHPOffice/PhpSpreadsheet/issues/2157) [PR #4187](https://github.com/PHPOffice/PhpSpreadsheet/pull/4187)
40+
- Allow ANCHORARRAY as Data Validation list. [Issue #4197](https://github.com/PHPOffice/PhpSpreadsheet/issues/4197) [PR #4203](https://github.com/PHPOffice/PhpSpreadsheet/pull/4203)
3841

3942
## 2024-09-29 - 3.3.0 (no 3.0.\*, 3.1.\*, 3.2.\*)
4043

src/PhpSpreadsheet/Reader/Xlsx.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,15 +304,19 @@ private static function castToString(?SimpleXMLElement $c): ?string
304304
return isset($c, $c->v) ? (string) $c->v : null;
305305
}
306306

307+
public static function replacePrefixes(string $formula): string
308+
{
309+
return str_replace(['_xlfn.', '_xlws.'], '', $formula);
310+
}
311+
307312
private function castToFormula(?SimpleXMLElement $c, string $r, string &$cellDataType, mixed &$value, mixed &$calculatedValue, string $castBaseType, bool $updateSharedCells = true): void
308313
{
309314
if ($c === null) {
310315
return;
311316
}
312317
$attr = $c->f->attributes();
313318
$cellDataType = DataType::TYPE_FORMULA;
314-
$formula = (string) $c->f;
315-
$formula = str_replace(['_xlfn.', '_xlws.'], '', $formula);
319+
$formula = self::replacePrefixes((string) $c->f);
316320
$value = "=$formula";
317321
$calculatedValue = self::$castBaseType($c);
318322

src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
44

55
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
6+
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
67
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
78
use SimpleXMLElement;
89

@@ -55,8 +56,8 @@ public function load(): void
5556
$docValidation->setError((string) $dataValidation['error']);
5657
$docValidation->setPromptTitle((string) $dataValidation['promptTitle']);
5758
$docValidation->setPrompt((string) $dataValidation['prompt']);
58-
$docValidation->setFormula1((string) $dataValidation->formula1);
59-
$docValidation->setFormula2((string) $dataValidation->formula2);
59+
$docValidation->setFormula1(Xlsx::replacePrefixes((string) $dataValidation->formula1));
60+
$docValidation->setFormula2(Xlsx::replacePrefixes((string) $dataValidation->formula2));
6061
$docValidation->setSqref($range);
6162
}
6263
}

src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -983,10 +983,10 @@ private function writeDataValidations(XMLWriter $objWriter, PhpspreadsheetWorksh
983983
$objWriter->writeAttribute('sqref', $dv->getSqref() ?? $coordinate);
984984

985985
if ($dv->getFormula1() !== '') {
986-
$objWriter->writeElement('formula1', $dv->getFormula1());
986+
$objWriter->writeElement('formula1', FunctionPrefix::addFunctionPrefix($dv->getFormula1()));
987987
}
988988
if ($dv->getFormula2() !== '') {
989-
$objWriter->writeElement('formula2', $dv->getFormula2());
989+
$objWriter->writeElement('formula2', FunctionPrefix::addFunctionPrefix($dv->getFormula2()));
990990
}
991991

992992
$objWriter->endElement();

tests/PhpSpreadsheetTests/Writer/Xlsx/ArrayFormulaPrefixTest.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@
1111

1212
class ArrayFormulaPrefixTest extends AbstractFunctional
1313
{
14-
protected function setUp(): void
15-
{
16-
parent::setUp();
17-
}
18-
1914
/**
2015
* Test to ensure that xlfn prefix is being added to functions
2116
* included in an array formula, if appropriate.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
6+
7+
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
8+
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
9+
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
10+
use PhpOffice\PhpSpreadsheet\Shared\File;
11+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
12+
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
13+
use PHPUnit\Framework\TestCase;
14+
15+
class ArrayFormulaValidationTest extends TestCase
16+
{
17+
private string $outputFile = '';
18+
19+
protected function tearDown(): void
20+
{
21+
if ($this->outputFile !== '') {
22+
unlink($this->outputFile);
23+
$this->outputFile = '';
24+
}
25+
}
26+
27+
/**
28+
* @dataProvider validationProvider
29+
*/
30+
public function testWriteArrayFormulaValidation(string $formula): void
31+
{
32+
$spreadsheet = new Spreadsheet();
33+
Calculation::getInstance($spreadsheet)
34+
->setInstanceArrayReturnType(
35+
Calculation::RETURN_ARRAY_AS_ARRAY
36+
);
37+
$sheet = $spreadsheet->getActiveSheet();
38+
$sheet->setCellValue('C1', 1);
39+
$sheet->setCellValue('C2', 2);
40+
$sheet->setCellValue('C3', 3);
41+
$sheet->setCellValue('C4', 3);
42+
$sheet->setCellValue('C5', 5);
43+
$sheet->setCellValue('C6', 6);
44+
$sheet->setCellValue('B1', '=UNIQUE(C1:C6)');
45+
46+
$validation = $sheet->getCell('A1')->getDataValidation();
47+
$validation->setType(DataValidation::TYPE_LIST);
48+
$validation->setErrorStyle(DataValidation::STYLE_STOP);
49+
$validation->setAllowBlank(true);
50+
$validation->setShowDropDown(true);
51+
$validation->setShowErrorMessage(true);
52+
$validation->setError('Invalid input');
53+
$validation->setFormula1($formula);
54+
$sheet->getCell('A1')->setDataValidation($validation);
55+
56+
$this->outputFile = File::temporaryFilename();
57+
$writer = new XlsxWriter($spreadsheet);
58+
$writer->save($this->outputFile);
59+
$spreadsheet->disconnectWorksheets();
60+
61+
$reader = new XlsxReader();
62+
$spreadsheet2 = $reader->load($this->outputFile);
63+
Calculation::getInstance($spreadsheet2)->setInstanceArrayReturnType(Calculation::RETURN_ARRAY_AS_ARRAY);
64+
$sheet2 = $spreadsheet2->getActiveSheet();
65+
$validation2 = $sheet2->getCell('A1')->getDataValidation();
66+
self::assertSame('ANCHORARRAY($B$1)', $validation2->getFormula1());
67+
$spreadsheet2->disconnectWorksheets();
68+
69+
$file = 'zip://';
70+
$file .= $this->outputFile;
71+
$file .= '#xl/worksheets/sheet1.xml';
72+
$data = file_get_contents($file);
73+
if ($data === false) {
74+
self::fail('Unable to read file');
75+
} else {
76+
self::assertStringContainsString('<formula1>_xlfn.ANCHORARRAY($B$1)</formula1>', $data);
77+
}
78+
}
79+
80+
public static function validationProvider(): array
81+
{
82+
return [
83+
['ANCHORARRAY($B$1)'],
84+
['$B$1#'],
85+
];
86+
}
87+
}

0 commit comments

Comments
 (0)