Skip to content

Commit

Permalink
Ods defined names unit tests (#2054)
Browse files Browse the repository at this point in the history
* Defined names/formulae in ODS are prefixed by $$ when used in a formula; so we need to strip this out to fully convert them to an Excel formula

* Test for ODS Writer for DefinedNames
  • Loading branch information
Mark Baker authored May 3, 2021
1 parent 83e55cf commit fd14da1
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 14 deletions.
10 changes: 0 additions & 10 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2810,16 +2810,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Reader/Ods.php

-
message: "#^Parameter \\#3 \\$subject of function preg_replace expects array\\|string, string\\|null given\\.$#"
count: 3
path: src/PhpSpreadsheet/Reader/Ods.php

-
message: "#^Parameter \\#3 \\$formula of static method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:translateSeparator\\(\\) expects string, string\\|null given\\.$#"
count: 1
path: src/PhpSpreadsheet/Reader/Ods.php

-
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\PageSettings\\:\\:\\$officeNs has no typehint specified\\.$#"
count: 1
Expand Down
8 changes: 5 additions & 3 deletions src/PhpSpreadsheet/Reader/Ods.php
Original file line number Diff line number Diff line change
Expand Up @@ -783,11 +783,13 @@ private function convertToExcelFormulaValue(string $openOfficeFormula): string
// Cell range reference in another sheet
$value = preg_replace('/\[\$?([^\.]+)\.([^\.]+):\.([^\.]+)\]/miu', '$1!$2:$3', $value);
// Cell reference in another sheet
$value = preg_replace('/\[\$?([^\.]+)\.([^\.]+)\]/miu', '$1!$2', $value);
$value = preg_replace('/\[\$?([^\.]+)\.([^\.]+)\]/miu', '$1!$2', $value ?? '');
// Cell range reference
$value = preg_replace('/\[\.([^\.]+):\.([^\.]+)\]/miu', '$1:$2', $value);
$value = preg_replace('/\[\.([^\.]+):\.([^\.]+)\]/miu', '$1:$2', $value ?? '');
// Simple cell reference
$value = preg_replace('/\[\.([^\.]+)\]/miu', '$1', $value);
$value = preg_replace('/\[\.([^\.]+)\]/miu', '$1', $value ?? '');
// Convert references to defined names/formulae
$value = str_replace('$$', '', $value ?? '');

$value = Calculation::translateSeparator(';', ',', $value, $inBraces);
}
Expand Down
4 changes: 3 additions & 1 deletion src/PhpSpreadsheet/Reader/Ods/BaseReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ protected function convertToExcelFormulaValue(string $openOfficeFormula): string
$value = preg_replace('/\[\.([^\.]+):\.([^\.]+)\]/miu', '$1:$2', $value ?? '');
// Simple cell reference
$value = preg_replace('/\[\.([^\.]+)\]/miu', '$1', $value ?? '');
// Convert references to defined names/formulae
$value = str_replace('$$', '', $value ?? '');

$value = Calculation::translateSeparator(';', ',', $value ?? '', $inBraces);
$value = Calculation::translateSeparator(';', ',', $value, $inBraces);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/PhpSpreadsheet/Reader/Ods/DefinedNames.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ protected function readDefinedExpressions(DOMElement $workbookData): void
$expression = $definedNameElement->getAttributeNS($this->tableNs, 'expression');

$baseAddress = $this->convertToExcelAddressValue($baseAddress);
$expression = substr($expression, strpos($expression, ':=') + 1);
$expression = $this->convertToExcelFormulaValue($expression);

$this->addDefinedName($baseAddress, $definedName, $expression);
Expand Down
35 changes: 35 additions & 0 deletions tests/PhpSpreadsheetTests/Reader/Ods/DefinedNamesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace PhpOffice\PhpSpreadsheetTests\Reader\Ods;

use PhpOffice\PhpSpreadsheet\Reader\Ods;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PHPUnit\Framework\TestCase;

class DefinedNamesTest extends TestCase
{
/**
* @var Spreadsheet
*/
private $spreadsheet;

protected function setUp(): void
{
$filename = 'tests/data/Reader/Ods/DefinedNames.ods';
$reader = new Ods();
$this->spreadsheet = $reader->load($filename);
}

public function testDefinedNames(): void
{
$worksheet = $this->spreadsheet->getActiveSheet();

$firstDefinedNameValue = $worksheet->getCell('First')->getValue();
$secondDefinedNameValue = $worksheet->getCell('Second')->getValue();
$calculatedFormulaValue = $worksheet->getCell('B2')->getCalculatedValue();

self::assertSame(3, $firstDefinedNameValue);
self::assertSame(4, $secondDefinedNameValue);
self::assertSame(12, $calculatedFormulaValue);
}
}
33 changes: 33 additions & 0 deletions tests/PhpSpreadsheetTests/Writer/Ods/DefinedNamesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace PhpOffice\PhpSpreadsheetTests\Writer\Ods;

use PhpOffice\PhpSpreadsheet\NamedFormula;
use PhpOffice\PhpSpreadsheet\NamedRange;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;

class DefinedNamesTest extends AbstractFunctional
{
public function testDefinedNamesWriter(): void
{
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();

$dataSet = [
[7, 'x', 5],
['=', '=FORMULA'],
];
$worksheet->fromArray($dataSet, null, 'A1');

$spreadsheet->addDefinedName(new NamedRange('FIRST', $worksheet, '$A$1'));
$spreadsheet->addDefinedName(new NamedRange('SECOND', $worksheet, '$C$1'));
$spreadsheet->addDefinedName(new NamedFormula('FORMULA', $worksheet, '=FIRST*SECOND'));

$reloaded = $this->writeAndReload($spreadsheet, 'Ods');

self::assertSame(7, $reloaded->getActiveSheet()->getCell('FIRST')->getValue());
self::assertSame(5, $reloaded->getActiveSheet()->getCell('SECOND')->getValue());
self::assertSame(35, $reloaded->getActiveSheet()->getCell('B2')->getCalculatedValue());
}
}
Binary file added tests/data/Reader/Ods/DefinedNames.ods
Binary file not shown.

0 comments on commit fd14da1

Please sign in to comment.