From e2c5014c43035cee48a0d347abad9f64d24d5c1c Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 1 Feb 2023 15:40:46 +0100 Subject: [PATCH 1/2] Wizards for defining Number Format masks for Numbers, Percentages, Scientific, Currency, and Accounting --- CHANGELOG.md | 1 + .../Style/NumberFormat/Wizard/Accounting.php | 79 +++++++++++++ .../Style/NumberFormat/Wizard/Currency.php | 108 ++++++++++++++++++ .../Style/NumberFormat/Wizard/Locale.php | 37 ++++++ .../Style/NumberFormat/Wizard/Number.php | 57 +++++++++ .../Style/NumberFormat/Wizard/NumberBase.php | 80 +++++++++++++ .../Style/NumberFormat/Wizard/Percentage.php | 40 +++++++ .../Style/NumberFormat/Wizard/Scientific.php | 33 ++++++ .../Style/NumberFormat/Wizard/Wizard.php | 8 ++ .../NumberFormat/Wizard/AccountingTest.php | 102 +++++++++++++++++ .../NumberFormat/Wizard/CurrencyTest.php | 101 ++++++++++++++++ .../Style/NumberFormat/Wizard/NumberTest.php | 70 ++++++++++++ .../NumberFormat/Wizard/PercentageTest.php | 91 +++++++++++++++ .../NumberFormat/Wizard/ScientificTest.php | 75 ++++++++++++ 14 files changed, 882 insertions(+) create mode 100644 src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php create mode 100644 src/PhpSpreadsheet/Style/NumberFormat/Wizard/Currency.php create mode 100644 src/PhpSpreadsheet/Style/NumberFormat/Wizard/Locale.php create mode 100644 src/PhpSpreadsheet/Style/NumberFormat/Wizard/Number.php create mode 100644 src/PhpSpreadsheet/Style/NumberFormat/Wizard/NumberBase.php create mode 100644 src/PhpSpreadsheet/Style/NumberFormat/Wizard/Percentage.php create mode 100644 src/PhpSpreadsheet/Style/NumberFormat/Wizard/Scientific.php create mode 100644 src/PhpSpreadsheet/Style/NumberFormat/Wizard/Wizard.php create mode 100644 tests/PhpSpreadsheetTests/Style/NumberFormat/Wizard/AccountingTest.php create mode 100644 tests/PhpSpreadsheetTests/Style/NumberFormat/Wizard/CurrencyTest.php create mode 100644 tests/PhpSpreadsheetTests/Style/NumberFormat/Wizard/NumberTest.php create mode 100644 tests/PhpSpreadsheetTests/Style/NumberFormat/Wizard/PercentageTest.php create mode 100644 tests/PhpSpreadsheetTests/Style/NumberFormat/Wizard/ScientificTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ef24bfb3e..be6db25669 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). ### Added - Support for configuring a Chart Title's overlay [PR #3325](https://github.com/PHPOffice/PhpSpreadsheet/pull/3325) +- Wizards for defining Number Format masks for Numbers, Percentages, Scientific, Currency and Accounting [PR #3334](https://github.com/PHPOffice/PhpSpreadsheet/pull/3334) ### Changed diff --git a/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php b/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php new file mode 100644 index 0000000000..803a0e5ac7 --- /dev/null +++ b/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php @@ -0,0 +1,79 @@ +setCurrencyCode($currencyCode); + $this->setThousandsSeparator($thousandsSeparator); + $this->setDecimals($decimals); + $this->setCurrencySymbolPosition($currencySymbolPosition); + $this->setCurrencySymbolSpacing($currencySymbolSpacing); + $this->setLocale($locale); + } + + protected function getLocaleFormat(): string + { + $formatter = new Locale($this->fullLocale, NumberFormatter::CURRENCY_ACCOUNTING); // @phpstan-ignore-line + + return str_replace('¤', $this->formatCurrencyCode(), $formatter->format()); + } + + private function formatCurrencyCode(): string + { + if ($this->locale === null) { + return $this->currencyCode . '*'; + } + + return "[\${$this->currencyCode}-{$this->locale}]"; + } + + public function format(): string + { + if ($this->localeFormat !== null) { + return $this->localeFormat; + } + + return sprintf( + '_-%s%s%s0%s%s%s_-', + $this->currencySymbolPosition === self::LEADING_SYMBOL ? $this->formatCurrencyCode() : null, + ( + $this->currencySymbolPosition === self::LEADING_SYMBOL && + $this->currencySymbolSpacing === self::SYMBOL_WITH_SPACING + ) ? ' ' : '', + $this->thousandsSeparator ? '#,##' : null, + $this->decimals > 0 ? '.' . str_repeat('0', $this->decimals) : null, + ( + $this->currencySymbolPosition === self::TRAILING_SYMBOL && + $this->currencySymbolSpacing === self::SYMBOL_WITH_SPACING + ) ? ' ' : '', + $this->currencySymbolPosition === self::TRAILING_SYMBOL ? $this->formatCurrencyCode() : null + ); + } +} diff --git a/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Currency.php b/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Currency.php new file mode 100644 index 0000000000..b25bbfd871 --- /dev/null +++ b/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Currency.php @@ -0,0 +1,108 @@ +setCurrencyCode($currencyCode); + $this->setThousandsSeparator($thousandsSeparator); + $this->setDecimals($decimals); + $this->setCurrencySymbolPosition($currencySymbolPosition); + $this->setCurrencySymbolSpacing($currencySymbolSpacing); + $this->setLocale($locale); + } + + public function setCurrencyCode(string $currencyCode): void + { + $this->currencyCode = $currencyCode; + } + + public function setCurrencySymbolPosition(bool $currencySymbolPosition = self::LEADING_SYMBOL): void + { + $this->currencySymbolPosition = $currencySymbolPosition; + } + + public function setCurrencySymbolSpacing(bool $currencySymbolSpacing = self::SYMBOL_WITHOUT_SPACING): void + { + $this->currencySymbolSpacing = $currencySymbolSpacing; + } + + protected function getLocaleFormat(): string + { + $formatter = new Locale($this->fullLocale, NumberFormatter::CURRENCY); // @phpstan-ignore-line + + return str_replace('¤', $this->formatCurrencyCode(), $formatter->format()); + } + + private function formatCurrencyCode(): string + { + if ($this->locale === null) { + return $this->currencyCode; + } + + return "[\${$this->currencyCode}-{$this->locale}]"; + } + + public function format(): string + { + if ($this->localeFormat !== null) { + return $this->localeFormat; + } + + return sprintf( + '%s%s%s0%s%s%s', + $this->currencySymbolPosition === self::LEADING_SYMBOL ? $this->formatCurrencyCode() : null, + ( + $this->currencySymbolPosition === self::LEADING_SYMBOL && + $this->currencySymbolSpacing === self::SYMBOL_WITH_SPACING + ) ? "\u{a0}" : '', + $this->thousandsSeparator ? '#,##' : null, + $this->decimals > 0 ? '.' . str_repeat('0', $this->decimals) : null, + ( + $this->currencySymbolPosition === self::TRAILING_SYMBOL && + $this->currencySymbolSpacing === self::SYMBOL_WITH_SPACING + ) ? "\u{a0}" : '', + $this->currencySymbolPosition === self::TRAILING_SYMBOL ? $this->formatCurrencyCode() : null + ); + } +} diff --git a/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Locale.php b/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Locale.php new file mode 100644 index 0000000000..2253e8120e --- /dev/null +++ b/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Locale.php @@ -0,0 +1,37 @@ +[a-z]{2})([-_](?P