Convertire numeri da lettere a cifre (UDF) Inviato da Roberto giovedì 02 aprile 2009 Ultimo aggiornamento giovedì 02 aprile 2009 Il Blog di Excelvba Ho trovato in internet alcune funzioni per convertire un numero nella corrispettiva parola in lettere e alcuni addinn scaricabili per eseguire questa operazione, ecco i link: http://groups.google.it/group/microsoft.public.it.office.excel/msg/80115650b9e88c61?hl=it http://support.microsoft.com/default.aspx?scid=kb;it;635601&product=accin2 http://ennius.interfree.it/vba/vba9.htm Su un forum à stata richiesta una funzione che svolga lopposto lavoro (es. da duemilanove restituisca 2009). Ho trovato interessante il quesito (per la sua utilitã ancora ci devo pensare :-) cosã ho scritto il codice che riporto in questo articolo. Le due funzioni Da_lettere_a_numeri e Da_uno_a_mille sono utilizzabili anche come UDF ovvero funzioni definite dallutente. Per adesso, come sempre, buon lavoro a tutti. saluti r p.s. si à resa necessaria una implementazione in quanto proprio oggi al G20 si à parlato di trilioni e nessuno dei presenti (al G20 e non) in veritã sapeva quanti zeri avessero:-)... la trovate nella seconda pagina.                                                Da_lettere_a_numeri à una funzione anche UDF che effettua la conversione di un numero scritto in lettere nel relativo numero scritto in cifre. Largomento snumero à la stringa che deve essere convertita per es. passando "duemilanove" la funzione restituisce 2009. Utilizza la function Da_uno_a_mille che converte stringhe che vanno da "uno" a "mille" nei relativi
numeri in cifre (accetta 108 nelle due forme centotto centootto) E possibile convertire qualunque stringa che utilizza fino ai miliardi di miliardi, sarebbe facile conprendere bilioni, trilioni etc. Su che valori ho testato la funzione: - tutti i valori da 0 a 100.000 step 1 - valori da 100.000 fino a 999.999.999 con  step random da 1 a 10.000 - valori superiori 999.999.999 solo alcune  prove manuali (non ho trovato infatti funzioni  che restituiscano il testo con numeri cosã  grandi - p.s. magari ne scriverã² una :-) Viene eseguito un controllo ortografico, la funzione restituisce "#VALORE!" qualora un numero venga scritto con errori di digitazione. es.1 Millle -> "#VALORE!" es.2 CentoMille -> 1100 Il codice utilizza le RegExp e un oggetto Dictionary ma non necessita di riferimenti alle librerie di VBScript e Scripting Il codice à commentato per spiegarne il funzionamento                                                  INIZIO DEL CODICE  DA INCOLLARE IN UN MODULO STANDARD
Option Explicit Function Da_lettere_a_numeri( _ ByVal snumero As String)                                               Di Roberto Mensa nick r                                               Dim RE As Object Dim v, l As Long setto lespressione regolare Set RE = CreateObject("VBScript.RegExp") converto il numero in caratteri minuscoli snumero = LCase(sNumero) se snumero à zero esco If snumero = "zero" Then Da_lettere_a_numeri = 0 Exit Function Imposto la ricerca su tutte le occorrenze RE.Global = True --> inizio la sostituzione di mila, milioni,
di milioni, miliardi, di miliardi imposto il pattern di ricerca RE.Pattern = "mila" verifico se cã almeno una occorrenza a occorrenza trovata effettuo la sostituzione If RE.test(sNumero) Then _ Â snumero = RE.Replace(sNumero, "*1000") RE.Pattern = "milioni di milioni" If RE.test(sNumero) Then _ Â snumero = RE.Replace(sNumero, _ Â "*1000000") Â RE.Pattern = "miliardi di miliardi" If RE.test(sNumero) Then _ Â snumero = RE.Replace(sNumero, _ Â "*1000000000") fine della sostituzione <-- tutte le parole rimaste vengono passate alla funzione Da_uno_a_mille, le parole saranno delimitate da numeri ecco la stringa di esempio a questo livello della funzione: snumero = "duemilanove" -> "due*1000nove" se questa restituisce 0 (zero) siamo in
presenza di un errore e la funzione restituisce #VALORE! RE.Pattern = _ "mille unmilione unmiliardo [a-z]+" If RE.test(sNumero) Then For Each v In RE.Execute(sNumero)  l = Da_uno_a_mille(CStr(v))  If l = 0 Then   Da_lettere_a_numeri = "#VALORE!"   Exit Function  Else   snumero = _ VBA.Replace(sNumero, v, _ "+" & l,, 1)  Else Da_lettere_a_numeri = "#VALORE!" Exit Function utilizza la funzioneâ di excel evaluate per ottenere il risultato della stringa che avrã un formato per esempio: snumero = "duemilanove" -> "2*1000+9" Da_lettere_a_numeri = _ Excel.Application.Evaluate(sNumero) End Function
Function Da_uno_a_mille( _ ByVal snumero As String) As Long                                               Di Roberto Mensa nick r                                               Dim RE As Object Dim Dic As Object Dim s(1 To 8) As String Dim sarr() As String Dim i As Long, l(3) As Long setto lespressione regolare e loggetto dic Set Dic = CreateObject("Scripting.Dictionary") Set RE = CreateObject("VBScript.RegExp") imposto le stringhe di pattern che verranno anche utilizare per il caricamento del dizionario s(1) = "due tre quattro cinque sei sette " & _ "otto nove" s(2) = "undici dodici tredici quattordici" & _ " quindici sedici diciassette dici" & _ "otto diciannove" s(3) = "venti trenta quaranta cinquanta s" & _ "essanta settanta ottanta novanta" s(4) = "ventuno trentuno quarantuno cinqu" & _
"antuno sessantuno settantuno otta" & _ "ntuno novantuno" s(5) = "ventotto trentotto quarantotto ci" & _ "nquantotto sessantotto settantott" & _ "o ottantotto novantotto centotto" s(6) = "uno dieci cento mille" s(7) = "unmilione" s(8) = "unmiliardo" --> inizio il caricamento delle voci con i relativi valori Dic.Add s(7), 1000000 Dic.Add s(8), 1000000000 sarr = Split(s(1), " ") Dic.Add sarr(i), i + 2 sarr = Split(s(2), " ") Dic.Add sarr(i), i + 11 sarr = Split(s(3), " ") Dic.Add sarr(i), (i + 2) * 10 sarr = Split(s(4), " ")
Dic.Add sarr(i), (i + 2) * 10 + 1 sarr = Split(s(5), " ") Dic.Add sarr(i), (i + 2) * 10 + 8 sarr = Split(s(6), " ") Dic.Add sarr(i), 10 ^ i   Il dizionario à stato caricato <--- Imposto la ricerca su tutte le occorrenze RE.Global = True Quello che segue effettua anche un controllo sulla ortografia della stringa passata, in quanto scompone snumero e verifica che ogni parola sia presente nel dizionario Prima controllo le stringhe composte da parola singola es. due, tredici, ventuno, trentotto RE.Pattern = "^(" & _   s(1) & " " & _   s(2) & " " & _   s(3) & " " & _   s(4) & " " & _
  s(5) & " " & _   s(6) & " " & _   s(7) & " " & _   s(8) & ")$" If RE.test(sNumero) Then Da_uno_a_mille = Dic.Item(sNumero) Exit Function Poi controllo le stringhe composte da una o due parole es. quaranta, quarantatre fino a 99 RE.Pattern = "^(" & _   s(2) & " " & _   s(3) & " " & _   s(4) & " " & _   s(5) & " " & _   s(6) & " " & _   s(7) & " " & _   s(8) & ")(" & _   s(1) & _   ")?$" se la ricerca che viene fatta sullintera stringa ha esito positivo sostituisco le parole recuperandole dal dizionario If RE.test(sNumero) Then Da_uno_a_mille = _  CLng(Dic.Item(RE.Replace(sNumero, "$1"))) + _  CLng(Dic.Item(RE.Replace(sNumero, "$2"))) Exit Function
