File

projects/wms-framework/src/lib/utils/BaseNumericStringFormatter.ts

Description

Base class for the string formatting functionality

Index

Methods

Methods

Private ConvertAbsoluteNumericValueToString
ConvertAbsoluteNumericValueToString(value: number, decimalDigits: number, decimalSeparator: string, groupSizes: number[], groupSeparator: string)

Converts a number to a string using specifying the number of:

  • decimal digits to use
  • decimal separator string to use
  • group sizes to use
  • group separator string to use

The value returned will be the string representation of the absolute value

Parameters :
Name Type Optional
value number No
decimalDigits number No
decimalSeparator string No
groupSizes number[] No
groupSeparator string No
Returns : any
Private FormatCurrencyToNegativeValue
FormatCurrencyToNegativeValue(strValue: string, globalizationInfo: GlobalizationHelper)

Formats the number with the currency symbol considering it is a negative value

Parameters :
Name Type Optional
strValue string No
globalizationInfo GlobalizationHelper No
Returns : string

{string}

Private FormatCurrencyToPositiveValue
FormatCurrencyToPositiveValue(strValue: string, globalizationInfo: GlobalizationHelper)

Formats the number with the currency symbol considering it is a positive value

Parameters :
Name Type Optional
strValue string No
globalizationInfo GlobalizationHelper No
Returns : string

{string}

Public FormatNumber
FormatNumber(value: number, formatString: string, globalizationInfo?: GlobalizationHelper)

Format a number with the given format string and for the specified globalization info

Parameters :
Name Type Optional Description
value number No

number to format

formatString string No

formatting string

globalizationInfo GlobalizationHelper Yes

optional globalization fino

Returns : string

{string} the formatted number

Private FormatNumberToNegativeValue
FormatNumberToNegativeValue(strValue: string, globalizationInfo: GlobalizationHelper)

Formats the number a negative value

Parameters :
Name Type Optional
strValue string No
globalizationInfo GlobalizationHelper No
Returns : string

{string}

Private FormatPercentToNegativeValue
FormatPercentToNegativeValue(strValue: string, globalizationInfo: GlobalizationHelper)

Formats the number with the percent symbol considering it is a negative value

Parameters :
Name Type Optional
strValue string No
globalizationInfo GlobalizationHelper No
Returns : string

{string}

Private FormatPercentToPositiveValue
FormatPercentToPositiveValue(strValue: string, globalizationInfo: GlobalizationHelper)

Formats the number with the percent symbol considering it is a positive value

Parameters :
Name Type Optional
strValue string No
globalizationInfo GlobalizationHelper No
Returns : string

{string}

Protected Abstract PerformCustomNumericFormatting
PerformCustomNumericFormatting(value: number, preprocessedValue: string)

Performs the string formatting using the presprocessed string

Parameters :
Name Type Optional Description
value number No

value to format

preprocessedValue string No

preprocessed format string

Returns : string

{string} the formatted string

Protected PerformStandardCurrencyFormatting
PerformStandardCurrencyFormatting(value: number, precision: number, globalizationInfo: GlobalizationHelper)

Performs the string formatting to currency

Parameters :
Name Type Optional
value number No
precision number No
globalizationInfo GlobalizationHelper No
Returns : string

{string}

Protected PerformStandardNumericFormatting
PerformStandardNumericFormatting(value: number, precision: number, globalizationInfo: GlobalizationHelper)

Performs the string formatting to numeric

Parameters :
Name Type Optional
value number No
precision number No
globalizationInfo GlobalizationHelper No
Returns : string

{string}

Protected PerformStandardPercentFormatting
PerformStandardPercentFormatting(value: number, precision: number, globalizationInfo: GlobalizationHelper)

Performs the string formatting to percentage

Parameters :
Name Type Optional
value number No
precision number No
globalizationInfo GlobalizationHelper No
Returns : string

{string}

Private ResolveStandardFormatApplied
ResolveStandardFormatApplied(formatString: string)

Tryies to resolve if the format applied is a standard numeric format and if a precision was specified

Parameters :
Name Type Optional
formatString string No
Returns : literal type

{{ StandardFormat: StandardNumericFormatsEnum, Precision: number }}

