Ir al contenido principal

[PB] - Convertir Numero en Letra

¿Alguna vez has necesitado crear un proceso que tenga que traducir números a letras?
Por ejemplo, para un proceso de emisión de cheques.

Pues esta es la rutina que necesitas
En este caso, vamos a desarrollar un traductor en dos idiomas, es castellano y en catalán.

Para ello vamos a usar la función GlobalReplace que viene con las PFC's, pero si no las usas, no importa porque la he extraído para este ejemplo.

1- Creamos un objeto de usuario no visual autoinstanciable, por ejemplo lo llamamos ncst_num2txt

2- Definimos las siguientes variables de instancia

private String is_cifra[],is_centenas[]

3- Creamos las funciones de of_GloblalReplace y otra para sobrecargar por defecto la opción de IgnoreCase (Esto lo puedes encontrar en la PFCs)

public function string of_GlobalReplace (string as_Source, string as_Old, string as_New, boolean ab_IgnoreCase);
//////////////////////////////////////////////////////////////////////////////
//
// Function:   of_GlobalReplace
//
// Access:   public
//
// Arguments:
// as_Source The string being searched.
// as_Old The old string being replaced.
// as_New The new string.
//      ab_IgnoreCase A boolean stating to ignore case sensitivity.
//
// Returns:   string
// as_Source with all occurrences of as_Old replaced with as_New.
// If any argument's value is NULL, function returns NULL.
//
// Description:   Replace all occurrences of one string inside another with
// a new string.
//
//////////////////////////////////////////////////////////////////////////////
//
// Revision History
//
// Version
// 5.0   Initial version
//
//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1996 Powersoft Corporation.  All Rights Reserved.
// Any distribution of the PowerBuilder Foundation Classes (PFC)
// source code by other than Powersoft is prohibited.
//
//////////////////////////////////////////////////////////////////////////////


Long ll_Start, ll_OldLen, ll_NewLen
String ls_Source


//Check parameters
If IsNull(as_source) or IsNull(as_old) or IsNull(as_new) or IsNull(ab_ignorecase) Then
string ls_null
SetNull(ls_null)
Return ls_null
End If


//Get the string lenghts
ll_OldLen = Len(as_Old)
ll_NewLen = Len(as_New)


//Should function respect case.
If ab_ignorecase Then
as_old = Lower(as_old)
ls_source = Lower(as_source)
Else
ls_source = as_source
End If


//Search for the first occurrence of as_Old
ll_Start = Pos(ls_Source, as_Old)


Do While ll_Start > 0
// replace as_Old with as_New
as_Source = Replace(as_Source, ll_Start, ll_OldLen, as_New)

//Should function respect case.
If ab_ignorecase Then 
ls_source = Lower(as_source)
Else
ls_source = as_source
End If

// find the next occurrence of as_Old
ll_Start = Pos(ls_Source, as_Old, (ll_Start + ll_NewLen))
Loop


Return as_Source


end function


public function string of_GlobalReplace (string as_Source, string as_Old, string s_New);
//////////////////////////////////////////////////////////////////////////////
//
// Function:   of_GlobalReplace
//
// Access:   public
//
// Arguments:
// as_Source The string being searched.
// as_Old The old string being replaced.
// as_New The new string.
// 
// Returns:   string
// as_Source with all occurrences of as_Old replaced with as_New.
// If any argument's value is NULL, function returns NULL.
//
// Description:   Replace all occurrences of one string inside another with
// a new string.
//
//////////////////////////////////////////////////////////////////////////////
//
// Revision History
//
// Version
// 5.0   Initial version
//
//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1996 Powersoft Corporation.  All Rights Reserved.
// Any distribution of the PowerBuilder Foundation Classes (PFC)
// source code by other than Powersoft is prohibited.
//
//////////////////////////////////////////////////////////////////////////////


Integer li_Start, li_OldLen, li_NewLen