Terzo controllo su stringhe composte da una due o tre parole che cominciano con cento es. centodue, centoquarantadue, centoquaranta da 100 a 199 RE.Pattern = "^(cento)(" & _ Â Â s(2) & " " & _ Â Â s(3) & " " & _ Â Â s(4) & " " & _ Â Â s(5) & " " & _ Â Â s(6) & " " & _ Â Â s(7) & " " & _ Â Â s(8) & ")?(" & _ Â Â s(1) & _ Â Â ")?$" If RE.test(sNumero) Then Da_uno_a_mille = _ Â CLng(Dic.Item(RE.Replace(sNumero, "$1"))) + _ Â CLng(Dic.Item(RE.Replace(sNumero, "$2"))) + _ Â CLng(Dic.Item(RE.Replace(sNumero, "$3"))) Exit Function Ultimo controllo su stringhe composte da una due tre o quattro parole che cominciano con un numero da 2 a 9 seguito da cento e opzionalmente da altre parole es. duecentodue duecentoquarantadue, duecentoquaranta da 200 a 999 RE.Pattern = "^(" & _ Â Â s(1) & ")(cento)(" & _ Â Â s(2) & " " & _
  s(3) & " " & _   s(4) & " " & _   s(5) & " " & _   s(6) & " " & _   s(7) & " " & _   s(8) & ")?(" & _   s(1) & _   ")?$" If RE.test(sNumero) Then Da_uno_a_mille = _  CLng(Dic.Item(RE.Replace(sNumero, "$1"))) * _  CLng(Dic.Item(RE.Replace(sNumero, "$2"))) + _  CLng(Dic.Item(RE.Replace(sNumero, "$3"))) + _  CLng(Dic.Item(RE.Replace(sNumero, "$4"))) Exit Function End Function                                                implementata per accettare anche bilioni, trilioni etc...                                                  INIZIO DEL CODICE  DA INCOLLARE IN UN MODULO STANDARD