import { GlobalizationHelper } from '../baseframework/globalization';
import { StandardNumericFormatsEnum } from './StandardNumericFormatsEnum';

/**
 *  Base class for the string formatting functionality
 *
 * @export
 * @abstract
 * @class BaseNumericStringFormatter
 */
export abstract class BaseNumericStringFormatter {
  /**
   *  Format a number with the given format string and for the specified globalization info
   *
   * @param {number} value number to format
   * @param {string} formatString formatting string
   * @param {GlobalizationHelper} [globalizationInfo] optional globalization fino
   * @return {*}  {string} the formatted number
   * @memberof BaseNumericStringFormatter
   */
  public FormatNumber(
    value: number,
    formatString: string,
    globalizationInfo?: GlobalizationHelper
  ): string {
    const formatDetails = this.ResolveStandardFormatApplied(formatString);
    switch (formatDetails.StandardFormat) {
      case StandardNumericFormatsEnum.Currency:
        return this.PerformStandardCurrencyFormatting(
          value,
          formatDetails.Precision,
          globalizationInfo ?? GlobalizationHelper.Current
        );
      case StandardNumericFormatsEnum.Percent:
        return this.PerformStandardPercentFormatting(
          value,
          formatDetails.Precision,
          globalizationInfo ?? GlobalizationHelper.Current
        );
      case StandardNumericFormatsEnum.Number:
        return this.PerformStandardNumericFormatting(
          value,
          formatDetails.Precision,
          globalizationInfo ?? GlobalizationHelper.Current
        );
      default:
        return this.PerformCustomNumericFormatting(value, formatString);
    }
  }

  /**
   * Tryies to resolve if the format applied is a standard numeric format and if a precision was
   * specified
   *
   * @private
   * @param {string} formatString
   * @return {*}  {{ StandardFormat: StandardNumericFormatsEnum, Precision: number }}
   * @memberof BaseNumericStringFormatter
   */
  private ResolveStandardFormatApplied(formatString: string): {
    StandardFormat: StandardNumericFormatsEnum;
    Precision: number;
  } {
    let formatType: StandardNumericFormatsEnum =
      StandardNumericFormatsEnum.Unknown;
    let precision: number = null;

    formatString = formatString ?? '';
    const matchForAlias = formatString
      .toLowerCase()
      .match(/^([cdefgnprx])([0-9]*)$/i);
    if (matchForAlias) {
      if (matchForAlias.length >= 2 && matchForAlias[2] !== '') {
        precision = parseInt(matchForAlias[2], 10);
      }
      switch (matchForAlias[1]) {
        case 'c':
          formatType = StandardNumericFormatsEnum.Currency;
          break;
        case 'd':
          formatType = StandardNumericFormatsEnum.Decimal;
          break;
        case 'e':
          formatType = StandardNumericFormatsEnum.Exponential;
          break;
        case 'f':
          formatType = StandardNumericFormatsEnum.FixedPoint;
          break;
        case 'g':
          formatType = StandardNumericFormatsEnum.General;
          break;
        case 'n':
          formatType = StandardNumericFormatsEnum.Number;
          break;
        case 'p':
          formatType = StandardNumericFormatsEnum.Percent;
          break;
        case 'r':
          formatType = StandardNumericFormatsEnum.RoundTrip;
          break;
        case 'x':
          formatType = StandardNumericFormatsEnum.Hexadecimal;
          break;
      }
    }

    return {
      StandardFormat: formatType,
      Precision: precision,
    };
  }

  /**
   *  Performs the string formatting using the presprocessed string
   *
   * @protected
   * @abstract
   * @param {number} value value to format
   * @param {string} preprocessedValue  preprocessed format string
   * @return {*}  {string} the formatted string
   * @memberof BaseNumericStringFormatter
   */
  protected abstract PerformCustomNumericFormatting(
    value: number,
    preprocessedValue: string
  ): string;

