Gestione recordset - FindFirst / FindNext

di il
12 risposte

Gestione recordset - FindFirst / FindNext

Ciao a tutti.

Ho un problema con la seguente parte di codice mentre opero su un recordset:

Set Tabella = CurrentDb.OpenRecordset("tblFornitoriOrdiniDett", dbOpenSnapshot)
With Tabella
     .FindFirst "IDOrdine=" & CInt(Forms!frmOrdini01!txtIDOrdine)
     
     Do Until .EOF
          Debug.Print !IDOrdineDett
     
          If !Evaso = -1 Then
               If !Quantita = !QtaEvasa Then
                    
                    DBEngine(0)(0).Execute ("UPDATE tblFornitoriOrdiniDett SET [DataEvas]=" & CLng(DataEvas) & ", [DDTNr]='" & DDT & "' WHERE [IDOrdineDett]=" & !IDOrdineDett), dbFailOnError
                    
               End If
          End If
          
          .FindNext "IDOrdine=" & CInt(Forms!frmOrdini01!txtIDOrdine)
     Loop
End With

Tabella.Close
Set Tabella = Nothing

Lo scopo  è di aggiornare la tabella sulla base del campo SI/NO !Evaso.

Funziona, solo che giunto all'ultimo record di interesse (cioè il gruppo di record identificato con !IDOrdine), invece di uscire dal loop lo continua all'infinito continuando a rimanere sull'ultimo record selezionato (lo identifico in debug dal campo !IDOrdineDett).

Dove sbaglio?

Grazie

Andrea