Function Da_lettere_a_numeri_G20( _ ByVal snumero As String)                                               Di Roberto Mensa nick r                                               Dim RE As Object Dim v, l setto lespressione regolare Set RE = CreateObject("VBScript.RegExp") converto il numero in caratteri minuscoli snumero = LCase(sNumero) se snumero à zero esco If snumero = "zero" Then Da_lettere_a_numeri_G20 = 0 Exit Function Imposto la ricerca su tutte le occorrenze RE.Global = True --> inizio la sostituzione di mila, milioni, di milioni, miliardi, di miliardi imposto il pattern di ricerca
RE.Pattern = "mila" verifico se cã almeno una occorrenza a occorrenza trovata effettuo la sostituzione If RE.test(sNumero) Then _ Â snumero = RE.Replace(sNumero, "*1000") RE.Pattern = "milioni di milioni" If RE.test(sNumero) Then _ Â snumero = RE.Replace(sNumero, _ Â "*1000000") Â RE.Pattern = "miliardi di miliardi" If RE.test(sNumero) Then _ Â snumero = RE.Replace(sNumero, _ Â "*1000000000") Â RE.Pattern = "bilioni di bilioni" If RE.test(sNumero) Then _ Â snumero = RE.Replace(sNumero, _ Â "*1000000000000") RE.Pattern = "biliardi di biliardi" If RE.test(sNumero) Then _ Â snumero = RE.Replace(sNumero, _ Â "*1000000000000000")
 RE.Pattern = "trilioni di trilioni" If RE.test(sNumero) Then _  snumero = RE.Replace(sNumero, _  "*1000000000000000000") RE.Pattern = "triliardi di triliardi" If RE.test(sNumero) Then _  snumero = RE.Replace(sNumero, _  "*1000000000000000000000")  fine della sostituzione <-- tutte le parole rimaste vengono passate alla funzione Da_uno_a_mille_G20, le parole saranno delimitate da numeri ecco la stringa di esempio a questo livello della funzione: snumero = "duemilanove" -> "due*1000nove" se questa restituisce 0 (zero) siamo in presenza di un errore e la funzione restituisce #VALORE! RE.Pattern = _ "mille unmilione unmiliardo unbilione " & _ "unbiliardo untrilione untriliardo [a-z]+" If RE.test(sNumero) Then For Each v In RE.Execute(sNumero)  l = Da_uno_a_mille_G20(CStr(v))  If l = 0 Then   Da_lettere_a_numeri_G20 = "#VALORE!"   Exit Function
 Else   snumero = _ VBA.Replace(sNumero, v, _ "+" & l,, 1)  Else Da_lettere_a_numeri_G20 = "#VALORE!" Exit Function utilizza la funzioneâ di excel evaluate per ottenere il risultato della stringa che avrã un formato per esempio: snumero = "duemilanove" -> "2*1000+9" Da_lettere_a_numeri_G20 = _ Excel.Application.Evaluate(sNumero) End Function Function Da_uno_a_mille_G20( _ ByVal snumero As String) As Double                                               Di Roberto Mensa nick r                                               Dim RE As Object Dim Dic As Object Dim s(1 To 8) As String Dim sarr() As String Dim i As Long, l(3) As Long
