Kwota słownie

Podczas generowania różnego rodzaju dokumentów, jak choćby blankiety wpłaty pieniędzy, czy faktur, napotykamy się na problem generowania słownej prezentacji kwoty. O ile wypełniając takie rzeczy ręcznie nie jest to trudne oraz oczywiście jeżeli ktoś nie ma problemów z pisownią na przykład „sześćset”(ile to razy widziało się mandaty czy inne rzeczy z napisem „szejset”), o tyle tworząc takie rzeczy, chcemy zautomatyzować jak najwięcej procesów. Głupstwem byłoby tworzenie ręcznego wprowadzania kwoty słownie, więc w każdym projekcie dochodzi się do zagadnienia generowania słownej reprezentacji kwoty. Od razu spieszę z pomocą. Mianowicie: stworzyłem klasę, która pozwala wygenerować ten zapis aż do kwoty 999 999 999 zł 99 gr. W Internecie można spotkać się z klasami do bilionów, trylionów itd., lecz powiedzmy sobie szczerze: kto to wykorzysta? Są to sporadyczne przypadki, gdzie już programista może się minimalnie bardziej zmęczyć i dopisać obsługę większych kwot, co przy już gotowym kodzie tysięcy i milionów, byłoby kwestią pięciu minut.

Klasa AmountInWords

Poniżej zamieszczam kod mojej klasy, która w bardzo prosty sposób umożliwi Ci wygenerowanie słownego zapisu kwoty. Bez większych przeszkód możesz jej używać w projektach komercyjnych, gdyż wybrana przeze mnie licencja na to w pełni zezwala. Wystarczy mi to, że pozostawisz komentarz, który znajduje się nad kodem klasy.

/**
*
* @copyright (c) 2010 Łukasz Rutkowski
* @license http://creativecommons.org/licenses/by/3.0/pl/ Creative Commons Uznanie autorstwa 3.0
*
*/
 
class AmountInWords {
    private static $units = array(
        'zero',
        'jeden',
        'dwa',
        'trzy',
        'cztery',
        'pięć',
        'sześć',
        'siedem',
        'osiem',
        'dziewięć',
        'dziesięć',
        'jedenaście',
        'dwanaście',
        'trzynaście',
        'czternaście',
        'piętnaście',
        'szesnaście',
        'siedemnaście',
        'osiemnaście',
        'dziewiętnaście'
    );
    private static $tens = array(
        '',
        'dziesięć',
        'dwadzieścia',
        'trzydzieści',
        'czterdzieści',
        'pięćdziesiąt',
        'sześćdziesiąt',
        'siedemdziesiąt',
        'osiemdziesiąt',
        'dziewięćdziesiąt'
    );
    private static $hundreds = array(
        '',
        'sto',
        'dwieście',
        'trzysta',
        'czterysta',
        'pięćset',
        'sześćset',
        'siedemset',
        'osiemset',
        'dziewięćset'
    );
 
    private static $thousands = array(
        'tysiąc',
        'tysiące',
        'tysięcy'
    );
 
    private static $millions = array(
        'milion',
        'miliony',
        'milionów'
    );
 
    public static function getGr($amount)
    {
        $gr = ( $amount - floor($amount) ) * 100;
        return $gr;
    }
 