//Check parameters
If IsNull(as_source) or IsNull(as_old) or IsNull(as_new) Then
string ls_null
SetNull(ls_null)
Return ls_null
End If


//The default is to ignore Case
as_Source = of_GlobalReplace (as_source, as_old, as_new, True)


Return as_Source


end function

4 - Definimos la función of_GetCifra(integer ai_numero) return String

private function string of_getcifra (integer ai_numero);
//////////////////////////////////////////////////////////////////////////////
//
// Función: of_getcifra
//
// Argumentos: integer ai_numero
//
// Retorno: string
//
// Descripción: Devuelve el número en letra
//
//////////////////////////////////////////////////////////////////////////////
//
// Historial de revisiones Autor: FLH
//
// Fecha       Versión
// 15/07/2004       1.0   Versión inicial
//
//////////////////////////////////////////////////////////////////////////////
String ls_CurrItm
Integer li_numero, li_pos


IF ai_numero <= 20 THEN
ls_CurrItm = is_cifra[ai_numero] // Del 1 al 20 coincide con la matriz
ELSE
li_numero = ai_numero - 30
CHOOSE CASE li_numero
CASE IS < 0
li_numero = li_numero * -1
li_pos = Int(li_numero / 10) + 21
CASE 0
li_pos = 21
CASE ELSE
li_pos = Int(li_numero / 10) + 21
END CHOOSE
ls_CurrItm = is_cifra[li_pos]
END IF


RETURN ls_CurrItm


end function

5 - Definimos la función of_trio(String as_trio, String as_codidiom) return String, esta función evalúa de 3 en 3 las cifras (cien, diez, etc..)

private function string of_trio (string as_trio, string as_codidiom);
//////////////////////////////////////////////////////////////////////////////
//
// Función: of_trio
//
// Argumentos: string as_trio
// string as_codidiom
//
// Retorno: string
//
// Descripción: Traduce un número de 1, 2 o 3 cifras en letras
//
//////////////////////////////////////////////////////////////////////////////
//
// Historial de revisiones Autor: FLH
//
// Fecha       Versión
// 15/07/2004       1.0   Versión inicial
//
//////////////////////////////////////////////////////////////////////////////
String ls_cif
String ls_ciento, ls_cientas, ls_and, ls_y
Integer li_cif1, li_cif2, li_cif3


ls_cif  = ''
li_cif1 = Integer(LEFT(as_trio,1))
li_cif2 = Integer(MID(as_trio,2,1))
li_cif3 = Integer(MID(as_trio,3,1))


Choose Case as_codidiom
case 'ESPA'
ls_ciento = 'cien'
ls_and = ''
ls_y = ' y '
case 'CATA'
ls_ciento = 'cent'
ls_and = ''
ls_y = ''
end choose


// Primera cifra. (Centenas)
CHOOSE CASE li_cif1
CASE 1
if li_cif2 = 0 and li_cif3 = 0 then
ls_cif = ls_ciento
else
ls_cif = is_centenas[li_cif1] + ' '
end if
CASE IS > 1
ls_cif = is_centenas[li_cif1] + ' '
END CHOOSE


// Segunda cifra (Decenas)
CHOOSE CASE li_cif2
CASE 3 TO 9
// Eliminamos las cifras que empiezan por 1 y 2
CHOOSE CASE li_cif3
CASE 0
// Decenas exactas
ls_cif = ls_cif + ls_and + of_GetCifra(li_cif2 * 10) + ' '
CASE IS > 0
ls_cif = ls_cif + ls_and + of_GetCifra(li_cif2 * 10) + ls_y
END CHOOSE
CASE 2
// En este caso, tenemos que tener en cuenta que 20 ( Veinte ) es diferente que Veinti
CHOOSE CASE li_cif3
CASE 0
// Veinte exacto
ls_cif = ls_cif + ls_and + is_cifra[29] + ' ' // Veinte
CASE IS > 0
// Igual que en el resto de números
ls_cif = ls_cif + ls_and + of_GetCifra(li_cif2 * 10)
END CHOOSE
CASE 1
// Esta forma tiene otra gestión
// Debemos de indicarle la 3º cifra
ls_cif = ls_cif + ls_and + of_GetCifra((li_cif2 * 10) + li_cif3) + ' '
END CHOOSE


