Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    7

    [VBA Access] Duplicare un record nello stesso recordset

    Buongiorno a tutti,
    dovrei duplicare un record nello stesso recordset, in pratica dovrei creare in base ad alcune condizioni un pagamento di una scadenza es.

    ----------------------------------------------------------
    Dim x As DAO.Recordset
    Set x = Me.Sottomaschera_Pagamenti_Query.Form.Recordset
    Dim c As Integer 'contatore


    If x.EOF Then Exit Sub Else GoTo avanti
    avanti:
    ' definiamo quanti record sono selezionati
    x.MoveFirst
    c = 0
    ' definisce se il record è selezionato
    Do Until x.EOF
    If x("selezione") = -1 Then GoTo s1 Else GoTo n1
    s1:
    c = c + 1
    n1:
    MoveNext
    Loop
    Select Case c

    Case Is = 0 ' nessuna selezione
    MsgBox "Nessuna selezione effettuata"

    Case Is = 1 ' un solo record
    ' duplicare il record invertendo il segno di pagamento
    -----------------------------------------------------------------
    Ora per trovare il record potrei utilizzare "seek" oppure "findfirst" ma vorrei sapere se c'è la possibilità di duplicare il record trovato senza memorizzare campo per campo con le variabili (sono più di 20) e senza violare l'integrità del contatore.
    Spero di essere stato chiaro.
    Ringrazio tutti quelli che potranno aiutarmi.
    Saluti
    El Chorro

  2. #2
    Utente di HTML.it L'avatar di gibra
    Registrato dal
    Apr 2008
    residenza
    Italy
    Messaggi
    4,244
    Piuttosto che andarsi a leggere tutto il recordset, la cosa più semplice è quella di fare una sola INSERT INTO in base alle <condizioni> che individuano il record, o più record, nella tabella.

    Per impostare un valore negativo basta moltiplicare il valore per -1

    Ti consiglio di consultare la guida per la INSERT INTO perchè vi sono vari modi di usarla, ad esempio la seguente istruzione inserisce un gruppo di record da una tabella diversa (la struttura deve essere identica, ovviamente):

    codice:
    dbs.Execute "INSERT INTO Clienti " _
        & "SELECT * " _
        & "FROM [Nuovi clienti];"
    Puoi utilizzare gli alias per inserire record presi dalla stessa tabella:
    codice:
    dbs.Execute "INSERT INTO Clienti " _
        & "SELECT * " _
        & "FROM Clienti C;"
    In questo caso C è l'alias per la tabella Clienti.
    N.B. ATTENTO! In questo caso, l'istruzione raddoppia tutti i record!!!!

    Puoi aggiungere una condizione WHERE alla SELECT precedente in modo da selezionare
    codice:
    dbs.Execute "INSERT INTO Clienti " _
        & "SELECT * " _
        & "FROM Clienti C " _
        & "WHERE Selezione=-1;"
    Raddoppia i record in cui il campo Selezione è Vero.


    Quindi, il mio consiglio è
    - apri il database in ambiente MSAccess
    - duplica la tua tabella, su cui farai le prove (così non comprometti i dati originali)
    - con il QBE di Access ti crei prima la SELECT che restituisce solo i record che vuoi duplicare
    - prendi la stringa (Struttura SQL) e gli anteponi l'istruzione "INSERT INTO <nometabella> "
    - esegui la query e vedi se il risultato è quello desiderato
    - se non lo è cancelli la tabella di prova, la ricrei e aggiusti la query
    Nel caso torna qui è chiedi aiuto di nuovo mostrando la query completa.


  3. #3
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    7
    ------------------------------------------------------------
    Select Case c
    Case Is = 0 ' nessuna selezione
    MsgBox "Nessuna selezione effettuata"

    Case Is = 1 ' un solo record

    'INSERT INTO

    Case Is > 1
    'sommare l'importo dei pagamenti selezionati

    do until x.eof
    if x("selettore") = -1 then p = 0 + p else p= x("importo") + p
    x.movenext
    loop

    End Select
    ---------------------------------------------------------------
    Ti ringrazio della risposta, proverò di sicuro il metodo INSERT INTO nella selezione di un singolo pagamento.
    Il problema è che il codice VBA lo devo usare lo stesso, perrchè se la selezione è maggiore di un singolo record (sopra ti ho copiato il codice con i case completi) deve effettuare una somma degli importi.

  4. #4
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    7
    Ho utilizzato con successo INSERT INTO su altri database, ma ora non riesco a spiegarmi come mai non funziona su questa istruzione

    Dim dbs as DAO.Database
    set dbs = CurrentDb

    c = [Forms]![Clienti]![Contratto].[Form]![IDContratto]


    ' duplico il contratto selezionato
    dbs.Execute " INSERT INTO Contratti ( IDContratto, DataInizio, DataFine, Cliente, Confermato, NoteContratto ) SELECT Contratti.IDContratto, Contratti.DataInizio, Contratti.DataFine, Contratti.Cliente, Contratti.Confermato, Contratti.NoteContratto FROM Contratti WHERE (((Contratti.IDContratto)=" & c & "));"

    la sintassi è corretta, copiando il codice SQL direttamente da una query.
    La query funziona il codice no.
    Non mi da errori ma non mi copia quello che voglio.
    Ho provato allora a far altri INSERT INTO, ma lo stesso database sembra non farne funzionare nessuno. A cosa è dovuto, forse a qualche riferimento errato delle librerie?

    Grazie
    ElChorro

  5. #5
    Utente di HTML.it L'avatar di gibra
    Registrato dal
    Apr 2008
    residenza
    Italy
    Messaggi
    4,244
    Non uso DAO da secoli, quindi non conosco i suoi meccanismi, e potrei dire qualcosa di inesatto, ma non credo:

    Tu scrivi:
    la sintassi è corretta, copiando il codice SQL direttamente da una query.
    La query funziona il codice no.
    Ciò mi fa supporre che tu abbia creato la query in ambiente MSAccess per poi copiarne il codice in VBA.
    Se è proprio così allora il fatto che 'possa' funzionare in MSAccess non significa che debba sempre funzionare in VBA (o VB6), perchè l'ambiente MSAccess fa delle cose per conto suo e spesso aggiusta quelle sbagliate (ove sia possibile, comunque).

    In pratica la tua query sta tentando di copiare i dati su sé stessa, il che ovviamente potrà essere sintatticamente corretto, ma potrebbe essere sbagliato nella logica:

    codice:
    ' duplico il contratto selezionato
    dbs.Execute " INSERT INTO Contratti ( IDContratto, DataInizio, DataFine, Cliente, Confermato, NoteContratto ) SELECT Contratti.IDContratto, Contratti.DataInizio, Contratti.DataFine, Contratti.Cliente, Contratti.Confermato, Contratti.NoteContratto FROM Contratti WHERE (((Contratti.IDContratto)=" & c & "));"
    Ora, io non so se IDContratto è la chiave primaria (come dovrebbe essere) ed è quindi univoco (contaotre?) ma se è così ovviamente la chiave primaria non può essere duplicata.

    Non vorrei dire cavolate, ma lo strano è invece che non ti restituisca alcun errore.
    Però qui mi fermo perchè non conosco niente del tuo database...

    In ogni caso, hai provato ad utilizzare un alias per la parte SELECT ?


  6. #6
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    7
    Buongiorno,
    ringrazio gibra della collaborazione e ho capito che duplicavo la chiave primaria come da lui indicato.
    La cosa strana è che dopo aver tolto la chiave primaria dalla SELECT la cosa non funzionasse correttamente. Mi dava gli stessi problemi di prima , pertanto ho sostituito dbs.execute con docmd.runsql, di seguito tutte le operazioni:

    Dim dbs As Database
    Dim x, y, z, k As DAO.Recordset
    Dim p, c, q As Integer

    Set dbs = CurrentDb
    Set x = dbs.OpenRecordset("Contratti", dbOpenDynaset)
    Set y = dbs.OpenRecordset("DClausole", dbOpenDynaset)
    Set z = dbs.OpenRecordset("Prezzi", dbOpenDynaset)
    Set k = dbs.OpenRecordset("Altro", dbOpenDynaset)

    c = [Forms]![Clienti]![Contratto].[Form]![IDContratto]

    ' duplico il contratto selezionato

    DoCmd.RunSQL "INSERT INTO Contratti " & "SELECT Contratti.DataInizio, Contratti.DataFine, Contratti.Cliente, Contratti.Confermato, Contratti.NoteContratto FROM Contratti " & " WHERE (((Contratti.IDContratto)=4))"



    ' definisco l'indice del nuovo contratto
    x.MoveLast
    p = x("IDContratto")

    ' duplico la parte relativa alle clausole

    If y.EOF Or y.BOF Then GoTo s1 Else GoTo n1
    n1:
    y.MoveLast
    q = y("IDDClausole")
    DoCmd.RunSQL "INSERT INTO DClausole SELECT DClausole.DataDClausole, DClausole.Contratto, DClausole.Clausola, DClausole.[Val%], DClausole.Importo, DClausole.Condizione, DClausole.NoteCondizione, DClausole.Liquidazione, DClausole.Tipo, DClausole.Chiusa, DClausole.Applicabile" & " FROM DClausole " & "WHERE (((DClausole.Contratto)=" & c & "));"
    dbs.Execute "UPDATE DClausole SET DClausole.Contratto =" & p & " WHERE (((DClausole.IDDClausole)>" & q & "));"

    ' duplico la parte relativa agli eventuali prezzi
    s1:
    If z.EOF Or z.BOF Then GoTo s2 Else GoTo n2
    n2:
    z.MoveLast
    q = z("IDPrezzi")
    DoCmd.RunSQL "INSERT INTO Prezzi SELECT Prezzi.Contratto, Prezzi.Articoli, Prezzi.Prezzo, Prezzi.Note FROM Prezzi WHERE (((Prezzi.Contratto)=" & c & "));"
    dbs.Execute "UPDATE Prezzi SET Prezzi.Contratto = " & p & " WHERE (((Prezzi.IDPrezzi)>" & q & "));"

    ' duplico la parte relativa all'altro
    s2:
    If k.EOF Or k.BOF Then GoTo s3 Else GoTo n3
    n3:
    k.MoveLast
    q = k("IDAltro")
    DoCmd.RunSQL "INSERT INTO Altro SELECT Altro.DataAltro, Altro.Contratto, Altro.Descrizione, Altro.Quantità FROM Altro WHERE (((Altro.Contratto)=" & c & "));"
    dbs.Execute "UPDATE Altro SET Altro.Contratto = " & p & " WHERE (((Altro.IDAltro) >" & q & "));"

    s3:
    Me.Contratti.Requery

    Set x = Nothing
    Set y = Nothing
    Set z = Nothing
    Set dbs = Nothing
    Così facendo mi indicava tramite la finestra quali operazioni impedivano il successo della query.
    Con grande stupore mi indicava che duplicavo ancora la chiave primaria cosa che in realtà non veniva fatta.
    Dopo però aver lanciato l'SQL due volte, non mi dava più errore e funzionava correttamente.
    Pertanto mia personalissima opinione, credo che con utilizzando database execute non mi abbia segnalato l'errore e scombinato qualcosa nelle tabelle, utilizzando docmd.runsql invece abbia bene o male rimesso a posto le cose.
    Sostituendo dopo il DOCMD.RUNSQL con il DATABASE.EXECUTE, la query ritorna a funzionare senza le finestre che ti dicono quanti record vengono inseriti.
    Ringrazio Gibra per l'aiuto fornito.
    Alla prossima.
    El Chorro

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.