Istanze multiple con Access

di il
12 risposte

Istanze multiple con Access

Ciao a tutti,

so che è un argomento ampio, quindi tralascio i dettagli sull'argomento.
Qualcuno sa come impostare una variabile Form tramite un parametro?
Vorrei rendere riutilizzabile il codice per aprire maschere con istanze multiple.
La parte di codice che uso è la seguente:

...
Dim frm as Form
Set frm = new Form_Nome_Form
...
E' possibile dare un valore ad una variabile per sostituire il nome della Form da assegnare alla variabile di tipo Form?

Grazie

12 Risposte

  • Re: Istanze multiple con Access

    Detta così non si capisce...
    Spiega cosa devo fare di concreto e perché devi istanziare l'oggetto in quel modo...
    Perché non usi la funzione OpenForm...?
  • Re: Istanze multiple con Access

    Non mi pare si possano aprire istanze multiple con OpenForm
  • Re: Istanze multiple con Access

    Se spieghi bene altrimenti vedrai tu...
  • Re: Istanze multiple con Access

    Da una maschera che mostra un elenco di record apro una maschera che mostri i dettagli di un singolo record.
    Ho bisogno di aprire i dettagli di più record con la stessa maschera e per farlo uso appunto le istanze con il comando
    Set frm = new Form_Nome_Form
    Tutto funziona come deve.
    Ora vorrei rendere pubblico il codice che apre le istanze, così da poterlo usare per aprire altre maschere.
    Per farlo avrei bisogno di impostare il nome della Form da aprire in una variabile, ma non trovo la sintassi.
    Ho provato la seguente:
        Dim nItem As Long
        Dim bFormExist As Boolean
        bFormExist = False
    
        For nItem = 0 To CurrentProject.AllForms.Count - 1
            'Debug.Print CurrentProject.AllForms(nItem).Name
            If CurrentProject.AllForms(nItem).Name = sFormName Then
                Set frm = Forms(CurrentProject.AllForms(nItem).Name)
                bFormExist = True
                Exit For
            End If
        Next
    ma non funziona.
  • Re: Istanze multiple con Access

    Tutto funziona a dovere ho forti perplessità dal momento che come avevi dichiarato la variabile oggetto prima non poteva andare in quanto veniva distrutta all'uscita della.funzione.
    Con la tua logica attuale dovresti dichiarare N oggetti per accettare N istanze.

    Ovviamente non sei sulla strada giusta.
    Tuttavia non si può fare quello che dici... se vuoi aprire una nuova istanza di classe devi istanziare QUELLA CLASSE non esiste un modo per istanziare una classe indicizzata da variabile.

    Quindi se guardi questo esempio capirai come gestire le istanze ma della stessa classe oggetto...

    http://allenbrowne.com/ser-35.htm

    Se vuoi poter istanziare genericamente varie classi oggetto dovrai scrivere un codice che, a seconda della classe oggetto(form per capirci meglio) va a dichiarare quella classe specifica come NEW Classe Instance...

    Poi una volta istanziata la sbatti nella collection che può contenere anche differenti ClassType.
  • Re: Istanze multiple con Access

    Riporto tutto il codice usato.

    Questo in un modulo generale
    Option Compare Database
    Public colForms As New Collection    'Serve per gestire le istanze
    
    Questo nella form chiamante
    Private Sub ElencoDS_DblClick(Cancel As Integer)
        ' Chiamo la funzione per aprire un'istanza
        ' Come parametri passo:
        ' - Nome maschera
        ' - Filtro
        ' - Etichetta per la Caption
        Call OpenForm("GestioneOre", "[ID_Stampo] = " & Me.ElencoDS.Column(0), Me.ElencoDS.Column(1))
    End Sub
    
    Function OpenForm(sFormName As String, sFilter As String, sDSCode As String)
        ' Apre una nuova istanza
    
        Dim frm As Form
        
        ' Apre l'istanza
        Set frm = New Form_GestioneOre
        ' Imposta il filtro e visualizza la maschera
        frm.Filter = sFilter
        frm.FilterOn = True
        ' Modifica l'Etichetta della form
        frm.Caption = "Gestione ore " & sDSCode
        ' La rendo visibile
        frm.Visible = True
    
        'La aggiungo alla collezione
        colForms.Add Item:=frm, Key:=CStr(frm.hwnd)
    
        Set frm = Nothing
    End Function
    Questo nella form chiamata
    Private Sub Form_Close()
         'Rimuovo l'istanza dalla raccolta colForms
        Dim obj As Object         'Oggetto in colForms
     
        Dim blnRemove As Boolean  'Segnala per rimuoverlo.
    
        'Controllo se questa istanza è nella raccolta.
        For Each obj In colForms
            If obj.hwnd = Me.hwnd Then
                blnRemove = True
                Exit For
            End If
        Next
        ' Disassegna l'oggetto
        Set obj = Nothing
        ' E lo rimuove dalla raccolta.
        If blnRemove Then
            colForms.Remove CStr(Me.hwnd)
        End If
    End Sub
    
    E fino a qui funziona tutto bene.
    Le maschere vengono aperte sul filtro impostato e si chiudono in modo indipendente e correttamente.

    Quello che vorrei fare è rendere pubblica la OpenForm e passargli i parametri:
    - Nome della maschera da aprire (String)
    - Filtro (String)
    - Nome dell'etichetta (String)

    Come ti dicevo all'inizio, ho trovato questo codice:
    Set frm = Forms(CurrentProject.AllForms(nItem).Name)
    
    e ho pensato che si potesse passare un valore, ma non funziona.
    Ho provato a cambiare la sintassi pensando che chi aveva riportato il codice avesse sbagliato qualcosa, ma non ho risolto.
    Perciò ho "sfogliato" tutte le maschere del database (e non solo quelle aperte), per recuperare l'oggetto da aprire.

    Invece mi dici che non si può fare e quel codice che ho trovato non ha solo un errore di sinstassi?
  • Re: Istanze multiple con Access

    Intanto dovresti rendere pubblica anche la cancellazione altrimenti devi scrivere codice in ogni maschera...

    Sulla openform non serve il nome della.form perché potrai istanziare SOLO 1 type per volta...
    Non puoi fare quello che hai pensato tu.
    Devi introdurre un parametro e con una serie di Select case istanziare la classe specifica di Form.

    P.S. non si cicla tutta la collection per vedere de c'è già l'istanza... si prova a recuperarla e si gestisce l'errore altrimenti rallenti per nulla.
  • Re: Istanze multiple con Access

    Ho risolto nel seguente modo:

    In pubblica
    Option Compare Database
    Public colForms As New Collection    'Serve per gestire le istanze
    
    Public Function OpenInstance(fForm As Form, sFilter As String, sDSCode As String)
        ' Aggiorna la variabile pubblica colForms di tipo Collection
        
        ' Imposta il filtro
        fForm.Filter = sFilter
        fForm.FilterOn = True
        ' Modifica l'Etichetta della form
        'frm.Caption = frm.hwnd & ", opened " & Now()
        fForm.Caption = "Gestione ore " & sDSCode
        ' La rendo visibile
        fForm.Visible = True
        'La aggiungo alla Collection
        colForms.Add Item:=fForm, Key:=CStr(fForm.hwnd)
        ' Vuota la variabile
        Set fForm = Nothing
    End Function
    
    Public Function CloseInstance(hwnd As Long)
         ' Rimuovo l'istanza dalla raccolta colForms
         ' Richiamo questa sub sull'evento chiusura della form aperta come istanza
        Dim obj As Object         'Oggetto in colForms
     
        Dim blnRemove As Boolean  'Segnala per rimuoverlo.
    
        'Controllo se questa istanza è nella raccolta.
        For Each obj In colForms
            If obj.hwnd = hwnd Then
                blnRemove = True
                Exit For
            End If
        Next
        ' Disassegna l'oggetto
        Set obj = Nothing
        ' E lo rimuove dalla raccolta.
        If blnRemove Then
            colForms.Remove CStr(hwnd)
        End If
    End Function
    Nella maschera chiamante
    Private Sub ElencoDS_DblClick(Cancel As Integer)
        ' Apro la maschera come istanza
        Dim fForm As New Form_GestioneOre
        ' Come parametri passo:
        ' - Maschera
        ' - Filtro
        ' - Etichetta per la Caption
        Call OpenInstance(fForm, "[ID_Stampo] = " & Me.ElencoDS.Column(0), Me.ElencoDS.Column(1))
    End Sub
    
    Nella maschera chiamata
    Private Sub Form_Close()
        ' Chiamo la funzione per chiudere l'istanza passando come parametro l'hwnd della maschera
        Call CloseInstance(Me.hwnd)
    End Sub
    Come mi hai suggerito ho spostato la chiusura in pubblica, così riuso più codice.
    E come avevi previsto, funziona solo per una maschera per volta per come è fatta, ma a me basta così per il momento.
    Non ho capito cosa intendi con:
    Sulla openform non serve il nome della.form perché potrai istanziare SOLO 1 type per volta...
  • Re: Istanze multiple con Access

    Nella funzione Open e Close ti basta rilevare l'oggetto CodeContextObject che risponde alla form che chiama la funzione, quindi su close non serve nulla
    
    Function CloseIstance() 
        On error goto ErrHandler
        Dim frm As Access.Form
        Set frm=CodecontextObject
        colForms.Remove CStr(frm.hwnd)
        CloseIstance=True
    Exit:
        Exit function
    ErrHandler:
        Err.clear
        Resume Exit
    End Function
    
    Basta chiamarla da evento =CloseIstance() nemmeno serve il vba
  • Re: Istanze multiple con Access

    Così chiude correttamente anche se apro istanze di maschere differenti!!!

    Ma non ho capito come posso usare CodeContextObject su Open.
    Come fa a sapere che Form aprire?
  • Re: Istanze multiple con Access

    La devi istanziare come fai, qyando la istanzi si generano gli eventi, e su open chiami la funzione che la aggiunge alla collection.
  • Re: Istanze multiple con Access

    Sono riuscito a sistemare le cose in modo da poter aprire la maschera sia con docmd.OpenForm che con le istanze.
    Per farlo ho aggiunto una variabile globale che imposto prima di aprire la Form, sia con OpenForm che come istanza.
    Su Open devo solo verificare se hwnd è già presente nella Collection prima di aggiungerla di nuovo, altrimenti mi dice che esiste già.
    Grazie davvero Alex!
Devi accedere o registrarti per scrivere nel forum
12 risposte