Skip to content

Commit 050a42d

Browse files
authored
Xlsx Reader External Data Validations Flag Missing (#3078)
* Xlsx Reader External Data Validations Flag Missing Fix #2677. This PR supersedes #2679, written by @technghiath, which lacks tests, and probably doesn't solve the problem entirely. The code causing the problem appears to be the last remnant in Xlsx Reader which calls `children` using a namespace prefix rather than a namespace. That is changed, and tests are added where the tag is unexpectedly missing, and also where it uses a non-standard namespace prefix. * Scrutinizer Reports 1 "new" error. It isn't, but fix it anyhow. * Fix One Existing Scrutinizer Problem Only remaining problem in Reader/Xlsx.
1 parent a193f36 commit 050a42d

File tree

6 files changed

+71
-43
lines changed

6 files changed

+71
-43
lines changed

src/PhpSpreadsheet/Reader/Xlsx.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
469469
$rels = $this->loadZip(self::INITIAL_FILE, Namespaces::RELATIONSHIPS);
470470

471471
$propertyReader = new PropertyReader($this->securityScanner, $excel->getProperties());
472+
$chartDetails = [];
472473
foreach ($rels->Relationship as $relx) {
473474
$rel = self::getAttributes($relx);
474475
$relTarget = (string) $rel['Target'];
@@ -929,13 +930,16 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
929930
$xmlSheet->addChild('dataValidations');
930931
}
931932

932-
foreach ($xmlSheet->extLst->ext->children('x14', true)->dataValidations->dataValidation as $item) {
933+
foreach ($xmlSheet->extLst->ext->children(Namespaces::DATA_VALIDATIONS1)->dataValidations->dataValidation as $item) {
934+
$item = self::testSimpleXml($item);
933935
$node = self::testSimpleXml($xmlSheet->dataValidations)->addChild('dataValidation');
934936
foreach ($item->attributes() ?? [] as $attr) {
935937
$node->addAttribute($attr->getName(), $attr);
936938
}
937-
$node->addAttribute('sqref', $item->children('xm', true)->sqref);
938-
$node->addChild('formula1', $item->formula1->children('xm', true)->f);
939+
$node->addAttribute('sqref', $item->children(Namespaces::DATA_VALIDATIONS2)->sqref);
940+
if (isset($item->formula1)) {
941+
$node->addChild('formula1', $item->formula1->children(Namespaces::DATA_VALIDATIONS2)->f);
942+
}
939943
}
940944
}
941945

@@ -1278,15 +1282,14 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
12781282

12791283
if ($xmlDrawingChildren->oneCellAnchor) {
12801284
foreach ($xmlDrawingChildren->oneCellAnchor as $oneCellAnchor) {
1285+
$oneCellAnchor = self::testSimpleXml($oneCellAnchor);
12811286
if ($oneCellAnchor->pic->blipFill) {
12821287
/** @var SimpleXMLElement $blip */
12831288
$blip = $oneCellAnchor->pic->blipFill->children(Namespaces::DRAWINGML)->blip;
12841289
/** @var SimpleXMLElement $xfrm */
12851290
$xfrm = $oneCellAnchor->pic->spPr->children(Namespaces::DRAWINGML)->xfrm;
12861291
/** @var SimpleXMLElement $outerShdw */
12871292
$outerShdw = $oneCellAnchor->pic->spPr->children(Namespaces::DRAWINGML)->effectLst->outerShdw;
1288-
/** @var SimpleXMLElement $hlinkClick */
1289-
$hlinkClick = $oneCellAnchor->pic->nvPicPr->cNvPr->children(Namespaces::DRAWINGML)->hlinkClick;
12901293

12911294
$objDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
12921295
$objDrawing->setName((string) self::getArrayItem(self::getAttributes($oneCellAnchor->pic->nvPicPr->cNvPr), 'name'));
@@ -1363,11 +1366,11 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
13631366
}
13641367
if ($xmlDrawingChildren->twoCellAnchor) {
13651368
foreach ($xmlDrawingChildren->twoCellAnchor as $twoCellAnchor) {
1369+
$twoCellAnchor = self::testSimpleXml($twoCellAnchor);
13661370
if ($twoCellAnchor->pic->blipFill) {
13671371
$blip = $twoCellAnchor->pic->blipFill->children(Namespaces::DRAWINGML)->blip;
13681372
$xfrm = $twoCellAnchor->pic->spPr->children(Namespaces::DRAWINGML)->xfrm;
13691373
$outerShdw = $twoCellAnchor->pic->spPr->children(Namespaces::DRAWINGML)->effectLst->outerShdw;
1370-
$hlinkClick = $twoCellAnchor->pic->nvPicPr->cNvPr->children(Namespaces::DRAWINGML)->hlinkClick;
13711374
$objDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
13721375
/** @scrutinizer ignore-call */
13731376
$editAs = $twoCellAnchor->attributes();

src/PhpSpreadsheet/Reader/Xlsx/Namespaces.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ class Namespaces
5858

5959
const VBA = 'http://schemas.microsoft.com/office/2006/relationships/vbaProject';
6060

61+
const DATA_VALIDATIONS1 = 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/main';
62+
63+
const DATA_VALIDATIONS2 = 'http://schemas.microsoft.com/office/excel/2006/main';
64+
6165
const DC_ELEMENTS = 'http://purl.org/dc/elements/1.1/';
6266

6367
const DC_TERMS = 'http://purl.org/dc/terms';
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
4+
5+
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
6+
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
7+
use PHPUnit\Framework\TestCase;
8+
9+
class DataValidationTest extends TestCase
10+
{
11+
public function testLoadXlsxDataValidation(): void
12+
{
13+
$filename = 'tests/data/Reader/XLSX/dataValidationTest.xlsx';
14+
$reader = new Xlsx();
15+
$spreadsheet = $reader->load($filename);
16+
17+
$worksheet = $spreadsheet->getActiveSheet();
18+
19+
self::assertTrue($worksheet->getCell('B3')->hasDataValidation());
20+
$spreadsheet->disconnectWorksheets();
21+
}
22+
23+
/**
24+
* Test for load drop down lists of another sheet.
25+
* Pull #2150, issue #2149. Also issue #2677.
26+
*
27+
* @dataProvider providerExternalSheet
28+
*/
29+
public function testDataValidationOfAnotherSheet(string $expectedB14, string $filename): void
30+
{
31+
$reader = new Xlsx();
32+
$spreadsheet = $reader->load($filename);
33+
34+
$worksheet = $spreadsheet->getActiveSheet();
35+
36+
// same sheet
37+
$validationCell = $worksheet->getCell('B5');
38+
self::assertTrue($validationCell->hasDataValidation());
39+
self::assertSame(DataValidation::TYPE_LIST, $validationCell->getDataValidation()->getType());
40+
self::assertSame('$A$5:$A$7', $validationCell->getDataValidation()->getFormula1());
41+
42+
// another sheet
43+
$validationCell = $worksheet->getCell('B14');
44+
self::assertTrue($validationCell->hasDataValidation());
45+
self::assertSame(DataValidation::TYPE_LIST, $validationCell->getDataValidation()->getType());
46+
self::assertSame($expectedB14, $validationCell->getDataValidation()->getFormula1());
47+
$spreadsheet->disconnectWorksheets();
48+
}
49+
50+
public function providerExternalSheet(): array
51+
{
52+
return [
53+
'standard spreadsheet' => ['Feuil2!$A$3:$A$5', 'tests/data/Reader/XLSX/dataValidation2Test.xlsx'],
54+
'alternate namespace prefix' => ['Feuil2!$A$3:$A$5', 'tests/data/Reader/XLSX/issue.2677.namespace.xlsx'],
55+
'missing formula' => ['', 'tests/data/Reader/XLSX/issue.2677.removeformula1.xlsx'],
56+
];
57+
}
58+
}

tests/PhpSpreadsheetTests/Reader/Xlsx/XlsxTest.php

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

55
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
6-
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
76
use PhpOffice\PhpSpreadsheet\IOFactory;
87
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
98
use PhpOffice\PhpSpreadsheet\Shared\File;
@@ -163,42 +162,6 @@ public function testLoadXlsxConditionalFormatting(): void
163162
self::assertInstanceOf(Style::class, $conditionalRule->getStyle());
164163
}
165164

166-
public function testLoadXlsxDataValidation(): void
167-
{
168-
$filename = 'tests/data/Reader/XLSX/dataValidationTest.xlsx';
169-
$reader = new Xlsx();
170-
$spreadsheet = $reader->load($filename);
171-
172-
$worksheet = $spreadsheet->getActiveSheet();
173-
174-
self::assertTrue($worksheet->getCell('B3')->hasDataValidation());
175-
}
176-
177-
/*
178-
* Test for load drop down lists of another sheet.
179-
* Pull #2150, issue #2149
180-
*/
181-
public function testLoadXlsxDataValidationOfAnotherSheet(): void
182-
{
183-
$filename = 'tests/data/Reader/XLSX/dataValidation2Test.xlsx';
184-
$reader = new Xlsx();
185-
$spreadsheet = $reader->load($filename);
186-
187-
$worksheet = $spreadsheet->getActiveSheet();
188-
189-
// same sheet
190-
$validationCell = $worksheet->getCell('B5');
191-
self::assertTrue($validationCell->hasDataValidation());
192-
self::assertSame(DataValidation::TYPE_LIST, $validationCell->getDataValidation()->getType());
193-
self::assertSame('$A$5:$A$7', $validationCell->getDataValidation()->getFormula1());
194-
195-
// another sheet
196-
$validationCell = $worksheet->getCell('B14');
197-
self::assertTrue($validationCell->hasDataValidation());
198-
self::assertSame(DataValidation::TYPE_LIST, $validationCell->getDataValidation()->getType());
199-
self::assertSame('Feuil2!$A$3:$A$5', $validationCell->getDataValidation()->getFormula1());
200-
}
201-
202165
/**
203166
* Test load Xlsx file without cell reference.
204167
*
10.7 KB
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)