Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
- Mpdf and Tcpdf Borders on Merged Cells. [Issue #3557](https://github.com/PHPOffice/PhpSpreadsheet/issues/3557) [PR #4047](https://github.com/PHPOffice/PhpSpreadsheet/pull/4047)
- Xls Conditional Format Improvements. [PR #4030](https://github.com/PHPOffice/PhpSpreadsheet/pull/4030) [PR #4033](https://github.com/PHPOffice/PhpSpreadsheet/pull/4033)
- Conditional Range Unions and Intersections [Issue #4039](https://github.com/PHPOffice/PhpSpreadsheet/issues/4039) [PR #4042](https://github.com/PHPOffice/PhpSpreadsheet/pull/4042)
- Propagate errors in Text functions. [Issue #2581](https://github.com/PHPOffice/PhpSpreadsheet/issues/2581) [PR #4080](https://github.com/PHPOffice/PhpSpreadsheet/pull/4080)
- Csv Reader allow use of html mimetype. [Issue #4036](https://github.com/PHPOffice/PhpSpreadsheet/issues/4036) [PR #4040](https://github.com/PHPOffice/PhpSpreadsheet/pull/4040)
- Problem rendering line chart with missing plot label. [PR #4074](https://github.com/PHPOffice/PhpSpreadsheet/pull/4074)
- More RTL in Xlsx/Html Comments [Issue #4004](https://github.com/PHPOffice/PhpSpreadsheet/issues/4004) [PR #4065](https://github.com/PHPOffice/PhpSpreadsheet/pull/4065)
Expand Down
29 changes: 21 additions & 8 deletions src/PhpSpreadsheet/Calculation/Calculation.php
Original file line number Diff line number Diff line change
Expand Up @@ -4792,13 +4792,20 @@ private function processTokenStack(mixed $tokens, ?string $cellID = null, ?Cell

for ($row = 0; $row < $rows; ++$row) {
for ($column = 0; $column < $columns; ++$column) {
$operand1[$row][$column]
= Shared\StringHelper::substring(
self::boolToString($operand1[$row][$column])
. self::boolToString($operand2[$row][$column]),
0,
DataType::MAX_STRING_LENGTH
);
$op1x = self::boolToString($operand1[$row][$column]);
$op2x = self::boolToString($operand2[$row][$column]);
if (Information\ErrorValue::isError($op1x)) {
// no need to do anything
} elseif (Information\ErrorValue::isError($op2x)) {
$operand1[$row][$column] = $op2x;
} else {
$operand1[$row][$column]
= Shared\StringHelper::substring(
$op1x . $op2x,
0,
DataType::MAX_STRING_LENGTH
);
}
}
}
$result = $operand1;
Expand All @@ -4808,7 +4815,13 @@ private function processTokenStack(mixed $tokens, ?string $cellID = null, ?Cell
// using the concatenation operator
// with literals that fits in 32K,
// so I don't think we can overflow here.
$result = self::FORMULA_STRING_QUOTE . str_replace('""', self::FORMULA_STRING_QUOTE, self::unwrapResult($operand1) . self::unwrapResult($operand2)) . self::FORMULA_STRING_QUOTE;
if (Information\ErrorValue::isError($operand1)) {
$result = $operand1;
} elseif (Information\ErrorValue::isError($operand2)) {
$result = $operand2;
} else {
$result = self::FORMULA_STRING_QUOTE . str_replace('""', self::FORMULA_STRING_QUOTE, self::unwrapResult($operand1) . self::unwrapResult($operand2)) . self::FORMULA_STRING_QUOTE;
}
}
$this->debugLog->writeDebugLog('Evaluation Result is %s', $this->showTypeDetails($result));
$stack->push('Value', $result);
Expand Down
4 changes: 3 additions & 1 deletion src/PhpSpreadsheet/Calculation/Functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class Functions
const RETURNDATE_PHP_DATETIME_OBJECT = 'O';
const RETURNDATE_EXCEL = 'E';

public const NOT_YET_IMPLEMENTED = '#Not Yet Implemented';

/**
* Compatibility mode to use for error checking and responses.
*/
Expand Down Expand Up @@ -123,7 +125,7 @@ public static function getReturnDateType(): string
*/
public static function DUMMY(): string
{
return '#Not Yet Implemented';
return self::NOT_YET_IMPLEMENTED;
}

public static function isMatrixValue(mixed $idx): bool
Expand Down
6 changes: 5 additions & 1 deletion src/PhpSpreadsheet/Calculation/Information/ErrorValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace PhpOffice\PhpSpreadsheet\Calculation\Information;

use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;

class ErrorValue
{
Expand Down Expand Up @@ -35,7 +36,7 @@ public static function isErr(mixed $value = ''): array|bool
* @return array|bool If an array of numbers is passed as an argument, then the returned result will also be an array
* with the same dimensions
*/
public static function isError(mixed $value = ''): array|bool
public static function isError(mixed $value = '', bool $tryNotImplemented = false): array|bool
{
if (is_array($value)) {
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
Expand All @@ -44,6 +45,9 @@ public static function isError(mixed $value = ''): array|bool
if (!is_string($value)) {
return false;
}
if ($tryNotImplemented && $value === Functions::NOT_YET_IMPLEMENTED) {
return true;
}

return in_array($value, ExcelError::ERROR_CODES, true);
}
Expand Down
19 changes: 16 additions & 3 deletions src/PhpSpreadsheet/Calculation/TextData/CaseConvert.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;

use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;

class CaseConvert
Expand All @@ -26,7 +27,11 @@ public static function lower(mixed $mixedCaseValue): array|string
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $mixedCaseValue);
}

$mixedCaseValue = Helpers::extractString($mixedCaseValue);
try {
$mixedCaseValue = Helpers::extractString($mixedCaseValue, true);
} catch (CalcExp $e) {
return $e->getMessage();
}

return StringHelper::strToLower($mixedCaseValue);
}
Expand All @@ -48,7 +53,11 @@ public static function upper(mixed $mixedCaseValue): array|string
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $mixedCaseValue);
}

$mixedCaseValue = Helpers::extractString($mixedCaseValue);
try {
$mixedCaseValue = Helpers::extractString($mixedCaseValue, true);
} catch (CalcExp $e) {
return $e->getMessage();
}

return StringHelper::strToUpper($mixedCaseValue);
}
Expand All @@ -70,7 +79,11 @@ public static function proper(mixed $mixedCaseValue): array|string
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $mixedCaseValue);
}

$mixedCaseValue = Helpers::extractString($mixedCaseValue);
try {
$mixedCaseValue = Helpers::extractString($mixedCaseValue, true);
} catch (CalcExp $e) {
return $e->getMessage();
}

return StringHelper::strToTitle($mixedCaseValue);
}
Expand Down
15 changes: 13 additions & 2 deletions src/PhpSpreadsheet/Calculation/TextData/CharacterConvert.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;

use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;

Expand All @@ -26,7 +27,12 @@ public static function character(mixed $character): array|string
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $character);
}

