For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

di il
14 risposte

For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

.
Salve a tutti, ritorno dopo un po' su questo forum perché ho una domanda su una questione più che altro estetica ma anche funzionale.

Ho inserito nel mio database la produzione del file di log scaricata da qui forum.masterdrive.it/attachments/access-79/1417d1346425008-events-tracer-northwind_tracer.zip, modificandola pesantemente ma che funziona.

Sarebbe carino se la scrittura effettuata nel log con ciclo Each For sui controlli dei campi dei record modificati/inseriti/eliminati nelle function FillDataCanged() e FillActiveData(), fosse eseguita in ordine di tabulazione crescente sfruttando la proprietà TabIndex dei controlli, visto che di suo sfrutta il numero di Item.

Se avete dei suggerimenti in merito e non è troppo complicato, ve ne sarei grato.

Alex66

14 Risposte

  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    Mi fa piacere tu abbia trovato interesse nel Demo.

    Quello che chiedi è fattibile ma lentissimo in quanto la proprietà TabIndex non è iterabile o indicizzata in un array.
    Quindi la cosa più semplice e funzionale sarebbe creare una Collection ControlEx ed inserire su Load di form i controlli con l'ordine TabIndex.
    A quel punto usi quella collection invece della colletion Control.
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    .
    Figurati, fa piacere a me che ci sia qualcuno come te che mette a disposizione la sua conoscenza ed esperienza a disposizione, e io non so come sdebitarmi.

    Ma torniamo al mio quesito.
    In effetti come la metti tu sembra molto semplice, ma io non ho assolutamente idea di come creare una Collection e di come inserire nell’evento Load i controlli in ordine di TabIndex. Non farti ingannare dal fatto che sono riuscito a personalizzarmi la tua demo. Era fatta così bene che persino una sega come me non ha “quasi” avuto problemi.
    Non è che avresti un piccolo esempio sul quale applicarmi?

    Se puoi grazie in anticipo altrimenti grazie lo stesso.

    Alex66
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    Per fare una cosa veloce... immagino che tutti i Controlli non siano oggetto del tuo lavoro specifico... hai assegnato un range al TabIndex oppure proprio tutti...?
    Se così fosse converrebbe forse usare un array...
    
    Private mArray() as Access.Control
    
    Private sub form_load()
      Dim c as Ccess.control
      Redim Preseeve mArray(me.controls.count)
      For each c in me.controls
         Set array(c.TabIndex).ctl=c
      Next
    End sub
    Ora nell'area hai i controlli di Maschera in ordine TabIndex.

    Ovviamente se la logica dell'assegnazione del TabIndex è diversa serve ragionare diversamente.
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    .
    Nessun range. Quindi direi che l’array va benissimo.
    Però prima di martedì non posso applicarmici. Solo due domande:
    1) la private mArray() va inserita nel modulo di classe o nella form?
    2) come faccio a far vedere alle function FillDataChange() e FillActiveData() l’array? Oppure non devo fare niente?
    Una risposta per martedì va benissimo.
    Grazie in anticipo.

    Alex66
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    Alla 1 la risposta è si ma in realtà forse la risposta 2 condiziona questa.
    Alla 2 siccome non ricordo le funzioni e non ho modo di scaricare nulla per qualche gg... dovresti pubblicare una funzione e ricordare la logica con cui.viene chiamata.
    Andando a memoria credo sarebbe da realizzare in tutte le forms la stessa struttura... ma per rimanere in linea con il demo, che gestisce tutto fuori, probabilmente andrebbe ragionata pernantenere la filosofia del demo, di conseguenza internamente all'istanza della classe dedicata alla.form... non nel modulo di classe della form.

    Purtroppo però ripeto non lo ricordo molto bene e dovrei riaprirlo.
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    Ok, martedì ti posto il codice.

    Ciao.

    Alex66
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    .
    Ciao @Alex, ti invio il codice originale per la produzione del log.


    Questo è il mudulo basForms dove c'è la function OpenFormEX da usare al posto del comando Domcd.OpenForm
    
    
    Option Compare Database
    Option Explicit
    
    Private mcolForms As Collection
    -------------------------------
    
    Public Function OpenFormEX(FormName, Optional View As AcFormView = acNormal, _
                               Optional FilterName As String, Optional WhereCondition As String, _
                               Optional DataMode As AcFormOpenDataMode = acFormPropertySettings, _
                               Optional WindowMode As AcWindowMode = acWindowNormal, Optional OpenArgs)
                         
        On Error GoTo Proc_Err
    
        Dim rs                      As DAO.Recordset
        
        DoCmd.OpenForm FormName, View, FilterName, WhereCondition, DataMode, WindowMode, OpenArgs
        
        DoEvents
        
        Set rs = DBEngine(0)(0).OpenRecordset("SELECT * FROM [_EFORMSEVENTS] WHERE TraceON=True AND NomeMaschera='" & FormName & "'", dbOpenDynaset, dbReadOnly)
        
        If Not rs.EOF Then
            
            If CurrentProject.AllForms(FormName).IsLoaded Then
                Call AddEventsHandler(Forms(FormName))
            End If
        
        End If
        
    Exit_Here:
        On Error Resume Next
        rs.Close
        Set rs = Nothing
    
        Exit Function
        
    Proc_Err:
        MsgBox Err.Number & Err.Description
        Resume Exit_Here
    
    End Function
    
    -------------------------------
    
    Public Function AddEventsHandler(frmIn As Access.Form) As clsForm
        On Error GoTo Proc_Err
        
        Dim curForm                 As clsForm
        Dim strKEY                  As String
    
        Dim mTraceBeforeUpdate      As Boolean
        Dim mTraceBeforeInsert      As Boolean
        Dim mTraceBeforeDelConfirm  As Boolean
        Dim mTraceError             As Boolean
    
                    
        If mcolForms Is Nothing Then
            Set mcolForms = New Collection
        End If
        
        strKEY = CStr(CollectionCount()) & "_" & frmIn.Name
        
        If Not FormExists(strKEY) Then
            Set curForm = New clsForm
            
            Set curForm.Form = frmIn
            curForm.Key = strKEY
            
            mcolForms.Add curForm, strKEY
        Else
            Set curForm = mcolForms(strKEY)
        End If
        Set AddEventsHandler = curForm
    
    Exit_Here:
    
        Exit Function
        
    Proc_Err:
        MsgBox Err.Number & Err.Description
        Resume Exit_Here
    End Function
    
    -------------------------------
    
    Public Function Item(strKEY As String) As clsForm
        On Error GoTo Proc_Err
        
        If FormExists(strKEY) Then
            Set Item = mcolForms.Item(strKEY)
        End If
        
    Proc_Exit:
        Exit Function
        
    Proc_Err:
        Item = Nothing
    End Function
    
    -------------------------------
    
    Public Sub RemoveForm(strKEY As String)
        On Error Resume Next
        
        If FormExists(strKEY) Then
            mcolForms.Remove strKEY
        End If
        
    End Sub
    
    -------------------------------
    
    Public Function CollectionCount() As Long
            
        If mcolForms Is Nothing Then
           CollectionCount = 0
        Else
           CollectionCount = mcolForms.Count
        End If
    
    End Function
    
    -------------------------------
    
    Public Function FormExists(strKEY As String) As Boolean
        On Error Resume Next
        Dim strValue As String
        
        strValue = mcolForms.Item(strKEY).Key
        FormExists = (Err.Number = 0)
        Err.Clear
    
    End Function
    
    -------------------------------
    
    Function CollectionItems() As Collection
        Set CollectionItems = mcolForms
    End Function
    
    

    Questo è il modulo di classe clsForm dove vengono intercettati gli eventi e prodotte le stringhe dati da passare al modulo successivo basLog e per alcuni eventi attraverso le function FillDataChanged e FillActiveData:
    
    
    Option Compare Database
    Option Explicit
    
    Private mstrKey                 As String
    Private WithEvents mfrm         As Access.Form
    
    Private mOnUnloadTrace          As Boolean
    
    -------------------------------
    
    Public Property Get Key() As String
        Key = mstrKey
    End Property
    
    -------------------------------
    
    Public Property Let Key(Key As String)
        mstrKey = Key
    End Property
    
    -------------------------------
    
    Public Property Set Form(frmIn As Access.Form)
    
        On Error GoTo Err_Events
        
        Dim rs                      As DAO.Recordset
        Set mfrm = frmIn
        
        Dim ctl As Access.Control
        For Each ctl In mfrm.Controls
            If ctl.ControlType = acSubform Then Call AddEventsHandler(ctl.Form)
        Next
    
        Set rs = DBEngine(0)(0).OpenRecordset("SELECT * FROM [_EFORMSEVENTS] WHERE TraceON=True AND NomeMaschera='" & frmIn.Name & "' ORDER BY Evento", dbOpenDynaset, dbReadOnly)
        Do Until rs.EOF
            Select Case rs.Fields("Evento").Value
                    
                Case Is = "AfterDelCofirm"
                    mfrm.AfterDelConfirm = "[Event Procedure]"
                
                Case Is = "AfterInsert"
                    mfrm.AfterInsert = "[Event Procedure]"
                
                Case Is = "AfterUpdate"
                    mfrm.AfterUpdate = "[Event Procedure]"
        
                Case Is = "BeforeDelConfirm"
                    mfrm.BeforeDelConfirm = "[Event Procedure]"
                
                Case Is = "BeforeInsert"
                    mfrm.BeforeInsert = "[Event Procedure]"
                
                Case Is = "BeforeUpdate"
                    mfrm.BeforeUpdate = "[Event Procedure]"
                
                Case Is = "OnActivate"
                    mfrm.OnActivate = "[Event Procedure]"
                
                Case Is = "OnCurrent"
                    mfrm.OnCurrent = "[Event Procedure]"
                
                Case Is = "OnDeactivate"
                    mfrm.OnDeactivate = "[Event Procedure]"
                    
                Case Is = "OnError"
                    mfrm.OnError = "[Event Procedure]"
    
                Case Is = "OnLoad"
                    ' L'Evento LOAD si è già Verificato all'istanza, quindi
                    ' genero l'EventLOG in questo modo.
                    Call EventLog(mfrm.Name, "Load", "ON")
    
                Case Is = "OnUnload"
                    mOnUnloadTrace = True
            
            End Select
            rs.MoveNext
        Loop
        
        If IsSubForm(mfrm) = False Then mfrm.OnUnload = "[Event Procedure]"
        
    Exit_Here:
        On Error Resume Next
        rs.Close
        Set rs = Nothing
        Exit Property
    
    Err_Events:
        MsgBox Err.Number & " - " & Err.Description
        Resume Exit_Here
    End Property
    
    -------------------------------
                                 
    Private Sub mfrm_Activate()
        Call EventLog(mfrm.Name, "Activate", "ON")
    End Sub
    
    -------------------------------
    
    Private Sub mfrm_AfterDelConfirm(Status As Integer)
        Dim strStatus               As String
        Select Case Status
            Case Is = acDeleteOK
                strStatus = "Record CANCELLATO"
                
            Case Is = acDeleteCancel
                strStatus = "Evento Annullato da VBA"
                
            Case Is = acDeleteUserCancel
                strStatus = "Evento Annullato dall'Utente"
    
        End Select
        Call EventLog(mfrm.Name, "AfterDelConfirm", strStatus)
    End Sub
    
    -------------------------------
    
    Private Sub mfrm_AfterInsert()
        Call EventLog(mfrm.Name, "AfterInsert", FillActiveData())
    End Sub
    
    Private Sub mfrm_AfterUpdate()
        Dim strUPD                  As String
        strUPD = FillActiveData()
    
        Call EventLog(mfrm.Name, "AfterUpdate", strUPD)
    End Sub
    
    -------------------------------
    
    Private Sub mfrm_BeforeDelConfirm(Cancel As Integer, Response As Integer)
        Dim strUPD                  As String
        
        Response = acDataErrContinue
        ' Display custom dialog box.
        If MsgBox("Cancello questo record ?", vbOKCancel) = vbCancel Then
            Cancel = True
        Else
            strUPD = FillActiveData()
            ' LOG
            Call EventLog(mfrm.Name, "BeforeDelConfirm", strUPD)
        End If
    End Sub
    
    -------------------------------
    
    Private Sub mfrm_BeforeInsert(Cancel As Integer)
        Dim strUPD                  As String
        strUPD = FillActiveData()
        ' LOG
        Call EventLog(mfrm.Name, "BeforeInsert", strUPD)
    End Sub
    
    -------------------------------
    
    Private Sub mfrm_BeforeUpdate(Cancel As Integer)
        Dim strUPD                  As String
        strUPD = FillDataChanged()
        ' LOG
        Call EventLog(mfrm.Name, "BeforeUpdate", strUPD)
    End Sub
    
    -------------------------------
    
    Private Sub mfrm_Current()
        Dim strUPD                  As String
        strUPD = FillActiveData()
    
        Call EventLog(mfrm.Name, "Current", strUPD)
    End Sub
    
    -------------------------------
    
    Private Sub mfrm_Deactivate()
        Call EventLog(mfrm.Name, "Deactivate", "OFF")
    End Sub
    
    -------------------------------
    
    Private Sub mfrm_Error(DataErr As Integer, Response As Integer)
        Dim strChange               As String
        strChange = FillDataChanged()
        ' LOG
        Call EventLog(mfrm.Name, "ERROR", "ERR=" & DataErr & " " & Application.AccessError(DataErr) & " - " & strChange)
    End Sub
    
    -------------------------------
    
    Private Sub mfrm_Unload(Cancel As Integer)
        If mOnUnloadTrace Then Call EventLog(mfrm.Name, "Unload", "ON")
    
        Call RemoveForm(Me.Key)
    End Sub
    
    -------------------------------
    
    Private Function FillDataChanged() As String
        On Error GoTo Err_Fill
        
        Dim ctl                     As Access.Control
        Dim idx                     As Integer
        Dim strData                 As String
        
        FillDataChanged = vbNullString
            
        For Each ctl In mfrm.Controls
            If ctl.ControlType <> acImage And ctl.ControlType <> acSubform And ctl.ControlType <> acBoundObjectFrame Then
                If HasProperty(ctl, "ControlSource") Then
                    If Len(ctl.ControlSource) > 0 And Not ctl.ControlSource Like "=*" Then
                        If ctl.Value <> ctl.OldValue Then
                            strData = strData & "[" & ctl.Name & "] --> (OldVal=" & ctl.OldValue & ") - (NewVal=" & ctl.Value & ") ##"
                        End If
                    End If
                End If
            End If
        Next
        If Len(strData) > 0 Then strData = Mid$(strData, 1, Len(strData) - 3)
        FillDataChanged = strData
    Exit_Here:
    
        Exit Function
    Err_Fill:
        FillDataChanged = vbNullString
        Resume Exit_Here
    End Function
    
    -------------------------------
    
    Private Function FillActiveData() As String
        On Error GoTo Err_Del
        
        Dim ctl                     As Access.Control
        Dim idx                     As Integer
        Dim strData                 As String
        
        FillActiveData = vbNullString
            
        For Each ctl In mfrm.Controls
            If ctl.ControlType <> acImage And ctl.ControlType <> acSubform And ctl.ControlType <> acBoundObjectFrame Then
                If HasProperty(ctl, "ControlSource") Then
                    If Len(ctl.ControlSource) > 0 And Not ctl.ControlSource Like "=*" Then
                        strData = strData & "[" & ctl.Name & " = " & ctl.Value & "] ## "
                        Debug.Print strData
                    End If
                End If
            End If
        Next
        If Len(strData) > 0 Then strData = Mid$(strData, 1, Len(strData) - 4)
        FillActiveData = strData
    Exit_Here:
    
        Exit Function
    Err_Del:
        FillActiveData = vbNullString
        Resume Exit_Here
    End Function
    
    -------------------------------
    
    Private Function HasProperty(obj As Object, strPropName As String) As Boolean
        'Purpose:   Return true if the object has the property.
        Dim varDummy                As Variant
        On Error Resume Next
        varDummy = obj.Properties(strPropName)
        HasProperty = (Err.Number = 0)
    End Function
    
    -------------------------------
    
    Private Function IsSubForm(frm As Form) As Boolean
        ' =====================================================
        ' Verifica se la Form è caricata come SubForm
        ' cercando la proprietà Name della Form.Parent
        ' ed intercettando l'errore.
        ' In:
        '    frm: Form da verificare
        ' Out:
        '    Return value: True se è Subform
        '                  False se è Principale
        ' =====================================================
        On Error Resume Next
        Dim strName As String
        strName = frm.Parent.Name
        IsSubForm = (Err.Number = 0)
        Err.Clear
    End Function
    
    

    Questo è basLog, il terzo e ultimo modulo, dove vengono creati e popolati i file di log.
    
    
    Option Compare Database
    Option Explicit
    
    -------------------------------
    
    Function EventLog(ByVal FormName As String, _
                      ByVal EventAction As String, _
                      strDataChange As String) As Boolean
    
        On Error GoTo Err_LOG
        
        Dim intFile         As Integer
        Dim strPathFile     As String
        Dim strMsgOut       As String
        Dim strHeader       As String
        Const cDelimiter    As String = vbTab
        
    
        EventLog = False
    
        If FolderExists(CurrentProject.path & "\EventLog") = False Then MkDir CurrentProject.path & "\EventLog"
        
        strPathFile = CurrentProject.path & "\EventLog\Event_" & Format(Now(), "ddmmyyyy") & ".txt"
        intFile = FreeFile
        
        strMsgOut = Format(Now(), "dd/mm/yyyy hh:mm:ss")
        If Len(CurrentUser()) > 0 Then strMsgOut = strMsgOut & cDelimiter & CurrentUser()
        If Len(FormName & "") > 0 Then strMsgOut = strMsgOut & cDelimiter & FormName
        If Len(EventAction) > 0 Then strMsgOut = strMsgOut & cDelimiter & EventAction
        If Len(strDataChange) > 0 Then strMsgOut = strMsgOut & cDelimiter & strDataChange
        
        strHeader = vbNullString
        If FileExists(strPathFile) = False Then
            strHeader = "DATA" & cDelimiter & "USER" & cDelimiter & "MASCHERA" & cDelimiter & "AZIONE" & cDelimiter & "DATI"
        End If
        Open strPathFile For Append Shared As #intFile
            If Len(strHeader) > 0 Then Print #intFile, strHeader
            Print #intFile, strMsgOut
        Close #intFile
        EventLog = True
    Exit_Here:
        Exit Function
        
    Err_LOG:
        MsgBox "Errore non previsto. Impossibile accodare al LOG ERROR" & vbNewLine & " Visualizza CTRL+G"
        Resume Exit_Here
        
    End Function
    
    -------------------------------
    
    Public Function FileExists(ByVal str As String) As Boolean
        On Error Resume Next
        FileExists = (GetAttr(str) And vbDirectory) = 0
    End Function
    
    -------------------------------
    
    Function FolderExists(strPath As String) As Boolean
        On Error Resume Next
        FolderExists = ((GetAttr(strPath) And vbDirectory) = vbDirectory)
    End Function
    
    
    
    
    Aspetto notizie.

    Grazie.


    Alex66
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    .
    Intanto ti anticipo che la riga di comando

    Set array(c.TabIndex).ctl = c

    mi dà
    Errore di compilazione:
    Previsto: identificatore

    Alex66
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    alex66 ha scritto:


    .
    Intanto ti anticipo che la riga di comando

    Set array(c.TabIndex).ctl = c

    mi dà
    Errore di compilazione:
    Previsto: identificatore

    Alex66
    Come non detto, bisognava mettere mArray invece di array

    Alex66
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    Tu ovviamente non hai postato il codice giusto... ma ho avuto modo di aprire il Demo.
    Il Modulo da modificare è la Classe clsForm, in 2 punti...
    Devi inserire la dichiarazione dell'Array nella parte delle Variabili di Classe...
    
    Option Compare Database
    Option Explicit
    
    Private mstrKey                 As String
    Private WithEvents mfrm         As Access.Form
    
    Private mOnUnloadTrace          As Boolean
    Private mArray()                As Access.Control '<-------------QUESTO 
    Poi devi modificare la funzione di assegnazione della Form
    
    Public Property Set Form(frmIn As Access.Form)
    
        On Error GoTo Err_Events
        
        Dim rs                      As DAO.Recordset
        Set mfrm = frmIn
        
        Dim ctl As Access.Control
        For Each ctl In mfrm.Controls
            If ctl.ControlType = acSubform Then Call AddEventsHandler(ctl.Form)
        Next
    Devi sfruttarte il ciclo già esistente per popolare l'Array...

    Alla fine devi intervenire nella Funzione preposta a compilare la lista Campi/Valori [FillActiveData()]
    Questa funzione attualmente cicla la Collection Controls... tu devi sostituire questa parte con il ciclo sull'array mArray ed è fatto.

    Ovviamente non modifico io il codice, ma ti lascio fare tutte le prove del caso studiandoci... se poi qualche cosa non torna lo viediamo.
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    .
    Ho cominciato così nel modulo di classe:
    
    
    Option Compare Database
    Option Explicit
    
    Private mstrKey                 As String
    Private WithEvents mfrm         As Access.Form
    
    Private mOnUnloadTrace          As Boolean
    Private mArray()                As Access.Control <------------------------------------------------Codice per Array
    
    ------------------------------
    ....
    ------------------------------
    
    Public Property Set Form(frmIn As Access.Form)
    
        On Error GoTo Err_Events
        
        Dim rs                      As DAO.Recordset
        Set mfrm = frmIn
        
        Dim ctl As Access.Control
        
        ReDim Preserve mArray(mfrm.Controls.Count) <------------------------------------------------Codice per Array
        
        For Each ctl In mfrm.Controls
            If ctl.ControlType = acSubform Then Call AddEventsHandler(ctl.Form)
           Set mArray(ctl.TabIndex).ctl = ctl <-----------------------------------------------------Codice per Array
        Next
        
    
    Primo problema: all'apertura (OnLoad) di qualsiasi tipo di maschera, menu' e di inserimento dati: errore "438-Proprietà o metodo non supportati dall'oggetto".

    Ho pensato che quando andava a scorrere i controlli ne trovava senza la proprietà TabIndex.

    Quindi ho inserito le If usate nelle function FillDatachanged() e FillActiveData(), e aggiunto sulla seconda if "And HasProperty(ctl, "TabIndex")", cosi:
    
    
    Public Property Set Form(frmIn As Access.Form)
    
        On Error GoTo Err_Events
        
        Dim rs                      As DAO.Recordset
        Set mfrm = frmIn
       
        Dim ctl As Access.Control
     
        ReDim Preserve mArray(mfrm.Controls.Count) <------------------------------------------------Codice per Array
        
        For Each ctl In mfrm.Controls
            
            If ctl.ControlType = acSubform Then Call AddEventsHandler(ctl.Form)
            
            If ctl.ControlType <> acImage And ctl.ControlType <> acSubform And ctl.ControlType <> acBoundObjectFrame  Then
                If HasProperty(ctl, "ControlSource") And HasProperty(ctl, "TabIndex") Then
                    If Len(ctl.ControlSource) > 0 And Not ctl.ControlSource Like "=*" Then
                        Set mArray(ctl.TabIndex).ctl = ctl <----------------------------------------Codice per Array
                    End If
                End If
            End If
            
        Next
    
    
    Sui menù nessun problema perché ci sono solo pulsanti e campi non associati. A questo punto abbiamo risolto il primo errore.

    Secondo problema: all'apertura (OnLoad) delle maschere di inserimento dati adesso mi dà l'errore "91-Variabile oggetto o variabile del blocco With non impostata".
    Però la variabile mArray() è impostata nelle dichiarazioni iniziali del modulo. Non capisco. Che succede?

    Alex66
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    Fai debug mettendo un breackpoint su load dell'oggetto form
    nella classe clsForm... e da li segui il codice... verifica se l'array è già valorizzato o meno...
    Il codice che hai scritto nel property SET FORM... lascia molto a desiderare... il controllo prima gia cerca la subform va da se che se non si verifica la condizione sopra si verifica la tua...
    Quindi:
    If .... then

    Else

    End if.
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    @Alex ha scritto:


    Fai debug mettendo un breackpoint su load dell'oggetto form
    nella classe clsForm... e da li segui il codice... verifica se l'array è già valorizzato o meno...
    Il codice che hai scritto nel property SET FORM... lascia molto a desiderare... il controllo prima gia cerca la subform va da se che se non si verifica la condizione sopra si verifica la tua...
    Quindi:
    If .... then

    Else

    End if.
    Ho reimpostato le If come da te indicato e tolto la <And ctl.ControlType <> acSubform> nella prima If dell'Else, e modificato la riga del redim dell'array per delimitare gli elementi della matrice alla giusta quantità massima (Count - 1) così:
    
    
        ReDim Preserve mArray((mfrm.Controls.Count) - 1)
    
        For Each ctl In mfrm.Controls
            
            If ctl.ControlType = acSubform Then
                Call AddEventsHandler(ctl.Form)
            Else
                If ctl.ControlType <> acImage And ctl.ControlType <> acBoundObjectFrame Then
                    If HasProperty(ctl, "ControlSource") And HasProperty(ctl, "TabIndex") Then
                        If Len(ctl.ControlSource) > 0 And Not ctl.ControlSource Like "=*" Then
                            Set mArray(ctl.TabIndex).ctl = ctl
                        End If
                    End If
                End If
            End If
            
    
    Poi ho inserito il breakpoint sulla riga <Case Is = "OnLoad"> della stessa routine ma mi dà sempre errore 91 (che ho verificato viene dalla gestione degli errori alla riga <Err_Events:>), senza aprire il debug e senza valorizzare le variabili locali. Sono risalito con il breakpoint fino alla riga <Set rs = DBEngine(0)(0).etc...> con lo stesso risultato.
    Ho messo il breakpoint sul <Next> di <For Each...> e finalmente mi si apre il debug.
    Andando a scorrere le variabili locali in Me--->mArray di Tipo Control(0 to 34), essendo il Count 35, ci sono tutti gli elementi di Tipo Control denominati da mArray(0) a mArray(34). Ho provato anche su un'altra maschera con Count 58 e si comporta alla stessa maniera (da 0 a 57).
    Però nella colonna Valore a tutti c'è Nothing. Non è che bisogna modificare la riga <Set mArray(ctl.TabIndex).ctl = ctl>, ma non so come fare?

    Alex66
  • Re: For Each su controlli maschera in ordine crescente secondo la proprietà TabIndex

    Devi usare Optioj Base 1 altrimenti hai un disallineamento tra il TabIndex che parte da 1 e LBOUND dell'array che parte da 0... ma il problema è che il TabIndwx 35 genera sicuramente l'errore...
    Quindi o scali di 1 sempre il TabIndex oppure forzi con Option base 1 la gestione degli Array nella classe con LBOUND=1
Devi accedere o registrarti per scrivere nel forum
14 risposte