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.
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; } }
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.
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″.