Tweaks to Xml and Xls Readers

This commit is contained in:
oleibman
2024-12-30 20:11:36 -08:00
parent 38c4ce4836
commit bbc069e4b8
5 changed files with 46 additions and 26 deletions
@@ -2,9 +2,11 @@
namespace PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Cell\AddressRange;
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
use PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Writer\Xls\Worksheet as XlsWorksheet;
class DataValidationHelper extends Xls
{
@@ -175,8 +177,27 @@ class DataValidationHelper extends Xls
// offset: var; size: var; cell range address list with
$cellRangeAddressList = Biff8::readBIFF8CellRangeAddressList(substr($recordData, $offset));
$cellRangeAddresses = $cellRangeAddressList['cellRangeAddresses'];
$maxRow = (string) AddressRange::MAX_ROW;
$maxCol = AddressRange::MAX_COLUMN;
$maxXlsRow = (string) XlsWorksheet::MAX_XLS_ROW;
$maxXlsColumnString = (string) XlsWorksheet::MAX_XLS_COLUMN_STRING;
foreach ($cellRangeAddresses as $cellRange) {
$cellRange = preg_replace(
[
"/([a-z]+)1:([a-z]+)$maxXlsRow/i",
"/([a-z]+\\d+):([a-z]+)$maxXlsRow/i",
"/A(\\d+):$maxXlsColumnString(\\d+)/i",
"/([a-z]+\\d+):$maxXlsColumnString(\\d+)/i",
],
[
'$1:$2',
'$1:${2}' . $maxRow,
'$1:$2',
'$1:' . $maxCol . '$2',
],
$cellRange
) ?? $cellRange;
$objValidation = new DataValidation();
$objValidation->setType($type);
$objValidation->setErrorStyle($errorStyle);
@@ -3,7 +3,6 @@
namespace PhpOffice\PhpSpreadsheet\Reader\Xml;
use PhpOffice\PhpSpreadsheet\Cell\AddressHelper;
use PhpOffice\PhpSpreadsheet\Cell\AddressRange;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
@@ -84,27 +83,25 @@ class DataValidations
$this->thisColumn = (int) $selectionMatches[2];
$combinedCells .= "$separator$cell";
$separator = ' ';
} elseif (preg_match('/^C(\d+)$/', (string) $range, $selectionMatches) === 1) {
} elseif (preg_match('/^C(\d+)(:C(]\\d+))?$/', (string) $range, $selectionMatches) === 1) {
// column
$firstCell = Coordinate::stringFromColumnIndex((int) $selectionMatches[1])
. '1';
$cell = $firstCell
. ':'
. Coordinate::stringFromColumnIndex((int) $selectionMatches[1])
. ((string) AddressRange::MAX_ROW);
$this->thisColumn = (int) $selectionMatches[1];
$firstCol = $selectionMatches[1];
$firstColString = Coordinate::stringFromColumnIndex((int) $firstCol);
$lastCol = $selectionMatches[3] ?? $firstCol;
$lastColString = Coordinate::stringFromColumnIndex((int) $lastCol);
$firstCell = "{$firstColString}1";
$cell = "$firstColString:$lastColString";
$this->thisColumn = (int) $firstCol;
$sheet->getCell($firstCell);
$combinedCells .= "$separator$cell";
$separator = ' ';
} elseif (preg_match('/^R(\d+)$/', (string) $range, $selectionMatches)) {
} elseif (preg_match('/^R(\\d+)(:R(]\\d+))?$/', (string) $range, $selectionMatches)) {
// row
$firstCell = 'A'
. $selectionMatches[1];
$cell = $firstCell
. ':'
. AddressRange::MAX_COLUMN
. $selectionMatches[1];
$this->thisRow = (int) $selectionMatches[1];
$firstRow = $selectionMatches[1];
$lastRow = $selectionMatches[3] ?? $firstRow;
$firstCell = "A$firstRow";
$cell = "$firstRow:$lastRow";
$this->thisRow = (int) $firstRow;
$sheet->getCell($firstCell);
$combinedCells .= "$separator$cell";
$separator = ' ';
@@ -3262,10 +3262,12 @@ 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];
}
// or if cell is part of a data validation range
foreach ($this->dataValidationCollection as $key => $dataValidation) {
$keyParts = explode(' ', $key);
foreach ($keyParts as $keyPart) {
@@ -22,7 +22,7 @@ class DataValidationsTest extends AbstractFunctional
$sheet = $spreadsheet->getActiveSheet();
$assertions = $this->validationAssertions();
$validation = $sheet->getCell('A1')->getDataValidation();
self::assertSame('A1:A1048576', $validation->getSqref());
self::assertSame('A:A', $validation->getSqref());
$validation = $sheet->getCell('B3')->getDataValidation();
self::assertSame('B2:B1048576', $validation->getSqref());
@@ -42,14 +42,14 @@ class DataValidationsTest extends AbstractFunctional
$spreadsheet = $reader->load($this->filename2);
$sheet = $spreadsheet->getActiveSheet();
$collection = $sheet->getDataValidationCollection();
self::assertSame(['A1', 'A1:XFD1'], array_keys($collection));
self::assertSame(['A1', '1:1'], array_keys($collection));
$dv = $collection['A1'];
self::assertSame('"Item A,Item B,Item D"', $dv->getFormula1());
self::assertSame('warn', $dv->getErrorStyle());
self::assertFalse($dv->getShowDropDown());
self::assertFalse($dv->getShowErrorMessage());
$dv = $collection['A1:XFD1'];
$dv = $collection['1:1'];
self::assertSame('"Item A,Item B,Item C"', $dv->getFormula1());
self::assertSame('stop', $dv->getErrorStyle());
self::assertTrue($dv->getShowDropDown());
@@ -67,7 +67,7 @@ class DataValidationsTest extends AbstractFunctional
$sheet = $spreadsheet->getActiveSheet();
$assertions = $this->validationAssertions();
$validation = $sheet->getCell('A1')->getDataValidation();
self::assertSame('A1:A1048576', $validation->getSqref());
self::assertSame('A:A', $validation->getSqref());
$validation = $sheet->getCell('B3')->getDataValidation();
self::assertSame('B2:B1048576', $validation->getSqref());
@@ -87,10 +87,10 @@ class DataValidationsTest extends AbstractFunctional
$sheet = $spreadsheet->getActiveSheet();
$assertions = $this->validationAssertions();
//$validation = $sheet->getCell('A1')->getDataValidation();
//self::assertSame('A1:A1048576', $validation->getSqref());
//$validation = $sheet->getCell('B3')->getDataValidation();
//self::assertSame('B2:B1048576', $validation->getSqref());
$validation = $sheet->getCell('A1')->getDataValidation();
self::assertSame('A:A', $validation->getSqref(), 'limited number of rows in Xls');
$validation = $sheet->getCell('B3')->getDataValidation();
self::assertSame('B2:B1048576', $validation->getSqref());
foreach ($assertions as $title => $assertion) {
$sheet->getCell($assertion[1])->setValue($assertion[2]);
@@ -33,7 +33,7 @@ class DataValidationTest extends AbstractFunctional
$robj = $this->writeAndReload($spreadsheet, 'Xls');
$spreadsheet->disconnectWorksheets();
$sheet0 = $robj->getActiveSheet();
self::assertSame(['H1', 'C1:F1', 'A1:IV1'], array_keys($sheet0->getDataValidationCollection()));
self::assertSame(['H1', 'C1:F1', '1:1'], array_keys($sheet0->getDataValidationCollection()));
self::assertTrue(true);
$robj->disconnectWorksheets();
}