Verifica dati inseriti



  • Verifica dati inseriti
    di beppexile data: 24/11/2015 09:52:48

    Salve ragazzi, qualcuno di voi mi può aiutare con un controllo dati su una textbox?

    Sfruttando l'evento EXIT di una textbox vorrei controllare che l'utente digiti correttamente un codice alfanumerico composta da una lettera iniziale, 8 numeri e una lettera finale (esempio L12345678Z).
    Come faccio? Grazie a tutti per la pazienza nei miei confronti

    p.s.: non allego file in quanto credo che non ci sia di bisogno.



  • di gdito data: 24/11/2015 10:26:23

    Per queste cose ci sono 2 approcci, quello che preferisco è l'uso delle Espressioni Regolari, se le scopri te ne innamori

    Da "Riferimenti" aggiungi il riferimento a Microsoft VBScript Regular Expression 5.5

    Usa la funzione qui sotto per validare il tuo testo 
     
    Function Valida(codice As String) As Boolean
        Dim rgx As New RegExp
        
        'Cambia a false se vuoi che le lettere debbano essere solo maiuscole
        rgx.IgnoreCase = True
        rgx.Pattern = "^[A-Z]{1}[0-9]{8}[A-Z]{1}$"
     
        Valida = rgx.test(codice)
    End Function
    



  • di alfrimpa data: 24/11/2015 10:33:12

    Ciao Gdito

    Ho sempre voluto approfondire il tema delle RegExp senza riuscirvi.

    Potresti, cortesemente, postare qualche link dove questo argomento viene trattato esaustivamente ed in maniera chiara?

    Ti ringrazio in anticipo.

    Alfredo





  • di gdito data: 24/11/2015 10:51:16

    Certo, qui trovi la documentazione ufficiale di microsoft

    h t t p s : //msdn.microsoft.com/it-it/library/az24scfc(v=vs.110).aspx

    qui un articolo che a me è sembrato chiaro quando all'epoca ho iniziato ad usarle, parla in generale delle RegEx, non per VBA ma cambia poco (vedi articolo prima)

    h t t p : //blog.chalda.it/guida-alla-sintassi-delle-espressioni-regolari-217.html

    questo invece è un tool che ti permette di provare online se la tue espressione regolare funziona e te la spiega passo per passo

    h t t p s ://regex101.com/

    Se ti serve altro chiedi pure



  • di beppexile data: 24/11/2015 10:54:29

    Ciao gdito, grazie della dritta, tuttavia tra le mie enormi lacune ho qualche difficoltà ad applicare la tua funzione al mio codice.

    Partiamo dall'inizio: ho attivato il riferimento che mi dici;
    il codice che mi hai scritto lo devo scrivere in un modulo?
    E come faccio a richiamarlo nella textbox1 quando ci scrivo?

    grazie



  • di gdito data: 24/11/2015 11:15:31

    Ciao,
    si il codice devi metterlo in un modulo, poi, come hai detto tu sfrutti l'evento Exit della textbox e scrivi una sub tipo quella che trovi qui sotto, se la textbox è vuota puoi uscire, se è piena ed il codice è valido puoi uscire altrimenti ti mostra un messaggio di errore e torna sulla textbox colorandola di rosso (esempio 1).

    Puoi usare anche l'evento onchange per far diventare rossa la casella fino a quando non hai inserito il codice giusto (Esempio 2)
     
    'ESEMPIO 1
    Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
        If TextBox1.Text <> "" Then
            If Not Valida(TextBox1.Text) Then
                TextBox1.BackColor = RGB(255, 0, 0)
                MsgBox "Codice non valido", vbCritical, "Errore"
                Cancel = True
            Else
                TextBox1.BackColor = RGB(255, 255, 255)
            End If
        Else
            TextBox1.BackColor = RGB(255, 255, 255)
        End If
    End Sub
    
    'ESEMPIO 2
    Private Sub TextBox1_Change()
        If Valida(TextBox1.Text) Then
            TextBox1.BackColor = RGB(255, 255, 255)
        Else
            TextBox1.BackColor = RGB(255, 0, 0)
        End If
    End Sub



  • di beppexile data: 24/11/2015 11:34:05

    Grande!!!!

    Grazie infinite, hai fatto molto più di quello che mi serviva... e ti posso confermare che mi ha aperto un mondo!



  • di beppexile data: 24/11/2015 11:53:51

    Mi succede una cosa strana però... sul "Cancel = true" mi da "Errore di compilazione, variabile non definita", però non mi serve, quello che mi serviva che funzionasse però, è che il testo si evidenziasse, ed ho usato il codice seguente ma senza riuscirci:    
     
            Private Sub TB_LottoSugna_Exit(ByVal Cancel As MSForms.ReturnBoolean)
                With UserForm1_Avvio
                    If .TB_LottoSugna.Text <> "" Then
                        If Not Valida(.TB_LottoSugna.Text) Then
                            MsgBox "Lotto sugna non valido!", vbCritical, "Errore di digitazione!"
                            .TB_LottoSugna.SetFocus
                            .TB_LottoSugna.SelStart = 0
                            .TB_LottoSugna.SelLength = Len(.TB_LottoSugna)
                        End If
                    End If
                End With
            End Sub
    
    'il codice seguente è nel modulo 1
    
    'FUNZIONE DI CONTROLLO VALIDITA' LOTTO SUGNA O PEPE
        Function Valida(codice As String) As Boolean
            Dim rgx As New RegExp
            'Cambia a false se vuoi che le lettere debbano essere solo maiuscole
            rgx.IgnoreCase = False
            rgx.Pattern = "^[A-Z]{1}[0-9]{8}[A-Z]{1}$"
            Valida = rgx.Test(codice)
        End Function
    
    



  • di gdito data: 24/11/2015 13:25:12

    Il codice come lo hai inserito? Cliccando sulla TextBox con il tasto destro e poi su "Visualizza Codice"?
    Se è così VBE ti crea la TB_LottoSugna_Exit e non hai bisogno di mettere with With UserForm1_Avvio, basta ,ettere TB_LottoSugna.SetFocus etc.

    Se riesci ad allegare il file è meglio, così cerco di capire cosa non ti funziona perché replicandolo in locale va tutto



  • di beppexile data: 24/11/2015 15:38:41

    ho allegato un file di esempio con solo il codice in questione, e non mi funziona neanche così.

    nel file ho messo una userform che si avvia automaticamente, con 2 textbox, la prima con il controllo della tua funzione.

    digitando il codice sbagliato e premendo invio, appare il messaggio ma il cursore si posiziona sulla seconda textbox, io vorrei che evidenziasse il testo della textbox1, pronto per la modifica.



  • di Albatros54 data: 24/11/2015 16:07:59

    Modifica il codice come postato sotto
    Ciao
    Albatros54
     
    Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
        Call InsTextBox1
        Cancel = True
        TextBox1.SetFocus
    End Sub
    






  • di beppexile data: 24/11/2015 16:16:53

    grazie albatros, adesso funziona, ma non capisco se lo scrivo nella modulo 1 non funziona.
     
    Sub InsTextBox1()
        With UserForm1
            If .TextBox1.Text <> "" Then
                If Not Valida(.TextBox1.Text) Then
                    MsgBox "Lotto sugna non valido!", vbCritical, "Errore di digitazione!"
                    Cancel = True
                    .TextBox1.SetFocus
                    .TextBox1.SelStart = 0
                    .TextBox1.SelLength = Len(.TextBox1)
                Else
                    .TextBox1.Value = UCase(.TextBox1.Text)
                End If
            End If
        End With
    End Sub
    



  • di beppexile data: 24/11/2015 16:28:07

    Niente da fare, non mi funziona. Ho allegato il database, il punto di interesse è alla scheda sugnatura: seleziona un lotto dalla listbox, selezionate una categoria e il cursore si porta alla textbox "lotto sugna", digitando un lotto sbagliato è dando invio, appare il messaggio di errore, ma il cursore si porta nella textbox dei telai.



  • di Albatros54 data: 24/11/2015 16:35:13

    Cosi dovrebbe funzionare
     
    Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
       With UserForm1
            If .TextBox1.Text <> "" Then
                If Not Valida(.TextBox1.Text) Then
                
                    MsgBox "Lotto sugna non valido!", vbCritical, "Errore di digitazione!"
                    .TextBox1.SetFocus
                    .TextBox1.SelStart = 0
                    .TextBox1.SelLength = Len(.TextBox1)
                    Cancel = True
                Else
               
                    .TextBox1.Value = UCase(.TextBox1.Text)
                    
                End If
            End If
        End With
    End Sub
    






  • di gdito data: 24/11/2015 17:10:50

    Ciao a tutti, mi ri-intrometto nella discussione

    Il problema è il SetFocus, nella Exit non è valido perché fino a quando la Sub non è terminata il controllo non ha effettivamente perso il focus, quindi il comando viene ignorato.

    In teoria dovrebbe bastare il Cancel = true, ma c'è di mezzo un MsgBox e lo stesso una volta che prende il focus non lo restituisce al controllo ma al form che lo ha generato, quindi non se ne cava un ragno dal buco... o eviti il messagebox o eviti il setfocus



  • di Albatros54 data: 24/11/2015 17:17:29

    Non voglio contraddirti, ma hai provato il codice postato?
    con Excel 2007, il tutto funziona.





  • di gdito data: 24/11/2015 17:39:16

    Si Albatros54 e non funziona, il controllo non riprende il focus, se togli il MsgBox invece non ci sono problemi e puoi anche eliminare il SetFocus

    Ho provato modificando direttamente il suo file, ho provato anche con gli eventi AfterUpdate e BeforeUpdate ma nulla, le sto provando tutte per aggirare questo problema

    Io sto usando Office 365



  • di Albatros54 data: 24/11/2015 17:45:52

    Ho scaricato il File che beppexile ha allegato alla discussione, ho apportato le modifiche , cancellando la chiamata dell'evento Exit,è ho inserito il codice che ho postao direttamente sull'evento della textbox1.Ripeto con Excel 2007 tutto funziona.A questo punto non so che dirti
    Albatros54





  • di beppexile data: 25/11/2015 08:45:25

    Buongiorno.

    risp. ad albatros: purtroppo attualmente non ho a disposizione pc con altri office se non il 2013, ma son quasi sicuro anche io che sul 2007 funziona... dal 2010 in poi avrei qualche dubbio... avranno cambiato leggermente qualche controllo, magari rendendo il tutto più stabile.

    Alla fine sto usando l'esempio 2 di gdito, senza messaggio e sfruttando l'evento change:
    coloro di rosso il testo finché non viene scritto correttamente.

    Vorrei chiedere una cosa a gdito, se io volessi verificare che il mio lotto, anziché essere composta da 8 numeri in mezzo a 2 lettere, sia composto da un minimo di 5 a un massimo di 8 numeri in mezzo a 2 lettere, come dovrei fare? Ho letto dai link e mi sembra che il codice sotto sia giusto, tuttavia non funziona!  
     
        Function Valida(codice As String) As Boolean
            Dim rgx As New RegExp
            'Cambia a false se vuoi che le lettere debbano essere solo maiuscole
            rgx.IgnoreCase = True
            rgx.Pattern = "^[A-Z]{1}[0-9]{5,8}[A-Z]{1}$"
            Valida = rgx.Test(codice)
        End Function
    



  • di beppexile data: 25/11/2015 08:56:01

    gdito, altra domanda sulle espressioni regolari: si posso usare per trasformare i dati scritti in maniera corretta, ad esempio se l'utente scrive un peso con il punto separatore ma io vorrei caricarlo sempre con la virgola e la scritta Kg finale?
    se si, potresti farmi un'esempio? grazie infinite



  • di gdito data: 25/11/2015 10:08:10

    Ciao,
    allora, procediamo per passi, l'espressione regolare che hai indicato è corretta per catturare i numeri tra 5 e 8, ovvero

    "^[A-Z]{1}[0-9]{5,8}[A-Z]{1}$"

    Provata e funziona, provata anche su regex101.com e funziona, strano che a te non vada, il problema non è lì probabilmente.

    Per quanto riguarda la funzione su kg ti propongo la mia, usa le espressioni regolari ed un replace, ho considerato che potessero inserire 5 | 5 KG | 6.1 KG | 6,1 Kg | 6.1 | 8,2 (dovrebbero essere tutte le possibili combinazioni). Spero che non ci sia altro nel testo

    Per il primo problema possiamo rivedere insieme il tuo file per capire cosa non va
     
    Function validaKg(testo)
        Dim rgx As New RegExp
        Dim corrispondenze As Object
        Dim tempVal As String
        
        rgx.Global = True
        rgx.IgnoreCase = True
        
        'Cambio il case della stringa Kg (se presente) dai formati "KG", "kG", "kg" in "Kg"
        'Se non presente lo aggiungo
        rgx.Pattern = "(Kg)+"
        Set corrispondenze = rgx.Execute(testo)
        
        If corrispondenze.Count > 0 Then
            testo = rgx.Replace(testo, "Kg")
        Else
            testo = testo & " Kg"
        End If
        
        rgx.IgnoreCase = False
        'Controllo se il testo rispecchia il formato necessario
        rgx.Pattern = "[0-9]+,[0-9]+"
        Set corrispondenze = rgx.Execute(testo)
        
        'Se lo rispecchia restituisco il testo così com'è
        If corrispondenze.Count > 0 Then
            validaKg = testo
        End If
        
        'Catturo la stringa dei numeri separati dal .
        rgx.Pattern = "[0-9]+.[0-9]+"
    
        Set corrispondenze = rgx.Execute(testo)
        
        'Se la trovo imposto  tempVal alla stringa catturata altrimenti lascio il testo così com'è
        If corrispondenze.Count > 0 Then
            tempVal = corrispondenze.Item(0)
        Else
            tempVal = testo
        End If
        
        'Sostituisco il . con la ,
        tempVal = Replace(tempVal, ".", ",")
        
        'Restituisco il nuovo valore
        validaKg = rgx.Replace(testo, tempVal)
    End Function



  • di gdito data: 25/11/2015 10:18:55

    Nei preferiti mi sono trovato altri 2 tutorial sulle espressioni regolari

    Questo riferito a PHP ma in linea generale vale anche per vba

    h t t p : //www.html.it/articoli/espressioni-regolari-1/

    questo invece (in inglese) parla di VBA ed espressioni regolari

    h t t p : //www.analystcave.com/excel-regex-tutorial/




  • di beppexile data: 25/11/2015 11:30:59

    Allora, adesso funziona... evidentemente c'era qualche problema prima, quando avevo il messaggio e il setfocus;

    Per quanto riguarda il codice del controllo del peso, dovrebbe fare esattamente ciò che volevo (devo solo testarlo nel mio codice)! Adesso devo solo imparare a usarlo al meglio.

    Grazie a tutti.



  • di beppexile data: 25/11/2015 13:20:45

    Mi dispiace riaprire la discussione, ma qualcosa non mi va.

    Per implementare il controllo del peso ho utilizzato la stessa prassi di prima e utilizzato il codice in basso, tuttavia mi restituisce errore "Tipo non corrispondente" all'altezza del secondo If, cioè quando verifica i dati inseriti...

    Suggerimenti? Sbaglio qualcosa?
     
     
    Private Sub TextBox50_Change()
        If TextBox50.Text <> "" Then
            If ValidaKg(TextBox50.Text) Then 'questo il punto con l'errore
                TextBox50.ForeColor = &H0&
                TextBox50.BackColor = &HFFFFFF
                TextBox50.Font.Bold = False
            Else
                TextBox50.ForeColor = &HFFFFFF
                TextBox50.BackColor = &HFF&
                TextBox50.Font.Bold = True
            End If
        End If
    End Sub
    



  • di scossa data: 25/11/2015 13:24:05

    cit.: "Per quanto riguarda la funzione su kg ti propongo la mia, usa le espressioni regolari ed un replace, ho considerato che potessero inserire 5 | 5 KG | 6.1 KG | 6,1 Kg | 6.1 | 8,2 (dovrebbero essere tutte le possibili combinazioni). Spero che non ci sia altro nel test"

    Giusto per fornire altri spunti sulle RegEx, mi permetto di proporre una versione semplificata del codice, utilizzando come pattern questa stringa:
    (?:[A-Zs]*)([0-9]+)(,|.)?([0-9]*)( w*)*

    Qui un confronto, con alcuni input, tra i due risultati








    ABC
    1stringaregex scossaregex gdito
    2KG 15.515,5 KgKg 15,5
    3kg 251.25 KG251,25 KgKg 251,25 Kg
    4asdsdasdsd Kg
    5asd 4545 Kgasd 45 Kg
    6251.34251,34 Kg251,34 Kg
    7251,3454251,3454 Kg251,3454 Kg
    8kg 251,25 KG251,25 KgKg 251,25 Kg
    9450450 Kg450 Kg


    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)








     
    Function formatKg(ByVal sString As String) As String
      'by scossa
      Dim oRegEx As Object
    
      Set oRegEx = CreateObject("vbscript.regexp")
      With oRegEx
        .Global = True
        .IgnoreCase = True
        .Pattern = "(?:[A-Zs]*)([0-9]+)(,|.)?([0-9]*)( w*)*" '"(?:w*s*)([0-9]+).([0-9]+)+( w*)*" meglio: "(?:[A-Zs]*)([0-9]+)(,|.)?([0-9]*)( w*)*"
        If .test(sString) Then
          formatKg = Replace(Trim(.Replace(sString, "$1 $3")), " ", ",") & " Kg"
        End If
      End With
      Set oRegEx = Nothing
    
    End Function
    



  • di beppexile data: 25/11/2015 13:25:06

    Che stupido che sono.... sblagliavo l'evento da intercettare è l'utilizzo!!!

    Ecco come ho risolto!! Scusate!  
     
    Private Sub TextBox50_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
        TextBox50.Value = ValidaKg(TextBox50.Text)
    End Sub
    



  • di gdito data: 25/11/2015 14:58:26

    Grande scossa!



  • di beppexile data: 26/11/2015 10:13:57

    Salve ragazzi, come faccio a far si che ci sia il punto per le migliaia e dopo la virgola due cifre decimali al massimo?

    Non so proprio cosa e come modificare... sia il codice di scossa che di gdito, per me sono abbastanza complessi da metterci le mani e cavarne un ragno dal buco!

    Aspetto qualche aiutino

    Grazie a tutti.



  • di beppexile data: 26/11/2015 13:33:01

    Dimenticavo di illustrarvi il perché... visto che poi calcolo il peso medio (peso totale/ pezzi) mi escono dei numeri lunghissimi che dovrei approssimare alle 2 cifre decimali e aggiungere la dicitura Kg finale.



  • di scossa data: 26/11/2015 14:24:04

    Il codice sotto restituisce il valore alla seconda cifra decimale.


    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee.
    (George Bernard Shaw)

     
    Function formatKg(ByVal sString As String) As String
      'by scossa
      Dim oRegEx As Object
      Dim sToken3 As String
    
      Set oRegEx = CreateObject("vbscript.regexp")
      With oRegEx
        .Global = True
        .IgnoreCase = True
        .Pattern = "(?:[A-Zs]*)([0-9]+)(,|.)?([0-9]*)( w*)*" '"(?:w*s*)([0-9]+).([0-9]+)+( w*)*" meglio: "(?:[A-Zs]*)([0-9]+)(,|.)?([0-9]*)( w*)*"
        If .test(sString) Then
          formatKg = .Replace(sString, "$1")
          sToken3 = .Replace(sString, "$3")
          If sToken3 <> "" Then
            formatKg = formatKg & "," & Left(sToken3, 2)
          End If
          formatKg = formatKg & " Kg"
        End If
      End With
      Set oRegEx = Nothing
    
    End Function



  • di beppexile data: 26/11/2015 15:04:05

    Il codice funziona alla perfezione, manca solo il punto per le migliaia ed ottenere questo 10.254,89 Kg



  • di beppexile data: 27/11/2015 13:22:35

    scossa, come metto il punto per le migliaia???

    chiedo troppo, vero?



  • di scossa data: 27/11/2015 15:19:44

    cit. beppexile: "chiedo troppo, vero? "

    il problema non è quello che chiedi (la soluzione è facile), ma è come interagisci col forum.
    Ti rivolgi al singolo che ti ha dato un aiuto, ignorando le risposte di chi ti sembra non ti stia aiutando (vedi mie risposte in questo thread: "errore nel metodo Find") e questo modo di fare a me non garba nemmeno un po'.


    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)



  • di beppexile data: 27/11/2015 15:35:11

    Mi dispiace di aver utilizzato un approccio per te "sgarbato", non era mia intenzione.

    Scrivere su un forum non è come dialogare in prima persona, ed io non ho molta dimestichezza con le emoticon per trasferire emozioni.

    Il mio voleva essere solo un messaggio amichevole nel chiedere esplicitamente a te (solo perché era il tuo codice da modificare), la soluzione più consona.

    Ho sempre ringraziato i singoli aiuti, menzionando ed elogiando il forum e tutti i suoi componenti attivi che aiutano i principianti come me.
    I miei ringraziamenti ci sono sempre a conclusione delle discussione, in genere sempre dopo aver spuntato come risolta.

    Tuttavia ti chiedo umilmente scusa se qualcosa di quello che ho scritto, nel modo o nella forma, ti abbia urtato.
    Eviterò di chiamare in causa singoli individui, ma ripeto, visto che era il tuo codice, e visto il tuo enorme aiuto e bravura, reputavo giusto chiederlo direttamente a te; anche perché non mi pare esista un modo di scrivere messaggi privati.

    Giuseppe



  • di scossa data: 27/11/2015 16:05:52

    Ciao,

    ok, l'importante è aver chiarito.

    Sostituisci il codice dell'udf con quello sotto.



    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)

     
    Function formatKg(ByVal sString As String) As String
      'by scossa
      Dim oRegEx As Object
      Dim sToken3 As String
    
      Set oRegEx = CreateObject("vbscript.regexp")
      With oRegEx
        .Global = True
        .IgnoreCase = True
        .Pattern = "(?:[A-Zs]*)([0-9]+)(,|.)?([0-9]*)( w*)*"
        If .test(sString) Then
          formatKg = .Replace(sString, "$1")
          sToken3 = .Replace(sString, "$3")
          .Pattern = "(d)(?=(ddd)+(?!d))"
          formatKg = .Replace(formatKg, "$1.")
          If sToken3 <> "" Then
            formatKg = formatKg & "," & Left(sToken3, 2)
          End If
          formatKg = formatKg & " Kg"
        End If
      End With
      Set oRegEx = Nothing
    
    End Function
    



  • di beppexile data: 27/11/2015 16:16:12

    Funziona alla grande!

    Grazie a tutti per gli interventi, spunto come risolta.