    public static function getZl($amount)
    {
        $str = '';
 
        $zl = floor($amount);
        $len = strlen($zl);
        if($len >= 7) {
            $million = substr($zl, -7, 1);
            $million2 = substr($zl, -7, 1);
            if($len >= 5) {
                $million = substr($zl, -8, 1).$million;
            }
            if($len >= 6) {
                $million = substr($zl, -9, 1).$million;
            }
            if($million != 1) {
                $str .= self::getZl((float)$million).' ';
            }
            if($million2 == 1) {
                $str .= self::$millions[0].' ';
            } elseif($million2 >= 2 AND $million2 <= 4) {
                $str .= self::$millions[1].' ';
            } else {
                $str .= self::$millions[2].' ';
            }
        }
 
        if($len >= 4) {
            $thousand = substr($zl, -4, 1);
            $thousand2 = substr($zl, -4, 1);
            if($len >= 5) {
                $thousand = substr($zl, -5, 1).$thousand;
            }
            if($len >= 6) {
                $thousand = substr($zl, -6, 1).$thousand;
            }
            if($thousand > 1) {
                $str .= self::getZl((float)$thousand).' ';
            }
            if($thousand2 == 1) {
                $str .= self::$thousands[0].' ';
            } elseif($thousand2 >= 2 AND $thousand2 <= 4) {
                $str .= self::$thousands[1].' ';
            } elseif($thousand2 != 0) {
                $str .= self::$thousands[2].' ';
            }
        }
 
        if($len >= 3) {
            $hundreds = substr($zl, -3, 1);
            if($hundreds != 0) {
                $str .= self::$hundreds[$hundreds].' ';
            }
        }
        if($len >= 1) {
            if($len == 1) {
                $to99 = substr($zl, -1, 1);
            } else {
                $to99 = substr($zl, -2, 2);
            }
            if($to99 < 20) {
                if(substr($to99, 0, 1) == '0') {
                    $to99 = substr($to99, 1, 1);
                }
                if($to99 != 0) {
                    $str .= self::$units[$to99].' ';
                }
            } else {
                $ten = substr($to99, 0, 1);
                $str .= self::$tens[$ten].' ';
 
                $unit = substr($to99, 1, 2);
                if($unit != '0') {
                    $str .= ' '.self::$units[$unit].' ';
                }
            }
        }
        if($zl == 0) {
            $str .= self::$units[0].' ';
        }
        return $str;
    }
 
    public static function get($amount)
    {
        $str = self::getZl($amount).'zł '.self::getGr($amount).'/100';
        return $str;
    }
}

Używanie

Zastosowanie powyższej klasy w praktyce jest banalnie proste. Najbardziej banalnym odwołaniem do niej jest:

AmountInWords::get(212.59);

Wywołana metoda zwróci wtedy kwotę słownie w postaci:

dwieście dwanaście zł 59/100

Czyli w najpowszechniej stosowanym formacie na blankietach, fakturach i innych „papierkach”. W przypadku, kiedy chcemy sobie to wyświetlić inaczej, nie ma największego problemu i wystarczy, że manualnie wykorzystamy dwie metody: getZl() i getGr(). Pierwsza zwróci samo:

dwieście dwanaście

Zaś druga:

59

Nic nie stoi również na przeszkodzie, aby grosze przekazać do funkcji getZl() i również wyświetlić je w postaci słownej. Czas na przykład:

echo AmountInWords::getZl(212.59).' złoty oraz '.AmountInWords::getZl(59).' groszy';

Wyświetli to:

dwieście dwanaście złoty oraz pięćdziesiąt dziewięć groszy

Resztę pozostawiam Twojej wyobraźni. Dodam tylko, że nic nie stoi na przeszkodzie, aby wykorzystać powyższą klasę do generowania słownych zapisów liczb innego typu.

Za ten artykuł podziękowano 0 raz(y). Chcesz i Ty ?

3 Comments

  • 24 lipca 2010 - 14:43 | Permalink

    no tak, a nie lepiej odrazy w metodzie „get” wykryć ze jest kwota z groszami wy wywołać metodę getZl dla złotówek i groszy, skleić to i zwrócić tak jak należy?

  • 24 lipca 2010 - 16:31 | Permalink

    Fabain, jeżeli ktoś chce, może sobie zmienić zawartość metody get() na taką, jaka zapewni mu wartość w odpowiednim formacie. Jak na dzień dzisiejszy, chyba wszędzie spotykałem się z zapisem w formacie”złotówki_słownie zł ilość_groszy/100″.

  • luk4s
    7 czerwca 2011 - 11:41 | Permalink

    Coś nie działa, np. dla kwoty 12345 daje
    dwanaście tysiące trzysta czterdzieści pięć zł 0/100
    dla 111111
    sto jedenaście tysiąc sto jedenaście zł 0/100

    Jeśli można, proszę o zamieszczenie poprawionej wersji. :)

  • Dodaj komentarz

    Twój adres e-mail nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

    *

    Możesz użyć następujących tagów oraz atrybutów HTML-a: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">