CifrasEnLetras.vb

  1. ' CifrasEnLetras.vb — ProInf.net — 19-ene-2011
  2. ' http://proinf.net/permalink/convertir_cifras_en_letras
  3.  
  4. Imports System.Text
  5.  
  6. ''' <summary>
  7. ''' CifrasEnLetras sirve para expresar una serie de cifras en letras.
  8. ''' A modo de ejemplo convierte <q>22</q> en <q>veintidós</q>.
  9. ''' Puede convertir un número entre una y ciento veintiséis cifras como máximo.
  10. ''' </summary>
  11. ''' <dl>
  12. ''' <dt>Ejemplos de uso:</dt>
  13. ''' <dd><code>CifrasEnLetras.convertirEurosEnLetras(22.34)</code> &rarr; <samp>"veintidós euros con treinta y cuatro céntimos"</samp></dd>
  14. ''' <dd><code>CifrasEnLetras.convertirNumeroEnLetras("35,67")</code> &rarr; <samp>"treinta y cinco con sesenta y siete"</samp></dd>
  15. '''
  16. ''' <dt>Enlaces de referencia:</dt>
  17. ''' <dd><a href="http://es.wikipedia.org/wiki/Anexo:Lista_de_n%C3%BAmeros">Lista de números en la Wikipedia</a></dd>
  18. ''' <dd><a href="http://es.encarta.msn.com/encyclopedia_761577100/Signos_matem%C3%A1ticos.html">Signos matemáticos en Encarta</a></dd>
  19. ''' <dd><a href="http://es.wikipedia.org/wiki/Nombres_de_los_n%C3%BAmeros_en_espa%C3%B1ol">Nombres de los números en español</a></dd>
  20. '''
  21. ''' <dt>Tareas pendientes:</dt>
  22. ''' <dd>Función ConvertirAñosEnLetras: "cuatro años", "un lustro", "una década", "dos décadas", "un siglo", "un milenio"</dd>
  23. ''' <dd>Función ConvertirOrdinalesEnLetras: "primero", "segundo", etc.</dd>
  24. ''' <dd>Función ConvertirCifrasEnRomano y convertirRomanoEnCifras</dd>
  25. ''' <dd>Función ConvertirFechasEnLetras: "21-XI-2007" &rarr; "veintiuno de noviembre de dos mil siete"</dd>
  26. '''
  27. ''' <dt>Licencia:</dt>
  28. ''' <dd><a href="http://creativecommons.org/licenses/GPL/2.0/deed.es">
  29. ''' Este software está sujeto a la CC-GNU GPL</a>
  30. ''' </dd>
  31. ''' </dl>
  32. '''
  33. ''' @author Francisco Cascales <fco@proinf.net>
  34. ''' @version 0.01, 8-dic-2007 - Inicio del proyecto
  35. ''' @version 0.02, 12-dic-2007 - Cifras en femenino
  36. ''' @version 0.03, 17-dic-2007 - Formatear cifras separándolas en grupos
  37. ''' @version 0.04, 22-dic-2007 - Múltiplos de millón con preposición "de" antes del concepto:
  38. ''' "un millón de euros", "dos millones de euros", "un millón mil un euros"
  39. ''' Las cifras superiores al millón siempre en masculino.
  40. ''' "doscientos millones doscientas mil personas"
  41. ''' @version 0.05, 7-ene-2008 - Mejoras estructurales
  42. ''' @versión 0.06 19-ene-2011 - Convertido a C# con MonoDevelop 2.4
  43. ''' @version 0.07 20-ene-2011 - Convertido a VB.NET
  44. '''
  45. Public NotInheritable Class CifrasEnLetras
  46.  
  47. '------------------------------------------------------------
  48. ' CONSTANTES
  49.  
  50. Private Const PREFIJO_ERROR As String = "Error: "
  51. Private Const COMA As String = ","
  52. Private Const MENOS As String = "-"
  53.  
  54. '------------------------------------------------------------
  55. ' ENUMERACIONES
  56.  
  57. Public Enum Genero
  58. neutro
  59. masculino
  60. femenino
  61. End Enum
  62.  
  63. Public Shared Function generoDesdeNumero(ByVal numero As Integer) As Genero
  64. If numero = 0 Then
  65. Return Genero.neutro
  66. ElseIf numero = 1 Then
  67. Return Genero.masculino
  68. End If
  69. Return Genero.femenino
  70. End Function
  71.  
  72. '------------------------------------------------------------
  73. ' LISTAS
  74.  
  75. ' Letras de los números entre el 0 y el 29
  76. Private Shared listaUnidades As String() = {"cero", "un", "dos", "tres", "cuatro", "cinco", _
  77. "seis", "siete", "ocho", "nueve", "diez", "once", _
  78. "doce", "trece", "catorce", "quince", "dieciséis", "diecisiete", _
  79. "dieciocho", "diecinueve", "veinte", "veintiún", "veintidós", "veintitrés", _
  80. "veinticuatro", "veinticinco", "veintiséis", "veintisiete", "veintiocho", "veintinueve"}
  81.  
  82. ' Letras de las decenas
  83. Private Shared listaDecenas As String() = {"", "diez", "veinte", "treinta", "cuarenta", "cincuenta", _
  84. "sesenta", "setenta", "ochenta", "noventa"}
  85.  
  86. ' Letras de las centenas
  87. Private Shared listaCentenas As String() = {"", "cien", "doscientos", "trescientos", "cuatrocientos", "quinientos", _
  88. "seiscientos", "setecientos", "ochocientos", "novecientos"}
  89.  
  90. ' Letras en singular de los órdenes de millón.
  91. Private Shared listaOrdenesMillonSingular As String() = {"", "millón", "billón", "trillón", "cuatrillón", "quintillón", _
  92. "sextillón", "septillón", "octillón", "nonillón", "decillón", "undecillón", _
  93. "duodecillón", "tridecillón", "cuatridecillón", "quidecillón", "sexdecillón", "septidecillón", _
  94. "octodecillón", "nonidecillón", "vigillón"}
  95.  
  96. ' Letras en plural de los órdenes de millón
  97. Private Shared listaOrdenesMillonPlural As String() = {"", "millones", "billones", "trillones", "cuatrillones", "quintillones", _
  98. "sextillones", "septillones", "octillones", "nonillones", "decillones", "undecillones", _
  99. "duodecillones", "tridecillones", "cuatridecillones", "quidecillones", "sexdecillones", "septidecillones", _
  100. "octodecillones", "nonidecillones", "vigillones"}
  101.  
  102. '------------------------------------------------------------
  103. ' MÉTODOS PRINCIPALES
  104.  
  105. ''' Convierte a letras los números entre 0 y 29.
  106. ''' Ejemplo: <code>convertirUnidades(21,Genero.femenino)</code> &rarr; <samp>"veintiuna"</samp>
  107. '''
  108. Public Shared Function convertirUnidades(ByVal unidades As Integer, ByVal elGenero As Genero) As String
  109. If unidades = 1 Then
  110. If elGenero = Genero.masculino Then
  111. Return "uno"
  112. ElseIf elGenero = Genero.femenino Then
  113. Return "una"
  114. End If
  115. ElseIf unidades = 21 Then
  116. If elGenero = Genero.masculino Then
  117. Return "veintiuno"
  118. ElseIf elGenero = Genero.femenino Then
  119. Return "veintiuna"
  120. End If
  121. End If
  122. Return listaUnidades(unidades)
  123. End Function
  124.  
  125. ''' Convierte a letras las centenas
  126. ''' Ejemplo: <code>convertirCentenas(2,Genero.femenino)</code> &rarr; <samp>"doscientas"</samp>
  127. '''
  128. Public Shared Function convertirCentenas(ByVal centenas As Integer, ByVal elGenero As Genero) As String
  129. Dim resultado As String = listaCentenas(centenas)
  130. If elGenero = Genero.femenino Then
  131. resultado = resultado.Replace("iento", "ienta")
  132. End If
  133. Return resultado
  134. End Function
  135.  
  136. ''' Primer centenar: del cero al noventa y nueve.
  137. ''' <dl>
  138. ''' <dt>Ejemplos:</dt>
  139. ''' <dd><code>convertirDosCifras(22,Genero.neutro)</code> &rarr; <samp>"veintidós"</samp></dd>
  140. ''' </dl>
  141. ''' <see cref="convertirUnidades(int,Genero)"/>
  142. '''
  143. Public Shared Function convertirDosCifras(ByVal cifras As Integer, ByVal elGenero As Genero) As String
  144. Dim unidad As Integer = cifras Mod 10
  145. Dim decena As Integer = cifras \ 10
  146. If cifras < 30 Then
  147. Return convertirUnidades(cifras, elGenero)
  148. ElseIf unidad = 0 Then
  149. Return listaDecenas(decena)
  150. Else
  151. Return listaDecenas(decena) & " y " & convertirUnidades(unidad, elGenero)
  152. End If
  153. End Function
  154.  
  155. ''' Primer millar: del cero al novecientos noventa y nueve.
  156. ''' <dl>
  157. ''' <dt>Ejemplos:</dt>
  158. ''' <dd><code>convertirTresCifras(222,Genero.neutro)</code> &rarr; <samp>"doscientos veintidós"</samp></dd>
  159. ''' </dl>
  160. ''' <see cref="convertirDosCifras(int,Genero)"/>
  161. ''' <see cref="convertirCentenas(int,Genero)"/>
  162. '''
  163. Public Shared Function convertirTresCifras(ByVal cifras As Integer, ByVal elGenero As Genero) As String
  164. Dim decenas_y_unidades As Integer = cifras Mod 100
  165. Dim centenas As Integer = cifras \ 100
  166. If cifras < 100 Then
  167. Return convertirDosCifras(cifras, elGenero)
  168. ElseIf decenas_y_unidades = 0 Then
  169. Return convertirCentenas(centenas, elGenero)
  170. ElseIf centenas = 1 Then
  171. Return "ciento " & convertirDosCifras(decenas_y_unidades, elGenero)
  172. Else
  173. Return convertirCentenas(centenas, elGenero) & " " & convertirDosCifras(decenas_y_unidades, elGenero)
  174. End If
  175. End Function
  176.  
  177. ''' Primer millón: del cero al novecientos noventa y nueve mil novecientos noventa y nueve.
  178. ''' <dl>
  179. ''' <dt>Ejemplos:</dt>
  180. ''' <dd><code>convertirSeisCifras(222222)</code> &rarr; <samp>"doscientos veintidós mil doscientos veintidós"</samp></dd>
  181. ''' </dl>
  182. ''' <see cref="convertirTresCifras(int,Genero)"/>
  183. '''
  184. Public Shared Function convertirSeisCifras(ByVal cifras As Integer, ByVal elGenero As Genero) As String
  185. Dim primerMillar As Integer = cifras Mod 1000
  186. Dim grupoMiles As Integer = cifras \ 1000
  187. Dim generoMiles As Genero = If(elGenero = Genero.masculino, Genero.neutro, elGenero)
  188. If grupoMiles = 0 Then
  189. Return convertirTresCifras(primerMillar, elGenero)
  190. ElseIf grupoMiles = 1 Then
  191. If primerMillar = 0 Then
  192. Return "mil"
  193. Else
  194. Return "mil " & convertirTresCifras(primerMillar, elGenero)
  195. End If
  196. ElseIf primerMillar = 0 Then
  197. Return convertirTresCifras(grupoMiles, generoMiles) & " mil"
  198. Else
  199. Return convertirTresCifras(grupoMiles, generoMiles) & " mil " & convertirTresCifras(primerMillar, elGenero)
  200. End If
  201. End Function
  202.  
  203. ''' <summary>
  204. ''' Números enteros entre el cero y el novecientos noventa y nueve mil novecientos noventa y nueve vigillones... etc, etc.<br />
  205. ''' Es decir entre el 0 y el (10<sup>126</sup>)-1 o bien números entre 1 y 126 cifras.<br />
  206. ''' Las cifras por debajo del millón pueden ir en masculino o en femenino.
  207. ''' </summary>
  208. '''<dl>
  209. '''<dt>Ejemplos:</dt>
  210. '''<dd><code>convertirCifrasEnLetras("22222222")</code> &rarr; <samp>"veintidós millones doscientos veintidós mil doscientos veintidós"</samp></dd>
  211. ''' <dd><code>convertirCifrasEnLetras("")</code> &rarr; <samp>"No hay ningún número"</samp></dd>
  212. ''' <dd><code>convertirCifrasEnLetras(repetirCaracter('9',127))</code> &rarr; <samp>"El número es demasiado grande ya que tiene más de 126 cifras"</samp></dd>
  213. ''' <dd><code>convertirCifrasEnLetras("0x")</code> &rarr; <samp>"Uno de los caracteres no es una cifra decimal"</samp></dd>
  214. ''' <dd><code>convertirCifrasEnLetras(repetirCaracter('9',126))</code> &rarr; <samp>"novecientos noventa y nueve mil novecientos noventa y nueve vigillones..."</samp></dd>
  215. ''' <dd><code>convertirCifrasEnLetras(10^6)</code> &rarr; <samp>"un millón"</samp></dd>
  216. ''' <dd><code>convertirCifrasEnLetras(10^12)</code> &rarr; <samp>"un billón"</samp></dd>
  217. ''' <dd><code>convertirCifrasEnLetras(10200050)</code> &rarr; <samp>"diez millones doscientos mil cincuenta"</samp></dd>
  218. ''' <dd><code>convertirCifrasEnLetras(10001000)</code> &rarr; <samp>"diez millones mil"</samp></dd>
  219. ''' <dd><code>convertirCifrasEnLetras("1" + repetirCaracter('0',120))</code> &rarr; <samp>"un vigillón"</samp></dd>
  220. ''' <dd><code>convertirCifrasEnLetras("2" + repetirCaracter('0',18))</code> &rarr; <samp>"dos trillones"</samp></dd>
  221. ''' <dd><code>convertirCifrasEnLetras("4792347927489", "\n")</code> &rarr; <samp>"..."</samp></dd>
  222. ''' <dd><code>convertirCifrasEnLetrasFemeninas("501")</code> &rarr; <samp>"quinientas una"</samp></dd>
  223. ''' <dd><code>convertirCifrasEnLetrasFemeninas("240021")</code> &rarr; <samp>"doscientas cuarenta mil veintiuna"</samp></dd>
  224. ''' </dl>
  225. ''' <see cref="convertirSeisCifras(int,Genero)"/>
  226. '''
  227. Public Shared Function convertirCifrasEnLetras( _
  228. ByVal cifras As String, _
  229. ByVal elGenero As Genero, _
  230. ByVal separadorGruposSeisCifras As String _
  231. ) As String
  232.  
  233. ' Inicialización
  234. cifras = cifras.Trim()
  235. Dim numeroCifras As Integer = cifras.Length
  236.  
  237. ' Comprobación
  238. If numeroCifras = 0 Then
  239. Return PREFIJO_ERROR & "No hay ningún número"
  240. End If
  241. For indiceCifra As Integer = 0 To numeroCifras - 1
  242. Dim cifra As Char = cifras(indiceCifra)
  243. Dim esDecimal As Boolean = "0123456789".IndexOf(cifra) >= 0
  244. If Not esDecimal Then
  245. Return PREFIJO_ERROR & "Uno de los caracteres no es una cifra decimal"
  246. End If
  247. Next
  248. If numeroCifras > 126 Then
  249. Return PREFIJO_ERROR & "El número es demasiado grande ya que tiene más de 126 cifras"
  250. End If
  251.  
  252. ' Preparación
  253. Dim numeroGruposSeisCifras As Integer = numeroCifras \ 6 + Math.Sign(numeroCifras)
  254. Dim cerosIzquierda As New String("0"c, numeroGruposSeisCifras * 6 - numeroCifras)
  255. cifras = cerosIzquierda & cifras
  256. Dim ordenMillon As Integer = numeroGruposSeisCifras - 1
  257.  
  258. ' Procesamiento
  259. Dim resultado As New StringBuilder()
  260. For indiceGrupo As Integer = 0 To numeroGruposSeisCifras * 6 - 1 Step 6
  261. Dim seisCifras As Integer = Integer.Parse(cifras.Substring(indiceGrupo, 6))
  262. If seisCifras <> 0 Then
  263. If resultado.Length > 0 Then
  264. resultado.Append(separadorGruposSeisCifras)
  265. End If
  266.  
  267. If ordenMillon = 0 Then
  268. resultado.Append(convertirSeisCifras(seisCifras, elGenero))
  269. ElseIf seisCifras = 1 Then
  270. resultado.Append("un " & listaOrdenesMillonSingular(ordenMillon))
  271. Else
  272. resultado.Append(convertirSeisCifras(seisCifras, Genero.neutro) & " " & listaOrdenesMillonPlural(ordenMillon))
  273. End If
  274. End If
  275. ordenMillon -= 1
  276. Next
  277.  
  278. ' Finalización
  279. If resultado.Length = 0 Then
  280. resultado.Append(listaUnidades(0))
  281. End If
  282. Return resultado.ToString()
  283. End Function
  284.  
  285. ''' <see cref="convertirCifrasEnLetras(string, Genero, string)"/>
  286. Public Shared Function convertirCifrasEnLetras(ByVal cifras As String) As String
  287. Return convertirCifrasEnLetras(cifras, Genero.neutro, " ")
  288. End Function
  289. ''' <see cref="convertirCifrasEnLetras(string, Genero, string)"/>
  290. Public Shared Function convertirCifrasEnLetrasMasculinas(ByVal cifras As String) As String
  291. Return convertirCifrasEnLetras(cifras, Genero.masculino, " ")
  292. End Function
  293. ''' <see cref="convertirCifrasEnLetras(string, Genero, string)"/>
  294. Public Shared Function convertirCifrasEnLetrasFemeninas(ByVal cifras As String) As String
  295. Return convertirCifrasEnLetras(cifras, Genero.femenino, " ")
  296. End Function
  297.  
  298. ''' Expresa un número con decimales y signo en letras
  299. ''' acompañado del tipo de medida para la parte entera y la parte decimal.
  300. ''' <ul>
  301. ''' <li>Los caracteres no numéricos son ignorados.</li>
  302. ''' <li>Los múltiplos de millón tienen la preposición <q>de</q> antes de la palabra.</li>
  303. ''' <li>El género masculino o femenino sólo puede influir en las cifras inferiores al millón</li>
  304. ''' </ul>
  305. ''' <dl><dt>Ejemplos:</dt>
  306. ''' <dd><code>convertirNumeroEnLetras("-123,45",2)</code> &rarr; <samp>"menos ciento veintitrés con cuarenta y cinco"</samp></dd>
  307. ''' <dd><code>convertirNumeroEnLetras("2.000,25", 3, "kilo","gramo")</code> &rarr; <samp>"dos mil kilos con doscientos cincuenta gramos"</samp></dd>
  308. ''' <dd><code>convertirNumeroEnLetras("43,005", 3, "kilómetro","metro")</code> &rarr; <samp>"cuarenta y tres kilómetros con cinco metros"</samp></dd>
  309. ''' <dd><code>convertirNumeroEnLetras("1.270,23", 2, "euro","céntimo")</code> &rarr; <samp>"mil doscientos setenta euros con veintitrés céntimos"</samp></dd>
  310. ''' <dd><code>convertirNumeroEnLetras("1", 2, "euro","céntimo")</code> &rarr; <samp>"un euro con cero céntimos"</samp></dd>
  311. ''' <dd><code>convertirNumeroEnLetras("0,678", 2, "euro","céntimo")</code> &rarr; <samp>"cero euros con sesenta y siete céntimos"</samp></dd>
  312. ''' <dd><code>convertirNumeroEnLetras("22.000,55", 0, "euro","")</code> &rarr; <samp>"veintidós mil euros"</samp></dd>
  313. ''' <dd><code>convertirNumeroEnLetras("-,889")</code> &rarr; <samp>"menos cero con ochocientos ochenta y nueve"</samp></dd>
  314. ''' <dd><code>convertirNumeroEnLetras("200",0,"manzana",true)</code> &rarr; <samp>"doscientas manzanas"</samp></dd>
  315. ''' <dd><code>convertirNumeroEnLetras("1,5",2,"peseta","céntimo",true,false)</code> &rarr; <samp>"una peseta con cincuenta céntimos"</samp></dd>
  316. ''' <dd><code>convertirNumeroEnLetras("300,56",3,"segundo","milésima",false,true)</code> &rarr; <samp>"trescientos segundos con quinientas sesenta milésimas"</samp></dd>
  317. ''' <dd><code>convertirNumeroEnLetras("21,21",2,"niño","niña",false,true)</code> &rarr; <samp>"veintiún niños con veintiuna niñas"</samp></dd>
  318. ''' <dd><code>convertirNumeroEnLetras("1000000",,"euro")</code> &rarr; <samp>"un millón de euros"</samp></dd>
  319. ''' <dd><code>convertirNumeroEnLetras("200.200.200","persona",true)</code> &rarr; <samp>"doscientos millones doscientas mil doscientas personas"</samp></dd>
  320. ''' <dd><code>convertirNumeroEnLetras("221.221.221")</code> &rarr; <samp>"doscientos veintiún millones doscientos veintiún mil doscientos veintiuno"</samp></dd>
  321. ''' </dl>
  322. ''' @param numeroDecimales Si es -1 el número de decimales es automático
  323. ''' <see cref="convertirCifrasEnLetras(string, Genero, string)"/>
  324. ''' <see cref="procesarEnLetras(string, string, string, bool)"/>
  325. '''
  326. Public Shared Function convertirNumeroEnLetras( _
  327. ByVal cifras As String, ByVal numeroDecimales As Integer, _
  328. ByVal palabraEnteraSingular As String, ByVal palabraEnteraPlural As String, ByVal esFemeninaPalabraEntera As Boolean, _
  329. ByVal palabraDecimalSingular As String, ByVal palabraDecimalPlural As String, ByVal esFemeninaPalabraDecimal As Boolean _
  330. ) As String
  331.  
  332. ' Limpieza
  333. cifras = dejarSoloCaracteresDeseados(cifras, "0123456789" & COMA & MENOS)
  334.  
  335. ' Comprobaciones
  336. Dim repeticionesMenos As Integer = numeroRepeticiones(cifras, MENOS)
  337. Dim repeticionesComa As Integer = numeroRepeticiones(cifras, COMA)
  338. If repeticionesMenos > 1 OrElse (repeticionesMenos = 1 AndAlso Not cifras.StartsWith(MENOS)) Then
  339. Return PREFIJO_ERROR & "Símbolo negativo incorrecto o demasiados símbolos negativos"
  340. ElseIf repeticionesComa > 1 Then
  341. Return PREFIJO_ERROR & "Demasiadas comas decimales"
  342. End If
  343.  
  344. ' Negatividad
  345. Dim esNegativo As Boolean = cifras.StartsWith(MENOS)
  346. If esNegativo Then
  347. cifras = cifras.Substring(1)
  348. End If
  349.  
  350. ' Preparación
  351. Dim posicionComa As Integer = cifras.IndexOf(COMA)
  352. If posicionComa = -1 Then
  353. posicionComa = cifras.Length
  354. End If
  355.  
  356. Dim cifrasEntera As String = cifras.Substring(0, posicionComa)
  357. If cifrasEntera.Equals("") OrElse cifrasEntera.Equals(MENOS) Then
  358. cifrasEntera = "0"
  359. End If
  360. Dim cifrasDecimal As String = cifras.Substring(Math.Min(posicionComa + 1, cifras.Length))
  361.  
  362. Dim esAutomaticoNumeroDecimales As Boolean = numeroDecimales < 0
  363. If esAutomaticoNumeroDecimales Then
  364. numeroDecimales = cifrasDecimal.Length
  365. Else
  366. cifrasDecimal = cifrasDecimal.Substring(0, Math.Min(numeroDecimales, cifrasDecimal.Length))
  367. Dim cerosDerecha As New String("0"c, numeroDecimales - cifrasDecimal.Length)
  368. cifrasDecimal = cifrasDecimal & cerosDerecha
  369. End If
  370.  
  371. ' Cero
  372. Dim esCero As Boolean = dejarSoloCaracteresDeseados(cifrasEntera, "123456789").Equals("") AndAlso dejarSoloCaracteresDeseados(cifrasDecimal, "123456789").Equals("")
  373.  
  374. ' Procesar
  375. Dim resultado As New StringBuilder()
  376.  
  377. If esNegativo AndAlso Not esCero Then
  378. resultado.Append("menos ")
  379. End If
  380.  
  381. Dim parteEntera As String = procesarEnLetras(cifrasEntera, palabraEnteraSingular, palabraEnteraPlural, esFemeninaPalabraEntera)
  382. If parteEntera.StartsWith(PREFIJO_ERROR) Then
  383. Return parteEntera
  384. End If
  385. resultado.Append(parteEntera)
  386.  
  387. If Not cifrasDecimal.Equals("") Then
  388. Dim parteDecimal As String = procesarEnLetras(cifrasDecimal, palabraDecimalSingular, palabraDecimalPlural, esFemeninaPalabraDecimal)
  389. If parteDecimal.StartsWith(PREFIJO_ERROR) Then
  390. Return parteDecimal
  391. End If
  392. resultado.Append(" con ")
  393. resultado.Append(parteDecimal)
  394. End If
  395.  
  396. Return resultado.ToString()
  397. End Function
  398.  
  399. ''' @see #convertirNumeroEnLetras(string, int, string, string, bool, string, string, bool)
  400. Public Shared Function convertirNumeroEnLetras(ByVal cifras As String) As String
  401. Return convertirNumeroEnLetras(cifras, -1, "", "", False, "", "", False)
  402. End Function
  403. ''' @see #convertirNumeroEnLetras(string, int, string, string, bool, string, string, bool)
  404. Public Shared Function convertirNumeroEnLetras(ByVal cifras As String, ByVal numeroDecimales As Integer) As String
  405. Return convertirNumeroEnLetras(cifras, numeroDecimales, "", "", False, "", "", False)
  406. End Function
  407. ''' @see #convertirNumeroEnLetras(string, int, string, string, bool, string, string, bool)
  408. Public Shared Function convertirNumeroEnLetras(ByVal cifras As String, ByVal palabraEntera As String) As String
  409. Return convertirNumeroEnLetras(cifras, 0, palabraEntera, palabraEntera & "s", False, "", "", False)
  410. End Function
  411. ''' @see #convertirNumeroEnLetras(string, int, string, string, bool, string, string, bool)
  412. Public Shared Function convertirNumeroEnLetras(ByVal cifras As String, ByVal palabraEntera As String, ByVal esFemeninaPalabraEntera As Boolean) As String
  413. Return convertirNumeroEnLetras(cifras, 0, palabraEntera, palabraEntera & "s", esFemeninaPalabraEntera, "", "", False)
  414. End Function
  415. ''' @see #convertirNumeroEnLetras(string, int, string, string, bool, string, string, bool)
  416. Public Shared Function convertirNumeroEnLetras(ByVal cifras As String, ByVal numeroDecimales As Integer, ByVal palabraEntera As String, ByVal palabraDecimal As String) As String
  417. Return convertirNumeroEnLetras(cifras, numeroDecimales, palabraEntera, palabraEntera & "s", False, palabraDecimal, palabraDecimal & "s", False)
  418. End Function
  419. ''' @see #convertirNumeroEnLetras(string, int, string, string, bool, string, string, bool)
  420. Public Shared Function convertirNumeroEnLetras(ByVal cifras As String, ByVal numeroDecimales As Integer, ByVal palabraEntera As String, ByVal palabraDecimal As String, ByVal esFemeninaPalabraEntera As Boolean, ByVal esFemeninaPalabraDecimal As Boolean) As String
  421. Return convertirNumeroEnLetras(cifras, numeroDecimales, palabraEntera, palabraEntera & "s", esFemeninaPalabraEntera, palabraDecimal, palabraDecimal & "s", esFemeninaPalabraDecimal)
  422. End Function
  423.  
  424. ''' Función auxiliar de <code>convertirNumeroEnLetras</code>
  425. ''' para procesar por separado la parte entera y la parte decimal
  426. ''' <see cref="convertirCifrasEnLetras(string, bool, string)"/>
  427. '''
  428. Private Shared Function procesarEnLetras(ByVal cifras As String, ByVal palabraSingular As String, ByVal palabraPlural As String, ByVal esFemenina As Boolean) As String
  429. ' Género
  430. Dim elGenero As Genero = Genero.neutro
  431. If esFemenina Then
  432. elGenero = Genero.femenino
  433. ElseIf palabraSingular.Equals("") Then
  434. elGenero = Genero.masculino
  435. End If
  436.  
  437. ' Letras
  438. Dim letras As String = convertirCifrasEnLetras(cifras, elGenero, " ")
  439. If letras.StartsWith(PREFIJO_ERROR) Then
  440. Return letras
  441. End If
  442.  
  443. ' Propiedades // 7-ene-2008
  444. Dim esCero As Boolean = letras.Equals(convertirUnidades(0, elGenero)) OrElse letras.Equals("")
  445. '---letras.Equals("cero") || letras.Equals("");
  446. Dim esUno As Boolean = letras.Equals(convertirUnidades(1, elGenero))
  447. '---letras.Equals("un") || letras.Equals("una") || letras.Equals("uno");
  448. Dim esMultiploMillon As Boolean = Not esCero AndAlso cifras.EndsWith("000000")
  449.  
  450. ' Palabra
  451. Dim palabra As String = ""
  452. If Not palabraSingular.Equals("") Then
  453. If esUno OrElse palabraPlural.Equals("") Then
  454. palabra = palabraSingular
  455. Else
  456. palabra = palabraPlural
  457. End If
  458. End If
  459.  
  460. ' Resultado
  461. Dim resultado As New StringBuilder()
  462. resultado.Append(letras)
  463. If Not palabra.Equals("") Then
  464. If esMultiploMillon Then
  465. resultado.Append(" de ")
  466. Else
  467. resultado.Append(" ")
  468. End If
  469. resultado.Append(palabra)
  470. End If
  471. Return resultado.ToString()
  472. End Function
  473.  
  474. ''' Convertir euros en letras
  475. ''' <dl>
  476. ''' <dt>Ejemplos:</dt>
  477. ''' <dd><code>convertirEurosEnLetras("44276598801,2",2)</code> &rarr; <samp>"cuatrocientos noventa y ocho mil un euros con veinte céntimos"</samp></dd>
  478. ''' <dd><code>convertirEurosEnLetras(85009)</code> &rarr; <samp>"ochenta y cinco mil nueve euros"</samp></dd>
  479. ''' <dd><code>convertirEurosEnLetras(10200.35)</code> &rarr; <samp>"diez mil doscientos euros con treinta y cinco céntimos"</samp></dd>
  480. ''' </dl>
  481. ''' <see cref="convertirNumeroEnLetras(string, int, string, string)"/>
  482. '''
  483. Public Shared Function convertirEurosEnLetras(ByVal cifras As String, ByVal numeroDecimales As Integer) As String
  484. Return convertirNumeroEnLetras(cifras, numeroDecimales, "euro", "céntimo")
  485. End Function
  486. ''' <see cref="convertirEurosEnLetras(string, int)"/>
  487. Public Shared Function convertirEurosEnLetras(ByVal euros As Long) As String
  488. Dim cifras As String = euros.ToString()
  489. Return convertirEurosEnLetras(cifras, 0)
  490. End Function
  491. ''' <see cref="convertirEurosEnLetras(string, int)"/>
  492. Public Shared Function convertirEurosEnLetras(ByVal euros As Double) As String
  493. Dim cifras As String = euros.ToString().Replace("."c, ","c)
  494. Return convertirEurosEnLetras(cifras, 2)
  495. End Function
  496.  
  497. '------------------------------------------------------------
  498. ' FUNCIONES AUXILIARES
  499.  
  500. ''' Borra todos los caracteres del texto que no sea alguno de los caracteres deseados.
  501. ''' <dl>
  502. ''' <dt>Ejemplos:</dt>
  503. ''' <dd><code>dejarSoloCaracteresDeseados("89.500.400","0123456789")</code> &rarr; <samp>"89500400"</samp></dd>
  504. ''' <dd><code>dejarSoloCaracteresDeseados("ABC-000-123-X-456","0123456789")</code> &rarr; <samp>"000123456"</samp></dd>
  505. ''' </dl>
  506. '''
  507. Public Shared Function dejarSoloCaracteresDeseados(ByVal texto As String, ByVal caracteresDeseados As String) As String
  508. Dim indice As Integer = 0
  509. Dim resultado As New StringBuilder(texto)
  510. While indice < resultado.Length
  511. Dim caracter As Char = resultado(indice)
  512. If caracteresDeseados.IndexOf(caracter) < 0 Then
  513. resultado.Remove(indice, 1)
  514. Else
  515. indice += 1
  516. End If
  517. End While
  518. Return resultado.ToString()
  519. End Function
  520.  
  521. ''' Cuenta el número de repeticiones en el texto de los caracteres indicados
  522. ''' <dl>
  523. ''' <dt>Ejemplos:</dt>
  524. ''' <dd><code>numeroRepeticiones("89.500.400","0")</code> &rarr; <samp>4</samp></dd>
  525. ''' </dl>
  526. '''
  527. Public Shared Function numeroRepeticiones(ByVal texto As String, ByVal caracteres As String) As Integer
  528. Dim resultado As Integer = 0
  529. For indice As Integer = 0 To texto.Length - 1
  530. Dim caracter As Char = texto(indice)
  531. If caracteres.IndexOf(caracter) >= 0 Then
  532. resultado += 1
  533. End If
  534. Next
  535. Return resultado
  536. End Function
  537.  
  538. ''' Separa las cifras en grupos de 6 con subrayados y los grupos de 6 en grupos de 2 con punto
  539. ''' <dl>
  540. ''' <dt>Ejemplos:</dt>
  541. ''' <dd><code>formatearCifras("-4739249,2")</code> &rarr; <samp>"-4_739.249,2"</samp></dd>
  542. ''' </dl>
  543. '''
  544. Public Shared Function formatearCifras(ByVal cifras As String) As String
  545. cifras = dejarSoloCaracteresDeseados(cifras, "0123456789" & COMA & MENOS)
  546. If cifras.Length = 0 Then
  547. Return cifras
  548. End If
  549.  
  550. Dim esNegativo As Boolean = cifras.StartsWith(MENOS)
  551. If esNegativo Then
  552. cifras = cifras.Substring(1)
  553. End If
  554.  
  555. Dim posicionComa As Integer = cifras.IndexOf(COMA)
  556. Dim esDecimal As Boolean = posicionComa >= 0
  557.  
  558. If Not esDecimal Then
  559. posicionComa = cifras.Length
  560. End If
  561. Dim cifrasEntera As String = cifras.Substring(0, posicionComa)
  562. Dim cifrasDecimal As String = ""
  563.  
  564. If esDecimal Then
  565. cifrasDecimal = cifras.Substring(Math.Min(posicionComa + 1, cifras.Length))
  566. End If
  567. If cifrasEntera.Equals("") Then
  568. cifrasEntera = "0"
  569. End If
  570.  
  571. Dim resultado As New StringBuilder()
  572. Dim numeroCifras As Integer = cifrasEntera.Length
  573. 'int numeroGruposTresCifras = numeroCifras / 3 + Integer.signum(numeroCifras);
  574. Dim par As Boolean = True
  575.  
  576. For indice As Integer = 0 To numeroCifras - 1 Step 3
  577. Dim indiceGrupo As Integer = numeroCifras - indice
  578. Dim tresCifras As String = cifras.Substring(Math.Max(indiceGrupo - 3, 0), indiceGrupo)
  579. If indice > 0 Then
  580. resultado.Insert(0, If(par = True, "."c, "_"c))
  581. par = Not par
  582. End If
  583. resultado.Insert(0, tresCifras)
  584. Next
  585. If esNegativo Then
  586. resultado.Insert(0, MENOS)
  587. End If
  588. If esDecimal Then
  589. resultado.Append(COMA & cifrasDecimal)
  590. End If
  591.  
  592. Return resultado.ToString()
  593. End Function
  594.  
  595. End Class ' class CifrasEnLetras
  596.  
  597.  

Proinf.net