Compilazione automatica campo in tabella

di il
14 risposte

Compilazione automatica campo in tabella

Buongiorno,

in un database Access 2019 (BE-FE) ho due tabelle: in una vengono inseriti i dati principali dei DDT fornitori (quindi ID fornitore, numero DDT, data emissione, link al documento pdf, importo e IDfattura), nell'altra inserisco  i dati principali delle fatture. Gli inserimenti avvengono in periodi differenti: i DDT vengono inseriti durante il mese in corso man mano che la merce viene consegnata, le fatture invece vengono inserite a distanza di uno mese e mezzo circa dal ricevimento merce. Dovendo “accoppiare” ogni DDT con la rispettiva fattura, vorrei effettuarlo in automatico flaggando i DDT che devono essere collegati alla fattura. 

Ogni fattura puo' avere da 1 a N DDT e nello stesso mese posso avere, piu' fatture dello stesso fornitore.

Avevo pensato ad una subform in visualizzazione foglio dati, nella from delle fatture, che mostrasse tutti i DDT del fornitore che non hanno IDfattura compilato, con un controllo non associato di tipo FLAG che, selezionandolo, copiasse, via codice, l'IDfattura nella tabella dei DDT; questo approccio pero' non funziona perche' il FLAG e' comune a tutti i records e selezionandone uno si flaggano tutti. Avevo provato anche un secondo approccio, mettendo il campo FLAG in tabella dei DDT e con una routine After Update copiare l'IDfattura nel modo seguente:

Private Sub frmDDqryFAflgaccoppia_AfterUpdate()
On Error GoTo Err_frmDDqryFAflgaccoppia_AfterUpdate

Dim rs As DAO.Recordset
Dim indice As Integer
    
    indice = Me.frmDDfrmFActridfatturacorrente  'indice = a ID fattura del recordo corrente
    Set rs = DBEngine(0)(0).OpenRecordset("SELECT * FROM tblDDddtfornitori WHERE IDtabDDid=" & Me.frmDDqryFActrIDtabDDid, dbOpenDynaset) ' apro record della tabella dei DDT che ha ID = ID del record corrente della subform

    If Me.frmDDqryFAflgaccoppia.Value = True Then 'se flag attivato
        With rs
            rs.Edit
            rs.Fields("NUMtabDDIDtabFAid") = indice 'copio ID fattura nel recordset
            rs.Update
        End With
    Else
        With rs
            rs.Edit
            rs.Fields("NUMtabDDIDtabFAid") = Null 'se flag disattivato elimino eventuale valore dal campo IDfattura
            rs.Update
        End With
    End If
    rs.Close
    Set rs = Nothing
    
Exit_frmDDqryFAflgaccoppia_AfterUpdate:
    Exit Sub

Err_frmDDqryFAflgaccoppia_AfterUpdate:
    MsgBox Err.Description
    Resume Exit_frmDDqryFAflgaccoppia_AfterUpdate

End Sub

Questa soluzione pero' mi da errore seguente:

Che tipo di soluzione potrei adottare (sempre che si possa fare)?

Grazie in anticipo 

