RegEx in VBA



  • RegEx in VBA
    di Raelear data: 31/10/2014 22:16:23

    Salve a tutti,

    in un sito ho trovato una Espressione Regolare per verificare che il codice ISBN sia stato inserito correttamente. Vorrei inserirla nel mio programma per verificare se il dato immesso in un textbox é un ISBN valido.
    Qualcuno puó aiutarmi con il codice VBA?
    Questa é la espressione, anche se potrebbe essere una qualsiasi: ISBN(-1(?:(0)|3))?:?x20(s)*[0-9]+[- ][0-9]+[- ][0-9]+[- ][0-9]*[- ]*[xX0-9]
    Il problema é non so dove devo definirla e come associarla al textbox..
    Help plz :)

    Grazie in anticipo a tutti

    Rael



  • di lepat (utente non iscritto) data: 01/11/2014 05:59:25

    Nella tua domanda mancano alcuni elementi che potrebbero essere di aiuto
    1) cosa è un ISBN
    2) il link del sito (scrivilo inserendo spazi così h t t p://............



  • di lepat (utente non iscritto) data: 01/11/2014 06:00:44

    inoltre manca un file di esempio su cui fare le prove



  • di Raelear data: 01/11/2014 09:00:24

    Ciao Lepat,

    ISBN ( International Standard Book Number) é il codice univoco internazionale di identificazione di un libro.

    Il sito dal quale l'ho presa é h t t p : / / regexlib.com facendo poi la ricerca con keyword isbn

    Per quanto riguarda il file di esempio.. non saprei cosa postare, nel senso che é una TextBox nella quale viene inserito il codice ISBN (consiglio di dare una occhiata in wiki per vedere come é composto l'ISBN, qui mi pare inopportuno). Nell'evento TextBox_Exit si deve fare il controllo (con questa espressione RegEx) per vedere se é un ISBN valido... giusto come anticipazione, l'ISBN é formato da gruppi di cifre che identificano cose come il tipo libro, autore, editore, edizione, ecc..

    Spero questi dettagli chiariscano meglio il problema.




  • di lepat (utente non iscritto) data: 01/11/2014 11:10:03

    basta allegare il file su cui stai provando senza successo, perché dovrei ricostruirlo io ?



  • di Zer0Kelvin data: 01/11/2014 15:16:46

    Salve a tutti.
    Premesso che, come scritto da Patel, sarebbe tutto molto più semplice con un file e dei dati su cui fare dei test; per utilizzare le espressioni regolari da VBA devi prima aggiungere (Menù Strumenti->Riferimenti) il riferimenot a
    Microsoft VBScript Regular Expression 5.5

    Per effettuare il test, puoi utilizzare (come da esempio) una funzione booleana che accetti come parametri il contenuto della textbox (o altro testo) e l'espressione regolare relativa all'ISBN.
    Ho provato a testare la funzione con dei codici presi dalla rete e l'espressione regolare da te riportata, ma sembra non funzionare.
    Il codice comunque è questo
     
    Public Function Test(Txt As String, RExpr As String) As Boolean
    Dim regEx As New RegExp
        If RExpr <> "" Then
            With regEx
                .Global = True
                .MultiLine = True
                .IgnoreCase = True
                .Pattern = RExpr
            End With
            Test = regEx.Test(Txt)
        End If
    End Function



  • di Raelear data: 01/11/2014 23:40:43

    @ lepat
    scusami lepat, non volevo irritarti, ma mi sembrava di essere stato esaustivo giá all'apertura del thread dove dicevo
    "Il problema é (che) non so dove devo definirla e come associarla al textbox.. "
    non so se mi spiego.. ho solo trovato l'espressione nel web, ma, non sapendo come gestirla, ho solo un textbox vuoto e senza alcun codice ad esso associato.. forse sono io che mi spiego male.. (o non intendo la richiesta).
    Ad ogni buon conto, anche se mi sembra strano farlo, allego un file di prova contenente un form con il textbox, e, visto che ancora non so cosa inserire, aggiungo qualche nota e un paio di ISBN per fare prove.

    @Zer0Kelvin
    ti ringrazio per l'apporto.. ma data la mia scarsa dimestichezza con VBA, mi sfuggono alcune cose.. una, ad esempio, é che non ho capito dove dichiari la regular expression.
    Ho googleato sino alla nausea ed ho scoperto varie cose interessanti.. purtroppo, come dicevo, causa la scarsa conoscenza in materia, pur capendo che sono sulla strada giusta, non so da dove iniziare..
    Ho trovato alcuni link che potrei passarti, se lo ritieni opportuno.
    Seguendo le indicazioni di uno di questi ho provato a scrivere il codice che ho riportato qui sotto, ma al momento di specificargli la stringa con la regex mi va in errore..
    Ho provato con almeno 3 di quelle del link che ho passato nel thread, ma tutte mi danno errore.
    (non ho capito come funziona l'aggiunta di un file.. spero che quello postato Libro01.xlsm si veda..)

    Dimmi se non ti scoccia che ti passi i link trovati :)

    Saluti
    Rael

     
    Sub RegEx_Tester()
            Set objRegExp_1 = CreateObject("vbscript.regexp")
            objRegExp_1.Global = True
            objRegExp_1.IgnoreCase = False
            objRegExp_1.Pattern = ^(97(8|9))?d{9}(d|X)$                ' nell'esempio incontrato era:     objRegExp_1.Pattern=[a-z,A-Z]*@[a-z,A-Z]*.com. A me qualsiasi espressione da errore al primo carattere dicendo: "Errore di compilazione. Si aspettava espressione."
            ....l'esempio continua con
            strToSearch="ABC@xyz.com"
            Set regExp_Matches = objRegExp_1.Execute(strToSearch) 'che nel mio caso sarebbe TextBox1.Text    
            If regExp_Matches.Count = 1
            MsgBox("This string is a valid email address.")
            End if
    End Sub



  • di lepat (utente non iscritto) data: 02/11/2014 11:51:37

    quindi ti sembra strano aiutare chi ti vorrebbe aiutare e che ha già detto di non sapere cosa è un isbn



  • di Raelear data: 02/11/2014 17:22:27

    lepat.. ascolta..
    mi sembra strano, a questo punto, il tuo comportamento nei miei confronti.. scrivo in italiano correttissimo, con i modi piú educati e accomodanti di questo mondo.. ma vedo che forse hai dei problemi di empatia verso il mio Nick.. visto che non mi conosci personalmente.. quindi ...
    che ne dici di dedicarti ad un altro thread visto che questo lo stai usando solo per riempire di vuoto il nulla?
    Saluti
    Rael



  • di lepat (utente non iscritto) data: 02/11/2014 17:55:18

    non ho alcun problema nei tuoi confronti, cercavo soltanto di farti capire come evitare di sprecare il tuo tempo e quello degli altri in circostanze simili a questa, ma vedo che preferisci la polemica oltre a lodare te stesso.



  • di Raelear data: 02/11/2014 18:08:00

    cito:
    "quindi ti sembra strano aiutare chi ti vorrebbe aiutare e che ha già detto di non sapere cosa è un isbn"

    questa mi é sembrata polemica...

    la mia era solo una risposta che ricalcava lo stesso tono.. ho scritto che "mi sembrava strano" perché avevo davvero solo un form con un textbox senza alcun codice.. poi ho aggiunto che aggregavo qualcosa perché ho googleato piú che potevo e quindi ho aggiunto ció che ho trovato..

    In tutti i modi, forse questo é stato solo un malinteso, come spero che sia.. perché sicuramente non mi piace far perdere tempo a nessuno (soprattutto in un forum dove chiedo aiuto) e tanto meno mi piace perderlo..
    Quindi se sei daccordo, e se ritieni che possiamo serenamente voltare pagina, tornerei sul problema.
    Sono a disposizione se c'é altro che possa aggiungere a ció che ho inviato e, come dicevo a Zer0Kelvin, se lo ritenete opportuno posso passare alcuni link che spiegano varie cose a proposito di composizione di un ISBN e uso di RegEx.

    Saluti
    Rael



  • di scossa data: 02/11/2014 19:11:06

    Ciao,

    riporto sotto una modifica al codice della udf di Zer0.

    In A1:: il codice (es.: ISBN 978-0-470-47535-5 oppure ISBN-13 88-7131-898-6)
    in B1:: =Test2(A2)




    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)

     
    Public Function Test2(Txt As String) As Boolean
      Const sPattern = "ISBN(-1(?:(0)|3))?:?x20(s)*[0-9]+[- ][0-9]+[- ][0-9]+[- ][0-9]*[- ]*[xX0-9]"
      Dim regEx  As Object
      Set regEx = CreateObject("VBScript.RegExp")
      With regEx
          .Global = True
          .MultiLine = False
          .IgnoreCase = True
          .Pattern = sPattern
      End With
      Test2 = regEx.Test(Txt)
    End Function



  • di Raelear data: 02/11/2014 19:28:10

    Salve Scossa,

    per prima cosa ti ringrazio per l'apporto.

    Ho inserito il codice nel modulo ed ho completato le lcelle A1 e B1 come indicato peró mi restituisce "Falso" in B1. Ho provato anche con un ISBN di un libro che ho qui sotto mano, ma il risultato é uguale.
    Sto sbagliando qualcosa?
    Rael



  • di scossa data: 02/11/2014 19:34:43

    @Raelear: in A1 va inserita l'intera stringa ISBN 978-0-470-47535-5

    A me funziona regolarmente.



    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 Raelear data: 02/11/2014 19:53:41

    é quello che ho fatto..
    ma a te che valore restituisce in B1?



  • di Raelear data: 02/11/2014 20:02:12

    LOL..
    ho solo copiato quello che avevi scritto, ma solo adesso mi sono reso conto che "A2" era sbagliato.. é A1.. la colpa é mia di aver copiato senza leggere..

    Grazie Scossa,
    adesso provo con qualche altra regexp perché in realtá devo trovarne una che mi faccia il controllo per le tre tipologie di ISBN possibili: a 10 cifre, a10 cifre con una X come decima, a 13 cifre.. se potessi anche evitare di digitare la parola ISBN sarebbe il massimo..
    tu dove hai trovato questa regex?



  • di lepat (utente non iscritto) data: 02/11/2014 20:17:10

    prova questa per isbn senza la scritta isbe e senza trattini
     
    Public Function Test(Txt As String) As Boolean
    Dim regEx As New RegExp
    With regEx
                .Global = True
                .MultiLine = True
                .IgnoreCase = True
                .Pattern = "^(97(8|9))?d{9}(d|X)$" 
    End With
    Test = regEx.Test(Txt)
    End Function



  • di scossa data: 02/11/2014 20:23:21

    cit.: "tu dove hai trovato questa regex?"

    Come dove l'ho presa? è quella che hai indicato tu nel tuo primo post



    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 Raelear data: 02/11/2014 20:24:45

    grazie lepat, funziona anche questa.. nel mio caso é piú comodo non dover aggiungere il testo ISBN ed i trattini..

    se posso approfittare ancora della vostra disponibilitá..

    Come faccio ad inserire questo in un codice VBA?
    La prima domanda che vorrei fare é: il controllo é meglio dichiararlo nell'evento _Change o in quello _Exit?
    La seconda: ho definito la funzione nel modulo.. adesso posso richiamarla cosí com'é nel codice del mio UserForm.. ma immagino di doverla dichiarare tra parentesi nella stessa riga che definisce l'evento.. é corretto?



  • di lepat (utente non iscritto) data: 02/11/2014 20:34:36

    io non ho capito, ma ripeto, si perde meno tempo allegando un file, anche se con errori, basta aggiungervi commenti che descrivano i tuoi dubbi



  • di Raelear data: 02/11/2014 20:37:11

    pardon ..lo faccio subito



  • di Raelear data: 02/11/2014 20:39:08

    Libro02.xlsm



  • di scossa data: 02/11/2014 20:41:50

    cit. lepat: "prova questa per isbn senza la scritta isbe e senza trattini"

    Questa funziona solo per i codice a 13 cifre.

    N.B.: tenete presente che la reg-exp controlla solo la correttezza formale del codice.

    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 lepat (utente non iscritto) data: 02/11/2014 20:52:02

    Ciao Scossa, non ci ho dedicato tempo, una volta capito quale codice usare basta provare le varie espressioni fino a trovare quella che va bene e questo lo può fare Raelear



  • di Raelear data: 02/11/2014 20:53:43

    Scossa che cosa intendi per correttezza formale? uhmm forse ho capito..



  • di Raelear data: 02/11/2014 21:05:27

    concordo con lepat, la ricerca di quella che fa al caso mio é giusto che la faccia io..
    ma potreste darmi una indicazione su come passare questo nel textbox?

    cito:
    "Come faccio ad inserire questo in un codice VBA?
    La prima domanda che vorrei fare é: il controllo é meglio dichiararlo nell'evento _Change o in quello _Exit?
    La seconda: ho definito la funzione nel modulo.. adesso posso richiamarla cosí com'é nel codice del mio UserForm.. ma immagino di doverla dichiarare tra parentesi nella stessa riga che definisce l'evento.. é corretto?"

    scusate la ripetizione :)



  • di lepat (utente non iscritto) data: 02/11/2014 22:30:57

    sarebbe meglio spiegare cosa vuoi ottenere, azzardare un codice, anche se non funzionante.



  • di Zer0Kelvin data: 03/11/2014 09:06:32

    CIT:
    il controllo é meglio dichiararlo nell'evento _Change o in quello _Exit?
    _________________________________________________________
    Sicuramente non l'evento change, che si verifica ogni volta che digiti un carattere.
    Puoi inserire il controllo nell'evento Exit e, se il controllo dà esito negativo, visualizzare un messaggio ed impedire l'uscita dalla textbox impostando Cancel=True
     
    Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
        If Not Test(Me.TextBox1.Value) Then
            MsgBox "Valore errato"
            Cancel = True
        End If
    End Sub
    



  • di Raelear data: 03/11/2014 15:48:26

    per prima cosa desidero ringraziare entrambe, lepat & Zer0Kelvin, per l'aiuto che mi state dando.

    Ieri sera ho avuto problemi con la connessione e non ho potuto postare la risposta a lepat, dove fornivo tutti i dettagli su quello che desidero fare ed il mio pasticciatissimo file di prova.. alla luce della risposta di Zer0Kelvin che ho trovato questa mattina ho redatto nuovamente la risposta ed il file (adesso funziona)..
    ..ma..
    nel frattempo ho capito varie cose googleando qui e lí.. e vi riporto il tutto.
    In realtá le regex presenti nel sito che ho passato all'inizio del thread, servono quasi a nulla.. solo si limitano a verificare la presenza di 10 o 13 cifre nel codice (ISBN) immesso..
    Come dicevo all'apertura del thread, voglio controllare che l'ISBN immesso in textbox1 sia un ISBN valido, ed é proprio questo il punto: la validitá di un ISBN la definisce il suo ultimo carattere.. definito giustamente Carattere di Controllo.
    Il codice ISBN é un insieme di 5 gruppi di cifre che indicano rispettivamente (usando l'ISBN su cui abbiamo lavorato sin ora come esempio, 978-0-470-47535-5)
    - 978 : codice EAN (EuropeanArticleNumber) che per tutti i libri a livello mondiale puó essere 978 o 979
    - 0 : gruppo linguistico che puó utilizzare da 1 a 5 cifre
    - 470 : gruppo editore che utilizza da 2 a 7 cifre
    - 47535 : gruppo titolo utilizza da 1 a 6 cifre
    - 5 : carattere di controllo.
    Ora, laddove non si possa effettuare un controllo online del ISBN ed ammesso che nel web siano presenti tuti gli ISBN di tutti i Libri, l'unico controllo valido per verificare se l'ISBN immesso é un ISBN valido risiede nell'ultimo carattere, quello di controllo che serve appunto a questo.
    Il carattere di controllo si calcola in modo diverso a seconda che si tratti di un ISBN a 10 cifre, uno a 10 cifre dove l'ultima é una X, oppure uno a 13 cifre.
    Per non dilungarmi con il dettaglio dei singoli casi il carattere di controllo dell'ISBN a 13 cifre si calcola cosí:
    si moltiplica ogni cifra per un peso in base alla posizione della cifra stessa: la prima cifra per 1, la seconda per 3, la terza per 1 e così via.
    si sommano i risultati
    si divide la somma per 10 e si prende il resto della divisione
    si sottrae il risultato da 10: questa cifra è la cifra di controllo; se quest'ultimo risultato fosse proprio 10, lo si sostituirà con 0.
    978-0-470-47535-(5)
    9*1+7*3+8*1+0*3+4*1+7*3+0*1+4*3+7*1+5*3+3*1+5*3= =9+21+8+0+4+21+0+12+7+15+3+15=115
    115/10=11 con resto di 5
    Si sottrae a 10 il resto della divisione e si ottiene il valore del carattere di controllo, appunto 5.

    Credo fosse proprio a questo che si riferiva Zer0Kelvin parlando di "Correttezza Formale", se si riferisce a che cominci per 978 o 979 e sia formato da 13 cifre.

    Nel mio caso si stanno immettendo libri in un foglio excel tramite una UserForm ed é necessario che l'ISBN immesso sia corretto. A questo punto, il controllo che piú si avvicina al risultato richiesto é proprio la verifica che fa il Carattere di Controllo, da aggiungere a ció che fanno le altre formule viste sin ora.

    Detto questo.. :) mi aiutereste a scrivere l'espressione regolare che fa appunto questo? :)

    si potrebbe poi pubblicare in quel sito :)

    Saluti
    Rael



  • di Raelear data: 03/11/2014 18:21:25

    mi é venuta una idea..

    A) per controllare se l'ISBN é a 10 cifre, 10 cifre con l'ultima uguale a X, o a 13 cifre, uso una delle regex tra quelle del sito che faccia al caso.

    B) per fare il controllo dell'ultimo carattere, dovrei poter:
    1) Controllare se la stringa (ISBN) é di 10, 10 con X o 13 numeri
    2) estrarre ogni singolo carattere che la compone ed effettuare su ciascuno l'operazione che corrisponde in relazione al risultato al passo 1).
    3) Sommare i risultati ottenuti dalle singole operazioni, dividerli per il valore convenuto nei 3 casi differenti
    4) verificare se il resto della divisione corrisponde all'ultimo carattere della stringa(ISBN)

    é corretto?

    Ma come si fa ad isolare un singolo carattere dalla stringa?



  • di Raelear data: 03/11/2014 19:05:21

    Premesso quanto giá esposto in precedenza riguardo come si calcola il Carattere di Controllo nell'ISBN, nei 3 diversi casi,
    vedi h t t p ://it.wikipedia.org/wiki/ISBN

    si puó completare l'evento _Exit con qualcosa di simile? (che non so scrivere)

    Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    If Not Test2(Me.TextBox1.Value) Then
    MsgBox "Valore errato"
    Cancel = True
    ' End If
    Else


    With TextBox1
    'dim str come stringa
    'str = .Text
    'controlla la lunghezza di str con Len(str)
    'se str = 10
    'dimensiona p come intero
    'per ciascun i da 1 a 9
    'e per ciascun p da 10 a 2
    'Mid(str, i, 1)*p (peró poi dovrebbe sommare tutti i prodotti ottenuti da 1 a 9, come?)
    'poi, ottenuto il totale, lo divide per 10; se resto <> 0 allora se resto = Mid(str, 10, 1) msg"ok"
    'se resto = 10 e Mid(str, 10, 1)="X" allora msg"ok"..
    '...continua con il caso Len(str)=13....
    End Sub



  • di lepat (utente non iscritto) data: 03/11/2014 19:05:56

    con la funzione mid



  • di Raelear data: 03/11/2014 20:18:58

    si si, quello l'ho visto cercando qualcosa sulle stringhe.. e come ho scritto in quella bozza di codice (se cosí si puó chiamare).. ora il mio problema é che non saprei come..
    ma che ti sembra dell'idea? puó funzionare?
    e come faccio a dirgli che deve fare un prodotto e sommare i 9 risultati?
    puoi indicarmi la strada?



  • di lepat (utente non iscritto) data: 03/11/2014 21:11:41

    metti il codice isbn senza trattini in A1 e prova questo codice che di da la somma dei numeri moltiplicati per 3 e 1
     
    Option Base 1
    Sub a()
    Dim arr() As Integer
    isbn = Range("A1").Text
    L = Len(isbn)
    ReDim arr(L)
    molt = Array(1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3)
    For j = 1 To L
      arr(j) = Val(Mid(isbn, j, 1))
    Next
    For j = 1 To L
      s1 = s1 + arr(j) * molt(j)
    Next
    Debug.Print s1
    End Sub



  • di Zer0Kelvin data: 03/11/2014 21:43:18

    Su google ho trovato questo thread, penso possa essere utile.



  • di Zer0Kelvin data: 03/11/2014 21:44:04

    He, he ..scusate.
    Questo
    forum.masterdrive.it/visual-basic-6-17/codice-controllo-isbn-13-cifre-17679/



  • di Raelear data: 03/11/2014 21:51:23

    ho inserito il codice, gli ho solo cambiato
    molt = Array(1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3)
    con
    molt = Array(1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1)
    in quanto nella prima ci sono 14 valori e non 13, ma non vedo il risultato, cosa dovrebbe apparire?
    ho provato anche a cambiare l'ultima cifra, ma non vedo cambiamenti.
    Posto il file Libro03



  • di lepat (utente non iscritto) data: 03/11/2014 22:19:31

    probabilmente non hai la finestra di debug, sostituisci
    Debug.Print s1
    con
    msgbox s1



  • di lepat (utente non iscritto) data: 03/11/2014 22:21:51

    oppure
    range("A2") = s1



  • di Raelear data: 03/11/2014 22:25:14

    voglio morire... LOL

    corro a provare!

    peró lepat l'ha fatto da solo :)



  • di Raelear data: 03/11/2014 22:37:16

    lepat,
    ho fatto questo cambio e funziona

    Option Base 1
    Sub a()
    Dim arr() As Integer
    isbn = Range("A1").Text
    L = Len(isbn)
    ReDim arr(L)
    molt = Array(1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1)
    For j = 1 To L
    arr(j) = Val(Mid(isbn, j, 1))
    Next
    For j = 1 To L
    s1 = s1 + arr(j) * molt(j)
    Next
    If s1 Mod 10 = 0 Then

    'Debug.Print s1
    Range("B1") = "ok"
    Else
    Range("B1") = "Errore"
    End If
    End Sub



  • di Zer0Kelvin data: 04/11/2014 00:01:29

    Ciao.
    Per la cronaca, riporto la function allegata al post che citavo più sopra.
    La function restituisce il codice di controllo per un SBN a 13 cifre con o senza trattini.
     
    Public Function CheckIsbn13(codice As String) As String
        Dim i As Integer
        Dim r As Integer
        Dim somma As Long
        codice = Replace(codice, "-", "")
        If (Len(codice) < 12) Or (Len(codice) > 13) Then
            MsgBox "Codice Errato"
            Exit Function
        End If
        For i = 1 To 12
            r = CInt(Mid(codice, i, 1))
            If i Mod 2 = 1 Then
                somma = somma + r
            Else
                somma = somma + r * 3
            End If
        Next
        r = somma Mod 10
        If r <> 0 Then r = 10 - r
        CheckIsbn13 = CStr(r)
    End Function



  • di Zer0Kelvin data: 04/11/2014 00:19:52

    Daquella sopra ho ricavato questa per il controllo della validità delle 13 cifre
     
    Public Function Sbn13_Ok(codice As String) As Boolean
        Dim i As Integer
        Dim somma As Long
        codice = Replace(codice, "-", "")
        If Len(codice) <> 13 Then
            Sbn13_Ok = False
        Else
            For i = 1 To 12
                somma = somma + CInt(Mid(codice, i, 1)) * (3 - 2 * (i Mod 2))
            Next
            r = somma Mod 10
            Sbn13_Ok = CStr(IIf(somma Mod 10 = 0, 0, 10 - somma Mod 10)) = Mid(codice, 13, 1)
        End If
    End Function
    
    Sub test()
    MsgBox Sbn13_Ok(Range("A1"))
    End Sub
    



  • di Zer0Kelvin data: 04/11/2014 00:21:26

    PS: la riga
    r = somma Mod 10
    si deve cancellare.



  • di scossa data: 04/11/2014 18:02:14

    So che siamo su un forum di VBA ma propongo una soluzione al volo lato formule, giusto per ...... (aspettare ninai con le sue forbici).

    La seguente formula verifica la correttezza (in base al codice di controllo) sia degli ISBN 13 che 10:

    In A2:: il codice
    in B2::
    =SE(LUNGHEZZA(A2)=13;SE(RESTO(SOMMA({1313131313131}*INDICE(STRINGA.ESTRAI(A2;{12345678910111213};1);));10)=0;"OK";"ERRATO");SE(SOSTITUISCI(11-RESTO(SOMMA({1098765432}*INDICE(STRINGA.ESTRAI(A2;{123456789};1);));11);"10";"X")=DESTRA(A2;1);"OK";"ERRATO"))

    matriciale da confermare con ctrl+maiusc+invio






    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 scossa data: 04/11/2014 18:42:56

    Questa la versione UDF che ne deriva.


    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)

     
    '---------------------------------------------------------------------------------------
    ' Procedure : CheckIsbn
    ' Author    : scossa
    ' Date      : 04/11/2014
    ' Purpose   :
    '---------------------------------------------------------------------------------------
    '
    Public Function CheckIsbn(ByVal sIsbn As String) As Variant
    
      Dim vRet_ As Variant
      Dim nLen As Long
      nLen = Len(sIsbn)
      If nLen = 13 Then
        vRet_ = Evaluate("IF(MOD(SUM({1,3,1,3,1,3,1,3,1,3,1,3,1}*INDEX(MID(" & sIsbn & ",{1,2,3,4,5,6,7,8,9,10,11,12,13},1),)),10)=0,""OK"",""ERRATO"")")
      ElseIf nLen = 10 Then
        vRet_ = Replace(Evaluate("11-MOD(SUM({10,9,8,7,6,5,4,3,2}*INDEX(MID(" & Replace(sIsbn, "X", "") & ",{1,2,3,4,5,6,7,8,9},1),)),11)"), 10, "X") = Right(sIsbn, 1)
      Else
        vRet_ = ""
      End If
    
      CheckIsbn = vRet_
    
    End Function
    



  • di Zer0Kelvin data: 05/11/2014 00:03:14

    Uhm! ho paura che Raelear ci abbia lasciato proprio sul più bello.



  • di ninai (utente non iscritto) data: 05/11/2014 15:47:32

    Lungi da me capire l'insieme del quesito, ne tanto meno la formula di Scossa nel dettaglio. Ma siccome ormai sono la vittima sacrificale delle formule astruse, mi limito a tagliare di 12 caratteri con una sostituzione:

    =SE(LUNGHEZZA(A2)=13;SE(RESTO(SOMMA({1313131313131}*INDICE(STRINGA.ESTRAI(A2;RIF.COLONNA(A1:M1);1);));10)=0;"OK";"ERRATO");SE(SOSTITUISCI(11-RESTO(SOMMA({1098765432}*INDICE(STRINGA.ESTRAI(A2;RIF.COLONNA(A1:I1);1);));11);"10";"X")=DESTRA(A2;1);"OK";"ERRATO"))

    se riesco a entrare nel procedimento mi rifaccio leggere ;) ;)



  • di Raelear data: 05/11/2014 16:14:54

    no no... sono qui ..
    Ancora grazie per la pazienza e il vostro valido aiuto...

    sono troppo novellino e vi giuro che a volte é piú facile fare la domanda che capire la risposta :)
    per cui devo prendermi il tempo di metabolizzare e fare prove..

    il mio problema é stato mettere quello che provavamo su un foglio, nei miei Form e relativi Control.. non ridete vi prego.. non sapevo neanche come richiamare la Function dal modulo al codice della USerForm.. vabbé..

    Vorrei postare un file di prova, ma alla fine le modifiche le ho fatte nel mio file_progetto quindi allego questo.
    UserForm3 é quello che gestisce l'immissione dei Libri e quindi il maledetto ISBN :)
    Poiché ci possono essere libri di edizione antecedente al 1970 che quindi non hanno ISBN, ho inventato un codice (111) che li identifica.. (la colonna RefLibro in "DB_LIBROS" ha una formula che mi aggiunge un 'progressivo libro' ad ogni immissione).

    La convalida dei due tipi di ISBN funziona. Non riesco peró a dirgli di cancellare l'ISBN immesso se non é valido..

    Mi scuso se non posto un file piú semplice da visionare. :) I diritti sono riservati :)



  • di scossa data: 05/11/2014 18:13:45


    cit. ninai: "... mi limito a tagliare di 12 caratteri con una sostituzione"

    Tagli tu, taglio io: -5

    =SE(LUNGHEZZA(A2)=13;SE(RESTO(SOMMA({1313131313131}*INDICE(STRINGA.ESTRAI(A2;RIF.RIGA(A1:A13);1);));10)=0;"OK";"ERRATO");SE(SOSTITUISCI(11-RESTO(SOMMA({1098765432}*INDICE(STRINGA.ESTRAI(A2;RIF.RIGA(A1:A9);1);));11);"10";"X")=DESTRA(A2;1);"OK";"ERRATO"))



    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 ninai (utente non iscritto) data: 05/11/2014 19:26:21

    cit. "Tagli tu, taglio io: -5"
    Scossa, l'ultima a me non funziona ("." invece che "/"), comunque:
    =SE(LUNGHEZZA(A2)=13;SE(RESTO(SOMMA({1.3.1.3.1.3.1.3.1.3.1.3.1}*INDICE(STRINGA.ESTRAI(A2;RIF.RIGA(1:13);1);));10)=0;"OK";"ERRATO");SE(SOSTITUISCI(11-RESTO(SOMMA((11-RIF.RIGA(1:9))*INDICE(STRINGA.ESTRAI(A2;RIF.RIGA(1:9);1);));11);"10";"X")=DESTRA(A2;1);"OK";"ERRATO"))

    -6



  • di scossa data: 05/11/2014 19:38:53

    @ninai: ottimo taglio! direi che non resta altro da tagliare



    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 Zer0Kelvin data: 05/11/2014 23:32:30

    Ciao.
    Ho spezzato e rivisto la sub CommandButton5_Click per renderla più "maneggevole".
    Prova ad inserire quanto segue la posto della tua CommandButton5_Click:
     
    Private Sub GoBack()
        Me.TextBox1.BackColor = &H80000005
        blExit = True
        CommandButton2_Click
        Unload Me
        Sheets("Menu").Select
    End Sub
    
    Private Sub EmptyISBN()
        With Me.TextBox1
            If MsgBox(Prompt:="Campo Obligatorio!" & vbNewLine & vbNewLine _
                & "REINTENTAR para volver a ingresar o CANCELAR para Salir", _
                Buttons:=vbRetryCancel, Title:="Puesto de Libros") = vbCancel _
                Then
                .BackColor = &H80000005
                GoBack
            Else
                .BorderStyle = fmBorderStyleSingle
                .BorderColor = RGB(255, 80, 20)
                .BackColor = RGB(255, 255, 10)
                TextBox11.Text = ""
            End If
        End With
    End Sub
    
    Private Sub ValidISBN()
        With TextBox1
            TextBox11.Text = "ISBN VÁLIDO"
            .BorderStyle = fmBorderStyleSingle
            .BorderColor = RGB(0, 0, 70)
            .BackColor = RGB(150, 200, 255)
        End With
    End Sub
    
    Private Sub InvalidISBN()
        TextBox11.Text = "ISBN NO VÁLIDO"
        With TextBox1
            If MsgBox(Prompt:="Ingresar un ISBN válido" _
                & vbNewLine _
                & vbNewLine _
                & "REINTENTAR para volver a ingresar o CANCELAR para Salir", _
                Buttons:=vbRetryCancel, _
                Title:="Puesto de Libros") <> vbCancel _
            Then
                .BackColor = &H80000005
                .BorderStyle = fmBorderStyleSingle
                .BorderColor = RGB(255, 80, 20)
                .BackColor = RGB(255, 255, 10)
                .SetFocus
            Else
                GoBack
            End If
            .Text = ""
        End With
    End Sub
    
    Private Sub CommandButton5_Click()
    Dim cdgo, chrcontr As String
    Dim Res As VbMsgBoxResult
        If Not blExit Then
            With TextBox1
                cdgo = TextBox1.Text
                If cdgo = "" Then
                    EmptyISBN
                ElseIf cdgo = "111" Then
                    TextBox11.Text = "SÍN ISBN"
                    .BorderStyle = fmBorderStyleSingle
                    .BorderColor = RGB(0, 0, 70)
                    .BackColor = RGB(150, 200, 255)
                ElseIf Len(cdgo) = 13 Then
                    TextBox10.Text = CheckIsbn13(TextBox1.Text)
                    If CInt(Mid(cdgo, 13, 1)) = TextBox10.Text Then
                        ValidISBN
                    Else
                        InvalidISBN
                    End If
                ElseIf Len(cdgo) = 10 Then
                    If IsbnOk(cdgo) Then
                        ValidISBN
                    Else
                        InvalidISBN
                    End If
                Else
                    InvalidISBN
                End If
            End With
        End If
    End Sub
    



  • di Raelear data: 06/11/2014 00:54:09

    Quante cose sto imparando!

    Grazie Zer0Kelvin.. non avrei mai immaginato di spezzarla quella Sub.. era davvero un gran papiro..

    Ringrazio anche gli altri, lepat, scossa e ninai per il loro apporto.. in realtá vi ho un po' perso nelle ultime parentesi tonde




  • di scossa data: 08/11/2014 18:39:58

    cit: "If CInt(Mid(cdgo, 13, 1)) = TextBox10.Text Then"

    Solo un'annotazione: trasformare con CInt() un "numero stringa" in numero (p.e. "6" -> 6) per poi confrontarla con una stringa (il contenuto di una Textbox) è un aggravio di lavoro



    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 Zer0Kelvin data: 09/11/2014 00:34:43

    Beh! in realtà si potrebbe proprio fare a meno di Textbox10 ed effettuare il controllo direttamente all'interno della funzione CheckIsbn13, modificandola per far restituire un Boolean al posto del carattere di controllo.



  • di Zer0Kelvin data: 09/11/2014 00:38:56

    Cioè, come avevo suggerito più sopra
     
    Public Function Sbn13_Ok(codice As String) As Boolean
        Dim i As Integer
        Dim somma As Long
        codice = Replace(codice, "-", "")
        If Len(codice) <> 13 Then
            Sbn13_Ok = False
        Else
            For i = 1 To 12
                somma = somma + CInt(Mid(codice, i, 1)) * (3 - 2 * (i Mod 2))
            Next
            Sbn13_Ok = CStr(IIf(somma Mod 10 = 0, 0, 10 - somma Mod 10)) = Mid(codice, 13, 1)
        End If
    End Function



  • di Zer0Kelvin data: 09/11/2014 00:41:24

    ...magari aggiungendo un Trim (qualche spazio ci può sempre scappare)
     
    codice = Trim(Replace(codice, "-", ""))



  • di scossa data: 09/11/2014 00:41:53

    @Zer0kelvin: non ho scaricato il file, ho solo letto il codice nel tuo post .... per cui mi fido di quanto dici




    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 Raelear data: 10/11/2014 21:33:35

    siete dei veri Mostri......

    ....

    ..di Bravura!