Merge branch 'master' into Issue-3056_Update-DataValidation-SqRef-On-Insert-Delete-Rows-Columns

This commit is contained in:
Mark Baker 2022-09-18 17:26:27 +02:00 committed by GitHub
commit a6cfd8c504
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 465 additions and 57 deletions

View File

@ -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

View File

@ -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",

14
composer.lock generated
View File

@ -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",

View File

@ -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;

View File

@ -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;
} }
} }

View File

@ -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}";
} }
} }

View File

@ -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];
} }

View File

@ -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)) ||

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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]));
} }
} }

View File

@ -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;

View File

@ -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);

View File

@ -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'],
];
}
}

View File

@ -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
* *

View File

@ -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],
];
}
}

View File

@ -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
];
}
} }

View File

@ -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);
} }
/** /**

View File

@ -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');
}
} }
} }
} }

View File

@ -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';

View File

@ -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];

View File

@ -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) {

View File

@ -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());

View File

@ -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');

View File

@ -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,

View File

@ -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)',
],
]; ];