Merge branch 'master' into Named-Range-Alias-Cell-Collection

This commit is contained in:
MarkBaker 2022-05-01 09:14:38 +02:00
commit 5112503a06
8 changed files with 77 additions and 107 deletions

View File

@ -20,16 +20,6 @@ parameters:
count: 6 count: 6
path: src/PhpSpreadsheet/Calculation/Calculation.php path: src/PhpSpreadsheet/Calculation/Calculation.php
-
message: "#^Cannot call method getColumn\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\|null\\.$#"
count: 2
path: src/PhpSpreadsheet/Calculation/Calculation.php
-
message: "#^Cannot call method getCoordinate\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\|null\\.$#"
count: 2
path: src/PhpSpreadsheet/Calculation/Calculation.php
- -
message: "#^Cannot call method getHighestColumn\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#" message: "#^Cannot call method getHighestColumn\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
count: 1 count: 1
@ -40,21 +30,6 @@ parameters:
count: 1 count: 1
path: src/PhpSpreadsheet/Calculation/Calculation.php path: src/PhpSpreadsheet/Calculation/Calculation.php
-
message: "#^Cannot call method getRow\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\|null\\.$#"
count: 2
path: src/PhpSpreadsheet/Calculation/Calculation.php
-
message: "#^Cannot call method getTitle\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
count: 1
path: src/PhpSpreadsheet/Calculation/Calculation.php
-
message: "#^Cannot call method has\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Collection\\\\Cells\\|null\\.$#"
count: 1
path: src/PhpSpreadsheet/Calculation/Calculation.php
- -
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:_translateFormulaToEnglish\\(\\) has no return type specified\\.$#" message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:_translateFormulaToEnglish\\(\\) has no return type specified\\.$#"
count: 1 count: 1
@ -140,11 +115,6 @@ parameters:
count: 1 count: 1
path: src/PhpSpreadsheet/Calculation/Calculation.php path: src/PhpSpreadsheet/Calculation/Calculation.php
-
message: "#^Parameter \\#1 \\$parent of method PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\:\\:attach\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Collection\\\\Cells, PhpOffice\\\\PhpSpreadsheet\\\\Collection\\\\Cells\\|null given\\.$#"
count: 1
path: src/PhpSpreadsheet/Calculation/Calculation.php
- -
message: "#^Parameter \\#1 \\$str of function preg_quote expects string, int\\|string given\\.$#" message: "#^Parameter \\#1 \\$str of function preg_quote expects string, int\\|string given\\.$#"
count: 1 count: 1
@ -790,26 +760,6 @@ parameters:
count: 3 count: 3
path: src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php path: src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\VLookup\\:\\:vlookupSort\\(\\) has no return type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\VLookup\\:\\:vlookupSort\\(\\) has parameter \\$a with no type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\VLookup\\:\\:vlookupSort\\(\\) has parameter \\$b with no type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php
-
message: "#^Parameter \\#2 \\$callback of function uasort expects callable\\(T, T\\)\\: int, array\\{'self', 'vlookupSort'\\} given\\.$#"
count: 1
path: src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php
- -
message: "#^Binary operation \"/\" between array\\|float\\|int\\|string and array\\|float\\|int\\|string results in an error\\.$#" message: "#^Binary operation \"/\" between array\\|float\\|int\\|string and array\\|float\\|int\\|string results in an error\\.$#"
count: 2 count: 2
@ -2370,36 +2320,6 @@ parameters:
count: 1 count: 1
path: src/PhpSpreadsheet/Reader/Xls/ErrorCode.php path: src/PhpSpreadsheet/Reader/Xls/ErrorCode.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\\\MD5\\:\\:f\\(\\) has no return type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Reader/Xls/MD5.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\\\MD5\\:\\:g\\(\\) has no return type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Reader/Xls/MD5.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\\\MD5\\:\\:h\\(\\) has no return type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Reader/Xls/MD5.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\\\MD5\\:\\:i\\(\\) has no return type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Reader/Xls/MD5.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\\\MD5\\:\\:rotate\\(\\) has no return type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Reader/Xls/MD5.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\\\MD5\\:\\:step\\(\\) has parameter \\$func with no type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Reader/Xls/MD5.php
- -
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\\\RC4\\:\\:\\$i has no type specified\\.$#" message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\\\RC4\\:\\:\\$i has no type specified\\.$#"
count: 1 count: 1