14 Risposte

  • Re: Compilazione automatica campo in tabella

    18/02/2023 - Mailman ha scritto:


    ho due tabelle: in una vengono inseriti i dati principali dei DDT fornitori (quindi ID fornitore, numero DDT, data emissione, link al documento pdf, importo e IDfattura), nell'altra inserisco  i dati principali delle fatture.

    18/02/2023 - Mailman ha scritto:


    Ogni fattura puo' avere da 1 a N DDT e nello stesso mese posso avere, piu' fatture dello stesso fornitore.

    Se hai le relazioni Fornitori uno-a-molti Fatture e Fatture uno-a-molti DDT, è errato avere il campo IDFornitore nella tabella DDT.

  • Re: Compilazione automatica campo in tabella

    19/02/2023 - OsvaldoLaviosa ha scritto:


    Se hai le relazioni Fornitori uno-a-molti Fatture e Fatture uno-a-molti DDT, è errato avere il campo IDFornitore nella tabella DDT.

    Chiedo scusa, in realta' la relazione e' 0-N in quanto alcuni fornitori consegnano direttamente con fattura per cui non c'e' DDT. Ad ogni modo, anche fosse stata una relazione 1-N, il campo IDfornitore (semmai) era superfluo nella tabella delle fatture e non in quello dei DDT, visto che i DDT sono i primi che vengono inseriti…

  • Re: Compilazione automatica campo in tabella

    Hm… a dr la verità io vedo più logico il contrario. Cioè associare i ddt alle fatture e non il contrario. La fattura la generi usando i dati contenuti nei ddt e non il contrario. 

  • Re: Compilazione automatica campo in tabella

    20/02/2023 - fratac ha scritto:


    Hm… a dr la verità io vedo più logico il contrario. Cioè associare i ddt alle fatture e non il contrario. La fattura la generi usando i dati contenuti nei ddt e non il contrario. 

    ATTENZIONE: io mi sto riferendo alle fatture dei FORNITORI non a quelle verso i CLIENTI. 

    Credo che Tu ti riferisca alle fatture emesse che ovviamente vengono generate dai ddt. Non e' cio che devo realizzare.

    Io ricevo i DDT dai fornitori e, a seguire, ricevo le relative fatture. Per cui mi trovo con 80/90 DDT ogni mese da N fornitori che devo andare ad “accoppiare” con le rispettive fatture: per accoppiare io intendo che dal DDT devo poter risalire alla sua fattura e ovviamente dalla fattura a quali DDT e' riferita. Come spiegavo sopra, ora filtro i ddt per fornitore e per mese di competenza, poi dopo aver inserito la fattura, vado a copiare manualmente l'IDfattura nei relativi records  dei DDT. non e' detto che tutti i DDT filtrati si riferiscano alla stessa fattura, perche', come gia' indicato sopra, ho alcuni fornitori che emettono piu' fatture nello stesso mese.

    Vorrei provare ad automatizzare il tutto, come indicato nel primo post. 

  • Re: Compilazione automatica campo in tabella

    Supponendo che l'errore dipenda dal fatto che nella tabella ddt stai modificando contemporaneamente il campo flag (sei nell'after update) e quello idfattura (da codice) per lo stesso record potresti aggirarlo usando una listbox al posto della subform ddt nella form fatture che la carichi su form.current con tutti i ddt del fornitore per ddt.idFornitore = fat.idFornitore filtrando solo i ddt non associati a una fattura.

    Quindi l'utente seleziona i ddt della listbox e con un pulsante cicli i ddt selezionati e valorizzi l'id fattura per quelli; poi aggiorni la listbox e maschera.

     In questo modo non usi il flag.

    Magari puoi mantenere una subform ddt che ti mostri solo i ddt associati dalla procedura sopra 

  • Re: Compilazione automatica campo in tabella

    Mailman, io ho capito che hai una struttura tabelle così:
    Fornitori.IDFornitore uno-a-molti DDT.IDFornitore
    Fornitori.IDFornitore uno-a-molti Fatture.IDFornitore
    Ho capito bene?

    Poi, caso per caso, può succedere che arrivano:
    CasoA) molti DDT e poi la fattura
    CasoB) direttamente la fattura (che…include automaticamente il proprio DDT)
    CasoC) fattura senza DDT
    Ho capito bene?

    Prima di proseguire, dammi conferma di quello che ho scritto qui.

  • Re: Compilazione automatica campo in tabella

    21/02/2023 - OsvaldoLaviosa ha scritto:


    Mailman, io ho capito che hai una struttura tabelle così:
    Fornitori.IDFornitore uno-a-molti DDT.IDFornitore
    Fornitori.IDFornitore uno-a-molti Fatture.IDFornitore

    Corretto

    21/02/2023 - OsvaldoLaviosa ha scritto:


    Poi, caso per caso, può succedere che arrivano:
    CasoA) molti DDT e poi la fattura
    CasoB) direttamente la fattura (che…include automaticamente il proprio DDT)
    CasoC) fattura senza DDT

    Non ho capito cosa intendi per caso B (che scritto cosi' sembrerebbe uguale a caso C), penso che ti possa riferire a fattura che contiene un solo DDT.

    Se e' cosi', lo scenario e' completo.

  • Re: Compilazione automatica campo in tabella

    21/02/2023 - VBAndre ha scritto:


    Supponendo che l'errore dipenda dal fatto che nella tabella ddt stai modificando contemporaneamente il campo flag (sei nell'after update) e quello idfattura (da codice) per lo stesso record potresti aggirarlo usando una listbox al posto della subform ddt nella form fatture che la carichi su form.current con tutti i ddt del fornitore per ddt.idFornitore = fat.idFornitore filtrando solo i ddt non associati a una fattura.

    Quindi l'utente seleziona i ddt della listbox e con un pulsante cicli i ddt selezionati e valorizzi l'id fattura per quelli; poi aggiorni la listbox e maschera.

    Grazie VBAndre, ho seguito il tuo consiglio e' ho testato la listbox funziona perfettamente.

    Nel pulsante ho inserito il seguente codice:

    Private Sub frmFAcmdcopiaidfattura_Click()
    On Error GoTo Err_frmFAcmdcopiaidfattura_Click
    
    Dim ctl As Control
    Dim varItm As Variant
    Dim rs As DAO.Recordset
    Dim indice As Integer
        
        indice = Me.frmFActrIDtabFAid  'indice = a ID fattura del record corrente
        Set ctl = Me.frmFAlstIDtabDDid  'ctl = listbox dei ddt
        For Each varItm In ctl.ItemsSelected
            Set rs = DBEngine(0)(0).OpenRecordset("SELECT * FROM tblDDddtfornitori WHERE IDtabDDid=" & ctl.ItemData(varItm), dbOpenDynaset) ' apro record della tabella dei DDT selezionati
            With rs
                rs.Edit
                rs.Fields("NUMtabDDIDtabFAid") = indice 'copio ID fattura nel recordset
                rs.Update
            End With
        Next varItm
        rs.Close
        Set rs = Nothing
        
        Me.sfrmFAqryFAaccoppiamentoddt.requery   ' aggiorno subform DDT collegati
    
    Exit_frmFAcmdcopiaidfattura_Click:
        Exit Sub
    
    Err_frmFAcmdcopiaidfattura_Click:
        MsgBox Err.Description
        Resume Exit_frmFAcmdcopiaidfattura_Click
    
    End Sub
    

    21/02/2023 - VBAndre ha scritto:


    Magari puoi mantenere una subform ddt che ti mostri solo i ddt associati dalla procedura sopra

    Si' infatti avevo gia' una subform con i DDT collegati

    Grazie ancora

  • Re: Compilazione automatica campo in tabella

    21/02/2023 - Mailman ha scritto:


    21/02/2023 - OsvaldoLaviosa ha scritto:


    Mailman, io ho capito che hai una struttura tabelle così:
    Fornitori.IDFornitore uno-a-molti DDT.IDFornitore
    Fornitori.IDFornitore uno-a-molti Fatture.IDFornitore

    Corretto

    21/02/2023 - OsvaldoLaviosa ha scritto:


    Poi, caso per caso, può succedere che arrivano:
    CasoA) molti DDT e poi la fattura
    CasoB) direttamente la fattura (che…include automaticamente il proprio DDT)
    CasoC) fattura senza DDT

    Non ho capito cosa intendi per caso B (che scritto cosi' sembrerebbe uguale a caso C), penso che ti possa riferire a fattura che contiene un solo DDT.

    Se e' cosi', lo scenario e' completo.

    Io continuo a leggere che si parla di UNA Fattura e di MOLTI DDT legati a una fattura. Solo questo concetto dovrebbe giustificare la relazione Fatture uno-a-molti DDT.
    Ma hai detto che capita che il Fornitore spicca prima qualche DDT e la Fattura “matura” dopo. Io questa “storia" la interpreto come un UNICO-DISCORSO e come unico-discorso lo chiamerei FORNITURA e chiamerei una tabella Forniture (molto simile a Ordini). Riepilogando io strutturerei le tabelle così:
    Fornitori.IDFornitore uno-a-molti Forniture.IDFornitore
    Forniture.IDFornitura uno-a-molti DocumentiForniture.IDFornitura

    Nella tabella Forniture metti un campo TipoDocumento che specifica se si tratta di Fattura o DDT.

  • Re: Compilazione automatica campo in tabella

    21/02/2023 - Mailman ha scritto:

    Private Sub frmFAcmdcopiaidfattura_Click()
    On Error GoTo Err_frmFAcmdcopiaidfattura_Click
    
    Dim ctl As Control
    Dim varItm As Variant
    Dim rs As DAO.Recordset
    Dim indice As Integer
        
        indice = Me.frmFActrIDtabFAid  'indice = a ID fattura del record corrente
        Set ctl = Me.frmFAlstIDtabDDid  'ctl = listbox dei ddt
        For Each varItm In ctl.ItemsSelected
            Set rs = DBEngine(0)(0).OpenRecordset("SELECT * FROM tblDDddtfornitori WHERE IDtabDDid=" & ctl.ItemData(varItm), dbOpenDynaset) ' apro record della tabella dei DDT selezionati
            With rs
                rs.Edit
                rs.Fields("NUMtabDDIDtabFAid") = indice 'copio ID fattura nel recordset
                rs.Update
            End With
        Next varItm
        rs.Close
        Set rs = Nothing
        
        Me.sfrmFAqryFAaccoppiamentoddt.requery   ' aggiorno subform DDT collegati
    
    Exit_frmFAcmdcopiaidfattura_Click:
        Exit Sub
    
    Err_frmFAcmdcopiaidfattura_Click:
        MsgBox Err.Description
        Resume Exit_frmFAcmdcopiaidfattura_Click
    
    End Sub
    

    Trovo poco ottimizzato, anzi per nulla, il codice.

    Nel LOOP continui ad interrogare la Tabella aprendo il Recordset… a mio avviso conviene costruire il CRITERIO ed eseguire una ACTION QUERY solo 1 volta…

    	Dim indice As Long
        Dim sWHR As String
        
    	indice = Me.frmFActrIDtabFAid  'indice = a ID fattura del record corrente
        For Each varItm In Me.frmFAlstIDtabDDid.ItemsSelected
        	sWHR=sWHR & ctl.ItemData(varItm) & ";"
        Next
        If Len(sWHR)>0 Then
        	sWHR=Mid$(sWHR,1,Len(sWHR)-1) ' Tolgo l'ultimo [;]
        	sWHHR="UPDATE tblDDddtfornitori  SET NUMtabDDIDtabFAid=" & Indice & " WHERE IDtabDDid IN (" sWHR & ")"
        	DbEngine(0)(0).EXECUTE sWHR
       	End If
       	
       	Me.sfrmFAqryFAaccoppiamentoddt.requery

    Come vedi è tutto molto più snello…

    Fai attenzione a come dichiari le variabili, [Indice] lo dichiari INTEGER, ma se il campo ID è Counter, è un errore, devi dichiararlo LONG.

  • Re: Compilazione automatica campo in tabella

    22/02/2023 - @Alex ha scritto:


    Trovo poco ottimizzato, anzi per nulla, il codice.

    Grazie Alex per la risposta, purtroppo la mia conoscenza di VBA e' molto limitata per cui cerco di programmare in base alle mie conoscenze (molto basiche).

    Ho modificato il tuo codice come segue perche' c'erano alcune inesattezze (sicuramente per non fornire la “pappa pronta”): 

    1) al posto del punto e virgola ho messo la virgola perche' mi dava errore nell' esecuzione della query (l'operatore IN chiede la virgola di separazione fra i valori)

    2) mancava la dichiarazione del ctl.Itemdata

    3) La WHERE condition mancava di un &

    Comunque grazie, ho imparato un'altro pezzettino di VBA

    Dim indice As Long
    Dim sWHR As String
        
        indice = Me.frmFActrIDtabFAid  'indice = a ID fattura del record corrente
        Set ctl = Me.frmFAlstIDtabDDid
            For Each varItm In Me.frmFAlstIDtabDDid.ItemsSelected
                sWHR = sWHR & ctl.ItemData(varItm) & ","
            Next
        If Len(sWHR) > 0 Then
            sWHR = Mid$(sWHR, 1, Len(sWHR) - 1) ' Tolgo l'ultima [,]
            sWHR = "UPDATE tblDDddtfornitori  SET NUMtabDDIDtabFAid=" & indice & " WHERE IDtabDDid IN (" & sWHR & ")"
            Debug.Print sWHR
            DBEngine(0)(0).Execute sWHR
        End If
        
        Me.sfrmFAqryFAaccoppiamentoddt.Requery
    

    22/02/2023 - @Alex ha scritto:


    Fai attenzione a come dichiari le variabili, [Indice] lo dichiari INTEGER, ma se il campo ID è Counter, è un errore, devi dichiararlo LONG

    Ho corretto anche la dichiarazione perche' giustamente un counter potrebbe arrivare a numeri molto elevati; non sarebbe comunque stato questo il caso perche' probabilmente prima di arrivare a 32.767 fatture inserite (equivalenti a circa 90 anni), il database sara' gia' finito nel bidone.

    Grazie ancora Alex

  • Re: Compilazione automatica campo in tabella

    Scusa Alex, volevo chiederti una chiarimento perche' non sono riuscito a trovare nulla riguardo all'operatore Mid seguito dal [$]: che funzione ha il $?

  • Re: Compilazione automatica campo in tabella

    22/02/2023 - Mailman ha scritto:


    Scusa Alex, volevo chiederti una chiarimento perche' non sono riuscito a trovare nulla riguardo all'operatore Mid seguito dal [$]: che funzione ha il $?

    Mi permetto di inserirmi perchè mi sono inbattuto in quest'argomento qualche tempo fa.

    Stando a questo articolo Mid e altre funzioni sono ottimizzate per gestire variabili di tipo Variant e risultano poco performanti quando hanno a che fare con stringhe. In questi casi, stando all'articolo, le stesse funzioni con il suffisso $ sono più veloci ma è necessario dichiarare le varibili che gli dai in pasto come stringhe.

  • Re: Compilazione automatica campo in tabella

    Perfetta spiegazione VBAndre.

Devi accedere o registrarti per scrivere nel forum
14 risposte