Filtro tabella access



  • Filtro tabella access
    di gugluca (utente non iscritto) data: 28/06/2013 17:05:02

    Ciao,
    Ho un problema intricato da risolvere e sinceramente non riesco a capire come fare. Provo a spiegarmi.
    Ho 2 tabelle in un db access, entrambe composte da un solo campo.
    La prima 'ORIG' alimentata, la seconda 'MOD' vuota.
    Vorrei alimentare la tabella MOD pescando i valori dalla tabella ORIG, creando un ciclo che faccia questa operazione:
    Iif(left(ORIG.CAMPO,3)=103,iif(val(mid(ORIG.CAMPO,4,8))>=20000000,
    inserisci nella tabella MOD dal campo precedente (quando trovi left(ORIG.CAMPO,3)=100) fino al prossimo campo dove trovi left(ORIG.CAMPO,3)=100.
    Fai questa operazione fino a EOF.

    Non so se mi son spiegato bene, ma proprio non riesco a capire come fare..
    Grazie per l'aiuto!

    Luca



  • di Vecchio Frac data: 28/06/2013 18:54:45

    Ci sono alcune cose che non capisco, provo a riscrivere la richiesta (mi piacerebbe fare tutto con una query senza usare VBA):
    se i primi tre caratteri di ORIG.CAMPO sono "103" (<-- quindi stringa, non numero)
    allora se il valore degli 8 caratteri di ORIG.CAMPO partendo dal quarto è maggiore o uguale a 20.000.000,
    allora se i primi tre caratteri di MOD.CAMPO sono "100" (<-- ma MOD.CAMPO è vuoto!)
    --cosa devo fare?--





  • di gugluca (utente non iscritto) data: 28/06/2013 19:11:00

    La tabella ORIG contiene un campo con questi valori 'stringhe':

    100........
    101........
    102........
    103........
    104........
    104........
    105........
    105........
    105.......
    ............
    100......
    101.....
    102.....
    .........

    Completando il tuo ragionamento....
    Se i primi 3 caratteri sono 103, se i caratteri da 4 a 12 sono > 20.000.000, allora copia le righe da quella che inizia con 100 immediatamente precedente, a quella che inizia con 100 successiva (esclusa). Le righe copiate vanno inserite nella tabella MOD.

    Spero di non averti fatto ulteriore casino.
    Ciao e grazie ancora

    Luca






  • di Vecchio Frac data: 28/06/2013 19:43:19

    Adesso (mi) è più chiaro.
    Non vuol dire che sia più semplice ^_^
    In sostanza vuoi copiare un blocco di righe delimitate da due righe i cui primi tre caratteri sono "100" (escluso il secondo), quando il blocco contiene un record i cui primi tre caratteri sono "103" e (AND) il valore dei caratteri tra 4 e 12 è >= 20.000.000
    Fammi pensare un attimo... difficile riuscirci con una query, bisognerà ricorrere a VBA e ai Bookmarks. Sarei felice di essere smentito ^_^





  • di Gugluca (utente non iscritto) data: 28/06/2013 21:18:57

    Perfetto.
    Hai inquadrato il problema.
    Anche io pensavo ad uno o più cicli Vba.
    Conosco piuttosto bene il SQL, ma non trovavo soluzioni..
    Aiuto!



  • di Vecchio Frac data: 28/06/2013 21:26:51

    E' un bel problema.
    Ho piazzato i miei bravi bookmarks nei punti giusti ma non riesco a recuperare le righe tra due bookmarks.
    Sto guardando adesso GetRows ma non conosco a priori il numero di righe da recuperare :(





  • di Vecchio Frac data: 28/06/2013 21:37:19

    Ho prodotto questo codice.
    Il ragionamento non è complicato, lo è la traduzione :)
    In pratica cerca e trova tutti i campi che cominciano con "103" e hanno valore interno >= 20.000.000, come da specifica.
    Quindi demanda a una sub ricorsiva il compito di scorrere la tabella per cercare i valori "100*" precedenti e successivi a questi valori trovati.
    Nella sub ricorsiva si scorrono le righe e si inseriscono nella nuova tabella i valori che stanno tra questi due estremi, escluso l'ultimo, come da tua indicazione.
    Fai sapere :)
     
    Option Compare Database
    Option Explicit
    
    Sub leggi_a_blocchi()
    Dim rs As DAO.Recordset, i As Integer
    
        Set rs = CurrentDb.OpenRecordset("ORIG", Type:=dbOpenSnapshot)
        
        With rs
            .MoveLast
            .FindFirst "left(campo,3)='103' and mid(campo, 4, 8)>=20000000"
             
            If .NoMatch Then Exit Sub
    
            Debug.Print "Found " & rs!campo
            retrieve_100 rs
            
            
        End With
        Debug.Print "*End*"
        
    End Sub
    
    
    Sub retrieve_100(ByVal rs As DAO.Recordset)
    Dim bkm1 As Variant, bkm2 As Variant, s As String
             
        Do While True
            
            rs.FindPrevious "left(campo,3)='100'"
            Debug.Print "From " & rs!campo
            bkm1 = rs.Bookmark
            
            rs.FindNext "left(campo,3)='100'"
            Debug.Print "To " & rs!campo
            bkm2 = rs.Bookmark
            s = rs!campo
            
            rs.Bookmark = bkm1
            Do Until rs!campo = s
                DoCmd.RunSQL "INSERT INTO mod (campo) VALUES (" & rs!campo & ")"
                Debug.Print rs!campo; " added to table MOD"
                rs.MoveNext
            Loop
            
            rs.Bookmark = bkm2
            rs.FindNext "left(campo,3)='103' and mid(campo, 4, 8)>=20000000"
            If rs.NoMatch Then
                Exit Sub
            End If
            
            Debug.Print "Found " & rs!campo
        Loop
    
    End Sub
    






  • di Vecchio Frac data: 28/06/2013 21:38:24

    Ah, i diversi Debug.print li puoi eliminare, mi sono serviti solo per fare i test.





  • di Gugluca (utente non iscritto) data: 28/06/2013 21:42:37

    Ma sei stato rapidissimo!
    Ho dato un'occhiata e mi sembra tutto filare..
    Lunedì la provo in ufficio e ti dico.
    Se funziona ho risolto un grosso casino..

    Grazie ancora di tutto
    Buona serata e buon weekend

    Luca



  • di gugluca (utente non iscritto) data: 01/07/2013 14:13:02

    Ho testato il codice ma mi esce fuori un errore alla riga che riporto.
    Mi viene indicato: Errore di sintassi (operatore mancante) nell'espressione della query.
    Ho provato ad inserire la parola select ed in fondo from la tabella rs, ma evidentemente o sbaglio qualcosa o non è quello l'errore..
    Secondo te cosa potrebbe essere?

    Grazie per l'aiuto
    Ciao

    Luca
     
         DoCmd.RunSQL "INSERT INTO mod (campo) VALUES (" & rs!campo & ")"



  • di Gugluca (utente non iscritto) data: 01/07/2013 16:00:33

    Ho risolto mettendo i due apicetti (dovendo inserire un testo).
    Riporto il codice sotto.

     
         DoCmd.RunSQL "INSERT INTO mod (campo) VALUES ('" & rs!campo & "')"
    



  • di Vecchio Frac data: 01/07/2013 16:37:32

    Eh già, se mi collegavo prima te lo dicevo subito che ci volevano gli apici, essendo un campo di testo ^_^
    A me questo genere di errori capitano ogni volta, perchè me ne dimentico :)





  • di gugluca (utente non iscritto) data: 01/07/2013 16:46:27



    Ora però la seconda sub mi va in loop.. Non capisco come mai

    Il codice continua a ripetersi dal 'Do while true' fino all'ultimo Loop
    In sostanza non passa ad analizzare il successivo blocco di valori



  • di Vecchio Frac data: 01/07/2013 18:54:55

    rs.movenext è specificato?
    Puoi postare l'esempio dei dati che si inchioda? se non puoi qui, almeno in privato a staff@excelvba.it





  • di Gugluca (utente non iscritto) data: 02/07/2013 09:59:49

    Ciao!
    In che senso rs.movenext é impostata? Cosa intendi?
    Ho lasciato il comando rs.movenext nello stesso posto dove lo avevi inserito tu, non modificando o impostando altro...




  • di Vecchio Frac data: 02/07/2013 13:55:02

    Sì, intendevo quello.
    E' come se .NoMatch non venisse rilevato.
    Per questo ti chiedevo un pezzo della base dati.
    Perchè dalle mie prove (come dai tuoi primi post) e la tabella con i campi numerici così come descritti, tutto funziona.





  • di gugluca (utente non iscritto) data: 02/07/2013 16:04:03

    Ciao,
    ho allegato il file contenente il DB (tabella DB_ORIG, con solo due blocchi per semplicità)
    Nel modulo 2 è contenuto il codice.

    Grazie ancora per l'aiuto




  • di Vecchio Frac data: 02/07/2013 23:17:56

    Io ho notato una cosa che ti chiedo di verificare:
    nella tabella originale *non* ci sono record che soddisfano la condizione che tu hai impostato
    left(TESTO,3)='103' and mid(TESTO,4,8)='20120901'
    (tra parentesi, ho messo gli apici per sicurezza, perchè è sempre un campo di testo e ho visto che lo tratti come una data)
    Ho manipolato un po' i dati, modificando una delle righe che iniziano con '103' e forzando una data tipo '20120902' e tutto fila liscio ^_^





  • di gugluca (utente non iscritto) data: 03/07/2013 08:28:53

    Ciao!
    Come sempre grazie per l'aiuto..
    Ho modificato la condizione nel codice da 20120901 a 20000000 (in questo modo dovrebbe inserire nella tabella FINALE tutti e 2 i blocchi di valori) e il ciclo va in loop. In particolare, inserisce nella tabella il primo blocco di valori ma non il secondo (generando un loop).
    Ho anche provato a mettere il 20000000 fra apicetti, oppure a mettere 'val' per convertirlo in numero (visto che si tratta di un '>' mi sembrava corretto trattarlo come numero), ma il ciclo va sempre in loop.



  • di gugluca (utente non iscritto) data: 09/07/2013 11:15:00

    Risolto il problema inserendo nella tabella DB_ORIG una riga in fondo con inizio 100...
    In questo modo ho dato la fine della tabella...
    Ora tutto funziona al meglio.

    Ulteriore complicazione al problema, inserendo un'ulteriore condizione.
    Vorrei che venissero presi i blocchi che hanno una riga left(testo,3) = 103, con val(mid(TESTO, 4, 8))>=20120900, e che hanno una riga left(testo,3) = 102, con val(mid(TESTO, 20, 2))= 'LE'

    E' possibile una cosa del genere?

    Grazie ancora per l'aiuto
    Ciao

    Luca



  • di Vecchio Frac data: 09/07/2013 13:43:05

    cit. "In questo modo ho dato la fine della tabella... "
    ---> ma naturalmente! che stupido, avrei dovuto pensarci meglio. E dire che il codice l'ho fatto io ^_^
    rs.FindNext "left(campo,3)='100'"
    Ti chiedo scusa per averti fatto perdere tempo e scervellarti quasi inutilmente.

    Sulla tua ultima specifica, hai già provato?


     
    ...
            rs.Bookmark = bkm2
            rs.FindNext "left(campo,3)='103' and mid(campo, 4, 8)>='20120900' and left(campo,3)='102' and mid(campo, 20, 2) = 'LE' '"
            If rs.NoMatch Then
                Exit Sub
            End If
    ...






  • di gugluca (utente non iscritto) data: 09/07/2013 16:13:28

    Figurati! Grazie a te per l'aiuto che mi stai dando!

    Ho provato ad inserire il pezzetto di codice che mi hai suggerito, ma sembrerebbe inserire solo un blocco...

    Per quanto riguarda il codice precedente invece, non capisco perchè l'inserimento nella tabella 'FINALE' non lo fa sempre in ordine, o meglio, il codice sembrerebbe girare ordinato, ma quando visualizzo la tabella, la tabella non ha lo stesso ordine di quella originaria..
    Non capisco come mai. Secondo te cosa potrebbe essere?

    Grazie ancora per tutto



  • di gugluca (utente non iscritto) data: 10/07/2013 14:31:22

    Ciao,
    allego il database con l'esempio incriminato.
    In sostanza ci sono 3 blocchi. Eseguendo il codice (ho inserito >=20000001 per prendere tutti i 3 blocchi) vedrai che la tabella FINALE risulta popolata ma non nell'ordine che aveva nella tabella ORIG. Non so quale sia il motivo (anche perchè eseguendo il codice passo passo sembrerebbe che il ciclo funzioni bene)..

    Grazie ancora per l'aiuto

    Luca