// Tercera cifra (Unidad)
IF li_cif3 > 0 THEN
// Tenemos que tener en cuenta que las deceneas ( 10 ) ya están gestionadas
IF li_cif2 <> 1 THEN
ls_cif = ls_cif + of_GetCifra(li_cif3)
END IF
END IF


RETURN ls_cif


end function

6- Y por último definimos la función de traducción con la parametrización de las palabras según idioma. of_num2txt (decimal adc_numero, string as_codidiom) return String

public function string of_num2txt (decimal adc_numero, string as_codidiom);
//////////////////////////////////////////////////////////////////////////////
//
// Función: of_num2txt
//
// Argumentos: decimal adc_numero
// string as_codidiom
//
// Retorno: string
//
// Descripción: Convierte un número en texto
//
//////////////////////////////////////////////////////////////////////////////
//
// Historial de revisiones Autor: FLH
//
// Fecha       Versión
// 15/07/2004       1.0   Versión inicial
//
//////////////////////////////////////////////////////////////////////////////
String ls_texto, ls_decimal
String ls_numero, ls_billones, ls_millardo, ls_millones, ls_miles, ls_centenas
Integer li_for
dec ldec_residuo
String ls_txt_billon, ls_txt_millon, ls_txt_miles, ls_txt_un
String ls_txt_billones, ls_txt_millones, ls_txt_cien, ls_conjuncion, ls_and
Boolean lb_decimal


lb_decimal = FALSE
// Si tiene parte decimal ponemos 'con'
ldec_residuo = adc_numero - (truncate(adc_numero,0))
if ldec_residuo >= 0.01 then
adc_numero = truncate(adc_numero,0)
lb_decimal = true
// si tiene decimales SIEMPRE trataremos solo dos decimales
ldec_residuo = Truncate((ldec_residuo * 100),0)
end if


Choose case as_codidiom
case 'ESPA'
ls_conjuncion = 'con'
ls_txt_billon = 'billón'
ls_txt_millon = 'millón'
ls_txt_billones = 'billones'
ls_txt_millones = 'millones'
ls_txt_miles = 'mil'
ls_txt_cien = 'cien'
ls_txt_un = 'un'
ls_and = ''
is_cifra[1]  = "uno"
is_cifra[2]  = "dos"
is_cifra[3]  = "tres"
is_cifra[4]  = "cuatro"
is_cifra[5]  = "cinco"
is_cifra[6]  = "seis"
is_cifra[7]  = "siete"
is_cifra[8]  = "ocho"
is_cifra[9]  = "nueve"
is_cifra[10] = "diez"
is_cifra[11] = "once"
is_cifra[12] = "doce"
is_cifra[13] = "trece"
is_cifra[14] = "catorce"
is_cifra[15] = "quince"
is_cifra[16] = "dieciseis"
is_cifra[17] = "diecisiete"
is_cifra[18] = "dieciocho"
is_cifra[19] = "diecinueve"
is_cifra[20] = "veinti"
is_cifra[21] = "treinta"
is_cifra[22] = "cuarenta"
is_cifra[23] = "cincuenta"
is_cifra[24] = "sesenta"
is_cifra[25] = "setenta"
is_cifra[26] = "ochenta"
is_cifra[27] = "noventa"
is_cifra[29] = "veinte"

