mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-08-31 12:40:00 +00:00
Allow Multiple Ranges
This commit is contained in:
@@ -37,26 +37,23 @@ class DataValidations
|
||||
foreach ($this->worksheetXml->dataValidations->dataValidation as $dataValidation) {
|
||||
// Uppercase coordinate
|
||||
$range = strtoupper((string) $dataValidation['sqref']);
|
||||
$rangeSet = explode(' ', $range);
|
||||
foreach ($rangeSet as $range) {
|
||||
$docValidation = new DataValidation();
|
||||
$docValidation->setType((string) $dataValidation['type']);
|
||||
$docValidation->setErrorStyle((string) $dataValidation['errorStyle']);
|
||||
$docValidation->setOperator((string) $dataValidation['operator']);
|
||||
$docValidation->setAllowBlank(filter_var($dataValidation['allowBlank'], FILTER_VALIDATE_BOOLEAN));
|
||||
// showDropDown is inverted (works as hideDropDown if true)
|
||||
$docValidation->setShowDropDown(!filter_var($dataValidation['showDropDown'], FILTER_VALIDATE_BOOLEAN));
|
||||
$docValidation->setShowInputMessage(filter_var($dataValidation['showInputMessage'], FILTER_VALIDATE_BOOLEAN));
|
||||
$docValidation->setShowErrorMessage(filter_var($dataValidation['showErrorMessage'], FILTER_VALIDATE_BOOLEAN));
|
||||
$docValidation->setErrorTitle((string) $dataValidation['errorTitle']);
|
||||
$docValidation->setError((string) $dataValidation['error']);
|
||||
$docValidation->setPromptTitle((string) $dataValidation['promptTitle']);
|
||||
$docValidation->setPrompt((string) $dataValidation['prompt']);
|
||||
$docValidation->setFormula1(Xlsx::replacePrefixes((string) $dataValidation->formula1));
|
||||
$docValidation->setFormula2(Xlsx::replacePrefixes((string) $dataValidation->formula2));
|
||||
$docValidation->setSqref($range);
|
||||
$this->worksheet->setDataValidation($range, $docValidation);
|
||||
}
|
||||
$docValidation = new DataValidation();
|
||||
$docValidation->setType((string) $dataValidation['type']);
|
||||
$docValidation->setErrorStyle((string) $dataValidation['errorStyle']);
|
||||
$docValidation->setOperator((string) $dataValidation['operator']);
|
||||
$docValidation->setAllowBlank(filter_var($dataValidation['allowBlank'], FILTER_VALIDATE_BOOLEAN));
|
||||
// showDropDown is inverted (works as hideDropDown if true)
|
||||
$docValidation->setShowDropDown(!filter_var($dataValidation['showDropDown'], FILTER_VALIDATE_BOOLEAN));
|
||||
$docValidation->setShowInputMessage(filter_var($dataValidation['showInputMessage'], FILTER_VALIDATE_BOOLEAN));
|
||||
$docValidation->setShowErrorMessage(filter_var($dataValidation['showErrorMessage'], FILTER_VALIDATE_BOOLEAN));
|
||||
$docValidation->setErrorTitle((string) $dataValidation['errorTitle']);
|
||||
$docValidation->setError((string) $dataValidation['error']);
|
||||
$docValidation->setPromptTitle((string) $dataValidation['promptTitle']);
|
||||
$docValidation->setPrompt((string) $dataValidation['prompt']);
|
||||
$docValidation->setFormula1(Xlsx::replacePrefixes((string) $dataValidation->formula1));
|
||||
$docValidation->setFormula2(Xlsx::replacePrefixes((string) $dataValidation->formula2));
|
||||
$docValidation->setSqref($range);
|
||||
$this->worksheet->setDataValidation($range, $docValidation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +282,13 @@ class ReferenceHelper
|
||||
)
|
||||
);
|
||||
}
|
||||
$newReference = $this->updateCellReference($cellAddress);
|
||||
$addressParts = explode(' ', $cellAddress);
|
||||
$newReference = '';
|
||||
$separator = '';
|
||||
foreach ($addressParts as $addressPart) {
|
||||
$newReference .= $separator . $this->updateCellReference($addressPart);
|
||||
$separator = ' ';
|
||||
}
|
||||
if ($cellAddress !== $newReference) {
|
||||
$dataValidation->setSqref($newReference);
|
||||
$worksheet->setDataValidation($newReference, $dataValidation);
|
||||
|
||||
@@ -296,6 +296,7 @@ class Worksheet
|
||||
|
||||
/**
|
||||
* Data validation objects. Indexed by cell coordinate, e.g. 'A1'.
|
||||
* Index can include ranges, and multiple cells/ranges.
|
||||
*/
|
||||
private array $dataValidationCollection = [];
|
||||
|
||||
@@ -3261,23 +3262,30 @@ class Worksheet
|
||||
*/
|
||||
public function getDataValidation(string $cellCoordinate): DataValidation
|
||||
{
|
||||
// return data validation if we already have one
|
||||
if (isset($this->dataValidationCollection[$cellCoordinate])) {
|
||||
return $this->dataValidationCollection[$cellCoordinate];
|
||||
}
|
||||
foreach ($this->dataValidationCollection as $dataValidation) {
|
||||
$sqref = $dataValidation->getSqref() ?? '';
|
||||
if (str_contains($sqref, ':')) {
|
||||
if (Coordinate::coordinateIsInsideRange($sqref, $cellCoordinate)) {
|
||||
|
||||
foreach ($this->dataValidationCollection as $key => $dataValidation) {
|
||||
$keyParts = explode(' ', $key);
|
||||
foreach ($keyParts as $keyPart) {
|
||||
if ($keyPart === $cellCoordinate) {
|
||||
return $dataValidation;
|
||||
}
|
||||
if (str_contains($keyPart, ':')) {
|
||||
if (Coordinate::coordinateIsInsideRange($keyPart, $cellCoordinate)) {
|
||||
return $dataValidation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// else create data validation
|
||||
$this->dataValidationCollection[$cellCoordinate] = new DataValidation();
|
||||
$dataValidation = new DataValidation();
|
||||
$dataValidation->setSqref($cellCoordinate);
|
||||
$this->dataValidationCollection[$cellCoordinate] = $dataValidation;
|
||||
|
||||
return $this->dataValidationCollection[$cellCoordinate];
|
||||
return $dataValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3308,12 +3316,17 @@ class Worksheet
|
||||
if (isset($this->dataValidationCollection[$coordinate])) {
|
||||
return true;
|
||||
}
|
||||
foreach ($this->dataValidationCollection as $dataValidation) {
|
||||
$sqref = $dataValidation->getSqref() ?? '';
|
||||
if (str_contains($sqref, ':')) {
|
||||
if (Coordinate::coordinateIsInsideRange($sqref, $coordinate)) {
|
||||
foreach ($this->dataValidationCollection as $key => $dataValidation) {
|
||||
$keyParts = explode(' ', $key);
|
||||
foreach ($keyParts as $keyPart) {
|
||||
if ($keyPart === $coordinate) {
|
||||
return true;
|
||||
}
|
||||
if (str_contains($keyPart, ':')) {
|
||||
if (Coordinate::coordinateIsInsideRange($keyPart, $coordinate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3327,7 +3340,17 @@ class Worksheet
|
||||
*/
|
||||
public function getDataValidationCollection(): array
|
||||
{
|
||||
return $this->dataValidationCollection;
|
||||
$collectionCells = [];
|
||||
$collectionRanges = [];
|
||||
foreach ($this->dataValidationCollection as $key => $dataValidation) {
|
||||
if (preg_match('/[: ]/', $key) === 1) {
|
||||
$collectionRanges[$key] = $dataValidation;
|
||||
} else {
|
||||
$collectionCells[$key] = $dataValidation;
|
||||
}
|
||||
}
|
||||
|
||||
return array_merge($collectionCells, $collectionRanges);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2605,7 +2605,14 @@ class Worksheet extends BIFFwriter
|
||||
private function writeDataValidity(): void
|
||||
{
|
||||
// Datavalidation collection
|
||||
$dataValidationCollection = $this->phpSheet->getDataValidationCollection();
|
||||
$dataValidationCollection1 = $this->phpSheet->getDataValidationCollection();
|
||||
$dataValidationCollection = [];
|
||||
foreach ($dataValidationCollection1 as $key => $dataValidation) {
|
||||
$keyParts = explode(' ', $key);
|
||||
foreach ($keyParts as $keyPart) {
|
||||
$dataValidationCollection[$keyPart] = $dataValidation;
|
||||
}
|
||||
}
|
||||
|
||||
// Write data validations?
|
||||
if (!empty($dataValidationCollection)) {
|
||||
|
||||
@@ -943,7 +943,6 @@ class Worksheet extends WriterPart
|
||||
|
||||
// Write data validations?
|
||||
if (!empty($dataValidationCollection)) {
|
||||
$dataValidationCollection = Coordinate::mergeRangesInCollection($dataValidationCollection);
|
||||
$objWriter->startElement('dataValidations');
|
||||
$objWriter->writeAttribute('count', (string) count($dataValidationCollection));
|
||||
|
||||
|
||||
@@ -130,4 +130,38 @@ class ReferenceHelperDVTest extends TestCase
|
||||
$validation->setPrompt('Please pick a value from the drop-down list.');
|
||||
$validation->setFormula1('$A$5:$A$8');
|
||||
}
|
||||
|
||||
public function testMultipleRanges(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->getCell('B1')->setValue(1);
|
||||
$sheet->getCell('B2')->setValue(2);
|
||||
$sheet->getCell('B3')->setValue(3);
|
||||
$dv = $sheet->getDataValidation('A1:A4 C5 D6:D7');
|
||||
$dv->setType(DataValidation::TYPE_LIST)
|
||||
->setShowDropDown(true)
|
||||
->setFormula1('$B$1:$B$3')
|
||||
->setErrorStyle(DataValidation::STYLE_STOP)
|
||||
->setShowErrorMessage(true)
|
||||
->setErrorTitle('Input Error')
|
||||
->setError('Value is not a member of allowed list');
|
||||
$sheet->insertNewColumnBefore('A');
|
||||
$dvs = $sheet->getDataValidationCollection();
|
||||
self::assertCount(1, $dvs);
|
||||
$expected = 'B1:B4 D5 E6:E7';
|
||||
self::assertSame([$expected], array_keys($dvs));
|
||||
$dv = $dvs[$expected];
|
||||
self::assertSame($expected, $dv->getSqref());
|
||||
self::assertSame('$C$1:$C$3', $dv->getFormula1());
|
||||
$sheet->getCell('B2')->setValue(3);
|
||||
self::assertTrue($sheet->getCell('B2')->hasValidValue());
|
||||
$sheet->getCell('D5')->setValue(7);
|
||||
self::assertFalse($sheet->getCell('D5')->hasValidValue());
|
||||
$sheet->getCell('E6')->setValue(7);
|
||||
self::assertFalse($sheet->getCell('E6')->hasValidValue());
|
||||
$sheet->getCell('E7')->setValue(1);
|
||||
self::assertTrue($sheet->getCell('E7')->hasValidValue());
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,14 +46,7 @@ class Issue2368Test extends AbstractFunctional
|
||||
$spreadsheet = $reader->load($filename);
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$validations = $sheet->getDataValidationCollection();
|
||||
/** @var string[] */
|
||||
$ranges = [];
|
||||
foreach ($validations as $validation) {
|
||||
$ranges[] = $validation->getSqref();
|
||||
}
|
||||
self::assertContains('A1:A5', $ranges);
|
||||
self::assertContains('A10:A14', $ranges);
|
||||
self::assertContains('A20:A24', $ranges);
|
||||
self::assertSame(['A1:A5 A10:A14 A20:A24'], array_keys($validations));
|
||||
self::assertSame('"yes,no"', $sheet->getCell('A3')->getDataValidation()->getFormula1());
|
||||
self::assertSame('"yes,no"', $sheet->getCell('A10')->getDataValidation()->getFormula1());
|
||||
self::assertSame('"yes,no"', $sheet->getCell('A24')->getDataValidation()->getFormula1());
|
||||
@@ -63,14 +56,7 @@ class Issue2368Test extends AbstractFunctional
|
||||
|
||||
$sheet2 = $reloadedSpreadsheet->getActiveSheet();
|
||||
$validation2 = $sheet2->getDataValidationCollection();
|
||||
/** @var string[] */
|
||||
$range2 = [];
|
||||
foreach ($validation2 as $validation) {
|
||||
$range2[] = $validation->getSqref();
|
||||
}
|
||||
self::assertContains('A1:A5', $range2);
|
||||
self::assertContains('A10:A14', $range2);
|
||||
self::assertContains('A20:A24', $range2);
|
||||
self::assertSame(['A1:A5 A10:A14 A20:A24'], array_keys($validation2));
|
||||
self::assertSame('"yes,no"', $sheet2->getCell('A3')->getDataValidation()->getFormula1());
|
||||
self::assertSame('"yes,no"', $sheet2->getCell('A10')->getDataValidation()->getFormula1());
|
||||
self::assertSame('"yes,no"', $sheet2->getCell('A24')->getDataValidation()->getFormula1());
|
||||
|
||||
Reference in New Issue
Block a user