Newsgroup: it.comp.lang.visual-basic
Titolo: Coerenza dei dati

Buondě. (non la merendina)
Ho letto un post di venerdě ("problema banale" mi sembra) in cui si parlava
della coerenza dei dati, nel senso che si citava la differenza tra virgola e
punto nel caso di impostazioni in italiano ecc.
Si trattava anche funzioni sensibili alle impostazioni locale (Cstr) e di
funzioni non localizzate (Val).
C'e' qualche risorsa che parla di come trattare correttamente i dati
numerici?
Grazie mille
Pelo

 numerici?
Non è molto complesso.
Le funzioni C<tipo>() si basano sul pannello di controllo, quindi sono
vicendevolmente invertibili:
x = CDbl(CStr(1.4#)) ' x vale 1.4
x = CStr(CDbl("1,4")) ' x vale "1,4", se "," è il sep. decimale
ovviamente questo vale sono da e per stringhe,
CDbl(Clng(1.4#)) non riporterà indietro il valore 1 a 1.4!
Queste funzioni quando non sono in grado di convertire un valore danno un
errore di runtime che andrà gestito.
Il Val() invecie è molto più semplice: converte solo da stringhe con il "."
come separatore decimale e in caso di conversione impossibile restituisce
0.0# anzichè scatenare un errore.
Diciamo che se fai applicazioni localizzate o sul modello gestionale
dovresti sempre basarti sulle funzioni C<tipo>(), stando attento che anche
il "." del tastierino numerico venga gestito come "," e non come "." nelle
situazioni che lo richiedono: è frustrante scivere un numero con il
tastierino e essere costretti a cercare la virgola sulla tastiera, il che
presupporrebbe anche che l'utente sappia quali sono le impostazioni del
pannello di controllo.
Un metodo "rozzo" ma semplice per conoscere il separatore decimale è questo:
Sep = Mid$(CStr(1.1), 2, 1)
Parallelamente per il separatore delle migliaia:
Sep = Mid$(CStr(1000), 2, 1)
Ultima considerazione: VB converte sempre usando le impostazioni
internazionali, quindi fare:
MiaStringa = CStr(1.2)
equivale a
MiaStringa = 1.2
Anche se poco corretto lo ritengo più leggibile, se risulta ben chiaro che
MiaStringa sia una stinga, come ad es. è inequivocabile che lo sia:
txtRisultato.Text = MioValoreDecimale
Ciao
--
Math Parser : 
http://www.neodatatype.net
Sito Comune : 
http://www.it-lang-vb.net

 pannello di controllo.
Pienamente d'accordo con te, ma ancora non esiste un modo per trattare il
separatore dei deimali in maniera svincolata dalle impostazioni
internazionali?
Io sono abituato ad inserire dati col tastierino, ma scommetto che il 90%
delle segretarie usa la tastiera... Non che voglia male alle segretarie, è
solo un esempio (che nella mia realtà lavorativa è pienamente rispecchiato).
Non sarebbe utile fare in modo che nel codice (ad esempio) si usi il punto,
mentre con
txtbox.text= 3.14*cdbl(1)
venga visualizzato "3,14" se l'impostazione internazionale prevede la
virgola e invece "3.14" se prevede il punto?
Esiste gia?
Grazie e ciao
Pelo

 virgola e invece "3.14" se prevede il punto?
L'acquisizione dei dati avviene normalmente con un textbox la cui proprietà
Text è una stringa. In fase di acquisizione (input) si possono intercettare
i caratteri , e . (comunque impostasti) e convertirli "al volo" in quello
che si desidera, secondo il contesto. Per esempio, io non ammetto
l'impostazione del separatore fra le migliaia e converto , e/o . in quello
che è il separatore previsto dal sistema (rilevabile, sempre per esempio,
come Zanna ti ha indicato).
La visualizzazione di un dato puramente numerico può avvenire trasformando
lo stesso in stringa e quindi agendo come meglio si crede o usando la Format
che produce una stringa tenendo automaticamente conto dei separatori come da
pannello di controllo.

 internazionali?
Allora una soluzione alternativa è questa:
1) abolisci l'uso del separatore delle migliaia oppure vedi punto 3
2) per ogni valore di tipo stringa da convertire in numero fai sempre un
replace(valore_stringa, sep_decimale, ".")
in modo da avere *sempre* e solo il punto come separatore decimale, in
qualunque caso.
3) rimuovi tutti i punti tranne l'ultimo: nessun separatore delle migliaia!
Magari metti il tutto in una funzione, es.:
Dim strSep As String
...
strSep = Mid$(CStr(1.1), 2, 1)
...
Function MyCDbl(byval num as string) as double
    Dim pos as long
    Dim str as string
    str = replace(num, strSep, ".")
    pos = instrrev(str, ".")
    if (pos > 1) then
        ' qui non ricordo a memoria la sintassi di Replace,
        ' l'intento è quello di rimuovere tutti i "." precedenti
        ' all'ultimo, che è il separatore dei decimali
        str = replace(num, strSep, "", 1, pos - 1)
    endif
    MyCDbl = Val(str)
end function