  /**
   * Performs the string formatting to currency
   *
   * @protected
   * @param {number} value
   * @param {number} precision
   * @param {GlobalizationHelper} globalizationInfo
   * @return {*}  {string}
   * @memberof BaseNumericStringFormatter
   */
  protected PerformStandardCurrencyFormatting(
    value: number,
    precision: number,
    globalizationInfo: GlobalizationHelper
  ): string {
    const decimalDigitCount =
      precision ?? globalizationInfo?.NumberFormat?.CurrencyDecimalDigits ?? 2;
    const groupSizes =
      globalizationInfo?.NumberFormat?.CurrencyGroupSizes != null &&
      globalizationInfo?.NumberFormat?.CurrencyGroupSizes?.length > 0
        ? [...globalizationInfo.NumberFormat.CurrencyGroupSizes]
        : [3]; //default value
    const decimalSeparator =
      globalizationInfo?.NumberFormat?.CurrencyDecimalSeparator ?? '.';
    const groupSeparator =
      globalizationInfo?.NumberFormat?.CurrencyGroupSeparator ?? ',';

    //Reduces the decimal to the one requested and split integer from decimal part
    let strValue = this.ConvertAbsoluteNumericValueToString(
      value,
      decimalDigitCount,
      decimalSeparator,
      groupSizes,
      groupSeparator
    );

    if (value < 0) {
      return this.FormatCurrencyToNegativeValue(strValue, globalizationInfo);
    } else {
      return this.FormatCurrencyToPositiveValue(strValue, globalizationInfo);
    }
  }

  /**
   * Performs the string formatting to percentage
   *
   * @protected
   * @param {number} value
   * @param {number} precision
   * @param {GlobalizationHelper} globalizationInfo
   * @return {*}  {string}
   * @memberof BaseNumericStringFormatter
   */
  protected PerformStandardPercentFormatting(
    value: number,
    precision: number,
    globalizationInfo: GlobalizationHelper
  ): string {
    const decimalDigitCount =
      precision ?? globalizationInfo?.NumberFormat?.PercentDecimalDigits ?? 2;
    const groupSizes =
      globalizationInfo?.NumberFormat?.PercentGroupSizes != null &&
      globalizationInfo?.NumberFormat?.PercentGroupSizes?.length > 0
        ? [...globalizationInfo.NumberFormat.PercentGroupSizes]
        : [3]; //default value
    const decimalSeparator =
      globalizationInfo?.NumberFormat?.PercentDecimalSeparator ?? '.';
    const groupSeparator =
      globalizationInfo?.NumberFormat?.PercentGroupSeparator ?? ',';

    value = (value ?? 0) * 100.0;

    //Reduces the decimal to the one requested and split integer from decimal part
    let strValue = this.ConvertAbsoluteNumericValueToString(
      value,
      decimalDigitCount,
      decimalSeparator,
      groupSizes,
      groupSeparator
    );

    if (value < 0) {
      return this.FormatPercentToNegativeValue(strValue, globalizationInfo);
    } else {
      return this.FormatPercentToPositiveValue(strValue, globalizationInfo);
    }
  }

  /**
   * Performs the string formatting to numeric
   *
   * @protected
   * @param {number} value
   * @param {number} precision
   * @param {GlobalizationHelper} globalizationInfo
   * @return {*}  {string}
   * @memberof BaseNumericStringFormatter
   */
  protected PerformStandardNumericFormatting(
    value: number,
    precision: number,
    globalizationInfo: GlobalizationHelper
  ): string {
    const decimalDigitCount =
      precision ?? globalizationInfo?.NumberFormat?.NumberDecimalDigits ?? 2;
    const groupSizes =
      globalizationInfo?.NumberFormat?.NumberGroupSizes != null &&
      globalizationInfo?.NumberFormat?.NumberGroupSizes?.length > 0
        ? [...globalizationInfo.NumberFormat.NumberGroupSizes]
        : [3]; //default value
    const decimalSeparator =
      globalizationInfo?.NumberFormat?.NumberDecimalSeparator ?? '.';
    const groupSeparator =
      globalizationInfo?.NumberFormat?.NumberGroupSeparator ?? ',';

    //Reduces the decimal to the one requested and split integer from decimal part
    let strValue = this.ConvertAbsoluteNumericValueToString(
      value,
      decimalDigitCount,
      decimalSeparator,
      groupSizes,
      groupSeparator
    );

    if (value < 0) {
      return this.FormatNumberToNegativeValue(strValue, globalizationInfo);
    } else {
      return strValue;
    }
  }

