diff --git a/src/PhpSpreadsheet/Calculation/CalculationBase.php b/src/PhpSpreadsheet/Calculation/CalculationBase.php index 9dc67fbc2..5bef04d7e 100644 --- a/src/PhpSpreadsheet/Calculation/CalculationBase.php +++ b/src/PhpSpreadsheet/Calculation/CalculationBase.php @@ -30,7 +30,10 @@ class CalculationBase public static function addFunction(string $key, array $value): bool { $key = strtoupper($key); - if (array_key_exists($key, FunctionArray::$phpSpreadsheetFunctions)) { + if ( + array_key_exists($key, FunctionArray::$phpSpreadsheetFunctions) + && !self::isDummy($key) + ) { return false; } $value['custom'] = true; @@ -39,6 +42,20 @@ class CalculationBase return true; } + private static function isDummy(string $key): bool + { + // key is already known to exist + $functionCall = FunctionArray::$phpSpreadsheetFunctions[$key]['functionCall'] ?? null; + if (!is_array($functionCall)) { + return false; + } + if (($functionCall[1] ?? '') !== 'DUMMY') { + return false; + } + + return true; + } + public static function removeFunction(string $key): bool { $key = strtoupper($key); diff --git a/tests/PhpSpreadsheetTests/Calculation/CustomFunction.php b/tests/PhpSpreadsheetTests/Calculation/CustomFunction.php index 1ce5cf5d2..7e0fea0a7 100644 --- a/tests/PhpSpreadsheetTests/Calculation/CustomFunction.php +++ b/tests/PhpSpreadsheetTests/Calculation/CustomFunction.php @@ -6,6 +6,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcException; use PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Helpers; +use PhpOffice\PhpSpreadsheet\Shared\StringHelper; class CustomFunction { @@ -19,4 +20,25 @@ class CustomFunction return $number ** 4; } + + /** + * ASC. + * Converts full-width (double-byte) characters to half-width (single-byte) characters. + * There are many difficulties with implementing this into PhpSpreadsheet. + */ + public static function ASC(mixed $stringValue): string + { + /*if (is_array($stringValue)) { + return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $stringValue); + }*/ + $stringValue = StringHelper::convertToString($stringValue, convertBool: true); + if (function_exists('mb_convert_kana')) { + return mb_convert_kana($stringValue, 'a', 'UTF-8'); + } + // Fallback if mb_convert_kana is not available. + // PhpSpreadsheet heavily relies on mbstring, so this is more of a theoretical fallback. + // A comprehensive manual conversion is extensive. + + return $stringValue; + } } diff --git a/tests/PhpSpreadsheetTests/Calculation/CustomFunctionTest.php b/tests/PhpSpreadsheetTests/Calculation/CustomFunctionTest.php index 1c536fad4..03262dfc0 100644 --- a/tests/PhpSpreadsheetTests/Calculation/CustomFunctionTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/CustomFunctionTest.php @@ -31,4 +31,19 @@ class CustomFunctionTest extends TestCase self::assertSame('#NAME?', $calculation->calculateFormula('=FOURTHPOWER(3)')); self::assertFalse(Calculation::removeFunction('WHATEVER')); } + + public static function testReplaceDummyFunction(): void + { + $functions = Calculation::getFunctions(); + $key = 'ASC'; + $oldValue = $functions[$key] ?? null; + self::assertIsArray($oldValue); + $calculation = Calculation::getInstance(); + $value = $oldValue; + $value['functionCall'] = [CustomFunction::class, 'ASC']; + self::assertTrue(Calculation::addFunction($key, $value)); + self::assertSame('ABC', $calculation->calculateFormula('=ASC("ABC")')); + self::assertTrue(Calculation::removeFunction('ASC')); + self::assertTrue(Calculation::addFunction($key, $oldValue)); + } }