Newsgroup: it.comp.appl.access
Titolo: Errore 3211

Non vorrei riaprire vecchie conversazioni ma non posso farne a meno.
Ho una maschera M con origine record su una tabella T. Nella maschera ho un Button che chiama un modulo che:
- chiude M
- crea una copia di T (CopyObject) come T1
- elimina i record presenti in T
- azzera il contatore di T
- riapre M
Il debug mi segnala errore sull'azzeramento del contatore di T anche se ho già chiuso M e, mi aspetto che di conseguenza sia chiusa, anche T. Invece sembra non sia così.
Tuttavia inserendo nel Button il codice
 
Me.RecordSource = ""
DoCmd.Close acForm, "M"
DoCmd.DeleteObject acTable, "T"
Call Copia_Rinomina
 
avvia l'evento Su_Corrente restituendo una serie di errori perché i campi riportano tutti la dicitura #Nome? (deduco che sia perché ho sganciato il RecordSource).
Se commento la riga del RecordSource mi restituisce l'errore 3211 quando voglio azzerare il contatore di T con:
 
DoCmd.RunSQL "ALTER TABLE [T] ALTER COLUMN [Id_M] COUNTER(1,1)"
 
come se T non fosse chiusa.


io farei fare queste cose ad una procedura in un modulo o in un'altra maschera.
hai provato?


Certo!
Nella maschera M ho inserito:
 
Private Sub BtnContab_Click()
' sgancia il RecordSource, chiude Form e Tabella e lancia laa 
Me.RecordSource = ""
DoCmd.Close acForm, "M"
DoCmd.DeleteObject acTable, "T"
Call Copia_Rinomina 'funziona anche senza "Call"
End Sub
 
Questo codice però ha un problema: mi avevi suggerito (sul mio precedente help) di utilizzare su Form_Current
If Not Me.NewRecord Then
    Controllo.Value = True
    altriControlli.locked= True
ma il la procedura si blocca prima della chiamata alla sub Copia_Rinomina e avvia la sub Form_Current, segnalando errore proprio su Controllo.Value=True. Naturalmente M non è più collegata a T tramite RecordSource e appare l'errore di runtime 2448
Se tolgo o commento la riga me.RecordSource = "" la procedura prosegue, chiude M e T, avvia Copia_Rinomina dal modulo che ha il seguente codice
 
Public Sub Copia_Rinomina()
Dim tblNewName As String
'Forms![Movimenti].RecordSource = "" *commentato perché la maschera è chiusa e restituiva errore
DoCmd.Close acForm, "M"     'è inutile ma non da errori perciò lo lascio
DoCmd.Close acTable, "T"      'è inutile ma non da errori perciò lo lascio
tblNewName = "T" & InputBox("Inserire l'anno di chiusura", "Chiusura contabile")
DoCmd.CopyObject , tblNewName, acTable, "T"    'crea una copia di T col nome T + anno precedente
DoCmd.RunSQL "Delete * FROM [T]"        'cancella tutti i record dalla tabella
DoCmd.RunSQL "ALTER TABLE [T] ALTER COLUMN [Id_Movim] COUNTER(1,1)"     'azzera il contatore della tabella
DoCmd.OpenForm "M"     'riapre la maschera M
End Sub
 
ma si blocca su
DoCmd.RunSQL "ALTER TABLE [T] ALTER COLUMN [Id_Movim] COUNTER(1,1)"
con errore di runtime 3211 - Il motore del database non può bloccare la tabella "T" perché in uso da una ltro utente o processo.
ma la form è stata chiusa (anche se il recordsource era rimasto agganciato) ed anche la tabella, entrambe addirittura 2 volte (?) in due sub diverse.
Ah, ho creato anche una query contenente lo stesso SQL. Se commento la riga incriminata e lancio manualmente la query l'azzeramento avviene senza problemi ma se inserisco la query prima dell'OpenForm
...
' DoCmd.RunSQL "ALTER TABLE [T] ALTER COLUMN [Id_Movim] COUNTER(1,1)"     'azzera il contatore della tabella *commentata
docmd.OpenQuery("QryCopia_Rinomina")
DoCmd.OpenForm "M"     'riapre la maschera M
End Sub
 
riappare l'errore 3211.
Scusa per la quantità di testo ma spero in tal modo di essere stato sufficientemente esplicito.
 

Il giorno giovedì 17 febbraio 2022 alle 20:43:13 UTC+1 Michele ha scritto:

Aggiungo un dettaglio: ho creato una function che chiude tutti gli oggetti aperti e la chiamo prima di lanciare la sub Copia_Rinomina.
Risultato: nulla! Sempre errore 3211 quando arriva al codice SQL


io farei
Private Sub BtnContab_Click()
   Call Copia_Rinomina 
End Sub
 
in un modulo
Public Sub Copia_Rinomina()
    Dim tblNewName As String
    DoCmd.Close acForm, "M"
    DoCmd.DeleteObject acTable, "T"
    tblNewName = "T" & InputBox("Inserire l'anno di chiusura", "Chiusura contabile")
    DoCmd.CopyObject , tblNewName, acTable, "T" 'crea una copia di T col nome T + anno precedente
    DoCmd.RunSQL "Delete * FROM [T]" 'cancella tutti i record dalla tabella
    DoCmd.RunSQL "ALTER TABLE [T] ALTER COLUMN [Id_Movim] COUNTER(1,1)" 'azzera il contatore della tabella
    DoCmd.OpenForm "M" 'riapre la maschera M