setto lespressione regolare e loggetto dic Set Dic = CreateObject("Scripting.Dictionary") Set RE = CreateObject("VBScript.RegExp") imposto le stringhe di pattern che verranno anche utilizare per il caricamento del dizionario s(1) = "due tre quattro cinque sei sette " & _ "otto nove" s(2) = "undici dodici tredici quattordici" & _ " quindici sedici diciassette dici" & _ "otto diciannove" s(3) = "venti trenta quaranta cinquanta s" & _ "essanta settanta ottanta novanta" s(4) = "ventuno trentuno quarantuno cinqu" & _ "antuno sessantuno settantuno otta" & _ "ntuno novantuno" s(5) = "ventotto trentotto quarantotto ci" & _ "nquantotto sessantotto settantott" & _ "o ottantotto novantotto centotto" s(6) = "uno dieci cento mille" s(7) = "unmilione unbilione untrilione" s(8) = "unmiliardo unbiliardo untriliardo"
--> inizio il caricamento delle voci con i relativi valori sarr = Split(s(7), " ") Dic.Add sarr(i), 1000000 * 1000000 ^ i sarr = Split(s(8), " ") Dic.Add sarr(i), 1000000000 * 1000000 ^ i sarr = Split(s(1), " ") Dic.Add sarr(i), i + 2 sarr = Split(s(2), " ") Dic.Add sarr(i), i + 11 sarr = Split(s(3), " ") Dic.Add sarr(i), (i + 2) * 10 sarr = Split(s(4), " ") Dic.Add sarr(i), (i + 2) * 10 + 1 sarr = Split(s(5), " ")
Dic.Add sarr(i), (i + 2) * 10 + 8 sarr = Split(s(6), " ") Dic.Add sarr(i), 10 ^ i   Il dizionario à stato caricato <--- Imposto la ricerca su tutte le occorrenze RE.Global = True Quello che segue effettua anche un controllo sulla ortografia della stringa passata, in quanto scompone snumero e verifica che ogni parola sia presente nel dizionario Prima controllo le stringhe composte da parola singola es. due, tredici, ventuno, trentotto RE.Pattern = "^(" & _   s(1) & " " & _   s(2) & " " & _   s(3) & " " & _   s(4) & " " & _   s(5) & " " & _   s(6) & " " & _   s(7) & " " & _   s(8) & ")$" If RE.test(sNumero) Then
Da_uno_a_mille_G20 = Dic.Item(sNumero) Exit Function Poi controllo le stringhe composte da una o due parole es. quaranta, quarantatre fino a 99 RE.Pattern = "^(" & _ Â Â s(2) & " " & _ Â Â s(3) & " " & _ Â Â s(4) & " " & _ Â Â s(5) & " " & _ Â Â s(6) & " " & _ Â Â s(7) & " " & _ Â Â s(8) & ")(" & _ Â Â s(1) & _ Â Â ")?$" se la ricerca che viene fatta sullintera stringa ha esito positivo sostituisco le parole recuperandole dal dizionario If RE.test(sNumero) Then Da_uno_a_mille_G20 = _ Â CLng(Dic.Item(RE.Replace(sNumero, "$1"))) + _ Â CLng(Dic.Item(RE.Replace(sNumero, "$2"))) Exit Function Terzo controllo su stringhe composte da una due o tre parole che cominciano con cento es. centodue, centoquarantadue, centoquaranta da 100 a 199
RE.Pattern = "^(cento)(" & _ Â Â s(2) & " " & _ Â Â s(3) & " " & _ Â Â s(4) & " " & _ Â Â s(5) & " " & _ Â Â s(6) & " " & _ Â Â s(7) & " " & _ Â Â s(8) & ")?(" & _ Â Â s(1) & _ Â Â ")?$" If RE.test(sNumero) Then Da_uno_a_mille_G20 = _ Â CLng(Dic.Item(RE.Replace(sNumero, "$1"))) + _ Â CLng(Dic.Item(RE.Replace(sNumero, "$2"))) + _ Â CLng(Dic.Item(RE.Replace(sNumero, "$3"))) Exit Function Ultimo controllo su stringhe composte da una due tre o quattro parole che cominciano con un numero da 2 a 9 seguito da cento e opzionalmente da altre parole es. duecentodue duecentoquarantadue, duecentoquaranta da 200 a 999 RE.Pattern = "^(" & _ Â Â s(1) & ")(cento)(" & _ Â Â s(2) & " " & _ Â Â s(3) & " " & _ Â Â s(4) & " " & _ Â Â s(5) & " " & _ Â Â s(6) & " " & _ Â Â s(7) & " " & _
  s(8) & ")?(" & _   s(1) & _   ")?$" If RE.test(sNumero) Then Da_uno_a_mille_G20 = _  CLng(Dic.Item(RE.Replace(sNumero, "$1"))) * _  CLng(Dic.Item(RE.Replace(sNumero, "$2"))) + _  CLng(Dic.Item(RE.Replace(sNumero, "$3"))) + _  CLng(Dic.Item(RE.Replace(sNumero, "$4"))) Exit Function End Function                                                 FINE DEL CODICE   Â