$character = Helpers::validateInt($character);
try {
$character = Helpers::validateInt($character, true);
} catch (CalcExp $e) {
return $e->getMessage();
}

$min = Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE ? 0 : 1;
if ($character < $min || $character > 255) {
return ExcelError::VALUE();
Expand All @@ -52,7 +58,12 @@ public static function code(mixed $characters): array|string|int
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $characters);
}

$characters = Helpers::extractString($characters);
try {
$characters = Helpers::extractString($characters, true);
} catch (CalcExp $e) {
return $e->getMessage();
}

if ($characters === '') {
return ExcelError::VALUE();
}
Expand Down
6 changes: 3 additions & 3 deletions src/PhpSpreadsheet/Calculation/TextData/Concatenate.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static function CONCATENATE(...$args): string

foreach ($aArgs as $arg) {
$value = Helpers::extractString($arg);
if (ErrorValue::isError($value)) {
if (ErrorValue::isError($value, true)) {
$returnValue = $value;

break;
Expand Down Expand Up @@ -85,7 +85,7 @@ private static function evaluateTextJoinArray(bool $ignoreEmpty, array &$aArgs):
{
foreach ($aArgs as $key => &$arg) {
$value = Helpers::extractString($arg);
if (ErrorValue::isError($value)) {
if (ErrorValue::isError($value, true)) {
return $value;
}

Expand Down Expand Up @@ -123,7 +123,7 @@ public static function builtinREPT(mixed $stringValue, mixed $repeatCount): arra

if (!is_numeric($repeatCount) || $repeatCount < 0) {
$returnValue = ExcelError::VALUE();
} elseif (ErrorValue::isError($stringValue)) {
} elseif (ErrorValue::isError($stringValue, true)) {
$returnValue = $stringValue;
} else {
$returnValue = str_repeat($stringValue, (int) $repeatCount);
Expand Down
22 changes: 17 additions & 5 deletions src/PhpSpreadsheet/Calculation/TextData/Extract.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static function left(mixed $value, mixed $chars = 1): array|string
}

try {
$value = Helpers::extractString($value);
$value = Helpers::extractString($value, true);
$chars = Helpers::extractInt($chars, 0, 1);
} catch (CalcExp $e) {
return $e->getMessage();
Expand Down Expand Up @@ -61,7 +61,7 @@ public static function mid(mixed $value, mixed $start, mixed $chars): array|stri
}

try {
$value = Helpers::extractString($value);
$value = Helpers::extractString($value, true);
$start = Helpers::extractInt($start, 1);
$chars = Helpers::extractInt($chars, 0);
} catch (CalcExp $e) {
Expand Down Expand Up @@ -90,7 +90,7 @@ public static function right(mixed $value, mixed $chars = 1): array|string
}

try {
$value = Helpers::extractString($value);
$value = Helpers::extractString($value, true);
$chars = Helpers::extractInt($chars, 0, 1);
} catch (CalcExp $e) {
return $e->getMessage();
Expand Down Expand Up @@ -132,7 +132,13 @@ public static function before(mixed $text, $delimiter, mixed $instance = 1, mixe
return self::evaluateArrayArgumentsIgnore([self::class, __FUNCTION__], 1, $text, $delimiter, $instance, $matchMode, $matchEnd, $ifNotFound);
}

$text = Helpers::extractString($text ?? '');
try {
$text = Helpers::extractString($text ?? '', true);
Helpers::extractString(Functions::flattenSingleValue($delimiter ?? ''), true);
} catch (CalcExp $e) {
return $e->getMessage();
}

$instance = (int) $instance;
$matchMode = (int) $matchMode;
$matchEnd = (int) $matchEnd;
Expand Down Expand Up @@ -190,7 +196,13 @@ public static function after(mixed $text, $delimiter, mixed $instance = 1, mixed
return self::evaluateArrayArgumentsIgnore([self::class, __FUNCTION__], 1, $text, $delimiter, $instance, $matchMode, $matchEnd, $ifNotFound);
}

$text = Helpers::extractString($text ?? '');
try {
$text = Helpers::extractString($text ?? '', true);
Helpers::extractString(Functions::flattenSingleValue($delimiter ?? ''), true);
} catch (CalcExp $e) {
return $e->getMessage();
}

$instance = (int) $instance;
$matchMode = (int) $matchMode;
$matchEnd = (int) $matchEnd;
Expand Down
15 changes: 12 additions & 3 deletions src/PhpSpreadsheet/Calculation/TextData/Format.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel;
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue;
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use PhpOffice\PhpSpreadsheet\RichText\RichText;
Expand Down Expand Up @@ -123,8 +124,13 @@ public static function TEXTFORMAT(mixed $value, mixed $format): array|string
return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $format);
}

$value = Helpers::extractString($value);
$format = Helpers::extractString($format);
try {
$value = Helpers::extractString($value, true);
$format = Helpers::extractString($format, true);
} catch (CalcExp $e) {
return $e->getMessage();
}

$format = (string) NumberFormat::convertSystemFormats($format);

if (!is_numeric($value) && Date::isDateTimeFormatCode($format)) {
Expand Down Expand Up @@ -152,6 +158,9 @@ private static function convertValue(mixed $value, bool $spacesMeanZero = false)
}
if (is_string($value)) {
$value = trim($value);
if (ErrorValue::isError($value, true)) {
throw new CalcExp($value);
}
if ($spacesMeanZero && $value === '') {
$value = 0;
}
Expand Down Expand Up @@ -220,7 +229,7 @@ public static function VALUE(mixed $value = '')
}

/**
* TEXT.
* VALUETOTEXT.
*
* @param mixed $value The value to format
* Or can be an array of values
Expand Down
14 changes: 12 additions & 2 deletions src/PhpSpreadsheet/Calculation/TextData/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static function extractString(mixed $value, bool $throwIfError = false):
if (is_bool($value)) {
return self::convertBooleanValue($value);
}
if ($throwIfError && is_string($value) && ErrorValue::isError($value)) {
if ($throwIfError && is_string($value) && ErrorValue::isError($value, true)) {
throw new CalcExp($value);
}

Expand Down Expand Up @@ -63,18 +63,28 @@ public static function extractFloat(mixed $value): float
$value = (float) $value;
}
if (!is_numeric($value)) {
if (is_string($value) && ErrorValue::isError($value, true)) {
throw new CalcExp($value);
}

throw new CalcExp(ExcelError::VALUE());
}

return (float) $value;
}

public static function validateInt(mixed $value): int
public static function validateInt(mixed $value, bool $throwIfError = false): int
{
if ($value === null) {
$value = 0;
} elseif (is_bool($value)) {
$value = (int) $value;
} elseif ($throwIfError && is_string($value) && !is_numeric($value)) {
if (!ErrorValue::isError($value, true)) {
$value = ExcelError::VALUE();
}

throw new CalcExp($value);
}

return (int) $value;
Expand Down
8 changes: 4 additions & 4 deletions src/PhpSpreadsheet/Calculation/TextData/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public static function sensitive(mixed $needle, mixed $haystack, mixed $offset =
}

try {
$needle = Helpers::extractString($needle);
$haystack = Helpers::extractString($haystack);
$needle = Helpers::extractString($needle, true);
$haystack = Helpers::extractString($haystack, true);
$offset = Helpers::extractInt($offset, 1, 0, true);
} catch (CalcExp $e) {
return $e->getMessage();
Expand Down Expand Up @@ -74,8 +74,8 @@ public static function insensitive(mixed $needle, mixed $haystack, mixed $offset
}

try {
$needle = Helpers::extractString($needle);
$haystack = Helpers::extractString($haystack);
$needle = Helpers::extractString($needle, true);
$haystack = Helpers::extractString($haystack, true);
$offset = Helpers::extractInt($offset, 1, 0, true);
} catch (CalcExp $e) {
return $e->getMessage();
Expand Down
Loading