// Cargamos las centenas
is_centenas[1] = 'ciento'
is_centenas[2] = 'doscientos'
is_centenas[3] = 'trescientos'
is_centenas[4] = 'cuatrocientos'
is_centenas[5] = 'quinientos'
is_centenas[6] = 'seicientos'
is_centenas[7] = 'setecientos'
is_centenas[8] = 'ochocientos'
is_centenas[9] = 'novecientos'
case 'CATA'
ls_conjuncion = 'amb'
ls_txt_billon = 'bilió'
ls_txt_millon = 'milió'
ls_txt_billones = 'bilions'
ls_txt_millones = 'milions'
ls_txt_miles = 'mil'
ls_txt_cien = 'cent'
ls_txt_un = 'un'
ls_and = ''
is_cifra[1]  = "u"
is_cifra[2]  = "dos"
is_cifra[3]  = "tres"
is_cifra[4]  = "quatre"
is_cifra[5]  = "cinc"
is_cifra[6]  = "sis"
is_cifra[7]  = "set"
is_cifra[8]  = "vuit"
is_cifra[9]  = "nou"
is_cifra[10] = "deu"
is_cifra[11] = "onze"
is_cifra[12] = "dotze"
is_cifra[13] = "tretze"
is_cifra[14] = "catorze"
is_cifra[15] = "quinze"
is_cifra[16] = "setze"
is_cifra[17] = "disset"
is_cifra[18] = "divuit"
is_cifra[19] = "dinou"
is_cifra[20] = "vint-i-"
is_cifra[21] = "trenta-"
is_cifra[22] = "quaranta-"
is_cifra[23] = "cinquanta-"
is_cifra[24] = "seixanta-"
is_cifra[25] = "setanta-"
is_cifra[26] = "vuitanta-"
is_cifra[27] = "noranta-"
is_cifra[29] = "vint"

// Cargamos las centenas
is_centenas[1] = 'cent'
is_centenas[2] = 'dos-cents'
is_centenas[3] = 'tres-cents'
is_centenas[4] = 'quatre-cents'
is_centenas[5] = 'cinc-cents'
is_centenas[6] = 'sis-cents'
is_centenas[7] = 'set-cents'
is_centenas[8] = 'vuit-cents'
is_centenas[9] = 'nou-cents'
case else
return 'No definido idioma ' + as_codidiom
end choose
ls_numero = String(adc_numero,'000000000000000')
ls_billones = LEFT(ls_numero,3)
ls_millardo = MID(ls_numero,4,3)
ls_millones = MID(ls_numero,7,3)
ls_miles = MID(ls_numero,10,3)
ls_centenas = MID(ls_numero,13,3)


ls_texto = ''


FOR li_for = 1 TO 5
CHOOSE CASE li_for
CASE 1
// Construccion de los billones
CHOOSE CASE Integer(ls_billones)
CASE 1
ls_texto = ls_txt_un + ' ' + ls_txt_billon
CASE is > 1
ls_texto = of_trio(ls_billones, as_codidiom) + ' ' + ls_txt_billones
END CHOOSE
CASE 2
// Construcción de los millardos
CHOOSE CASE Integer(ls_millardo)
CASE 1
ls_texto = ls_texto + ' ' + ls_txt_miles
CASE is > 1
ls_texto = ls_texto + ' ' + of_trio(ls_millardo, as_codidiom) + ' ' + ls_txt_miles
END CHOOSE
CASE 3
// Construcción de los millones
CHOOSE CASE Integer(ls_millones)
CASE 1
ls_texto = ls_texto + ' ' + ls_txt_un + ' ' + ls_txt_millon
CASE is > 1
ls_texto = ls_texto + ' ' + of_trio(ls_millones, as_codidiom) + ' ' + ls_txt_millones
CASE ELSE
// Si ha habido millardos pero no ha habido millones, ha
// de aparecer la palabra millones
if Integer(ls_millardo) > 0 then
ls_texto = ls_texto + ' ' + ls_txt_millones
end if
END CHOOSE
CASE 4
// Construcción de los miles
CHOOSE CASE Integer(ls_miles)
CASE 1
ls_texto = ls_texto + ' ' + ls_txt_miles 
CASE is > 1
ls_texto = ls_texto + ' '+ of_trio(ls_miles, as_codidiom) + ' ' + ls_txt_miles
END CHOOSE
CASE 5
// Construcción de las centenas
ls_texto = ls_texto + ' ' + of_trio(ls_centenas, as_codidiom)
END CHOOSE
NEXT