  /**
   * Converts a number to a string using specifying the number of:
   *  - decimal digits to use
   *  - decimal separator string to use
   *  - group sizes to use
   *  - group separator string to use
   *
   * The value returned will be the string representation of the absolute value
   *
   * @private
   * @param {number} value
   * @param {number} decimalDigits
   * @param {string} decimalSeparator
   * @param {number[]} groupSizes
   * @param {string} groupSeparator
   * @return {*}
   * @memberof BaseNumericStringFormatter
   */
  private ConvertAbsoluteNumericValueToString(
    value: number,
    decimalDigits: number,
    decimalSeparator: string,
    groupSizes: number[],
    groupSeparator: string
  ) {
    const valueParts = Math.abs(value).toFixed(decimalDigits).split('.');
    const strDecimals = valueParts.length == 2 ? valueParts[1] : null;
    let strInteger = valueParts[0];
    const strIntegerPars = [];

    //Create the groups of the integer part
    let groupSize: number = 0;
    while (strInteger != '') {
      if (groupSizes.length > 0) groupSize = groupSizes.shift();

      if (strInteger.length >= groupSize) {
        strIntegerPars.unshift(
          strInteger.substring(strInteger.length - groupSize)
        );
        strInteger = strInteger.substring(0, strInteger.length - groupSize);
      } else {
        strIntegerPars.unshift(strInteger);
        strInteger = '';
      }
    }

    //Joining all elements using the required separators
    let strValue = strIntegerPars.join(groupSeparator);
    if (strDecimals) {
      strValue += `${decimalSeparator}${strDecimals}`;
    }
    return strValue;
  }

  /**
   * Formats the number with the currency symbol considering it is a positive value
   *
   * @private
   * @param {string} strValue
   * @param {GlobalizationHelper} globalizationInfo
   * @return {*}  {string}
   * @memberof BaseNumericStringFormatter
   */
  private FormatCurrencyToPositiveValue(
    strValue: string,
    globalizationInfo: GlobalizationHelper
  ): string {
    const symbol = globalizationInfo?.NumberFormat?.CurrencySymbol ?? '$';
    switch (globalizationInfo?.NumberFormat?.CurrencyPositivePattern) {
      case 0: //  $n
        return `${symbol}${strValue}`;
      case 1: //  n$
        return `${strValue}${symbol}`;
      case 2: //  $ n
        return `${symbol} ${strValue}`;
      case 3: //  n $
        return `${strValue} ${symbol}`;
      default: //  $n
        return `${symbol}${strValue}`;
    }
  }

  /**
   * Formats the number with the currency symbol considering it is a negative value
   *
   * @private
   * @param {string} strValue
   * @param {GlobalizationHelper} globalizationInfo
   * @return {*}  {string}
   * @memberof BaseNumericStringFormatter
   */
  private FormatCurrencyToNegativeValue(
    strValue: string,
    globalizationInfo: GlobalizationHelper
  ): string {
    const symbol = globalizationInfo?.NumberFormat?.CurrencySymbol ?? '$';
    const negativeSign = globalizationInfo?.NumberFormat?.NegativeSign ?? '-';
    switch (globalizationInfo?.NumberFormat?.CurrencyNegativePattern) {
      case 0: //  ($n)
        return `(${symbol}${strValue})`;
      case 1: //  -$n
        return `${negativeSign}${symbol}${strValue}`;
      case 2: //  $-n
        return `${symbol}${negativeSign}${strValue}`;
      case 3: //  $n-
        return `${symbol}${strValue}${negativeSign}`;
      case 4: //  (n$)
        return `(${strValue}${symbol})`;
      case 5: //  -n$
        return `${negativeSign}${strValue}${symbol}`;
      case 6: //  n-$
        return `${strValue}${negativeSign}${symbol}`;
      case 7: //  n$-
        return `${strValue}${symbol}${negativeSign}`;
      case 8: //  -n $
        return `${negativeSign}${strValue} ${symbol}`;
      case 9: //  -$ n
        return `${negativeSign}${symbol} ${strValue}`;
      case 10: //  n $-
        return `${strValue} ${symbol}${negativeSign}`;
      case 11: //  $ n-
        return `${symbol} ${strValue}${negativeSign}`;
      case 12: //  $ -n
        return `${symbol} ${negativeSign}${strValue}`;
      case 13: //  n- $
        return `${strValue}${negativeSign} ${symbol}`;
      case 14: //  ($ n)
        return `(${symbol} ${strValue})`;
      case 15: //  (n $)
        return `(${strValue} ${symbol})`;
      default: //  ($n)
        return `(${symbol}${strValue})`;
    }
  }

  /**
   * Formats the number with the percent symbol considering it is a positive value
   *
   * @private
   * @param {string} strValue
   * @param {GlobalizationHelper} globalizationInfo
   * @return {*}  {string}
   * @memberof BaseNumericStringFormatter
   */
  private FormatPercentToPositiveValue(
    strValue: string,
    globalizationInfo: GlobalizationHelper
  ): string {
    const symbol = globalizationInfo?.NumberFormat?.PercentSymbol ?? '%';
    switch (globalizationInfo?.NumberFormat?.PercentPositivePattern) {
      case 0: //  n %
        return `${strValue} ${symbol}`;
      case 1: //  n%
        return `${strValue}${symbol}`;
      case 2: //  %n
        return `${symbol}${strValue}`;
      case 3: //  % n
        return `${symbol} ${strValue}`;
      default: //  n %
        return `${strValue} ${symbol}`;
    }
  }

  /**
   * Formats the number with the percent symbol considering it is a negative value
   *
   * @private
   * @param {string} strValue
   * @param {GlobalizationHelper} globalizationInfo
   * @return {*}  {string}
   * @memberof BaseNumericStringFormatter
   */
  private FormatPercentToNegativeValue(
    strValue: string,
    globalizationInfo: GlobalizationHelper
  ): string {
    const symbol = globalizationInfo?.NumberFormat?.PercentSymbol ?? '%';
    const negativeSign = globalizationInfo?.NumberFormat?.NegativeSign ?? '-';
    switch (globalizationInfo?.NumberFormat?.PercentNegativePattern) {
      case 0: //  -n %
        return `${negativeSign}${strValue} ${symbol}`;
      case 1: //  -n%
        return `${negativeSign}${strValue}${symbol}`;
      case 2: //  -%n
        return `${negativeSign}${symbol}${strValue}`;
      case 3: //  %-n
        return `${symbol}${negativeSign}${strValue}`;
      case 4: //  %n-
        return `${symbol}${strValue}${negativeSign}`;
      case 5: //  n-%
        return `${strValue}${negativeSign}${symbol}`;
      case 6: //  n%-
        return `${strValue}${symbol}${negativeSign}`;
      case 7: //  -% n
        return `${negativeSign}${symbol} ${strValue}`;
      case 8: //  n %-
        return `${strValue} ${symbol}${negativeSign}`;
      case 9: //  % n-
        return `${symbol} ${strValue}${negativeSign}`;
      case 10: //  % -n
        return `${symbol} ${negativeSign}${strValue}`;
      case 11: //  n- %
        return `${strValue}${negativeSign} ${symbol}`;
      default: //  -n %
        return `${negativeSign}${strValue} ${symbol}`;
    }
  }

  /**
   * Formats the number a negative value
   *
   * @private
   * @param {string} strValue
   * @param {GlobalizationHelper} globalizationInfo
   * @return {*}  {string}
   * @memberof BaseNumericStringFormatter
   */
  private FormatNumberToNegativeValue(
    strValue: string,
    globalizationInfo: GlobalizationHelper
  ): string {
    const negativeSign = globalizationInfo?.NumberFormat?.NegativeSign ?? '-';
    switch (globalizationInfo?.NumberFormat?.NumberNegativePattern) {
      case 0: //  (n)
        return `(${strValue})`;
      case 1: //  -n
        return `${negativeSign}${strValue}`;
      case 2: //  - n
        return `${negativeSign} ${strValue}`;
      case 3: //  n-
        return `${strValue}${negativeSign}`;
      case 4: //  n -
        return `${strValue} ${negativeSign}`;
      default: //  (n)
        return `(${strValue})`;
    }
  }
}

result-matching ""

    No results matching ""