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
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?
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″.
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. :)