if lb_decimal then
// Ponemos la parte decimal
ls_texto = ls_texto + ' ' + ls_conjuncion + ' ' + of_num2txt(ldec_residuo,as_codidiom)
end if


ls_texto = of_GlobalReplace(ls_texto,'  ',' ')


Return ls_texto


end function


Una vez creado nuestro objeto solo tendremos que llamarlo de la siguiente forma

ncst_num2txt lncst_num2txt
Decimal ldec_numero, ls_idioma
String ls_texto


ls_idioma = 'ESPA'


ldec_numero = 1234.56


ls_texto = lncst_num2txt.of_num2txt(ldec_numero,ls_idioma)


MessageBox("Num2Txt" + String(ldec_numero) + " en castellano" ls_texto)
ls_idioma = 'CATA'


ls_texto = lncst_num2txt.of_num2txt(ldec_numero,ls_idioma)
MessageBox("Num2Txt " + String(ldec_numero) + " en catalán" ,ls_texto)

Espero que os sea útil

Por si lo queréis descargar, aquí tenéis el enlace....
ncst_num2txt.rar

Comentarios

Publicar un comentario

Si quieres comentar, criticar, aportar mas informacion o simplemente felicitar, inserta tu comentario a continuacion. Entre todos podemos hacer cosas grandes.

Entradas populares de este blog

[VB] - Generar GUID

Esta si es buena... Como se nota que VB es un lenguaje con "solera", es decir, con años pero con robustez. Pero le pasa como al abuelo Cebolleta, tiene experiencia pero para los nuevos tiempos... ains.. le falta algo. Hoy en dia no sabriamos hacer nada sin un buen GUID, sobre todo si lo que queremos es identificar de forma unica y constante algun registro, objeto u otro componente. Usando SQL podemos generar un GUID en un santiamen a traves de la instrucción NEWID() , podemos crear un nuevo GUID en .NET usando la clase GUID.. pero... como lo hacemos con Visual Basic 6? Para empezar, vamos a ver en que se compone un GUID ¿Que es un GUID? Su significado es Globally Unique Identifier, osea Identificador globalmente único. Y su misión es la de proporcionar un identificador, de forma que es practicamente imposible que existan dos iguales en el mundo. Se compone de una palabra de 4 bytes, 3 palabras de 2 bytes y una de 6 bytes. Originalmente fue una idea de Microsoft pa

[.NET] Convertir Latitud y Longitud en Grados - Minutos y segundos

Hola a todos. Esta es una función para convertir un número de posición geográfica en grados, minutos y segundos. Como algunos pocos recordarán,una posición geográfica esta definida por latitud (Norte / Sur) y longitud (Este / Oeste) teniendo como referencia para la longitud el meridiano de Greenwich (Meridiano 0) y para la latitud la linea del Ecuador (Paralelo 0). Por lo que siempre hablaremos de posición " Grados Norte ", o " Grados Este ". Ahora es cuando entra en juego las matemáticas y la trigonometría (he de admitir que me encantan :D ). El hemisferio norte o sur solo tendría 90° Norte o Sur. Por ejemplo, El polo norte está a 90° 0' 0'' N de latitud. La longitud podríamos considerar el 0° 0' 0'' (estamos en el polo norte, por lo que es un solo punto, no hay longitud). En cambio, si nos movemos alrededor de la tierra por la linea de Ecuador, la latitud será 0° 0' 0'' (ni al norte, ni al sur) pero de Este a Oeste nos m