View File

@ -3223,10 +3223,11 @@ class Calculation
// So instead we skip replacing in any quoted strings by only replacing in every other array element // So instead we skip replacing in any quoted strings by only replacing in every other array element
// after we've exploded the formula // after we've exploded the formula
$temp = explode(self::FORMULA_STRING_QUOTE, $formula); $temp = explode(self::FORMULA_STRING_QUOTE, $formula);
$i = false; $notWithinQuotes = false;
foreach ($temp as &$value) { foreach ($temp as &$value) {
// Only adjust in alternating array entries // Only adjust in alternating array entries
if ($i = !$i) { $notWithinQuotes = !$notWithinQuotes;
if ($notWithinQuotes === true) {
$value = self::translateFormulaBlock($from, $to, $value, $inFunctionBracesLevel, $inMatrixBracesLevel, $fromSeparator, $toSeparator); $value = self::translateFormulaBlock($from, $to, $value, $inFunctionBracesLevel, $inMatrixBracesLevel, $fromSeparator, $toSeparator);
} }
} }
@ -3898,10 +3899,11 @@ class Calculation
$temp = explode(self::FORMULA_STRING_QUOTE, $formula); $temp = explode(self::FORMULA_STRING_QUOTE, $formula);
// Open and Closed counts used for trapping mismatched braces in the formula // Open and Closed counts used for trapping mismatched braces in the formula
$openCount = $closeCount = 0; $openCount = $closeCount = 0;
$i = false; $notWithinQuotes = false;
foreach ($temp as &$value) { foreach ($temp as &$value) {
// Only count/replace in alternating array entries // Only count/replace in alternating array entries
if ($i = !$i) { $notWithinQuotes = !$notWithinQuotes;
if ($notWithinQuotes === true) {
$openCount += substr_count($value, self::FORMULA_OPEN_MATRIX_BRACE); $openCount += substr_count($value, self::FORMULA_OPEN_MATRIX_BRACE);
$closeCount += substr_count($value, self::FORMULA_CLOSE_MATRIX_BRACE); $closeCount += substr_count($value, self::FORMULA_CLOSE_MATRIX_BRACE);
$value = str_replace($matrixReplaceFrom, $matrixReplaceTo, $value); $value = str_replace($matrixReplaceFrom, $matrixReplaceTo, $value);
@ -4593,7 +4595,7 @@ class Calculation
if (strpos($operand1Data['reference'], '!') !== false) { if (strpos($operand1Data['reference'], '!') !== false) {
[$sheet1, $operand1Data['reference']] = Worksheet::extractSheetTitle($operand1Data['reference'], true); [$sheet1, $operand1Data['reference']] = Worksheet::extractSheetTitle($operand1Data['reference'], true);
} else { } else {
$sheet1 = ($pCellParent !== null) ? $pCellWorksheet->getTitle() : ''; $sheet1 = ($pCellWorksheet !== null) ? $pCellWorksheet->getTitle() : '';
} }
[$sheet2, $operand2Data['reference']] = Worksheet::extractSheetTitle($operand2Data['reference'], true); [$sheet2, $operand2Data['reference']] = Worksheet::extractSheetTitle($operand2Data['reference'], true);
@ -4602,21 +4604,23 @@ class Calculation
} }
if (trim($sheet1, "'") === trim($sheet2, "'")) { if (trim($sheet1, "'") === trim($sheet2, "'")) {
if ($operand1Data['reference'] === null) { if ($operand1Data['reference'] === null && $cell !== null) {
if ((trim($operand1Data['value']) != '') && (is_numeric($operand1Data['value']))) { if (is_array($operand1Data['value'])) {
$operand1Data['reference'] = $cell->getCoordinate();
} elseif ((trim($operand1Data['value']) != '') && (is_numeric($operand1Data['value']))) {
$operand1Data['reference'] = $cell->getColumn() . $operand1Data['value']; $operand1Data['reference'] = $cell->getColumn() . $operand1Data['value'];
// @phpstan-ignore-next-line } elseif (trim($operand1Data['value']) == '') {
} elseif (trim($operand1Data['reference']) == '') {
$operand1Data['reference'] = $cell->getCoordinate(); $operand1Data['reference'] = $cell->getCoordinate();
} else { } else {
$operand1Data['reference'] = $operand1Data['value'] . $cell->getRow(); $operand1Data['reference'] = $operand1Data['value'] . $cell->getRow();
} }
} }
if ($operand2Data['reference'] === null) { if ($operand2Data['reference'] === null && $cell !== null) {
if ((trim($operand2Data['value']) != '') && (is_numeric($operand2Data['value']))) { if (is_array($operand2Data['value'])) {
$operand2Data['reference'] = $cell->getCoordinate();
} elseif ((trim($operand2Data['value']) != '') && (is_numeric($operand2Data['value']))) {
$operand2Data['reference'] = $cell->getColumn() . $operand2Data['value']; $operand2Data['reference'] = $cell->getColumn() . $operand2Data['value'];
// @phpstan-ignore-next-line } elseif (trim($operand2Data['value']) == '') {
} elseif (trim($operand2Data['reference']) == '') {
$operand2Data['reference'] = $cell->getCoordinate(); $operand2Data['reference'] = $cell->getCoordinate();
} else { } else {
$operand2Data['reference'] = $operand2Data['value'] . $cell->getRow(); $operand2Data['reference'] = $operand2Data['value'] . $cell->getRow();
@ -4829,7 +4833,7 @@ class Calculation
$this->debugLog->writeDebugLog('Evaluation Result for cell %s in worksheet %s is %s', $cellRef, $matches[2], $this->showTypeDetails($cellValue)); $this->debugLog->writeDebugLog('Evaluation Result for cell %s in worksheet %s is %s', $cellRef, $matches[2], $this->showTypeDetails($cellValue));
} else { } else {
$this->debugLog->writeDebugLog('Evaluating Cell %s in current worksheet', $cellRef); $this->debugLog->writeDebugLog('Evaluating Cell %s in current worksheet', $cellRef);
if ($pCellParent->has($cellRef)) { if ($pCellParent !== null && $pCellParent->has($cellRef)) {
$cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, false); $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, false);
$cell->attach($pCellParent); $cell->attach($pCellParent);
} else { } else {
@ -5281,7 +5285,7 @@ class Calculation
} }
// Named range? // Named range?
$namedRange = DefinedName::resolveName($range, $worksheet); $namedRange = DefinedName::resolveName($range, /** @scrutinizer ignore-type */ $worksheet);
if ($namedRange === null) { if ($namedRange === null) {
return Information\ExcelError::REF(); return Information\ExcelError::REF();
} }

View File

@ -49,7 +49,9 @@ class VLookup extends LookupBase
$firstColumn = array_shift($columnKeys) ?? 1; $firstColumn = array_shift($columnKeys) ?? 1;
if (!$notExactMatch) { if (!$notExactMatch) {
uasort($lookupArray, ['self', 'vlookupSort']); /** @var callable */
$callable = [self::class, 'vlookupSort'];
uasort($lookupArray, $callable);
} }
$rowNumber = self::vLookupSearch($lookupValue, $lookupArray, $firstColumn, $notExactMatch); $rowNumber = self::vLookupSearch($lookupValue, $lookupArray, $firstColumn, $notExactMatch);
@ -62,7 +64,7 @@ class VLookup extends LookupBase
return ExcelError::NA(); return ExcelError::NA();
} }
private static function vlookupSort($a, $b) private static function vlookupSort(array $a, array $b): int
{ {
reset($a); reset($a);
$firstColumn = key($a); $firstColumn = key($a);

View File

@ -79,10 +79,10 @@ class MD5
$C = $this->c; $C = $this->c;
$D = $this->d; $D = $this->d;
$F = ['self', 'f']; $F = [self::class, 'f'];
$G = ['self', 'g']; $G = [self::class, 'g'];
$H = ['self', 'h']; $H = [self::class, 'h'];
$I = ['self', 'i']; $I = [self::class, 'i'];
// ROUND 1 // ROUND 1
self::step($F, $A, $B, $C, $D, $words[0], 7, 0xd76aa478); self::step($F, $A, $B, $C, $D, $words[0], 7, 0xd76aa478);
@ -162,33 +162,34 @@ class MD5
$this->d = ($this->d + $D) & 0xffffffff; $this->d = ($this->d + $D) & 0xffffffff;
} }
private static function f(int $X, int $Y, int $Z) private static function f(int $X, int $Y, int $Z): int
{ {
return ($X & $Y) | ((~$X) & $Z); // X AND Y OR NOT X AND Z return ($X & $Y) | ((~$X) & $Z); // X AND Y OR NOT X AND Z
} }
private static function g(int $X, int $Y, int $Z) private static function g(int $X, int $Y, int $Z): int
{ {
return ($X & $Z) | ($Y & (~$Z)); // X AND Z OR Y AND NOT Z return ($X & $Z) | ($Y & (~$Z)); // X AND Z OR Y AND NOT Z
} }
private static function h(int $X, int $Y, int $Z) private static function h(int $X, int $Y, int $Z): int
{ {
return $X ^ $Y ^ $Z; // X XOR Y XOR Z return $X ^ $Y ^ $Z; // X XOR Y XOR Z
} }
private static function i(int $X, int $Y, int $Z) private static function i(int $X, int $Y, int $Z): int
{ {
return $Y ^ ($X | (~$Z)); // Y XOR (X OR NOT Z) return $Y ^ ($X | (~$Z)); // Y XOR (X OR NOT Z)
} }
private static function step($func, int &$A, int $B, int $C, int $D, int $M, int $s, int $t): void private static function step(callable $func, int &$A, int $B, int $C, int $D, int $M, int $s, int $t): void
{ {
$A = ($A + call_user_func($func, $B, $C, $D) + $M + $t) & 0xffffffff; $A = ($A + call_user_func($func, $B, $C, $D) + $M + $t) & 0xffffffff;
$A = self::rotate($A, $s); $A = self::rotate($A, $s);
$A = ($B + $A) & 0xffffffff; $A = ($B + $A) & 0xffffffff;
} }
/** @return float|int */
private static function rotate(int $decimal, int $bits) private static function rotate(int $decimal, int $bits)
{ {
$binary = str_pad(decbin($decimal), 32, '0', STR_PAD_LEFT); $binary = str_pad(decbin($decimal), 32, '0', STR_PAD_LEFT);

View File

@ -71,7 +71,7 @@ class Chart
$chartDetailsC = $chartDetails->children($namespacesChartMeta['c']); $chartDetailsC = $chartDetails->children($namespacesChartMeta['c']);
switch ($chartDetailsKey) { switch ($chartDetailsKey) {
case 'plotArea': case 'plotArea':
$plotAreaLayout = $XaxisLable = $YaxisLable = null; $plotAreaLayout = $XaxisLabel = $YaxisLabel = null;
$plotSeries = $plotAttributes = []; $plotSeries = $plotAttributes = [];
foreach ($chartDetails as $chartDetailKey => $chartDetail) { foreach ($chartDetails as $chartDetailKey => $chartDetail) {
switch ($chartDetailKey) { switch ($chartDetailKey) {

View File

@ -0,0 +1,17 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Reader\Xls\MD5;
use PHPUnit\Framework\TestCase;
class Md5Test extends TestCase
{
public function testMd5(): void
{
$md5 = new MD5();
$md5->add('123456789a123456789b123456789c123456789d123456789e123456789f1234');
$context = $md5->getContext();
self::assertSame('0761293f016b925b0bca11b34f1ed613', bin2hex($context));
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PHPUnit\Framework\TestCase;
class Issue2778Test extends TestCase
{
/**
* @var string
*/
private static $testbook = 'tests/data/Reader/XLSX/issue.2778.xlsx';
public function testIssue2778(): void
{
$filename = self::$testbook;
$reader = new Xlsx();
$spreadsheet = $reader->load($filename);
$sheet = $spreadsheet->getActiveSheet();
self::assertSame(6, $sheet->getCell('D1')->getCalculatedValue());
self::assertSame(63, $sheet->getCell('F1')->getCalculatedValue());
self::assertSame(10, $sheet->getCell('C10')->getCalculatedValue());
$spreadsheet->disconnectWorksheets();
}
}

Binary file not shown.