12 Risposte

  • Re: Gestione recordset - FindFirst / FindNext

    È ovvio che non esce mai dal loop. Stai ciclando sempre sullo stesso valore. Controlla la condizione indicata in FindFirst e FindNext.

  • Re: Gestione recordset - FindFirst / FindNext

    Sei obbligato ad usare FindFirst/FindNext?

    Se non sei obbligato fai una  cosa più pulita : ottieni un recordset già filtrato con SOLO gli ID che ti servono …

    Set Tabella = CurrentDb.OpenRecordset("Select * from tblFornitoriOrdiniDett where IDOrdine = " & CInt(Forms!frmOrdini01!txtIDOrdine), dbOpenSnapshot)

    e poi scorri il recordset ottenuto …

    do while not tabella.eof
    	... fai quell che devi fare
    	tabella.movenext
    	doevents
    loop

    Poi se vuoi fare una cosa ancora più sensata fai l'aggiornato utilizzando direttamente SQL (Update … where …) senza dover scorrere il recordset e poi aggiornare singolarmente i records.

  • Re: Gestione recordset - FindFirst / FindNext

    Ciao, 

    domanda … perchè non filtri la tabella invece di utilizzare il find ?

    non potresti aprire il recordset con la SELECT tabella WHERE  = IDOrdine ? 

    e poi fai un semplice Do While Not Recordset.Eof  / DBEngine Update / recordset.MoveNext / Loop 

  • Re: Gestione recordset - FindFirst / FindNext

    20/10/2023 - max.riservo ha scritto:


    Sei obbligato ad usare FindFirst/FindNext?

    Ciao Max… scusa ma non ti avevo visto, ci siamo accavallati ;-)

  • Re: Gestione recordset - FindFirst / FindNext

    20/10/2023 - By65Franco ha scritto:


    20/10/2023 - max.riservo ha scritto:


    Sei obbligato ad usare FindFirst/FindNext?

    Ciao Max… scusa ma non ti avevo visto, ci siamo accavallati ;-)

    Ciao Franco … tu è megl ke uan (dicesa così una nota pubblicità)  :)

    @Jocman : chiamare Tabella un recordset è un poco destabilizzante. Anche la nomenclatura adeguata aiuta nella manutenzione (oltre che nella progettazione) del sw …

  • Re: Gestione recordset - FindFirst / FindNext

    20/10/2023 - max.riservo ha scritto:


    Ciao Franco … tu è megl ke uan (dicesa così una nota pubblicità)  :)

    @Jocman : chiamare Tabella un recordset è un poco destabilizzante. Anche la nomenclatura adeguata aiuta nella manutenzione (oltre che nella progettazione) del sw …

    Decisamente si, almeno un minimo … sante parole.  

    Probabilmente è alle prime armi ;-)    

  • Re: Gestione recordset - FindFirst / FindNext

    20/10/2023 - Antony73 ha scritto:


    È ovvio che non esce mai dal loop. Stai ciclando sempre sullo stesso valore. Controlla la condizione indicata in FindFirst e FindNext.

    Si ciclo sempre sullo stesso valore, cioè quello che accomuna tutti i record di quell'ordine (!IDOrdine); ma mi aspetterei che una volta esauriti i record con quel valore !IDOrdine (e quindi nella condizione .EOF) esca dal loop. 

    Quello che mi figuro è che:

    • Apre la tabella e la scorre fino a trovare il primo !IDOrdine (e quindi il .FindFirst)
    • Fa quello che deve fare
    • Cerca il prossimo record con lo stesso !IDOrdine (e quindi il .FindNext)
    • Giunto all'ultimo di quei record continua a cercare, non trova più nulla ed esce

    Ma invece rimane sempre sull'ultimo trovato.

    @Max e @By65Franco:

    Si effettivamente potrei limitare il recordset in quel modo e evito la problematica FindFirst/FindNext

  • Re: Gestione recordset - FindFirst / FindNext

    20/10/2023 - Jocman ha scritto:


    Quello che mi figuro è che:

    • Apre la tabella e la scorre fino a trovare il primo !IDOrdine (e quindi il .FindFirst)
    • Fa quello che deve fare
    • Cerca il prossimo record con lo stesso !IDOrdine (e quindi il .FindNext)
    • Giunto all'ultimo di quei record continua a cercare, non trova più nulla ed esce

    Ma invece rimane sempre sull'ultimo trovato.

    @Max e @By65Franco:

    Si effettivamente potrei limitare il recordset in quel modo e evito la problematica FindFirst/FindNext

    In pratica non ti esce dal loop perchè non si verifica mai Eof 

    rimani sempre sull'Id che stai cercando.

  • Re: Gestione recordset - FindFirst / FindNext

    20/10/2023 - Jocman ha scritto:


    Si effettivamente potrei limitare il recordset in quel modo e evito la problematica FindFirst/FindNext

    Un classico ciclo dovrebbe essere una cosa di questo tipo:

    ' open recordset
    Dim rs As DAO.Recordset
    Set rs = DBEngine(0)(0).OpenRecordset("SELECT * FROM tuaTabella WHERE tuaCondizione;")
    ' read
    Do While Not rs.EOF
        ' update recordset
        DBEngine(0)(0).Execute ("Update ...... ;")
        ' record next
        rs.MoveNext
    Loop
    ' close
    rs.Close
    Set rs = Nothing

    Però direi che non hai bisogno di ciclare i records e aggiornarli …. puoi semplicemente farlo con una unica istruzione del tipo 

    DBEngine(0)(0).Execute ("Update ...... ;") 

    dove imposti la tua Where Condition per aggiornare solo i records che ti interessano

    Quindi a questo punto scriverai solo una semplice riga di codice e il gioco è fatto

  • Re: Gestione recordset - FindFirst / FindNext

    In questo caso specifico che il Rst di Loop è lo stesso da editare a mio avviso si sta facendo un discreto errore di concetto.

    Questo il Codice proposto da [Jokman] che come si vede apre un Rst basato su tblFornitoriOrdiniDett, poi fa una Query Action di Update interna al Loop sempre su tblFornitoriOrdiniDett

    Set Tabella = CurrentDb.OpenRecordset("tblFornitoriOrdiniDett", dbOpenSnapshot)
    With Tabella
         .FindFirst "IDOrdine=" & CInt(Forms!frmOrdini01!txtIDOrdine)
         Do Until .EOF
              Debug.Print !IDOrdineDett
              If !Evaso = -1 Then
                   If !Quantita = !QtaEvasa Then
                        DBEngine(0)(0).Execute ("UPDATE tblFornitoriOrdiniDett SET [DataEvas]=" & CLng(DataEvas) & ", [DDTNr]='" & DDT & "' WHERE [IDOrdineDett]=" & !IDOrdineDett), dbFailOnError
                   End If
              End If
              .FindNext "IDOrdine=" & CInt(Forms!frmOrdini01!txtIDOrdine)
         Loop
    End With
    Tabella.Close
    Set Tabella = Nothing

    Non è completamente insensato secondo voi…?

    Apro il Rs filtrando subito i dati come suggerito sopra, e li edito mentre li ciclo… “WHAT ELSE”…?
    Se penso sia lento inglobo il tutto in una TRANSAZIONE così lavoro in memoria ed accedo all'UpdateBatch in un solo colpo quando faccio il COMMIT.

    ' open recordset
    Dim rs As DAO.Recordset
    Set rs = DBEngine(0)(0).OpenRecordset("SELECT * FROM tuaTabella WHERE IDOrdine= & CInt(Forms!frmOrdini01!txtIDOrdine)
    Do While Not rs.EOF
        rs.Edit
        ![DataEvas]=CLng(DataEvas)
        rs.Update
        rs.MoveNext
    Loop
    Close
    rs.Close
    Set rs = Nothing

    Con transazione:

    Public Function XXX()...
    	Dim rs As DAO.Recordset
    
    	On Error Goto Err_Handler
    	Set rs = DBEngine(0)(0).OpenRecordset("SELECT * FROM tuaTabella WHERE IDOrdine= & CInt(Forms!frmOrdini01!txtIDOrdine)
    	rs.MoveFirst
    	DBEngine(0).BeginTrans
    	Do While Not rs.EOF
        	rs.Edit
        	![DataEvas]=CLng(DataEvas)
        	rs.Update
        	rs.MoveNext
    	Loop
    	DBEngine(0).CommitTrans
    Exit_HEre:
    	On Error Resume Next
    	rs.Close
    	Set rs = Nothing
    	Exit Function
    Err_Handler:
    	DBEngine(0).RollBack
    	Resume Exit_HEre
    End Function

    Saluti…

  • Re: Gestione recordset - FindFirst / FindNext

    20/10/2023 - Jocman ha scritto:


    Si effettivamente potrei limitare il recordset in quel modo e evito la problematica FindFirst/FindNext

    Ed è così che si fa, vai ad aprire un recordset inutilmente più grande per poi cercare le varie occorrenze. Detto questo, avanti.

    Quello che mi figuro è che:

    • Apre la tabella e la scorre fino a trovare il primo !IDOrdine (e quindi il .FindFirst)
    • Fa quello che deve fare
    • Cerca il prossimo record con lo stesso !IDOrdine (e quindi il .FindNext)
    • Giunto all'ultimo di quei record continua a cercare, non trova più nulla ed esce

    Ma invece rimane sempre sull'ultimo trovato.

    No, non funziona così. Con i vari tipi di Find (first, last, next, previous) si verifica il NoMatch.

    https://learn.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/recordset-findnext-method-dao

    If a record matching the criteria isn't located, the current record pointer is unknown, and the NoMatch property is set to True. If recordset contains more than one record that satisfies the criteria, FindFirst locates the first occurrence, FindNext locates the next occurrence, and so on.

    Always check the value of the NoMatch property to determine whether the Find operation has succeeded. If the search succeeds, NoMatch is False. If it fails, NoMatch is True and the current record isn't defined.

    (leggi anche il resto della pagina per avere il quadro completo)

  • Re: Gestione recordset - FindFirst / FindNext

    Grazie a tutti del supporto. E ho imparato (più o meno) qualcosa sul concetto di transazione.

    @Phil

    Hai ragione. Non usando da molto tempo quelle funzioni mi ero dimenticato che andavano associate alla verifica del match sulla ricerca.

    Andrea

Devi accedere o registrarti per scrivere nel forum
12 risposte