Convertir un número en letras
Artículo por Club Developers · 31 diciembre 2005
5306 vistas
Es muy probable que necesitemos, en recibos y demás, convertir un valor numérico en letras. para ellos tenemos la siguiente función
delphi
(**************************************) (* Conversión Número -> Letra    *) (*                  *) (* Parámetros:            *) (*                  *) (* mNum:  Número a convertir   *) (* iIdioma: Idioma de conversión  *) (*      1 -> Castellano    *) (*      2 -> Catalán      *) (* iModo: Modo de conversión   *) (*      1 -> Masculino     *) (*      2 -> Femenino     *) (*                  *) (* Restricciones:          *) (*                  *) (* - Redondeo a dos decimales    *) (* - Rango: 0,00 a 999.999.999.999,99 *) (*                  *) (**************************************) function NumLetra(const mNum: Currency; const iIdioma, iModo: Smallint): String; const  iTopFil: Smallint = 6;  iTopCol: Smallint = 10;  aCastellano: array[0..5, 0..9] of PChar =  ( ('UNA ','DOS ','TRES ','CUATRO ','CINCO ',   'SEIS ','SIETE ','OCHO ','NUEVE ','UN '),   ('ONCE ','DOCE ','TRECE ','CATORCE ','QUINCE ',   'DIECISEIS ','DIECISIETE ','DIECIOCHO ','DIECINUEVE ',''),   ('DIEZ ','VEINTE ','TREINTA ','CUARENTA ','CINCUENTA ',   'SESENTA ','SETENTA ','OCHENTA ','NOVENTA ','VEINTI'),   ('CIEN ','DOSCIENTAS ','TRESCIENTAS ','CUATROCIENTAS ','QUINIENTAS ',   'SEISCIENTAS ','SETECIENTAS ','OCHOCIENTAS ','NOVECIENTAS ','CIENTO '),   ('CIEN ','DOSCIENTOS ','TRESCIENTOS ','CUATROCIENTOS ','QUINIENTOS ',   'SEISCIENTOS ','SETECIENTOS ','OCHOCIENTOS ','NOVECIENTOS ','CIENTO '),   ('MIL ','MILLON ','MILLONES ','CERO ','Y ',   'UNO ','DOS ','CON ','','') );  aCatalan: array[0..5, 0..9] of PChar =  ( ( 'UNA ','DUES ','TRES ','QUATRE ','CINC ',   'SIS ','SET ','VUIT ','NOU ','UN '),   ( 'ONZE ','DOTZE ','TRETZE ','CATORZE ','QUINZE ',   'SETZE ','DISSET ','DIVUIT ','DINOU ',''),   ( 'DEU ','VINT ','TRENTA ','QUARANTA ','CINQUANTA ',   'SEIXANTA ','SETANTA ','VUITANTA ','NORANTA ','VINT-I-'),   ( 'CENT ','DOS-CENTES ','TRES-CENTES ','QUATRE-CENTES ','CINC-CENTES ',   'SIS-CENTES ','SET-CENTES ','VUIT-CENTES ','NOU-CENTES ','CENT '),   ( 'CENT ','DOS-CENTS ','TRES-CENTS ','QUATRE-CENTS ','CINC-CENTS ',   'SIS-CENTS ','SET-CENTS ','VUIT-CENTS ','NOU-CENTS ','CENT '),   ( 'MIL ','MILIO ','MILIONS ','ZERO ','-',   'UN ','DOS ','AMB ','','') ); var  aTexto: array[0..5, 0..9] of PChar;  cTexto, cNumero: String;  iCentimos, iPos: Smallint;  bHayCentimos, bHaySigni: Boolean;  (*************************************)  (* Cargar Textos según Idioma / Modo *)  (*************************************)  procedure NumLetra_CarTxt;  var   i, j: Smallint;  begin   (* Asignación según Idioma *)   for i := 0 to iTopFil - 1 do    for j := 0 to iTopCol - 1 do     case iIdioma of      1: aTexto[i, j] := aCastellano[i, j];      2: aTexto[i, j] := aCatalan[i, j];     else      aTexto[i, j] := aCastellano[i, j];     end;   (* Asignación si Modo Masculino *)   if (iModo = 1) then   begin    for j := 0 to 1 do     aTexto[0, j] := aTexto[5, j + 5];    for j := 0 to 9 do     aTexto[3, j] := aTexto[4, j];   end;  end;  (****************************)  (* Traducir DÃgito -Unidad- *)  (****************************)  procedure NumLetra_Unidad;  begin   if not( (cNumero[iPos] = '0') or (cNumero[iPos - 1] = '1')   or ((Copy(cNumero, iPos - 2, 3) = '001') and ((iPos = 3) or (iPos = 9))) ) then    if (cNumero[iPos] = '1') and (iPos <= 6) then     cTexto := cTexto + aTexto[0, 9]    else     cTexto := cTexto + aTexto[0, StrToInt(cNumero[iPos]) - 1];   if ((iPos = 3) or (iPos = 9)) and (Copy(cNumero, iPos - 2, 3) <> '000') then    cTexto := cTexto + aTexto[5, 0];   if (iPos = 6) then    if (Copy(cNumero, 1, 6) = '000001') then     cTexto := cTexto + aTexto[5, 1]    else     cTexto := cTexto + aTexto[5, 2];  end;  (****************************)  (* Traducir DÃgito -Decena- *)  (****************************)  procedure NumLetra_Decena;  begin   if (cNumero[iPos] = '0') then    Exit   else if (cNumero[iPos + 1] = '0') then    cTexto := cTexto + aTexto[2, StrToInt(cNumero[iPos]) - 1]   else if (cNumero[iPos] = '1') then    cTexto := cTexto + aTexto[1, StrToInt(cNumero[iPos + 1]) - 1]   else if (cNumero[iPos] = '2') then    cTexto := cTexto + aTexto[2, 9]   else    cTexto := cTexto + aTexto[2, StrToInt(cNumero[iPos]) - 1]     + aTexto[5, 4];  end;  (*****************************)  (* Traducir DÃgito -Centena- *)  (*****************************)  procedure NumLetra_Centena;  var   iPos2: Smallint;  begin   if (cNumero[iPos] = '0') then    Exit;   iPos2 := 4 - Ord(iPos > 6);   if (cNumero[iPos] = '1') and (Copy(cNumero, iPos + 1, 2) <> '00') then    cTexto := cTexto + aTexto[iPos2, 9]   else    cTexto := cTexto + aTexto[iPos2, StrToInt(cNumero[iPos]) - 1];  end;  (**************************************)  (* Eliminar Blancos previos a guiones *)  (**************************************)  procedure NumLetra_BorBla;  var   i: Smallint;  begin   i := Pos(' -', cTexto);   while (i > 0) do   begin    Delete(cTexto, i, 1);    i := Pos(' -', cTexto);   end;  end; begin  (* Control de Argumentos *)  if (mNum < 0.00) or (mNum > 999999999999.99) or (iIdioma < 1) or (iIdioma > 2)   or (iModo < 1) or (iModo > 2) then  begin   Result := 'ERROR EN ARGUMENTOS';   Abort;  end;  (* Cargar Textos según Idioma / Modo *)  NumLetra_CarTxt;  (* Bucle Exterior -Tratamiento Céntimos-  *)  (* NOTA: Se redondea a dos dÃgitos decimales *)  cNumero := Trim(Format('%12.0f', [Int(mNum)]));  cNumero := StringOfChar('0', 12 - Length(cNumero)) + cNumero;  iCentimos := Trunc((Frac(mNum) * 100) + 0.5);  repeat   (* Detectar existencia de Céntimos *)   if (iCentimos <> 0) then    bHayCentimos := True   else    bHayCentimos := False;   (* Bucle Interior -Traducción- *)   bHaySigni := False;   for iPos := 1 to 12 do   begin    (* Control existencia DÃgito significativo *)    if not(bHaySigni) and (cNumero[iPos] = '0') then     Continue    else     bHaySigni := True;    (* Detectar Tipo de DÃgito *)    case ((iPos - 1) mod 3) of     0: NumLetra_Centena;     1: NumLetra_Decena;     2: NumLetra_Unidad;    end;   end;   (* Detectar caso 0 *)   if (cTexto = '') then    cTexto := aTexto[5, 3];   (* Traducir Céntimos -si procede- *)   if (iCentimos <> 0) then   begin    cTexto := cTexto + aTexto[5, 7];    cNumero := Trim(Format('%.12d', [iCentimos]));    iCentimos := 0;   end;  until not (bHayCentimos);  (* Eliminar Blancos innecesarios -sólo Catalán- *)  if (iIdioma = 2) then   NumLetra_BorBla;  (* Retornar Resultado *)  Result := Trim(cTexto); end;