End Sub
 
Comunque hai invece pensato di aggiungere un campo "AnnoCont" e utilizzare la tabella T senza fare questi magheggi?
Se ti serve un contatore che inizi sempre da 1 per ogni anno puoi inserire un nuovo campo numerico.
Quindi avrai una chiave primaria contatore, con cui potrai gestire tutte le relazioni, mentre a video farai vedere il secondo contatore... Il mio database (che ho ereditato) così funziona.


Ciao, ho provato il tuo codice creando la sub:
 
Public Sub CopiaResetta(tblName As String, frmName As String)
    'Chiudo la maschera
    DoCmd.Close acForm, frmName, acSaveNo
    'Chiudo la tabella tblName
    DoCmd.Close acTable, tblName
    'Chiedo input anno
    tblNewName = tblName & "New" & InputBox("Inserire l'anno di chiusura", "Chiusura contabile")
    'Creo una copia di tblName col nome tblNewName
    DoCmd.CopyObject , tblNewName, acTable, "Tabella2"
    'Cancella tutti i record dalla tabella tblName
    DoCmd.RunSQL "Delete * FROM " & tblName
    'Azzero il contatore della tabella tblName
    DoCmd.RunSQL "ALTER TABLE " & tblName & " ALTER COLUMN [Id] COUNTER(1,1)"
End Sub
 
e mi funziona perfettamente!! Crea la nuova tabella, quella iniziale ha il contatore resettato e quando riapro la maschera continua ad essere associata alla tabella iniziale. 
Forse c'è qualche altra variabile che mi sfugge?

 Forse c'è qualche altra variabile che mi sfugge?
 
non so se prima o dopo aver aperto il form Movimenti devi cambiare il RecordSource..
Forms![Movimenti].RecordSource = ....
 
scusami ma non ho capito bene a cosa ti serva questo codice ;-)

 - riapre M        <== (questo ho dimenticato di inserirlo ma non credo sia importante)
 
però non si blocca. Pertanto mi chiedevo se ci fossero altri aspetti che io non ho considerato e che potrebbero essere la causa del blocco. E se non ci dovessero essere,  allora bisognerebbe capire perchè il suo codice si blocca. Tutto qui.
 
Infine, non mi sembra necessario modificare il RecordSource della maschera. Probabilmente perchè mi sfugge il motivo.


Grazie per i suggerimenti e...
Interessante!!! Non avevo provato a lanciare direttamente il modulo col mio codice.
Il codice da solo funziona perfettamente (esattamente come la Query) in più chiude la maschera prima dell'esecuzione e la riapre alla fine, ma non se avviato dall'evento button_click. Ma allora come lo eseguo se non posso lanciarlo dalla maschera? Anche il solo
Private Sub BtnContab_Click()
Call Copia_Rinomina
End Sub
genera l'errore, come se restasse una istanza aperta.
Questo era il motivo della modifica del RecordSource: se stacco la maschera dalla tabella poi le operazioni eseguite sulla tabella (non in uso) non genererebbero errori di "tabella in uso da un altro utente o processo".
..azz allora come  avvio la sub CopiaResetta se non posso dalla maschera???


Mi è stato chiesto che la tabella contenga solo i dati per l'anno contabile, nel tuo caso il database avrà una crescita lineare negli anni perché anno dopo anno i movimenti vengono aggiunti. Nel mio caso mi è stato spiegato che la tabella verrà eliminata dopo un certo tempo e che i dati potrebbero essere esportati. Così ho pensato che la soluzione più semplice fosse avere una tabella per ogni anno contabile.
Certo con un'unica tabella avrei comunque potuto gestire gli stessi dati: con una SELECT... WHERE avrei estratto quelli per data, con un DELETE... WHERE avrei potuto cancellarli, ecc. ma in quel momento la soluzione di usare più tabelle era quella più in linea con le richieste.
Sai, non uso le relazioni di Access, non sono mai riuscito a capirle (e me le hanno spiegate molte volte). Non ho mai avuto problemi scrivendomi le SELECT con INNER e OUTER JOIN anche se poi, lo so, è la stessa cosa, sarà il modo di ragionare a schemi/blocchi anziché graficamente.


Ho provato anche io ad avviare il modulo da un pulsante nella maschera ed effettivamente mi da l'errore 3211. Ho fatto qualche prova ma inutilmente. Probabilmente il codice lanciato da una maschera la tiene comunque attiva fino al suo completamente (anche se chiude la maschera stessa). Infatti ho provato a lanciare il modulo da una seconda maschera di conferma e funziona!
(qui trovi il db di prova: 
https://1drv.ms/u/s!AglTZh2zArXshulZLwtrxrxJO05lLA?e=iN6Q4A
)


Cosa dire... GRAZIE!!!!
Non mi sarebbe mai venuto in mente di creare una maschera "secondaria". Avevo però pensato di sganciare il recordSource dalla maschera e crearlo per ogni singolo campo. Un lavoraccio e non so nemmeno se poi avrebbe funzionato.