Bugfix for Issue #3013, Named ranges not usable as anchors in OFFSET function

This commit is contained in:
MarkBaker 2022-08-19 11:28:51 +02:00
parent d7da206103
commit 269e9ba14d
4 changed files with 66 additions and 1 deletions

View File

@ -687,7 +687,7 @@ class Functions
$worksheet2 = $defined->getWorkSheet(); $worksheet2 = $defined->getWorkSheet();
if (!$defined->isFormula() && $worksheet2 !== null) { if (!$defined->isFormula() && $worksheet2 !== null) {
$coordinate = "'" . $worksheet2->getTitle() . "'!" . $coordinate = "'" . $worksheet2->getTitle() . "'!" .
(string) preg_replace('/^=/', '', $defined->getValue()); (string) preg_replace('/^=/', '', str_replace('$', '', $defined->getValue()));
} }
} }

View File

@ -99,6 +99,8 @@ class Offset
private static function extractWorksheet($cellAddress, Cell $cell): array private static function extractWorksheet($cellAddress, Cell $cell): array
{ {
$cellAddress = self::assessCellAddress($cellAddress, $cell);
$sheetName = ''; $sheetName = '';
if (strpos($cellAddress, '!') !== false) { if (strpos($cellAddress, '!') !== false) {
[$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); [$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true);
@ -112,6 +114,15 @@ class Offset
return [$cellAddress, $worksheet]; return [$cellAddress, $worksheet];
} }
private static function assessCellAddress(string $cellAddress, Cell $cell): string
{
if (preg_match('/^' . Calculation::CALCULATION_REGEXP_DEFINEDNAME . '$/mui', $cellAddress) !== false) {
$cellAddress = Functions::expandDefinedName($cellAddress, $cell);
}
return $cellAddress;
}
private static function adjustEndCellColumnForWidth(string $endCellColumn, $width, int $startCellColumn, $columns) private static function adjustEndCellColumnForWidth(string $endCellColumn, $width, int $startCellColumn, $columns)
{ {
$endCellColumn = Coordinate::columnIndexFromString($endCellColumn) - 1; $endCellColumn = Coordinate::columnIndexFromString($endCellColumn) - 1;

View File

@ -5,6 +5,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\LookupRef; use PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\NamedRange;
use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -91,6 +92,44 @@ class HLookupTest extends TestCase
self::assertSame($expectedResult, $result); self::assertSame($expectedResult, $result);
} }
/**
* @dataProvider providerHLookupNamedRange
*/
public function testHLookupNamedRange(string $expectedResult, string $cellAddress): void
{
$lookupData = [
['Rating', 1, 2, 3, 4],
['Level', 'Poor', 'Average', 'Good', 'Excellent'],
];
$formData = [
['Category', 'Rating', 'Level'],
['Service', 2, '=HLOOKUP(C5,Lookup_Table,2,FALSE)'],
['Quality', 3, '=HLOOKUP(C6,Lookup_Table,2,FALSE)'],
['Value', 4, '=HLOOKUP(C7,Lookup_Table,2,FALSE)'],
['Cleanliness', 3, '=HLOOKUP(C8,Lookup_Table,2,FALSE)'],
];
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray($lookupData, null, 'F4');
$worksheet->fromArray($formData, null, 'B4');
$spreadsheet->addNamedRange(new NamedRange('Lookup_Table', $worksheet, '=$G$4:$J$5'));
$result = $worksheet->getCell($cellAddress)->getCalculatedValue();
self::assertEquals($expectedResult, $result);
}
public function providerHLookupNamedRange(): array
{
return [
['Average', 'D5'],
['Good', 'D6'],
['Excellent', 'D7'],
['Good', 'D8'],
];
}
/** /**
* @dataProvider providerHLookupArray * @dataProvider providerHLookupArray
*/ */

View File

@ -3,6 +3,7 @@
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef; namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
use PhpOffice\PhpSpreadsheet\Calculation\LookupRef; use PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
use PhpOffice\PhpSpreadsheet\NamedRange;
class OffsetTest extends AllSetupTeardown class OffsetTest extends AllSetupTeardown
{ {
@ -46,4 +47,18 @@ class OffsetTest extends AllSetupTeardown
$sheet->getCell('A5')->setValue('=OFFSET(C1, 0, 0)'); $sheet->getCell('A5')->setValue('=OFFSET(C1, 0, 0)');
self::assertSame(5, $sheet->getCell('A5')->getCalculatedValue()); self::assertSame(5, $sheet->getCell('A5')->getCalculatedValue());
} }
public function testOffsetNamedRange(): void
{
$workSheet = $this->getSheet();
$workSheet->setCellValue('A1', 1);
$workSheet->setCellValue('A2', 2);
$this->getSpreadsheet()->addNamedRange(new NamedRange('demo', $workSheet, '=$A$1'));
$workSheet->setCellValue('B1', '=demo');
$workSheet->setCellValue('B2', '=OFFSET(demo, 1, 0)');
self::assertSame(2, $workSheet->getCell('B2')->getCalculatedValue());
}
} }