Merge branch 'master' into Issue-3056_Update-DataValidation-SqRef-On-Insert-Delete-Rows-Columns
This commit is contained in:
commit
a6cfd8c504
|
|
@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Implementation of the `ARRAYTOTEXT()` and `VALUETOTEXT()` Excel Functions
|
- Implementation of the `ARRAYTOTEXT()` and `VALUETOTEXT()` Excel Functions
|
||||||
- Support for [mitoteam/jpgraph](https://packagist.org/packages/mitoteam/jpgraph) implementation of
|
- Support for [mitoteam/jpgraph](https://packagist.org/packages/mitoteam/jpgraph) implementation of
|
||||||
JpGraph library to render charts added.
|
JpGraph library to render charts added.
|
||||||
- Charts: Add Gradients, Transparency, Hidden Axes, Rounded Corners, Trendlines.
|
- Charts: Add Gradients, Transparency, Hidden Axes, Rounded Corners, Trendlines, Date Axes.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
@ -50,6 +50,11 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Add setName Method for Chart [Issue #2991](https://github.com/PHPOffice/PhpSpreadsheet/issues/2991) [PR #3001](https://github.com/PHPOffice/PhpSpreadsheet/pull/3001)
|
- Add setName Method for Chart [Issue #2991](https://github.com/PHPOffice/PhpSpreadsheet/issues/2991) [PR #3001](https://github.com/PHPOffice/PhpSpreadsheet/pull/3001)
|
||||||
- Eliminate partial dependency on php-intl in StringHelper [Issue #2982](https://github.com/PHPOffice/PhpSpreadsheet/issues/2982) [PR #2994](https://github.com/PHPOffice/PhpSpreadsheet/pull/2994)
|
- Eliminate partial dependency on php-intl in StringHelper [Issue #2982](https://github.com/PHPOffice/PhpSpreadsheet/issues/2982) [PR #2994](https://github.com/PHPOffice/PhpSpreadsheet/pull/2994)
|
||||||
- Minor changes for Pdf [Issue #2999](https://github.com/PHPOffice/PhpSpreadsheet/issues/2999) [PR #3002](https://github.com/PHPOffice/PhpSpreadsheet/pull/3002) [PR #3006](https://github.com/PHPOffice/PhpSpreadsheet/pull/3006)
|
- Minor changes for Pdf [Issue #2999](https://github.com/PHPOffice/PhpSpreadsheet/issues/2999) [PR #3002](https://github.com/PHPOffice/PhpSpreadsheet/pull/3002) [PR #3006](https://github.com/PHPOffice/PhpSpreadsheet/pull/3006)
|
||||||
|
- Html/Pdf Do net set background color for cells using (default) nofill [PR #3016](https://github.com/PHPOffice/PhpSpreadsheet/pull/3016)
|
||||||
|
- Add support for Date Axis to Chart [Issue #2967](https://github.com/PHPOffice/PhpSpreadsheet/issues/2967) [PR #3018](https://github.com/PHPOffice/PhpSpreadsheet/pull/3018)
|
||||||
|
- Reconcile Differences Between Css and Excel for Cell Alignment [PR #3048](https://github.com/PHPOffice/PhpSpreadsheet/pull/3048)
|
||||||
|
- R1C1 Format Internationalization and Better Support for Relative Offsets [Issue #1704](https://github.com/PHPOffice/PhpSpreadsheet/issues/1704) [PR #3052](https://github.com/PHPOffice/PhpSpreadsheet/pull/3052)
|
||||||
|
- Minor Fix for Percentage Formatting [Issue #1929](https://github.com/PHPOffice/PhpSpreadsheet/issues/1929) [PR #3053](https://github.com/PHPOffice/PhpSpreadsheet/pull/3053)
|
||||||
|
|
||||||
## 1.24.1 - 2022-07-18
|
## 1.24.1 - 2022-07-18
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
|
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
|
||||||
"dompdf/dompdf": "^1.0 || ^2.0",
|
"dompdf/dompdf": "^1.0 || ^2.0",
|
||||||
"friendsofphp/php-cs-fixer": "^3.2",
|
"friendsofphp/php-cs-fixer": "^3.2",
|
||||||
"mitoteam/jpgraph": "10.2.3",
|
"mitoteam/jpgraph": "10.2.4",
|
||||||
"mpdf/mpdf": "8.1.1",
|
"mpdf/mpdf": "8.1.1",
|
||||||
"phpcompatibility/php-compatibility": "^9.3",
|
"phpcompatibility/php-compatibility": "^9.3",
|
||||||
"phpstan/phpstan": "^1.1",
|
"phpstan/phpstan": "^1.1",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "b5bdb9f96d18ce59557436521053fdd9",
|
"content-hash": "6d946e91cbe5d38e1cfb0208512ab981",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "ezyang/htmlpurifier",
|
"name": "ezyang/htmlpurifier",
|
||||||
|
|
@ -1342,16 +1342,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mitoteam/jpgraph",
|
"name": "mitoteam/jpgraph",
|
||||||
"version": "10.2.3",
|
"version": "10.2.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/mitoteam/jpgraph.git",
|
"url": "https://github.com/mitoteam/jpgraph.git",
|
||||||
"reference": "21121535537e05c32e7964327b80746462a6057d"
|
"reference": "9ce4d106a89f120c7e220ea22205ef7956a7027b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/mitoteam/jpgraph/zipball/21121535537e05c32e7964327b80746462a6057d",
|
"url": "https://api.github.com/repos/mitoteam/jpgraph/zipball/9ce4d106a89f120c7e220ea22205ef7956a7027b",
|
||||||
"reference": "21121535537e05c32e7964327b80746462a6057d",
|
"reference": "9ce4d106a89f120c7e220ea22205ef7956a7027b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -1382,9 +1382,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/mitoteam/jpgraph/issues",
|
"issues": "https://github.com/mitoteam/jpgraph/issues",
|
||||||
"source": "https://github.com/mitoteam/jpgraph/tree/10.2.3"
|
"source": "https://github.com/mitoteam/jpgraph/tree/10.2.4"
|
||||||
},
|
},
|
||||||
"time": "2022-09-14T04:02:09+00:00"
|
"time": "2022-09-15T05:57:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mpdf/mpdf",
|
"name": "mpdf/mpdf",
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ class LocaleGenerator
|
||||||
$translationValue = $translationCell->getValue();
|
$translationValue = $translationCell->getValue();
|
||||||
if ($this->isFunctionCategoryEntry($translationCell)) {
|
if ($this->isFunctionCategoryEntry($translationCell)) {
|
||||||
$this->writeFileSectionHeader($functionFile, "{$translationValue} ({$functionName})");
|
$this->writeFileSectionHeader($functionFile, "{$translationValue} ({$functionName})");
|
||||||
} elseif (!array_key_exists($functionName, $this->phpSpreadsheetFunctions)) {
|
} elseif (!array_key_exists($functionName, $this->phpSpreadsheetFunctions) && substr($functionName, 0, 1) !== '*') {
|
||||||
$this->log("Function {$functionName} is not defined in PhpSpreadsheet");
|
$this->log("Function {$functionName} is not defined in PhpSpreadsheet");
|
||||||
} elseif (!empty($translationValue)) {
|
} elseif (!empty($translationValue)) {
|
||||||
$functionTranslation = "{$functionName} = {$translationValue}" . self::EOL;
|
$functionTranslation = "{$functionName} = {$translationValue}" . self::EOL;
|
||||||
|
|
|
||||||
|
|
@ -3110,7 +3110,7 @@ class Calculation
|
||||||
[$localeFunction] = explode('##', $localeFunction); // Strip out comments
|
[$localeFunction] = explode('##', $localeFunction); // Strip out comments
|
||||||
if (strpos($localeFunction, '=') !== false) {
|
if (strpos($localeFunction, '=') !== false) {
|
||||||
[$fName, $lfName] = array_map('trim', explode('=', $localeFunction));
|
[$fName, $lfName] = array_map('trim', explode('=', $localeFunction));
|
||||||
if ((isset(self::$phpSpreadsheetFunctions[$fName])) && ($lfName != '') && ($fName != $lfName)) {
|
if ((substr($fName, 0, 1) === '*' || isset(self::$phpSpreadsheetFunctions[$fName])) && ($lfName != '') && ($fName != $lfName)) {
|
||||||
self::$localeFunctions[$fName] = $lfName;
|
self::$localeFunctions[$fName] = $lfName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
|
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
|
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\AddressHelper;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
|
|
||||||
class Address
|
class Address
|
||||||
|
|
@ -72,6 +73,9 @@ class Address
|
||||||
|
|
||||||
$sheetName = self::sheetName($sheetName);
|
$sheetName = self::sheetName($sheetName);
|
||||||
|
|
||||||
|
if (is_int($referenceStyle)) {
|
||||||
|
$referenceStyle = (bool) $referenceStyle;
|
||||||
|
}
|
||||||
if ((!is_bool($referenceStyle)) || $referenceStyle === self::REFERENCE_STYLE_A1) {
|
if ((!is_bool($referenceStyle)) || $referenceStyle === self::REFERENCE_STYLE_A1) {
|
||||||
return self::formatAsA1($row, $column, $relativity, $sheetName);
|
return self::formatAsA1($row, $column, $relativity, $sheetName);
|
||||||
}
|
}
|
||||||
|
|
@ -113,7 +117,8 @@ class Address
|
||||||
if (($relativity == self::ADDRESS_ROW_RELATIVE) || ($relativity == self::ADDRESS_RELATIVE)) {
|
if (($relativity == self::ADDRESS_ROW_RELATIVE) || ($relativity == self::ADDRESS_RELATIVE)) {
|
||||||
$row = "[{$row}]";
|
$row = "[{$row}]";
|
||||||
}
|
}
|
||||||
|
[$rowChar, $colChar] = AddressHelper::getRowAndColumnChars();
|
||||||
|
|
||||||
return "{$sheetName}R{$row}C{$column}";
|
return "{$sheetName}$rowChar{$row}$colChar{$column}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,12 @@ class Helpers
|
||||||
|
|
||||||
public const CELLADDRESS_USE_R1C1 = false;
|
public const CELLADDRESS_USE_R1C1 = false;
|
||||||
|
|
||||||
private static function convertR1C1(string &$cellAddress1, ?string &$cellAddress2, bool $a1): string
|
private static function convertR1C1(string &$cellAddress1, ?string &$cellAddress2, bool $a1, ?int $baseRow = null, ?int $baseCol = null): string
|
||||||
{
|
{
|
||||||
if ($a1 === self::CELLADDRESS_USE_R1C1) {
|
if ($a1 === self::CELLADDRESS_USE_R1C1) {
|
||||||
$cellAddress1 = AddressHelper::convertToA1($cellAddress1);
|
$cellAddress1 = AddressHelper::convertToA1($cellAddress1, $baseRow ?? 1, $baseCol ?? 1);
|
||||||
if ($cellAddress2) {
|
if ($cellAddress2) {
|
||||||
$cellAddress2 = AddressHelper::convertToA1($cellAddress2);
|
$cellAddress2 = AddressHelper::convertToA1($cellAddress2, $baseRow ?? 1, $baseCol ?? 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ class Helpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function extractCellAddresses(string $cellAddress, bool $a1, Worksheet $sheet, string $sheetName = ''): array
|
public static function extractCellAddresses(string $cellAddress, bool $a1, Worksheet $sheet, string $sheetName = '', ?int $baseRow = null, ?int $baseCol = null): array
|
||||||
{
|
{
|
||||||
$cellAddress1 = $cellAddress;
|
$cellAddress1 = $cellAddress;
|
||||||
$cellAddress2 = null;
|
$cellAddress2 = null;
|
||||||
|
|
@ -52,7 +52,7 @@ class Helpers
|
||||||
if (strpos($cellAddress, ':') !== false) {
|
if (strpos($cellAddress, ':') !== false) {
|
||||||
[$cellAddress1, $cellAddress2] = explode(':', $cellAddress);
|
[$cellAddress1, $cellAddress2] = explode(':', $cellAddress);
|
||||||
}
|
}
|
||||||
$cellAddress = self::convertR1C1($cellAddress1, $cellAddress2, $a1);
|
$cellAddress = self::convertR1C1($cellAddress1, $cellAddress2, $a1, $baseRow, $baseCol);
|
||||||
|
|
||||||
return [$cellAddress1, $cellAddress2, $cellAddress];
|
return [$cellAddress1, $cellAddress2, $cellAddress];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
|
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
class Indirect
|
class Indirect
|
||||||
|
|
@ -63,6 +64,8 @@ class Indirect
|
||||||
*/
|
*/
|
||||||
public static function INDIRECT($cellAddress, $a1fmt, Cell $cell)
|
public static function INDIRECT($cellAddress, $a1fmt, Cell $cell)
|
||||||
{
|
{
|
||||||
|
[$baseCol, $baseRow] = Coordinate::indexesFromString($cell->getCoordinate());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$a1 = self::a1Format($a1fmt);
|
$a1 = self::a1Format($a1fmt);
|
||||||
$cellAddress = self::validateAddress($cellAddress);
|
$cellAddress = self::validateAddress($cellAddress);
|
||||||
|
|
@ -78,7 +81,11 @@ class Indirect
|
||||||
$cellAddress = self::handleRowColumnRanges($worksheet, ...explode(':', $cellAddress));
|
$cellAddress = self::handleRowColumnRanges($worksheet, ...explode(':', $cellAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
[$cellAddress1, $cellAddress2, $cellAddress] = Helpers::extractCellAddresses($cellAddress, $a1, $cell->getWorkSheet(), $sheetName);
|
try {
|
||||||
|
[$cellAddress1, $cellAddress2, $cellAddress] = Helpers::extractCellAddresses($cellAddress, $a1, $cell->getWorkSheet(), $sheetName, $baseRow, $baseCol);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return ExcelError::REF();
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/miu', $cellAddress1, $matches)) ||
|
(!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/miu', $cellAddress1, $matches)) ||
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -245,6 +245,7 @@ ROWS = RÆKKER
|
||||||
RTD = RTD
|
RTD = RTD
|
||||||
TRANSPOSE = TRANSPONER
|
TRANSPOSE = TRANSPONER
|
||||||
VLOOKUP = LOPSLAG
|
VLOOKUP = LOPSLAG
|
||||||
|
*RC = RK
|
||||||
|
|
||||||
##
|
##
|
||||||
## Matematiske og trigonometriske funktioner (Math & Trig Functions)
|
## Matematiske og trigonometriske funktioner (Math & Trig Functions)
|
||||||
|
|
|
||||||
|
|
@ -243,6 +243,7 @@ ROWS = ZEILEN
|
||||||
RTD = RTD
|
RTD = RTD
|
||||||
TRANSPOSE = MTRANS
|
TRANSPOSE = MTRANS
|
||||||
VLOOKUP = SVERWEIS
|
VLOOKUP = SVERWEIS
|
||||||
|
*RC = ZS
|
||||||
|
|
||||||
##
|
##
|
||||||
## Mathematische und trigonometrische Funktionen (Math & Trig Functions)
|
## Mathematische und trigonometrische Funktionen (Math & Trig Functions)
|
||||||
|
|
|
||||||
|
|
@ -245,6 +245,7 @@ ROWS = FILAS
|
||||||
RTD = RDTR
|
RTD = RDTR
|
||||||
TRANSPOSE = TRANSPONER
|
TRANSPOSE = TRANSPONER
|
||||||
VLOOKUP = BUSCARV
|
VLOOKUP = BUSCARV
|
||||||
|
*RC = FC
|
||||||
|
|
||||||
##
|
##
|
||||||
## Funciones matemáticas y trigonométricas (Math & Trig Functions)
|
## Funciones matemáticas y trigonométricas (Math & Trig Functions)
|
||||||
|
|
|
||||||
|
|
@ -245,6 +245,7 @@ ROWS = RIVIT
|
||||||
RTD = RTD
|
RTD = RTD
|
||||||
TRANSPOSE = TRANSPONOI
|
TRANSPOSE = TRANSPONOI
|
||||||
VLOOKUP = PHAKU
|
VLOOKUP = PHAKU
|
||||||
|
*RC = RS
|
||||||
|
|
||||||
##
|
##
|
||||||
## Matemaattiset ja trigonometriset funktiot (Math & Trig Functions)
|
## Matemaattiset ja trigonometriset funktiot (Math & Trig Functions)
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,7 @@ ROWS = LIGNES
|
||||||
RTD = RTD
|
RTD = RTD
|
||||||
TRANSPOSE = TRANSPOSE
|
TRANSPOSE = TRANSPOSE
|
||||||
VLOOKUP = RECHERCHEV
|
VLOOKUP = RECHERCHEV
|
||||||
|
*RC = LC
|
||||||
|
|
||||||
##
|
##
|
||||||
## Fonctions mathématiques et trigonométriques (Math & Trig Functions)
|
## Fonctions mathématiques et trigonométriques (Math & Trig Functions)
|
||||||
|
|
|
||||||
|
|
@ -245,6 +245,7 @@ ROWS = SOROK
|
||||||
RTD = VIA
|
RTD = VIA
|
||||||
TRANSPOSE = TRANSZPONÁLÁS
|
TRANSPOSE = TRANSZPONÁLÁS
|
||||||
VLOOKUP = FKERES
|
VLOOKUP = FKERES
|
||||||
|
*RC = SO
|
||||||
|
|
||||||
##
|
##
|
||||||
## Matematikai és trigonometrikus függvények (Math & Trig Functions)
|
## Matematikai és trigonometrikus függvények (Math & Trig Functions)
|
||||||
|
|
|
||||||
|
|
@ -245,6 +245,7 @@ ROWS = RADER
|
||||||
RTD = RTD
|
RTD = RTD
|
||||||
TRANSPOSE = TRANSPONER
|
TRANSPOSE = TRANSPONER
|
||||||
VLOOKUP = FINN.RAD
|
VLOOKUP = FINN.RAD
|
||||||
|
*RC = RK
|
||||||
|
|
||||||
##
|
##
|
||||||
## Matematikk- og trigonometrifunksjoner (Math & Trig Functions)
|
## Matematikk- og trigonometrifunksjoner (Math & Trig Functions)
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,7 @@ ROWS = RIJEN
|
||||||
RTD = RTG
|
RTD = RTG
|
||||||
TRANSPOSE = TRANSPONEREN
|
TRANSPOSE = TRANSPONEREN
|
||||||
VLOOKUP = VERT.ZOEKEN
|
VLOOKUP = VERT.ZOEKEN
|
||||||
|
*RC = RK
|
||||||
|
|
||||||
##
|
##
|
||||||
## Wiskundige en trigonometrische functies (Math & Trig Functions)
|
## Wiskundige en trigonometrische functies (Math & Trig Functions)
|
||||||
|
|
|
||||||
|
|
@ -242,6 +242,7 @@ ROWS = LINS
|
||||||
RTD = RTD
|
RTD = RTD
|
||||||
TRANSPOSE = TRANSPOR
|
TRANSPOSE = TRANSPOR
|
||||||
VLOOKUP = PROCV
|
VLOOKUP = PROCV
|
||||||
|
*RC = LC
|
||||||
|
|
||||||
##
|
##
|
||||||
## Funções matemáticas e trigonométricas (Math & Trig Functions)
|
## Funções matemáticas e trigonométricas (Math & Trig Functions)
|
||||||
|
|
|
||||||
|
|
@ -245,6 +245,7 @@ ROWS = LINS
|
||||||
RTD = RTD
|
RTD = RTD
|
||||||
TRANSPOSE = TRANSPOR
|
TRANSPOSE = TRANSPOR
|
||||||
VLOOKUP = PROCV
|
VLOOKUP = PROCV
|
||||||
|
*RC = LC
|
||||||
|
|
||||||
##
|
##
|
||||||
## Funções matemáticas e trigonométricas (Math & Trig Functions)
|
## Funções matemáticas e trigonométricas (Math & Trig Functions)
|
||||||
|
|
|
||||||
|
|
@ -243,6 +243,7 @@ ROWS = RADER
|
||||||
RTD = RTD
|
RTD = RTD
|
||||||
TRANSPOSE = TRANSPONERA
|
TRANSPOSE = TRANSPONERA
|
||||||
VLOOKUP = LETARAD
|
VLOOKUP = LETARAD
|
||||||
|
*RC = RK
|
||||||
|
|
||||||
##
|
##
|
||||||
## Matematiska och trigonometriska funktioner (Math & Trig Functions)
|
## Matematiska och trigonometriska funktioner (Math & Trig Functions)
|
||||||
|
|
|
||||||
|
|
@ -2,23 +2,44 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheet\Cell;
|
namespace PhpOffice\PhpSpreadsheet\Cell;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
use PhpOffice\PhpSpreadsheet\Exception;
|
use PhpOffice\PhpSpreadsheet\Exception;
|
||||||
|
|
||||||
class AddressHelper
|
class AddressHelper
|
||||||
{
|
{
|
||||||
public const R1C1_COORDINATE_REGEX = '/(R((?:\[-?\d*\])|(?:\d*))?)(C((?:\[-?\d*\])|(?:\d*))?)/i';
|
public const R1C1_COORDINATE_REGEX = '/(R((?:\[-?\d*\])|(?:\d*))?)(C((?:\[-?\d*\])|(?:\d*))?)/i';
|
||||||
|
|
||||||
|
/** @return string[] */
|
||||||
|
public static function getRowAndColumnChars()
|
||||||
|
{
|
||||||
|
$rowChar = 'R';
|
||||||
|
$colChar = 'C';
|
||||||
|
if (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_EXCEL) {
|
||||||
|
$rowColChars = Calculation::localeFunc('*RC');
|
||||||
|
if (mb_strlen($rowColChars) === 2) {
|
||||||
|
$rowChar = mb_substr($rowColChars, 0, 1);
|
||||||
|
$colChar = mb_substr($rowColChars, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$rowChar, $colChar];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an R1C1 format cell address to an A1 format cell address.
|
* Converts an R1C1 format cell address to an A1 format cell address.
|
||||||
*/
|
*/
|
||||||
public static function convertToA1(
|
public static function convertToA1(
|
||||||
string $address,
|
string $address,
|
||||||
int $currentRowNumber = 1,
|
int $currentRowNumber = 1,
|
||||||
int $currentColumnNumber = 1
|
int $currentColumnNumber = 1,
|
||||||
|
bool $useLocale = true
|
||||||
): string {
|
): string {
|
||||||
$validityCheck = preg_match('/^(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))$/i', $address, $cellReference);
|
[$rowChar, $colChar] = $useLocale ? self::getRowAndColumnChars() : ['R', 'C'];
|
||||||
|
$regex = '/^(' . $rowChar . '(\[?[-+]?\d*\]?))(' . $colChar . '(\[?[-+]?\d*\]?))$/i';
|
||||||
|
$validityCheck = preg_match($regex, $address, $cellReference);
|
||||||
|
|
||||||
if ($validityCheck === 0) {
|
if (empty($validityCheck)) {
|
||||||
throw new Exception('Invalid R1C1-format Cell Reference');
|
throw new Exception('Invalid R1C1-format Cell Reference');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +113,7 @@ class AddressHelper
|
||||||
// Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent,
|
// Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent,
|
||||||
// then modify the formula to use that new reference
|
// then modify the formula to use that new reference
|
||||||
foreach ($cellReferences as $cellReference) {
|
foreach ($cellReferences as $cellReference) {
|
||||||
$A1CellReference = self::convertToA1($cellReference[0][0], $currentRowNumber, $currentColumnNumber);
|
$A1CellReference = self::convertToA1($cellReference[0][0], $currentRowNumber, $currentColumnNumber, false);
|
||||||
$value = substr_replace($value, $A1CellReference, $cellReference[0][1], strlen($cellReference[0][0]));
|
$value = substr_replace($value, $A1CellReference, $cellReference[0][1], strlen($cellReference[0][0]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Properties as ChartProperties;
|
use PhpOffice\PhpSpreadsheet\Chart\Properties as ChartProperties;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\TrendLine;
|
use PhpOffice\PhpSpreadsheet\Chart\TrendLine;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Font;
|
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||||
use SimpleXMLElement;
|
use SimpleXMLElement;
|
||||||
|
|
@ -94,7 +95,7 @@ class Chart
|
||||||
break;
|
break;
|
||||||
case 'chart':
|
case 'chart':
|
||||||
foreach ($chartElement as $chartDetailsKey => $chartDetails) {
|
foreach ($chartElement as $chartDetailsKey => $chartDetails) {
|
||||||
$chartDetailsC = $chartDetails->children($this->cNamespace);
|
$chartDetails = Xlsx::testSimpleXml($chartDetails);
|
||||||
switch ($chartDetailsKey) {
|
switch ($chartDetailsKey) {
|
||||||
case 'autoTitleDeleted':
|
case 'autoTitleDeleted':
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
|
|
@ -113,8 +114,8 @@ class Chart
|
||||||
$plotSeries = $plotAttributes = [];
|
$plotSeries = $plotAttributes = [];
|
||||||
$catAxRead = false;
|
$catAxRead = false;
|
||||||
$plotNoFill = false;
|
$plotNoFill = false;
|
||||||
/** @var SimpleXMLElement $chartDetail */
|
|
||||||
foreach ($chartDetails as $chartDetailKey => $chartDetail) {
|
foreach ($chartDetails as $chartDetailKey => $chartDetail) {
|
||||||
|
$chartDetail = Xlsx::testSimpleXml($chartDetail);
|
||||||
switch ($chartDetailKey) {
|
switch ($chartDetailKey) {
|
||||||
case 'spPr':
|
case 'spPr':
|
||||||
$possibleNoFill = $chartDetails->spPr->children($this->aNamespace);
|
$possibleNoFill = $chartDetails->spPr->children($this->aNamespace);
|
||||||
|
|
@ -122,8 +123,8 @@ class Chart
|
||||||
$plotNoFill = true;
|
$plotNoFill = true;
|
||||||
}
|
}
|
||||||
if (isset($possibleNoFill->gradFill->gsLst)) {
|
if (isset($possibleNoFill->gradFill->gsLst)) {
|
||||||
/** @var SimpleXMLElement $gradient */
|
|
||||||
foreach ($possibleNoFill->gradFill->gsLst->gs as $gradient) {
|
foreach ($possibleNoFill->gradFill->gsLst->gs as $gradient) {
|
||||||
|
$gradient = Xlsx::testSimpleXml($gradient);
|
||||||
/** @var float */
|
/** @var float */
|
||||||
$pos = self::getAttribute($gradient, 'pos', 'float');
|
$pos = self::getAttribute($gradient, 'pos', 'float');
|
||||||
$gradientArray[] = [
|
$gradientArray[] = [
|
||||||
|
|
@ -348,6 +349,7 @@ class Chart
|
||||||
$legendLayout = null;
|
$legendLayout = null;
|
||||||
$legendOverlay = false;
|
$legendOverlay = false;
|
||||||
foreach ($chartDetails as $chartDetailKey => $chartDetail) {
|
foreach ($chartDetails as $chartDetailKey => $chartDetail) {
|
||||||
|
$chartDetail = Xlsx::testSimpleXml($chartDetail);
|
||||||
switch ($chartDetailKey) {
|
switch ($chartDetailKey) {
|
||||||
case 'legendPos':
|
case 'legendPos':
|
||||||
$legendPos = self::getAttribute($chartDetail, 'val', 'string');
|
$legendPos = self::getAttribute($chartDetail, 'val', 'string');
|
||||||
|
|
@ -399,11 +401,13 @@ class Chart
|
||||||
$caption = [];
|
$caption = [];
|
||||||
$titleLayout = null;
|
$titleLayout = null;
|
||||||
foreach ($titleDetails as $titleDetailKey => $chartDetail) {
|
foreach ($titleDetails as $titleDetailKey => $chartDetail) {
|
||||||
|
$chartDetail = Xlsx::testSimpleXml($chartDetail);
|
||||||
switch ($titleDetailKey) {
|
switch ($titleDetailKey) {
|
||||||
case 'tx':
|
case 'tx':
|
||||||
if (isset($chartDetail->rich)) {
|
if (isset($chartDetail->rich)) {
|
||||||
$titleDetails = $chartDetail->rich->children($this->aNamespace);
|
$titleDetails = $chartDetail->rich->children($this->aNamespace);
|
||||||
foreach ($titleDetails as $titleKey => $titleDetail) {
|
foreach ($titleDetails as $titleKey => $titleDetail) {
|
||||||
|
$titleDetail = Xlsx::testSimpleXml($titleDetail);
|
||||||
switch ($titleKey) {
|
switch ($titleKey) {
|
||||||
case 'p':
|
case 'p':
|
||||||
$titleDetailPart = $titleDetail->children($this->aNamespace);
|
$titleDetailPart = $titleDetail->children($this->aNamespace);
|
||||||
|
|
@ -440,6 +444,7 @@ class Chart
|
||||||
}
|
}
|
||||||
$layout = [];
|
$layout = [];
|
||||||
foreach ($details as $detailKey => $detail) {
|
foreach ($details as $detailKey => $detail) {
|
||||||
|
$detail = Xlsx::testSimpleXml($detail);
|
||||||
$layout[$detailKey] = self::getAttribute($detail, 'val', 'string');
|
$layout[$detailKey] = self::getAttribute($detail, 'val', 'string');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -472,8 +477,8 @@ class Chart
|
||||||
$lineStyle = null;
|
$lineStyle = null;
|
||||||
$labelLayout = null;
|
$labelLayout = null;
|
||||||
$trendLines = [];
|
$trendLines = [];
|
||||||
/** @var SimpleXMLElement $seriesDetail */
|
|
||||||
foreach ($seriesDetails as $seriesKey => $seriesDetail) {
|
foreach ($seriesDetails as $seriesKey => $seriesDetail) {
|
||||||
|
$seriesDetail = Xlsx::testSimpleXml($seriesDetail);
|
||||||
switch ($seriesKey) {
|
switch ($seriesKey) {
|
||||||
case 'idx':
|
case 'idx':
|
||||||
$seriesIndex = self::getAttribute($seriesDetail, 'val', 'integer');
|
$seriesIndex = self::getAttribute($seriesDetail, 'val', 'integer');
|
||||||
|
|
@ -786,6 +791,7 @@ class Chart
|
||||||
$pointCount = 0;
|
$pointCount = 0;
|
||||||
|
|
||||||
foreach ($seriesValueSet as $seriesValueIdx => $seriesValue) {
|
foreach ($seriesValueSet as $seriesValueIdx => $seriesValue) {
|
||||||
|
$seriesValue = Xlsx::testSimpleXml($seriesValue);
|
||||||
switch ($seriesValueIdx) {
|
switch ($seriesValueIdx) {
|
||||||
case 'ptCount':
|
case 'ptCount':
|
||||||
$pointCount = self::getAttribute($seriesValue, 'val', 'integer');
|
$pointCount = self::getAttribute($seriesValue, 'val', 'integer');
|
||||||
|
|
@ -858,7 +864,6 @@ class Chart
|
||||||
private function parseRichText(SimpleXMLElement $titleDetailPart): RichText
|
private function parseRichText(SimpleXMLElement $titleDetailPart): RichText
|
||||||
{
|
{
|
||||||
$value = new RichText();
|
$value = new RichText();
|
||||||
$objText = null;
|
|
||||||
$defaultFontSize = null;
|
$defaultFontSize = null;
|
||||||
$defaultBold = null;
|
$defaultBold = null;
|
||||||
$defaultItalic = null;
|
$defaultItalic = null;
|
||||||
|
|
|
||||||
|
|
@ -1461,9 +1461,6 @@ class Html extends BaseWriter
|
||||||
foreach ($values as $cellAddress) {
|
foreach ($values as $cellAddress) {
|
||||||
[$cell, $cssClass, $coordinate] = $this->generateRowCellCss($worksheet, $cellAddress, $row, $colNum);
|
[$cell, $cssClass, $coordinate] = $this->generateRowCellCss($worksheet, $cellAddress, $row, $colNum);
|
||||||
|
|
||||||
$colSpan = 1;
|
|
||||||
$rowSpan = 1;
|
|
||||||
|
|
||||||
// Cell Data
|
// Cell Data
|
||||||
$cellData = $this->generateRowCellData($worksheet, $cell, $cssClass, $cellType);
|
$cellData = $this->generateRowCellData($worksheet, $cell, $cssClass, $cellType);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Settings;
|
||||||
|
|
||||||
|
class AddressInternationalTest extends AllSetupTeardown
|
||||||
|
{
|
||||||
|
/** @var string */
|
||||||
|
private $locale;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->locale = Settings::getLocale();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
Settings::setLocale($this->locale);
|
||||||
|
// CompatibilityMode is restored in parent
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerInternational
|
||||||
|
*/
|
||||||
|
public function testR1C1International(string $locale, string $r, string $c): void
|
||||||
|
{
|
||||||
|
if ($locale !== '') {
|
||||||
|
Settings::setLocale($locale);
|
||||||
|
}
|
||||||
|
$sheet = $this->getSheet();
|
||||||
|
$sheet->getCell('A1')->setValue('=LEFT(ADDRESS(1,1,1,0),1)');
|
||||||
|
$sheet->getCell('A2')->setValue('=MID(ADDRESS(1,1,1,0),3,1)');
|
||||||
|
self::assertSame($r, $sheet->getCell('A1')->getCalculatedValue());
|
||||||
|
self::assertSame($c, $sheet->getCell('A2')->getCalculatedValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerInternational(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'Default' => ['', 'R', 'C'],
|
||||||
|
'English' => ['en', 'R', 'C'],
|
||||||
|
'French' => ['fr', 'L', 'C'],
|
||||||
|
'German' => ['de', 'Z', 'S'],
|
||||||
|
'Made-up' => ['xx', 'R', 'C'],
|
||||||
|
'Spanish' => ['es', 'F', 'C'],
|
||||||
|
'Bulgarian' => ['bg', 'R', 'C'],
|
||||||
|
'Czech' => ['cs', 'R', 'C'], // maybe should be R/S
|
||||||
|
'Polish' => ['pl', 'R', 'C'], // maybe should be W/K
|
||||||
|
'Turkish' => ['tr', 'R', 'C'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerCompatibility
|
||||||
|
*/
|
||||||
|
public function testCompatibilityInternational(string $compatibilityMode, string $r, string $c): void
|
||||||
|
{
|
||||||
|
Functions::setCompatibilityMode($compatibilityMode);
|
||||||
|
Settings::setLocale('de');
|
||||||
|
$sheet = $this->getSheet();
|
||||||
|
$sheet->getCell('A1')->setValue('=LEFT(ADDRESS(1,1,1,0),1)');
|
||||||
|
$sheet->getCell('A2')->setValue('=MID(ADDRESS(1,1,1,0),3,1)');
|
||||||
|
self::assertSame($r, $sheet->getCell('A1')->getCalculatedValue());
|
||||||
|
self::assertSame($c, $sheet->getCell('A2')->getCalculatedValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerCompatibility(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[Functions::COMPATIBILITY_EXCEL, 'Z', 'S'],
|
||||||
|
[Functions::COMPATIBILITY_OPENOFFICE, 'R', 'C'],
|
||||||
|
[Functions::COMPATIBILITY_GNUMERIC, 'R', 'C'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,17 +3,11 @@
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
|
use PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class AddressTest extends TestCase
|
class AddressTest extends TestCase
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerADDRESS
|
* @dataProvider providerADDRESS
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Settings;
|
||||||
|
|
||||||
|
class IndirectInternationalTest extends AllSetupTeardown
|
||||||
|
{
|
||||||
|
/** @var string */
|
||||||
|
private $locale;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->locale = Settings::getLocale();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
Settings::setLocale($this->locale);
|
||||||
|
// CompatibilityMode is restored in parent
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerInternational
|
||||||
|
*/
|
||||||
|
public function testR1C1International(string $locale): void
|
||||||
|
{
|
||||||
|
Settings::setLocale($locale);
|
||||||
|
$sameAsEnglish = ['en', 'xx', 'ru', 'tr', 'cs', 'pl'];
|
||||||
|
$sheet = $this->getSheet();
|
||||||
|
$sheet->getCell('C1')->setValue('text');
|
||||||
|
$sheet->getCell('A2')->setValue('en');
|
||||||
|
$sheet->getCell('B2')->setValue('=INDIRECT("R1C3", false)');
|
||||||
|
$sheet->getCell('A3')->setValue('fr');
|
||||||
|
$sheet->getCell('B3')->setValue('=INDIRECT("L1C3", false)');
|
||||||
|
$sheet->getCell('A4')->setValue('de');
|
||||||
|
$sheet->getCell('B4')->setValue('=INDIRECT("Z1S3", false)');
|
||||||
|
$sheet->getCell('A5')->setValue('es');
|
||||||
|
$sheet->getCell('B5')->setValue('=INDIRECT("F1C3", false)');
|
||||||
|
$sheet->getCell('A6')->setValue('xx');
|
||||||
|
$sheet->getCell('B6')->setValue('=INDIRECT("R1C3", false)');
|
||||||
|
$sheet->getCell('A7')->setValue('ru');
|
||||||
|
$sheet->getCell('B7')->setValue('=INDIRECT("R1C3", false)');
|
||||||
|
$sheet->getCell('A8')->setValue('cs');
|
||||||
|
$sheet->getCell('B8')->setValue('=INDIRECT("R1C3", false)');
|
||||||
|
$sheet->getCell('A9')->setValue('tr');
|
||||||
|
$sheet->getCell('B9')->setValue('=INDIRECT("R1C3", false)');
|
||||||
|
$sheet->getCell('A10')->setValue('pl');
|
||||||
|
$sheet->getCell('B10')->setValue('=INDIRECT("R1C3", false)');
|
||||||
|
$maxRow = $sheet->getHighestRow();
|
||||||
|
for ($row = 2; $row <= $maxRow; ++$row) {
|
||||||
|
$rowLocale = $sheet->getCell("A$row")->getValue();
|
||||||
|
if (in_array($rowLocale, $sameAsEnglish, true) && in_array($locale, $sameAsEnglish, true)) {
|
||||||
|
$expectedResult = 'text';
|
||||||
|
} else {
|
||||||
|
$expectedResult = ($locale === $sheet->getCell("A$row")->getValue()) ? 'text' : '#REF!';
|
||||||
|
}
|
||||||
|
self::assertSame($expectedResult, $sheet->getCell("B$row")->getCalculatedValue(), "Locale $locale error in cell B$row $rowLocale");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerInternational(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'English' => ['en'],
|
||||||
|
'French' => ['fr'],
|
||||||
|
'German' => ['de'],
|
||||||
|
'Made-up' => ['xx'],
|
||||||
|
'Spanish' => ['es'],
|
||||||
|
'Russian' => ['ru'],
|
||||||
|
'Czech' => ['cs'],
|
||||||
|
'Polish' => ['pl'],
|
||||||
|
'Turkish' => ['tr'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerRelativeInternational
|
||||||
|
*/
|
||||||
|
public function testRelativeInternational(string $locale, string $cell, string $relative): void
|
||||||
|
{
|
||||||
|
Settings::setLocale($locale);
|
||||||
|
$sheet = $this->getSheet();
|
||||||
|
$sheet->getCell('C3')->setValue('text');
|
||||||
|
$sheet->getCell($cell)->setValue("=INDIRECT(\"$relative\", false)");
|
||||||
|
self::assertSame('text', $sheet->getCell($cell)->getCalculatedValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerRelativeInternational(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'English A3' => ['en', 'A3', 'R[]C[+2]'],
|
||||||
|
'French B4' => ['fr', 'B4', 'L[-1]C[+1]'],
|
||||||
|
'German C5' => ['de', 'C5', 'Z[-2]S[]'],
|
||||||
|
'Spanish E1' => ['es', 'E1', 'F[+2]C[-2]'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerCompatibility
|
||||||
|
*/
|
||||||
|
public function testCompatibilityInternational(string $compatibilityMode): void
|
||||||
|
{
|
||||||
|
Functions::setCompatibilityMode($compatibilityMode);
|
||||||
|
if ($compatibilityMode === Functions::COMPATIBILITY_EXCEL) {
|
||||||
|
$expected1 = '#REF!';
|
||||||
|
$expected2 = 'text';
|
||||||
|
} else {
|
||||||
|
$expected2 = '#REF!';
|
||||||
|
$expected1 = 'text';
|
||||||
|
}
|
||||||
|
Settings::setLocale('fr');
|
||||||
|
$sheet = $this->getSheet();
|
||||||
|
$sheet->getCell('C3')->setValue('text');
|
||||||
|
$sheet->getCell('A1')->setValue('=INDIRECT("R3C3", false)');
|
||||||
|
$sheet->getCell('A2')->setValue('=INDIRECT("L3C3", false)');
|
||||||
|
self::assertSame($expected1, $sheet->getCell('A1')->getCalculatedValue());
|
||||||
|
self::assertSame($expected2, $sheet->getCell('A2')->getCalculatedValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerCompatibility(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[Functions::COMPATIBILITY_EXCEL],
|
||||||
|
[Functions::COMPATIBILITY_OPENOFFICE],
|
||||||
|
[Functions::COMPATIBILITY_GNUMERIC],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -132,4 +132,48 @@ class IndirectTest extends AllSetupTeardown
|
||||||
$result = \PhpOffice\PhpSpreadsheet\Calculation\Functions::flattenSingleValue($result);
|
$result = \PhpOffice\PhpSpreadsheet\Calculation\Functions::flattenSingleValue($result);
|
||||||
self::assertSame('This is it', $result);
|
self::assertSame('This is it', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null|int|string $expectedResult
|
||||||
|
*
|
||||||
|
* @dataProvider providerRelative
|
||||||
|
*/
|
||||||
|
public function testR1C1Relative($expectedResult, string $address): void
|
||||||
|
{
|
||||||
|
$sheet = $this->getSheet();
|
||||||
|
$sheet->fromArray([
|
||||||
|
['a1', 'b1', 'c1'],
|
||||||
|
['a2', 'b2', 'c2'],
|
||||||
|
['a3', 'b3', 'c3'],
|
||||||
|
['a4', 'b4', 'c4'],
|
||||||
|
]);
|
||||||
|
$sheet->getCell('B2')->setValue('=INDIRECT("' . $address . '", false)');
|
||||||
|
self::assertSame($expectedResult, $sheet->getCell('B2')->getCalculatedValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerRelative(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'same row with bracket next column' => ['c2', 'R[]C[+1]'],
|
||||||
|
'same row without bracket next column' => ['c2', 'RC[+1]'],
|
||||||
|
'same row without bracket next column no plus sign' => ['c2', 'RC[1]'],
|
||||||
|
'same row previous column' => ['a2', 'RC[-1]'],
|
||||||
|
'previous row previous column' => ['a1', 'R[-1]C[-1]'],
|
||||||
|
'previous row same column with bracket' => ['b1', 'R[-1]C[]'],
|
||||||
|
'previous row same column without bracket' => ['b1', 'R[-1]C'],
|
||||||
|
'previous row next column' => ['c1', 'R[-1]C[+1]'],
|
||||||
|
'next row no plus sign previous column' => ['a3', 'R[1]C[-1]'],
|
||||||
|
'next row previous column' => ['a3', 'R[+1]C[-1]'],
|
||||||
|
'next row same column' => ['b3', 'R[+1]C'],
|
||||||
|
'next row next column' => ['c3', 'R[+1]C[+1]'],
|
||||||
|
'two rows down same column' => ['b4', 'R[+2]C'],
|
||||||
|
'invalid row' => ['#REF!', 'R[-2]C'],
|
||||||
|
'invalid column' => ['#REF!', 'RC[-2]'],
|
||||||
|
'circular reference' => [0, 'RC'], // matches Excel's treatment
|
||||||
|
'absolute row absolute column' => ['c2', 'R2C3'],
|
||||||
|
'absolute row relative column' => ['a2', 'R2C[-1]'],
|
||||||
|
'relative row absolute column lowercase' => ['a2', 'rc1'],
|
||||||
|
'uninitialized cell' => [null, 'RC[+2]'], // Excel result is 0
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,18 +19,23 @@ class TranslationTest extends TestCase
|
||||||
*/
|
*/
|
||||||
private $returnDate;
|
private $returnDate;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private $locale;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->compatibilityMode = Functions::getCompatibilityMode();
|
$this->compatibilityMode = Functions::getCompatibilityMode();
|
||||||
$this->returnDate = Functions::getReturnDateType();
|
$this->returnDate = Functions::getReturnDateType();
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||||
Functions::setReturnDateType(Functions::RETURNDATE_EXCEL);
|
Functions::setReturnDateType(Functions::RETURNDATE_EXCEL);
|
||||||
|
$this->locale = Settings::getLocale();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function tearDown(): void
|
protected function tearDown(): void
|
||||||
{
|
{
|
||||||
Functions::setCompatibilityMode($this->compatibilityMode);
|
Functions::setCompatibilityMode($this->compatibilityMode);
|
||||||
Functions::setReturnDateType($this->returnDate);
|
Functions::setReturnDateType($this->returnDate);
|
||||||
|
Settings::setLocale($this->locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -11,31 +11,59 @@ class LocaleGeneratorTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testLocaleGenerator(): void
|
public function testLocaleGenerator(): void
|
||||||
{
|
{
|
||||||
|
$directory = realpath(__DIR__ . '/../../src/PhpSpreadsheet/Calculation/locale/') ?: '';
|
||||||
|
self::assertNotEquals('', $directory);
|
||||||
$phpSpreadsheetFunctionsProperty = (new ReflectionClass(Calculation::class))
|
$phpSpreadsheetFunctionsProperty = (new ReflectionClass(Calculation::class))
|
||||||
->getProperty('phpSpreadsheetFunctions');
|
->getProperty('phpSpreadsheetFunctions');
|
||||||
$phpSpreadsheetFunctionsProperty->setAccessible(true);
|
$phpSpreadsheetFunctionsProperty->setAccessible(true);
|
||||||
$phpSpreadsheetFunctions = $phpSpreadsheetFunctionsProperty->getValue();
|
$phpSpreadsheetFunctions = $phpSpreadsheetFunctionsProperty->getValue();
|
||||||
|
|
||||||
$localeGenerator = new LocaleGenerator(
|
$localeGenerator = new LocaleGenerator(
|
||||||
(string) realpath(__DIR__ . '/../../src/PhpSpreadsheet/Calculation/locale/'),
|
$directory . DIRECTORY_SEPARATOR,
|
||||||
'Translations.xlsx',
|
'Translations.xlsx',
|
||||||
$phpSpreadsheetFunctions
|
$phpSpreadsheetFunctions
|
||||||
);
|
);
|
||||||
$localeGenerator->generateLocales();
|
$localeGenerator->generateLocales();
|
||||||
|
|
||||||
$testLocales = [
|
$testLocales = [
|
||||||
|
'bg',
|
||||||
|
'cs',
|
||||||
|
'da',
|
||||||
|
'de',
|
||||||
|
'en',
|
||||||
|
'es',
|
||||||
|
'fi',
|
||||||
'fr',
|
'fr',
|
||||||
|
'hu',
|
||||||
|
'it',
|
||||||
|
'nb',
|
||||||
'nl',
|
'nl',
|
||||||
|
'pl',
|
||||||
'pt',
|
'pt',
|
||||||
'pt_br',
|
|
||||||
'ru',
|
'ru',
|
||||||
|
'sv',
|
||||||
|
'tr',
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($testLocales as $locale) {
|
$count = count(glob($directory . DIRECTORY_SEPARATOR . '*') ?: []) - 1; // exclude Translations.xlsx
|
||||||
$locale = str_replace('_', '/', $locale);
|
self::assertCount($count, $testLocales);
|
||||||
$path = realpath(__DIR__ . "/../../src/PhpSpreadsheet/Calculation/locale/{$locale}");
|
$testLocales[] = 'pt_br';
|
||||||
self::assertFileExists("{$path}/config");
|
$testLocales[] = 'en_uk';
|
||||||
self::assertFileExists("{$path}/functions");
|
$noconfig = ['en'];
|
||||||
|
$nofunctions = ['en', 'en_uk'];
|
||||||
|
foreach ($testLocales as $originalLocale) {
|
||||||
|
$locale = str_replace('_', DIRECTORY_SEPARATOR, $originalLocale);
|
||||||
|
$path = $directory . DIRECTORY_SEPARATOR . $locale;
|
||||||
|
if (in_array($originalLocale, $noconfig, true)) {
|
||||||
|
self::assertFileDoesNotExist($path . DIRECTORY_SEPARATOR . 'config');
|
||||||
|
} else {
|
||||||
|
self::assertFileExists($path . DIRECTORY_SEPARATOR . 'config');
|
||||||
|
}
|
||||||
|
if (in_array($originalLocale, $nofunctions, true)) {
|
||||||
|
self::assertFileDoesNotExist($path . DIRECTORY_SEPARATOR . 'functions');
|
||||||
|
} else {
|
||||||
|
self::assertFileExists($path . DIRECTORY_SEPARATOR . 'functions');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Reader\Csv;
|
namespace PhpOffice\PhpSpreadsheetTests\Reader\Csv;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\IValueBinder;
|
use PhpOffice\PhpSpreadsheet\Cell\IValueBinder;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\StringValueBinder;
|
use PhpOffice\PhpSpreadsheet\Cell\StringValueBinder;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Csv;
|
use PhpOffice\PhpSpreadsheet\Reader\Csv;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Settings;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class CsvIssue2232Test extends TestCase
|
class CsvIssue2232Test extends TestCase
|
||||||
|
|
@ -16,14 +16,19 @@ class CsvIssue2232Test extends TestCase
|
||||||
*/
|
*/
|
||||||
private $valueBinder;
|
private $valueBinder;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private $locale;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->valueBinder = Cell::getValueBinder();
|
$this->valueBinder = Cell::getValueBinder();
|
||||||
|
$this->locale = Settings::getLocale();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function tearDown(): void
|
protected function tearDown(): void
|
||||||
{
|
{
|
||||||
Cell::setValueBinder($this->valueBinder);
|
Cell::setValueBinder($this->valueBinder);
|
||||||
|
Settings::setLocale($this->locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -78,7 +83,7 @@ class CsvIssue2232Test extends TestCase
|
||||||
Cell::setValueBinder($binder);
|
Cell::setValueBinder($binder);
|
||||||
}
|
}
|
||||||
|
|
||||||
Calculation::getInstance()->setLocale('fr');
|
Settings::setLocale('fr');
|
||||||
|
|
||||||
$reader = new Csv();
|
$reader = new Csv();
|
||||||
$filename = 'tests/data/Reader/CSV/issue.2232.csv';
|
$filename = 'tests/data/Reader/CSV/issue.2232.csv';
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ class AutoFilter2Test extends TestCase
|
||||||
self::assertCount(1, $columns);
|
self::assertCount(1, $columns);
|
||||||
$column = $columns['A'] ?? null;
|
$column = $columns['A'] ?? null;
|
||||||
self::assertNotNull($column);
|
self::assertNotNull($column);
|
||||||
|
/** @scrutinizer ignore-call */
|
||||||
$ruleset = $column->getRules();
|
$ruleset = $column->getRules();
|
||||||
self::assertCount(1, $ruleset);
|
self::assertCount(1, $ruleset);
|
||||||
$rule = $ruleset[0];
|
$rule = $ruleset[0];
|
||||||
|
|
|
||||||
|
|
@ -14,19 +14,25 @@ class PageSetupTest extends TestCase
|
||||||
private const MARGIN_UNIT_CONVERSION = 2.54; // Inches to cm
|
private const MARGIN_UNIT_CONVERSION = 2.54; // Inches to cm
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Spreadsheet
|
* @var ?Spreadsheet
|
||||||
*/
|
*/
|
||||||
private $spreadsheet;
|
private $spreadsheet;
|
||||||
|
|
||||||
protected function setup(): void
|
/** @var string */
|
||||||
|
private $filename = 'tests/data/Reader/Xml/PageSetup.xml';
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
{
|
{
|
||||||
$filename = 'tests/data/Reader/Xml/PageSetup.xml';
|
if ($this->spreadsheet !== null) {
|
||||||
$reader = new Xml();
|
$this->spreadsheet->disconnectWorksheets();
|
||||||
$this->spreadsheet = $reader->load($filename);
|
$this->spreadsheet = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPageSetup(): void
|
public function testPageSetup(): void
|
||||||
{
|
{
|
||||||
|
$reader = new Xml();
|
||||||
|
$this->spreadsheet = $reader->load($this->filename);
|
||||||
$assertions = $this->pageSetupAssertions();
|
$assertions = $this->pageSetupAssertions();
|
||||||
|
|
||||||
foreach ($this->spreadsheet->getAllSheets() as $worksheet) {
|
foreach ($this->spreadsheet->getAllSheets() as $worksheet) {
|
||||||
|
|
@ -49,6 +55,8 @@ class PageSetupTest extends TestCase
|
||||||
|
|
||||||
public function testPageMargins(): void
|
public function testPageMargins(): void
|
||||||
{
|
{
|
||||||
|
$reader = new Xml();
|
||||||
|
$this->spreadsheet = $reader->load($this->filename);
|
||||||
$assertions = $this->pageMarginAssertions();
|
$assertions = $this->pageMarginAssertions();
|
||||||
|
|
||||||
foreach ($this->spreadsheet->getAllSheets() as $worksheet) {
|
foreach ($this->spreadsheet->getAllSheets() as $worksheet) {
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,51 @@ namespace PhpOffice\PhpSpreadsheetTests\Reader\Xml;
|
||||||
|
|
||||||
use DateTimeZone;
|
use DateTimeZone;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Xml;
|
use PhpOffice\PhpSpreadsheet\Reader\Xml;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Settings;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class XmlLoadTest extends TestCase
|
class XmlLoadTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testLoad(): void
|
/** @var ?Spreadsheet */
|
||||||
|
private $spreadsheet;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private $locale;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->locale = Settings::getLocale();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
if ($this->spreadsheet !== null) {
|
||||||
|
$this->spreadsheet->disconnectWorksheets();
|
||||||
|
$this->spreadsheet = null;
|
||||||
|
}
|
||||||
|
Settings::setLocale($this->locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadEnglish(): void
|
||||||
|
{
|
||||||
|
$this->xtestLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadFrench(): void
|
||||||
|
{
|
||||||
|
Settings::setLocale('fr');
|
||||||
|
$this->xtestLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function xtestLoad(): void
|
||||||
{
|
{
|
||||||
$filename = __DIR__
|
$filename = __DIR__
|
||||||
. '/../../../..'
|
. '/../../../..'
|
||||||
. '/samples/templates/excel2003.xml';
|
. '/samples/templates/excel2003.xml';
|
||||||
$reader = new Xml();
|
$reader = new Xml();
|
||||||
$spreadsheet = $reader->load($filename);
|
$this->spreadsheet = $spreadsheet = $reader->load($filename);
|
||||||
self::assertEquals(2, $spreadsheet->getSheetCount());
|
self::assertEquals(2, $spreadsheet->getSheetCount());
|
||||||
|
|
||||||
$sheet = $spreadsheet->getSheet(1);
|
$sheet = $spreadsheet->getSheet(1);
|
||||||
|
|
@ -71,7 +104,7 @@ class XmlLoadTest extends TestCase
|
||||||
$reader = new Xml();
|
$reader = new Xml();
|
||||||
$filter = new XmlFilter();
|
$filter = new XmlFilter();
|
||||||
$reader->setReadFilter($filter);
|
$reader->setReadFilter($filter);
|
||||||
$spreadsheet = $reader->load($filename);
|
$this->spreadsheet = $spreadsheet = $reader->load($filename);
|
||||||
self::assertEquals(2, $spreadsheet->getSheetCount());
|
self::assertEquals(2, $spreadsheet->getSheetCount());
|
||||||
$sheet = $spreadsheet->getSheet(1);
|
$sheet = $spreadsheet->getSheet(1);
|
||||||
self::assertEquals('Report Data', $sheet->getTitle());
|
self::assertEquals('Report Data', $sheet->getTitle());
|
||||||
|
|
@ -87,7 +120,7 @@ class XmlLoadTest extends TestCase
|
||||||
. '/samples/templates/excel2003.xml';
|
. '/samples/templates/excel2003.xml';
|
||||||
$reader = new Xml();
|
$reader = new Xml();
|
||||||
$reader->setLoadSheetsOnly(['Unknown Sheet', 'Report Data']);
|
$reader->setLoadSheetsOnly(['Unknown Sheet', 'Report Data']);
|
||||||
$spreadsheet = $reader->load($filename);
|
$this->spreadsheet = $spreadsheet = $reader->load($filename);
|
||||||
self::assertEquals(1, $spreadsheet->getSheetCount());
|
self::assertEquals(1, $spreadsheet->getSheetCount());
|
||||||
$sheet = $spreadsheet->getSheet(0);
|
$sheet = $spreadsheet->getSheet(0);
|
||||||
self::assertEquals('Report Data', $sheet->getTitle());
|
self::assertEquals('Report Data', $sheet->getTitle());
|
||||||
|
|
@ -102,7 +135,7 @@ class XmlLoadTest extends TestCase
|
||||||
. '/../../../..'
|
. '/../../../..'
|
||||||
. '/samples/templates/excel2003.short.bad.xml';
|
. '/samples/templates/excel2003.short.bad.xml';
|
||||||
$reader = new Xml();
|
$reader = new Xml();
|
||||||
$spreadsheet = $reader->load($filename);
|
$this->spreadsheet = $spreadsheet = $reader->load($filename);
|
||||||
self::assertEquals(1, $spreadsheet->getSheetCount());
|
self::assertEquals(1, $spreadsheet->getSheetCount());
|
||||||
$sheet = $spreadsheet->getSheet(0);
|
$sheet = $spreadsheet->getSheet(0);
|
||||||
self::assertEquals('Sample Data', $sheet->getTitle());
|
self::assertEquals('Sample Data', $sheet->getTitle());
|
||||||
|
|
|
||||||
|
|
@ -87,12 +87,14 @@ class FileTest extends TestCase
|
||||||
|
|
||||||
public function testNotReadable(): void
|
public function testNotReadable(): void
|
||||||
{
|
{
|
||||||
if (PHP_OS_FAMILY === 'Windows') {
|
if (PHP_OS_FAMILY === 'Windows' || stristr(PHP_OS, 'CYGWIN') !== false) {
|
||||||
self::markTestSkipped('chmod does not work reliably on Windows');
|
self::markTestSkipped('chmod does not work reliably on Windows');
|
||||||
}
|
}
|
||||||
$this->tempfile = $temp = File::temporaryFileName();
|
$this->tempfile = $temp = File::temporaryFileName();
|
||||||
file_put_contents($temp, '');
|
file_put_contents($temp, '');
|
||||||
chmod($temp, 0070);
|
if (chmod($temp, 0070) === false) {
|
||||||
|
self::markTestSkipped('chmod failed');
|
||||||
|
}
|
||||||
self::assertFalse(File::testFileNoThrow($temp));
|
self::assertFalse(File::testFileNoThrow($temp));
|
||||||
$this->expectException(ReaderException::class);
|
$this->expectException(ReaderException::class);
|
||||||
$this->expectExceptionMessage('for reading');
|
$this->expectExceptionMessage('for reading');
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,22 @@ return [
|
||||||
false,
|
false,
|
||||||
'EXCEL SHEET',
|
'EXCEL SHEET',
|
||||||
],
|
],
|
||||||
|
'0 instead of bool for 4th arg' => [
|
||||||
|
"'EXCEL SHEET'!R2C3",
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
'EXCEL SHEET',
|
||||||
|
],
|
||||||
|
'1 instead of bool for 4th arg' => [
|
||||||
|
"'EXCEL SHEET'!\$C\$2",
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
'EXCEL SHEET',
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"'EXCEL SHEET'!\$C\$2",
|
"'EXCEL SHEET'!\$C\$2",
|
||||||
2,
|
2,
|
||||||
|
|
|
||||||
|
|
@ -80,4 +80,14 @@ return [
|
||||||
'nb',
|
'nb',
|
||||||
'=MAX(ABS({2,-3;-4,5}), ABS{-2,3;4,-5})',
|
'=MAX(ABS({2,-3;-4,5}), ABS{-2,3;4,-5})',
|
||||||
],
|
],
|
||||||
|
'not fooled by *RC' => [
|
||||||
|
'=3*RC(B1)',
|
||||||
|
'fr',
|
||||||
|
'=3*RC(B1)',
|
||||||
|
],
|
||||||
|
'handle * for ROW' => [
|
||||||
|
'=3*LIGNE(B1)',
|
||||||
|
'fr',
|
||||||
|
'=3*ROW(B1)',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue