We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 51020
    • 670 Posts
    Quote from: bwente at May 12, 2017, 02:40 PM
    Output an easy-to-read number (U.S. english)

    $[[++Assets:fmt.humanNumber]]


    Outputs:
    247,704,360 -> 247.7 million
    866,965,260,000 -> 867 billion

    or

    [[++Financial_Benefits:fmt.humanNumber=`stripWords=1&decimals=1`]]


    Outputs:
    247,704,360 -> 247.7
    866,965,260,000 -> 867

    <!--?php
    $optionsXpld = @explode('&', $options);
    $optionsArray = array();
    foreach ($optionsXpld as $xpld) {
        $params = @explode('=', $xpld);
        array_walk($params, create_function('&$v', '$v = trim($v);'));
        if (isset($params[1])) {
            $optionsArray[$params[0]] = $params[1];
        } else {
            $optionsArray[$params[0]] = '';
        }
    }
    $stripWords = isset($optionsArray['stripWords']) ? $optionsArray['stripWords'] : null;
    $decimals = isset($optionsArray['decimals']) ? $optionsArray['decimals'] : 0;
    #    Output easy-to-read numbers
    #    by james at bandit.co.nz
    $number = $input;
            // first strip any formatting;
            $n = (0+str_replace(",","",$number));
            
            // is this a number?
            if(!is_numeric($n)) return false;
            
            // now filter it;
        if ($n-->1000000000000):
        $num = round(($n/1000000000000),1);
        $wrd = 'trillion';
    elseif ($n>1000000000):
        $num = round(($n/1000000000),1);
        $wrd = 'billion';
    elseif ($n>1000000):
        $num = round(($n/1000000),1);
        $wrd = 'million';
    elseif ($n>1000):
        $num = round(($n/1000),1);
        $wrd = 'thousand';
    elseif ($n>100):
        $num = round(($n/100),1);
        $wrd = 'hundred';
    endif;
    if($stripWords=1){
            $output = number_format($num, $decimals);
    }else{
            $output = number_format($num, $decimals) . " " . $wrd;    
    }
            return $output;
    

    I cannot get this to work! I have added your code as a snippet called humanNumber

    Then call it as an output filter to my chunk:

    [[$bigNumber:fmt.humanNumber=`stripWords=1&decimals=1`]]
    


    but nothing happens?

      • 51020
      • 670 Posts
      Hi again - sorry, I just saw you had a fmt. prefix on your snippet - I removed that and it worked.
      looks good - but it's rounding the final number up - so that:

      12,999,999

      outputs as 13 (million)

      but in my text i'm saying the number is 'over 12.9 million'.

        • 51020
        • 670 Posts
        Quote from: bwente at May 12, 2017, 02:40 PM
        Output an easy-to-read number (U.S. english)

        $[[++Assets:fmt.humanNumber]]


        Outputs:
        247,704,360 -> 247.7 million
        866,965,260,000 -> 867 billion

        or

        [[++Financial_Benefits:fmt.humanNumber=`stripWords=1&decimals=1`]]


        Outputs:
        247,704,360 -> 247.7
        866,965,260,000 -> 867

        <!--?php
        $optionsXpld = @explode('&', $options);
        $optionsArray = array();
        foreach ($optionsXpld as $xpld) {
            $params = @explode('=', $xpld);
            array_walk($params, create_function('&$v', '$v = trim($v);'));
            if (isset($params[1])) {
                $optionsArray[$params[0]] = $params[1];
            } else {
                $optionsArray[$params[0]] = '';
            }
        }
        $stripWords = isset($optionsArray['stripWords']) ? $optionsArray['stripWords'] : null;
        $decimals = isset($optionsArray['decimals']) ? $optionsArray['decimals'] : 0;
        #    Output easy-to-read numbers
        #    by james at bandit.co.nz
        $number = $input;
                // first strip any formatting;
                $n = (0+str_replace(",","",$number));
                
                // is this a number?
                if(!is_numeric($n)) return false;
                
                // now filter it;
            if ($n-->1000000000000):
            $num = round(($n/1000000000000),1);
            $wrd = 'trillion';
        elseif ($n>1000000000):
            $num = round(($n/1000000000),1);
            $wrd = 'billion';
        elseif ($n>1000000):
            $num = round(($n/1000000),1);
            $wrd = 'million';
        elseif ($n>1000):
            $num = round(($n/1000),1);
            $wrd = 'thousand';
        elseif ($n>100):
            $num = round(($n/100),1);
            $wrd = 'hundred';
        endif;
        if($stripWords=1){
                $output = number_format($num, $decimals);
        }else{
                $output = number_format($num, $decimals) . " " . $wrd;    
        }
                return $output;
        

        Also it's not outputting the words 'million, billion etc?
          • 51020
          • 670 Posts
          Quote from: clareoconsulting at May 12, 2017, 02:02 PM
          Created a quick hack that matches your use case as I see it, but gives you a bit of flexibility for how to output numbers with different numbers of digits. It's a bit inelegant and procedural, but appears to give what you're looking for.

          Tinker with the 5 arrays at the top to adjust the display to different input lengths. NOTE: Only good as-is for up to 999,999,999, but you could add more array entries if you want to go higher. See sample outputs below code.
          <!--?php
              // Configure the following 5 arrays to control output based on
              // the number of digits in the input number
          
              // Cases where output will be displayed in multiples, i.e. "5 million"
              // instead of "5,000,000". Enter the number to divide by (eg. 1000000 for a million,
              // 1000 for a thousand, 1 for no division)
              $displayDivisor = array(
                  1 =--> 1,
                  2 => 1,
                  3 => 1,
                  4 => 1,
                  5 => 1,
                  6 => 1,
                  7 => 1000000,
                  8 => 1000000,
                  9 => 1000000
              );
              
              // Precision of rounding of input. Eg. 3 rounds at thousands
              // 6 rounds at millions, 5 rounds to tenth of million, etc.
              $roundingDigits = array(
                  1 => 0,
                  2 => 0,
                  3 => 0,
                  4 => 2,
                  5 => 3,
                  6 => 3,
                  7 => 5,
                  8 => 6,
                  9 => 6
              );
              
              // How many decimal places to display in the output
              $displayDecimals = array(
                  1 => 0,
                  2 => 0,
                  3 => 0,
                  4 => 0,
                  5 => 0,
                  6 => 0,
                  7 => 1,
                  8 => 0,
                  9 => 0
              );
          
              // Text prefix for output
              $displayPrefix = array(
                  1 => '',
                  2 => '',
                  3 => '',
                  4 => 'more than ',
                  5 => 'more than ',
                  6 => 'more than ',
                  7 => 'more than ',
                  8 => 'more than ',
                  9 => 'more than '
              );
              
              // Text suffix for output
              $displaySuffix = array(
                  1 => '',
                  2 => '',
                  3 => '',
                  4 => '',
                  5 => '',
                  6 => '',
                  7 => ' million',
                  8 => ' million',
                  9 => ' million'
              );
          
          
              // CHANGE NOTHING AFTER THIS POINT
              $value              = floatval($input);
              $digitCount         = intval(log10($value)) + 1;
              
              if (! isset($displayDivisor[$digitCount]) || 
                  ! isset($roundingDigits[$digitCount]) || 
                  ! isset($displayDecimals[$digitCount]) || 
                  ! isset($displayPrefix[$digitCount]) || 
                  ! isset($displaySuffix[$digitCount])
                  ) { return ''; }
              
              $roundingPrecision  = pow(10, $roundingDigits[$digitCount]);
              $floorValue         = floor($value / $roundingPrecision) * $roundingPrecision / $displayDivisor[$digitCount];
              $outputValue        = number_format($floorValue, $displayDecimals[$digitCount]);
              
              $output = $displayPrefix[$digitCount] .  
                        $outputValue .
                        $displaySuffix[$digitCount];
          
              $return $output;
          


          Sample (Input | Output)

          • 1 | 1
          • 12 | 12
          • 123 | 123
          • 1234 | more than 1,200
          • 12345 | more than 12,000
          • 123456 | more than 123,000
          • 1234567 | more than 1.2 million
          • 12345678 | more than 12 million
          • 123456789 | more than 123 million

          I'm getting a syntax error on the last line:

              $return $output;


          Unexpected T_VARIABLE

            • 36816
            • 109 Posts
            Quote from: tm2000 at May 15, 2017, 03:45 AM

            I'm getting a syntax error on the last line:
                $return $output;


            Remove the $ from in front of return in that line. Not sure how I got that in there; sorry. I've edited my original post to reflect the change.

            To answer your earlier question, yes, save it as a snippet (named whatever you want) and use it as a custom output filter.

            Background on custom output filters is here: https://docs.modx.com/revolution/2.x/making-sites-with-modx/customizing-content/input-and-output-filters-(output-modifiers)/custom-output-filter-examples
              • 51020
              • 670 Posts
              Quote from: clareoconsulting at May 15, 2017, 08:00 AM
              Quote from: tm2000 at May 15, 2017, 03:45 AM

              I'm getting a syntax error on the last line:
                  $return $output;


              Remove the $ from in front of return in that line. Not sure how I got that in there; sorry. I've edited my original post to reflect the change.

              To answer your earlier question, yes, save it as a snippet (named whatever you want) and use it as a custom output filter.

              Background on custom output filters is here: https://docs.modx.com/revolution/2.x/making-sites-with-modx/customizing-content/input-and-output-filters-(output-modifiers)/custom-output-filter-examples

              Fantastic - thanks! - I think it's working. You're a genius! smiley

              One question - if my number is:
              123,456.10
              instead of
              123456.10 - is it possible to ignore the commas that separate the thousands?
              I think I will need the input to include the commas for when they need to be readable as a full number

              Thanks so much for your help so far!
                • 51020
                • 670 Posts
                Quote from: tm2000 at May 15, 2017, 08:09 AM
                Quote from: clareoconsulting at May 15, 2017, 08:00 AM
                Quote from: tm2000 at May 15, 2017, 03:45 AM

                I'm getting a syntax error on the last line:
                    $return $output;


                Remove the $ from in front of return in that line. Not sure how I got that in there; sorry. I've edited my original post to reflect the change.

                To answer your earlier question, yes, save it as a snippet (named whatever you want) and use it as a custom output filter.

                Background on custom output filters is here: https://docs.modx.com/revolution/2.x/making-sites-with-modx/customizing-content/input-and-output-filters-(output-modifiers)/custom-output-filter-examples

                Fantastic - thanks! - I think it's working. You're a genius! smiley

                One question - if my number is:
                123,456.10
                instead of
                123456.10 - is it possible to ignore the commas that separate the thousands?
                I think I will need the input to include the commas for when they need to be readable as a full number

                Thanks so much for your help so far!

                It\s OK _ I solved this part myself by adding:

                :stripString=`,`


                before the snippet - job done!

                Thank you again for you help and advice! smiley
                  • 36816
                  • 109 Posts
                  Quote from: tm2000 at May 15, 2017, 08:09 AM

                  One question - if my number is:
                  123,456.10
                  instead of
                  123456.10 - is it possible to ignore the commas that separate the thousands?
                  I think I will need the input to include the commas for when they need to be readable as a full number

                  Because the snippet/filter is doing math, if you put commas (or any other non-numeric characters) into the input, the snippet won't work at all.

                  As posted, the snippet/filter should output your input value of 123456.10 as "more than 123,000".

                  If you'd like different outputs, you can experiment (trial and error) with changing the configuration of the snippet in the five arrays at the top.
                    • 36816
                    • 109 Posts
                    Quote from: tm2000 at May 15, 2017, 08:19 AM

                    It\s OK _ I solved this part myself by adding:
                    :stripString=`,`


                    Glad you sorted it out that way. If you want, you could modify the snippet/filter line 75 from

                    $value              = floatval($input);


                    to:

                    $value              = floatval(preg_replace("/[^-0-9\.]/", "", $input));


                    It's a more robust approach to the snippet (proof that the original was a quick effort). That will strip out anything but digits and decimal place, and you could drop your stripString filter.

                    NOTE: This whole thing is assuming that you're using a period for decimal point; some languages/countries use a comma. Game changes if that's the case.
                      • 51020
                      • 670 Posts
                      Quote from: clareoconsulting at May 15, 2017, 08:34 AM
                      Quote from: tm2000 at May 15, 2017, 08:19 AM

                      It\s OK _ I solved this part myself by adding:
                      :stripString=`,`


                      Glad you sorted it out that way. If you want, you could modify the snippet/filter line 75 from

                      $value              = floatval($input);


                      to:

                      $value              = floatval(preg_replace("/[^-0-9\.]/", "", $input));


                      It's a more robust approach to the snippet (proof that the original was a quick effort). That will strip out anything but digits and decimal place, and you could drop your stripString filter.

                      NOTE: This whole thing is assuming that you're using a period for decimal point; some languages/countries use a comma. Game changes if that's the case.

                      That's great - yes the figures will always use a period as the decimal point.
                      Thanks again for being so thorough!