Do not confuse defined names and cell refs

CALCULATION_REGEXP_CELLREF is not sufficiently robust.
It treats some perfectly legal defined names, e.g. A1A, as cell refs.
When the Xlsx Writer tries to save a worksheet which uses such a name
in a formula in a cell, it throws an exception.

The new DefinedNameConfusedForCellTest is a simple demonstration.
The Regexp has been changed to ensure the name starts on a Word boundary,
and to make sure it is not followed by a word character or period.
This fixes the problem, and does not appear to cause any regression
problems in the test suite.

Closes #1263
This commit is contained in:
Owen Leibman 2019-11-27 08:52:34 -08:00 committed by Adrien Crivelli
parent 86fa5424a6
commit 9552172b85
No known key found for this signature in database
GPG Key ID: B182FD79DC6DE92E
2 changed files with 23 additions and 1 deletions

View File

@ -25,7 +25,7 @@ class Calculation
// Function (allow for the old @ symbol that could be used to prefix a function, but we'll ignore it)
const CALCULATION_REGEXP_FUNCTION = '@?(?:_xlfn\.)?([A-Z][A-Z0-9\.]*)[\s]*\(';
// Cell reference (cell or range of cells, with or without a sheet reference)
const CALCULATION_REGEXP_CELLREF = '((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]{1,3})\$?(\d{1,7})';
const CALCULATION_REGEXP_CELLREF = '((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?\b([a-z]{1,3})\$?(\d{1,7})(?![\w.])';
// Named Range of cells
const CALCULATION_REGEXP_NAMEDRANGE = '((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?([_A-Z][_A-Z0-9\.]*)';
// Error

View File

@ -0,0 +1,22 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Calculation;
use PhpOffice\PhpSpreadsheet\Shared\File;
use PHPUnit\Framework\TestCase;
class DefinedNameConfusedForCellTest extends TestCase
{
public function testDefinedName()
{
$obj = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$sheet0 = $obj->setActiveSheetIndex(0);
$sheet0->setCellValue('A1', 2);
$obj->addNamedRange(new \PhpOffice\PhpSpreadsheet\NamedRange('A1A', $sheet0, 'A1'));
$sheet0->setCellValue('B1', '=2*A1A');
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($obj, 'Xlsx');
$filename = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
$writer->save($filename);
self::assertTrue(true);
}
}