Trova primo numero disponibile

di il
7 risposte

Trova primo numero disponibile

Buongiorno, avrei bisogno di un aiuto per scrivere qualche riga di codice VBA.

Ho una tabella denominata tblNominativi. All'interno i seguenti campi: IdNominativo(num. automatica), NumeroTessera(numerico), Cognome(testo breve), Nome(testo breve)

In una maschera denominata frmInserisciNominativi, vado ad inserire nella tblNominativi i nuovi record.

Il mio problema è che devo riuscire a far comparire nella TextBox (non associata) txtNumeroTessera (presente all'interno della frmInserisciNominativi) il primo numero disponibile, interrogando il campo NumeroTessera della tblNominativi.

Immagino che bisognerebbe aprire un RecordSet, ordinarlo in base all'ordine crescente, assegnare ad una variabile X il valore del campo NumeroTessera del primo Record (attualmente ordinato) e confrontare, attraverso un ciclo, il record attuale con quello successivo (o precedente). Se successivo è maggiore di più di 1 rispetto a quello attuale allora assegna alla variabile Y il valore attuale + 1. Infine valorizza la txtNumeroTessera con la variabile Y.

Credo che a grandi linee sia questo il ragionamento. Ora io ho provato a scrivere qualche linea di codice:
Private Sub Form_Open(Cancel As Integer)
Dim X As Integer, Y As Integer, W As Integer

	Set rs = CurrentDb.OpenRecordset("SELECT NumeroTessera FROM tblNominativi")
        
        OrderByOn = False
        OrderBy = rs(0)
        OrderByOn = True
        
        X = rs(0)
        
        rs.MoveFirst
        
        Do Until rs.EOF
	
        	'QUI DOVREI FARE UNA COMPARAZIONE TRA IL CAMPO NumeroTessera DEL RECORD ATTUALE E QUELLO SUCCESSIVO (o precedente)
 		'SE VALORE DEL CAMPO NumeroTessera DEL RECORD SUCCESSIVO RISULTA MAGGIORE DI 2 NUMERI RISPETTO A QUELLO ATTUALE ALLORA
 		'VARIABILE W RISULTA = A VALORE CAMPO NumeroTessera ATTUALE + 1
 		
            	txtNumeroTessera.Value = W
                
            End If
        rs.MoveNext
        Loop
        
        rs.Close
        Set rs = Nothing
End Sub
Facendo un esempio descrittivo:

Id -------NumeroTessera---------Cognome-------------Nome
1--------------1----------------------AAAAA---------------AAAAAA
2--------------7----------------------BBBBB---------------BBBBBBB
3--------------6----------------------CCCCC--------------CCCCCCC
4--------------5----------------------DDDDD--------------DDDDDDD

ORDINAMENTO:


Id -------NumeroTessera---------Cognome-------------Nome
1--------------1----------------------AAAAA---------------AAAAAA
4--------------5----------------------DDDDD--------------DDDDDDD
3--------------6----------------------CCCCC--------------CCCCCCC
2--------------7----------------------BBBBB---------------BBBBBBB

RISULTATO:

Primo numero che deve comparire nella txtNumeroTessera deve essere il 2 visto che dopo il numero 1 c'è subito il numero 5.

Immagino che il mio codice sia pieno di errori e confusione e che la strada non sia quella giusta. A tal proposito qualcuno mi può suggerire il codice corretto o almeno qualche riga?

Grazie a tutti

7 Risposte

  • Re: Trova primo numero disponibile

    Si hai ragionato in modo corretto... il codice però... no.

    Io fare in acosa simile:
    
    Private Sub Form_Load()
        me!txtNumeroTessera.Value=GetFirstFree()
    End Sub
    
    Function GetFirstFree() As Long
        Dim lLast       As Long
        
        Set rs = CurrentDb.OpenRecordset("SELECT NumeroTessera FROM tblNominativi ORDER BY NumeroTessera")
            lLast = rs.Fields(0)
            Do Until rs.EOF
                
                If (rs.Fields(0) - lLast) > 1 Then
                    Exit Do
                Else
                    lLast = rs.Fields(0)
                End If
                    
                rs.MoveNext
            Loop
            
            GetFirstFree = lLast + 1
            rs.Close
            Set rs = Nothing
    
    End Function
    Se serve lo commentiamo...
  • Re: Trova primo numero disponibile

    Grazie mille per la risposta immediata e per il suggerimento che mi hai fornito.

    Credo di aver di aver capito bene il codice:
    Private Sub Form_Load()
        me!txtNumeroTessera.Value=GetFirstFree() ------->Mia textbox assume il valore della funzione GetFirstFree()
    End Sub
    
    Function GetFirstFree() As Long
        Dim lLast As Long
        
        Set rs = CurrentDb.OpenRecordset("SELECT NumeroTessera FROM tblNominativi ORDER BY NumeroTessera") ---->Apro RecordSet e lo ordino in base al campo NumeroTessera
        
            lLast = rs.Fields(0) ----> Variabile lLast uguale al contenuto del campo NumeroTessera del primo record 
            Do Until rs.EOF ------>Fai finché non sei alla fine del file
                
                If (rs.Fields(0) - lLast) > 1 Then ------> Se valore campo NumeroTessera del record successivo meno valore variabile lLast (record precedente) è maggiore di 1 allora....
                
                    Exit Do ----->Esci dal ciclo 
                Else -------> altrimenti
                    lLast = rs.Fields(0) ----->Variabile lLast è uguale al valore del campo analizzato
                End If
                    
                rs.MoveNext ----->Muoviti al prossimo record
            Loop ------->Ripeti il DO
            
            GetFirstFree = lLast + 1------>Funzione GetFirstFree assume come valore la variabile lLast + 1
            rs.Close ------>Chiudi recorsdet
            Set rs = Nothing ------>Distruggi recordset
    
    End Function
    Spero di aver interpretato bene il tuo codice. Devo dire che una funzione è anche meglio, così posso richiamarla in altri momenti se mi dovesse servire.

    Cmq ho provato e funziona ma ovviamente se non ci sono Record in tabella mi mostra la schermata di Errore di mancanza Record. Come posso gestire questo errore?

    Pensavo a qualcosa del genere:
    If IsNull(rs.Fields(0)) = True Then
    Ma non saprei se è la strada giusta.

    Devo far in modo che quando apro la maschera per l'inserimento dei nuovi dati, se non esistono record allora la txtNumeroTessere si deve valorizzare con il numero 1, dopo che chiaramente la Function GetFirstFree ha effettuato il suo controllo.

    Grazie......spero di concludere questo progetto.
  • Re: Trova primo numero disponibile

    Ovvio... non ho inserito né la gestione errori né il controllo EmptyTable...

    Quando apri il recordset verifica se EOF e BOF dell'oggetto recordset sono entrambe vere... in questo caso il rs è vuoto...
    
    Function GetFirstFree() As Long
        Dim lLast As Long
        
        Set rs = CurrentDb.OpenRecordset("SELECT NumeroTessera FROM tblNominativi ORDER BY NumeroTessera") ---->Apro RecordSet e lo ordino in base al campo NumeroTessera
         If Not( rs.EOF And rs.BOF ) then
            lLast = rs.Fields(0) ----> Variabile lLast uguale al contenuto del campo NumeroTessera del primo record 
            Do Until rs.EOF ------>Fai finché non sei alla fine del file
                
                If (rs.Fields(0) - lLast) > 1 Then ------> Se valore campo NumeroTessera del record successivo meno valore variabile lLast (record precedente) è maggiore di 1 allora....
                
                    Exit Do ----->Esci dal ciclo 
                Else -------> altrimenti
                    lLast = rs.Fields(0) ----->Variabile lLast è uguale al valore del campo analizzato
                End If
                    
                rs.MoveNext ----->Muoviti al prossimo record
            Loop ------->Ripeti il DO
        Else
            lLast=0 ---> se per te il primo valore utile è 1
        End if
            GetFirstFree = lLast + 1------>Funzione GetFirstFree assume come valore la variabile lLast + 1
            rs.Close ------>Chiudi recorsdet
            Set rs = Nothing ------>Distruggi recordset
    
    End Function
    
    Metti la gestione errori...
  • Re: Trova primo numero disponibile

    Perfetto, grazie. Adesso tutto funziona bene. Ho solo dovuto inserire un paio di righe di codice per verificare se manca nel campo NumeroTessera il numero 1.

    In pratica, secondo la funzione GetFirstFree, se in tabella il primo record ha nel campo NumeroTessera il numero 2, succede che il primo numero disponibile per il prossimo inserimento di record è il 3
    rs.Field(0) - lLast = 0 '(campo del record attuale 2 - campo record precedente sempre 2 = 0 quindi minore di 1 allora la variabile lLast diventa 3 perché 2+1)
    Quindi ho inserito il codice:
    If rs.Fields(0) = 1 Then
    -----------------
    -----------------
    -----------------
    Else
    	GetFirstFree = lLast
    End If
    -----------------
    ----------------
    
    In questo modo controllo che se il campo del primo record è diverso da 1 allora la funzione GetFirstFree assume valore 1 (lLast = 0 + 1 come valorizzata precedentemente).

    Così funziona tutto a meraviglia. Spero di aver descritto bene la mia spiegazione e che abbia risolto in modo corretto.
  • Re: Trova primo numero disponibile

    Forse basta mettere
    
    lLast = 0
  • Re: Trova primo numero disponibile

    Ottimo, allora ho risolto così
    If rs.Fields(0) <> 1 Then lLast = 0
    Direi che il 3D si può considerare concluso. Grazie come sempre Alex (a proposito: come si chiude e si spunta RISOLTO il 3D? )
  • Re: Trova primo numero disponibile

    alexps81 ha scritto:


    Ottimo, allora ho risolto così
    If rs.Fields(0) <> 1 Then lLast = 0
    Direi che il 3D si può considerare concluso. Grazie come sempre Alex (a proposito: come si chiude e si spunta RISOLTO il 3D? )
    Hai provato a mettere SOLO:
    lLast = 0
    Non si mette risolto...
Devi accedere o registrarti per scrivere nel forum
7 risposte