From 5b7fce928618052f009cb1a7637d0be8d23caf92 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Thu, 14 Dec 2023 13:29:30 -0800 Subject: [PATCH] Strip `_xlfn.` and `_xlfs.` In Formula Translations Fix #3819. Excel can add these prefixes (basically invisible to end-user). Formula translation in PhpSpreadsheet fails when dealing with these unexpected prefixes, and, even if it handled it correctly, the unexpected prefixes confuse the users. I have changed to strip those prefixes when translating to a locale. This is probably not perfect, but is almost certainly good enough. I could easily add the same change when translating from a locale to English, but I don't think there's a good use case for that, so am opting not to do so for now. The documentation mentions `translateFormulaToLocale` and `translateFormulaToEnglish`. Neither of these exist; both names are preceded by an underscore. I have changed the code to match the documentation rather than vice versa, retaining deprecated versions of the underscored routines which merely invoke the non-underscored routines. --- CHANGELOG.md | 3 ++- src/PhpSpreadsheet/Calculation/Calculation.php | 17 +++++++++++++++++ .../Calculation/TranslationTest.php | 2 +- tests/data/Calculation/Translations.php | 10 ++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76f9746d4..caa11144e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). ### Deprecated -- Nothing +- Functions `_translateFormulaToLocale` and `_translateFormulaEnglish` are replaced by versions without leading underscore. [PR #3829](https://github.com/PHPOffice/PhpSpreadsheet/pull/3829) ### Removed @@ -78,6 +78,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). - Html omitting some charts. [Issue #3767](https://github.com/PHPOffice/PhpSpreadsheet/issues/3767) [PR #3771](https://github.com/PHPOffice/PhpSpreadsheet/pull/3771) - Case Insensitive Comparison for Sheet Names [PR #3791](https://github.com/PHPOffice/PhpSpreadsheet/pull/3791) - Performance improvement for Xlsx Reader. [Issue #3683](https://github.com/PHPOffice/PhpSpreadsheet/issues/3683) [PR #3810](https://github.com/PHPOffice/PhpSpreadsheet/pull/3810) +- Strip `xlfn.` and `xlws.` from Formula Translations. [Issue #3819](https://github.com/PHPOffice/PhpSpreadsheet/issues/3819) [PR #3829](https://github.com/PHPOffice/PhpSpreadsheet/pull/3829) - Prevent loop in Shared/File. [Issue #3807](https://github.com/PHPOffice/PhpSpreadsheet/issues/3807) [PR #3809](https://github.com/PHPOffice/PhpSpreadsheet/pull/3809) ## 1.29.0 - 2023-06-15 diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 960db939c..395189457 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -3326,8 +3326,17 @@ class Calculation /** @var ?array */ private static $functionReplaceToLocale; + /** + * @deprecated 1.30.0 use translateFormulaToLocale() instead + */ public function _translateFormulaToLocale(string $formula): string { + return $this->translateFormulaToLocale($formula); + } + + public function translateFormulaToLocale(string $formula): string + { + $formula = preg_replace('/_(xlfn|xlws)[.]/', '', $formula) ?? ''; // Build list of function names and constants for translation if (self::$functionReplaceFromExcel === null) { self::$functionReplaceFromExcel = []; @@ -3364,7 +3373,15 @@ class Calculation /** @var ?array */ private static $functionReplaceToExcel; + /** + * @deprecated 1.30.0 use translateFormulaToEnglish() instead + */ public function _translateFormulaToEnglish(string $formula): string + { + return $this->translateFormulaToEnglish($formula); + } + + public function translateFormulaToEnglish(string $formula): string { if (self::$functionReplaceFromLocale === null) { self::$functionReplaceFromLocale = []; diff --git a/tests/PhpSpreadsheetTests/Calculation/TranslationTest.php b/tests/PhpSpreadsheetTests/Calculation/TranslationTest.php index c14ee0a64..714b938e9 100644 --- a/tests/PhpSpreadsheetTests/Calculation/TranslationTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/TranslationTest.php @@ -47,7 +47,7 @@ class TranslationTest extends TestCase self::assertSame($expectedResult, $translatedFormula); $restoredFormula = Calculation::getInstance()->_translateFormulaToEnglish($translatedFormula); - self::assertSame($formula, $restoredFormula); + self::assertSame(preg_replace('/_(xlfn|xlws)[.]/', '', $formula), $restoredFormula); } public static function providerTranslations(): array diff --git a/tests/data/Calculation/Translations.php b/tests/data/Calculation/Translations.php index b0849ff27..dee382662 100644 --- a/tests/data/Calculation/Translations.php +++ b/tests/data/Calculation/Translations.php @@ -92,4 +92,14 @@ return [ 'fr', '=3*ROW(B1)', ], + 'handle _xlfn' => [ + '=MAXWENNS(C5:C10; C5:C10; "<30")', + 'de', + '=_xlfn.MAXIFS(C5:C10, C5:C10, "<30")', + ], + 'handle _xlfn and _xlws' => [ + '=ФИЛЬТР(A5:D20;C5:C20=H2;"")', + 'ru', + '=_xlfn._xlws.FILTER(A5:D20,C5:C20=H2,"")', + ], ];