functionsnumtoword.lib.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <?php
  2. /* Copyright (C) 2015 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2015 Víctor Ortiz Pérez <victor@accett.com.mx>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. * or see http://www.gnu.org/
  18. */
  19. /**
  20. * \file htdocs/core/lib/functionsnumbertoword.lib.php
  21. * \brief A set of functions for Dolibarr
  22. * This file contains all frequently used functions.
  23. */
  24. /**
  25. * Function to return number in text.
  26. *
  27. *
  28. * @param float $num Number to convert
  29. * @param Lang $langs Language
  30. * @param boolean $currency 0=number to translate | 1=currency to translate
  31. * @param boolean $centimes 0=no centimes | 1=centimes to translate
  32. * @return string Text of the number
  33. */
  34. function dol_convertToWord($num, $langs, $currency=false, $centimes=false)
  35. {
  36. global $conf;
  37. $num = str_replace(array(',', ' '), '', trim($num));
  38. if(! $num) {
  39. return false;
  40. }
  41. if($centimes && strlen($num) == 1) {
  42. $num = $num*10;
  43. }
  44. $TNum = explode('.',$num);
  45. $num = (int) $TNum[0];
  46. $words = array();
  47. $list1 = array(
  48. '',
  49. $langs->transnoentitiesnoconv('one'),
  50. $langs->transnoentitiesnoconv('two'),
  51. $langs->transnoentitiesnoconv('three'),
  52. $langs->transnoentitiesnoconv('four'),
  53. $langs->transnoentitiesnoconv('five'),
  54. $langs->transnoentitiesnoconv('six'),
  55. $langs->transnoentitiesnoconv('seven'),
  56. $langs->transnoentitiesnoconv('eight'),
  57. $langs->transnoentitiesnoconv('nine'),
  58. $langs->transnoentitiesnoconv('ten'),
  59. $langs->transnoentitiesnoconv('eleven'),
  60. $langs->transnoentitiesnoconv('twelve'),
  61. $langs->transnoentitiesnoconv('thirteen'),
  62. $langs->transnoentitiesnoconv('fourteen'),
  63. $langs->transnoentitiesnoconv('fifteen'),
  64. $langs->transnoentitiesnoconv('sixteen'),
  65. $langs->transnoentitiesnoconv('seventeen'),
  66. $langs->transnoentitiesnoconv('eighteen'),
  67. $langs->transnoentitiesnoconv('nineteen')
  68. );
  69. $list2 = array(
  70. '',
  71. $langs->transnoentitiesnoconv('ten'),
  72. $langs->transnoentitiesnoconv('twenty'),
  73. $langs->transnoentitiesnoconv('thirty'),
  74. $langs->transnoentitiesnoconv('forty'),
  75. $langs->transnoentitiesnoconv('fifty'),
  76. $langs->transnoentitiesnoconv('sixty'),
  77. $langs->transnoentitiesnoconv('seventy'),
  78. $langs->transnoentitiesnoconv('eighty'),
  79. $langs->transnoentitiesnoconv('ninety'),
  80. $langs->transnoentitiesnoconv('hundred')
  81. );
  82. $list3 = array(
  83. '',
  84. $langs->transnoentitiesnoconv('thousand'),
  85. $langs->transnoentitiesnoconv('million'),
  86. $langs->transnoentitiesnoconv('billion'),
  87. $langs->transnoentitiesnoconv('trillion'),
  88. $langs->transnoentitiesnoconv('quadrillion')
  89. );
  90. $num_length = strlen($num);
  91. $levels = (int) (($num_length + 2) / 3);
  92. $max_length = $levels * 3;
  93. $num = substr('00' . $num, -$max_length);
  94. $num_levels = str_split($num, 3);
  95. $nboflevels = count($num_levels);
  96. for ($i = 0; $i < $nboflevels; $i++) {
  97. $levels--;
  98. $hundreds = (int) ($num_levels[$i] / 100);
  99. $hundreds = ($hundreds ? ' ' . $list1[$hundreds] . ' '.$langs->transnoentities('hundred') . ( $hundreds == 1 ? '' : 's' ) . ' ': '');
  100. $tens = (int) ($num_levels[$i] % 100);
  101. $singles = '';
  102. if ( $tens < 20 ) {
  103. $tens = ($tens ? ' ' . $list1[$tens] . ' ' : '' );
  104. } else {
  105. $tens = (int) ($tens / 10);
  106. $tens = ' ' . $list2[$tens] . ' ';
  107. $singles = (int) ($num_levels[$i] % 10);
  108. $singles = ' ' . $list1[$singles] . ' ';
  109. }
  110. $words[] = $hundreds . $tens . $singles . ( ( $levels && ( int ) ( $num_levels[$i] ) ) ? ' ' . $list3[$levels] . ' ' : '' );
  111. } //end for loop
  112. $commas = count($words);
  113. if ($commas > 1) {
  114. $commas = $commas - 1;
  115. }
  116. $concatWords = implode(' ', $words);
  117. // Delete multi whitespaces
  118. $concatWords = trim(preg_replace('/[ ]+/', ' ', $concatWords));
  119. if(!empty($currency)) {
  120. $concatWords .= ' '.$currency;
  121. }
  122. // If we need to write cents call again this function for cents
  123. if(!empty($TNum[1])) {
  124. if(!empty($currency)) $concatWords .= ' '.$langs->transnoentities('and');
  125. $concatWords .= ' '.dol_convertToWord($TNum[1], $langs, $currency, true);
  126. if(!empty($currency)) $concatWords .= ' '.$langs->transnoentities('centimes');
  127. }
  128. return $concatWords;
  129. }
  130. /**
  131. * Function to return number or amount in text.
  132. *
  133. * @deprecated
  134. * @param float $numero Number to convert
  135. * @param Lang $langs Language
  136. * @param string $numorcurrency 'number' or 'amount'
  137. * @return string Text of the number or -1 in case TOO LONG (more than 1000000000000.99)
  138. */
  139. function dolNumberToWord($numero, $langs, $numorcurrency='number')
  140. {
  141. // If the number is negative convert to positive and return -1 if is too long
  142. if ($numero < 0) $numero *= -1;
  143. if ($numero >= 1000000000001)
  144. return -1;
  145. // Get 2 decimals to cents, another functions round or truncate
  146. $strnumber = number_format ($numero,10);
  147. $len=strlen($strnumber);
  148. for ($i=0; $i<$len; $i++)
  149. {
  150. if ($strnumber[$i]=='.') {
  151. $parte_decimal = $strnumber[$i+1].$strnumber[$i+2];
  152. break;
  153. }
  154. }
  155. /*In dolibarr 3.6.2 (my current version) doesn't have $langs->default and
  156. in case exist why ask $lang like a parameter?*/
  157. if (((is_object($langs) && $langs->default == 'es_MX') || (! is_object($langs) && $langs == 'es_MX')) && $numorcurrency == 'currency')
  158. {
  159. if ($numero>=1 && $numero<2) {
  160. return ("UN PESO ".$parte_decimal." / 100 M.N.");
  161. }
  162. elseif ($numero>=0 && $numero<1){
  163. return ("CERO PESOS ".$parte_decimal." / 100 M.N.");
  164. }
  165. elseif ($numero>=1000000 && $numero<1000001){
  166. return ("UN MILL&OacuteN DE PESOS ".$parte_decimal." / 100 M.N.");
  167. }
  168. elseif ($numero>=1000000000000 && $numero<1000000000001){
  169. return ("UN BILL&OacuteN DE PESOS ".$parte_decimal." / 100 M.N.");
  170. }
  171. else {
  172. $entexto ="";
  173. $number = $numero;
  174. if ($number >= 1000000000){
  175. $CdMMillon = (int) ($numero / 100000000000);
  176. $numero = $numero - $CdMMillon * 100000000000;
  177. $DdMMillon = (int) ($numero / 10000000000);
  178. $numero = $numero - $DdMMillon * 10000000000;
  179. $UdMMillon = (int) ($numero / 1000000000);
  180. $numero = $numero - $UdMMillon * 1000000000;
  181. $entexto .= hundreds2text ($CdMMillon, $DdMMillon, $UdMMillon);
  182. $entexto .= " MIL ";
  183. }
  184. if ($number >= 1000000){
  185. $CdMILLON = (int) ($numero / 100000000);
  186. $numero = $numero - $CdMILLON * 100000000;
  187. $DdMILLON = (int) ($numero / 10000000);
  188. $numero = $numero - $DdMILLON * 10000000;
  189. $udMILLON = (int) ($numero / 1000000);
  190. $numero = $numero - $udMILLON * 1000000;
  191. $entexto .= hundreds2text ($CdMILLON, $DdMILLON, $udMILLON);
  192. if (!$CdMMillon && !$DdMMillon && !$UdMMillon && !$CdMILLON && !$DdMILLON && $udMILLON==1)
  193. $entexto .= " MILL&OacuteN ";
  194. else
  195. $entexto .= " MILLONES ";
  196. }
  197. if ($number >= 1000) {
  198. $cdm = (int) ($numero / 100000);
  199. $numero = $numero - $cdm * 100000;
  200. $ddm = (int) ($numero / 10000);
  201. $numero = $numero - $ddm * 10000;
  202. $udm = (int) ($numero / 1000);
  203. $numero = $numero - $udm * 1000;
  204. $entexto .= hundreds2text ($cdm, $ddm, $udm);
  205. if ($cdm || $ddm || $udm)
  206. $entexto .= " MIL ";
  207. }
  208. $c = (int) ($numero / 100);
  209. $numero = $numero - $c * 100;
  210. $d = (int) ($numero / 10);
  211. $u = (int) $numero - $d * 10;
  212. $entexto .= hundreds2text ($c, $d, $u);
  213. if (!$cdm && !$ddm && !$udm && !$c && !$d && !$u && $number>1000000)
  214. $entexto .= " DE";
  215. $entexto .= " PESOS ".$parte_decimal." / 100 M.N.";
  216. }
  217. return $entexto;
  218. }
  219. }
  220. /**
  221. * hundreds2text
  222. *
  223. * @param integer $hundreds Hundreds
  224. * @param integer $tens Tens
  225. * @param integer $units Units
  226. */
  227. function hundreds2text($hundreds, $tens, $units)
  228. {
  229. if ($hundreds==1 && $tens==0 && $units==0){
  230. return "CIEN";
  231. }
  232. $centenas = array("CIENTO","DOSCIENTOS","TRESCIENTOS","CUATROCIENTOS","QUINIENTOS","SEISCIENTOS","SETECIENTOS","OCHOCIENTOS","NOVECIENTOS");
  233. $decenas = array("","","TREINTA ","CUARENTA ","CINCUENTA ","SESENTA ","SETENTA ","OCHENTA ","NOVENTA ");
  234. $veintis = array("VEINTE","VEINTIUN","VEINTID&OacuteS","VEINTITR&EacuteS","VEINTICUATRO","VEINTICINCO","VEINTIS&EacuteIS","VEINTISIETE","VEINTIOCHO","VEINTINUEVE");
  235. $diecis = array("DIEZ","ONCE","DOCE","TRECE","CATORCE","QUINCE","DIECIS&EacuteIS","DIECISIETE","DIECIOCHO","DIECINUEVE");
  236. $unidades = array("UN","DOS","TRES","CUATRO","CINCO","SEIS","SIETE","OCHO","NUEVE");
  237. $entexto = "";
  238. if ($hundreds!=0){
  239. $entexto .= $centenas[$hundreds-1];
  240. }
  241. if ($tens>2){
  242. if ($hundreds!=0) $entexto .= " ";
  243. $entexto .= $decenas[$tens-1];
  244. if ($units!=0){
  245. $entexto .= " Y ";
  246. $entexto .= $unidades[$units-1];
  247. }
  248. return $entexto;
  249. }
  250. elseif ($tens==2){
  251. if ($hundreds!=0) $entexto .= " ";
  252. $entexto .= " ".$veintis[$units];
  253. return $entexto;
  254. }
  255. elseif ($tens==1){
  256. if ($hundreds!=0) $entexto .= " ";
  257. $entexto .= $diecis[$units];
  258. return $entexto;
  259. }
  260. if ($units!=0) {
  261. if ($hundreds!=0 || $tens!=0) $entexto .= " ";
  262. $entexto .= $unidades[$units-1];
  263. }
  264. return $entexto;
  265. }