IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Discussion :

Créez des formulaires de dialogue avec acDialog et sans variable globale [Trucs & Astuces]


Sujet :

Contribuez

  1. #1
    Responsable Access

    Avatar de Arkham46
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    5 865
    Détails du profil
    Informations personnelles :
    Localisation : France, Loiret (Centre)

    Informations forums :
    Inscription : Septembre 2003
    Messages : 5 865
    Points : 14 524
    Points
    14 524
    Par défaut Créez des formulaires de dialogue avec acDialog et sans variable globale
    Bonjour,

    Pour remplacer les boîtes de dialogue MsgBox et InputBox, on peut créer des formulaires personnalisés et les ouvrir avec OpenForm et le paramètre acDialog.
    Le problème est que lorsque OpenForm nous rend la main, le formulaire est fermé et ne peut pas lire le résultat.

    Il y a des solutions discutables avec des variables globales ou des boucles d'attente.

    Ici l'astuce consiste à rendre invisible le formulaire (Visible = False) au lieu de le fermer.
    Le programme appelant reprend la main dès que le formulaire de dialogue est rendu invisible, et on peut lire le résultat avant de le fermer définitivement.

    Pour mettre tout ça en pratique, insérez ce code dans le formulaire de dialogue :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    Option Compare Database
    Option Explicit
     
    '--------------------------------------------------------------------------------
    ' Formulaire dialogue
    '--------------------------------------------------------------------------------
    ' Définissez le résultat si fermeture dans Form_Unload, à la place des XXXXXX
    ' Définissez les résultats avec la propriété Result (Result = LaValeur)
    '--------------------------------------------------------------------------------
     
    ' Variable contenant le résultat
    Dim lResult As Variant
     
    '-------------------------------------------------
    ' Propriété de lecture/écriture du résultat
    '-------------------------------------------------
    Private Property Let Result(pResult As Variant)
    ' Met à jour le résultat
    lResult = pResult
    ' Rend le formulaire invisible pour rendre la main au programme appelant
    Me.Visible = False
    End Property
    Public Property Get Result() As Variant
    Result = lResult
    End Property
     
    '-------------------------------------------------
    ' Sur fermeture du formulaire
    '-------------------------------------------------
    Private Sub Form_Unload(Cancel As Integer)
    ' Seulement si le formulaire est visible
    ' Sinon le formulaire doit se fermer
    If Me.Visible Then
        ' Résultat si formulaire fermé
        Result = XXXXXX
        ' Annule la fermeture (le formulaire sera fermé par l'appelant)
        Cancel = True
    End If
    End Sub
    - Remplacez les XXXXXX par le résultat à renvoyer en cas de fermeture du formulaire.
    - Mettez à jour le résultat en fonction des actions sur le formulaire (click, mise à jour de contrôle, ...) avec la propriété Resultat.

    L'écriture dans cette propriété redonne la main au programme appelant.
    Si vous ne souhaitez pas ce comportement, retirez la ligne Me.Visible = False et insérez la à l'endroit où vous voulez redonner la main à l'appelant.

    Ensuite dans le code appelant le formulaire de dialogue :
    - Définissez une variable pour recevoir le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Dim lResult As Variant ' Modifier Variant par le type de données utilisé
    - Ouvrez le formulaire en mode dialogue :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ' Ouvre le formulaire en mode dialogue
    DoCmd.OpenForm "MonFormulaireDialogue", , , , , acDialog
    - Récupérez le résultat avec la propriété Result :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ' Récupère le résultat lorsque le formulaire est rendu invisible
    lResult = Forms("MonFormulaireDialogue").Result
    - Fermez le formulaire de dialogue (il est invisible mais il faut le fermer) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ' Ferme le formulaire invisible
    DoCmd.Close acForm, "MonFormulaireDialogue"
    lResult contient le résultat.

    On peut mettre ce code dans une fonction dans un module standard :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Public Function OpenDialogForm(pFormName As String, Optional pOpenArg As String) As Variant
    ' Ouvre le formulaire en mode dialogue
    DoCmd.OpenForm pFormName, , , , , acDialog, pOpenArg
    ' Récupère le résultat lorsque le formulaire est rendu invisible
    OpenDialogForm = Forms(pFormName).Result
    ' Ferme le formulaire invisible
    DoCmd.Close acForm, pFormName
    End Function
    Le code appelant est alors réduit à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Dim lResult As Variant
    ' Ouvre le formulaire de dialogue
    lResult = OpenDialogForm("MonFormulaireDialogue")
    En pièce-jointe, un petit exemple.
    Fichiers attachés Fichiers attachés

  2. #2
    Expert confirmé

    Homme Profil pro
    consultant développeur
    Inscrit en
    Mai 2005
    Messages
    2 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : consultant développeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 878
    Points : 4 754
    Points
    4 754
    Par défaut
    Merci Arkham !
    Je suis toujours admiratif et ... preneur de ces leçons de finesse !
    "Always look at the bright side of life." Monty Python.

  3. #3
    Modérateur
    Avatar de Chtulus
    Homme Profil pro
    Ingénieur
    Inscrit en
    Avril 2008
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Santé

    Informations forums :
    Inscription : Avril 2008
    Messages : 3 094
    Points : 8 678
    Points
    8 678
    Par défaut
    Bonsoir Arkham,

    « Je ne cherche pas à connaître les réponses, je cherche à comprendre les questions. »
    - Confucius -

    Les meilleurs cours, tutoriels et Docs sur les SGBD et le SQL
    Tous les cours Office
    Solutions d'Entreprise



  4. #4
    Membre expérimenté
    Homme Profil pro
    Développeur VBA Access
    Inscrit en
    Avril 2006
    Messages
    1 109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur VBA Access

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 109
    Points : 1 535
    Points
    1 535
    Par défaut
    Bonsoir,

    une alternative utiliser un objet PILE avec deux méthodes PUSH et POP.

    Maintenant pour l'objet PILE deux classes
    classe ClREGISTRE
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    ' ================================================================================================================================================
    '|| Module     :  ClREGISTRE
    '|| Créé le      : 29-05-2008
    '|| Modifié le :
    '|| Rôle          : Registre de pile LIFO ou FIFO et LISTE CHAINEE
    '||
    '||------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    '||
    '|| Tables          :
    '|| Objets          :
    '|| Formulaires  :
    '|| Menus          :
    ' ================================================================================================================================================
    Public ElementValue
    Public PreviousItem As ClREGISTRE
    Public NextItem As ClREGISTRE
    classe ClSTACK
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    ' ================================================================================================================================================
    '|| Module     :  ClSTACK
    '|| Créé le      : 29-05-2008
    '|| Modifié le :
    '|| Rôle          : Objet Pile de type LIFO (Last IN First Out) Dernier entré-Premier sorti
    '||
    '||------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    '||
    '|| Tables          :
    '|| Objets          :
    '|| Formulaires  :
    '|| Menus          :
    ' ================================================================================================================================================
    Private PtrSTACK As ClREGISTRE
    Private StackSize As Long
    Private SizeAllowed As Long
    Const DEFAULT_STACKSIZE = 32768
    '-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    'Procédure       : PUSH
    'Créée le         : 02-06-2008          Modifée le :
    '
    'Rôle              : Place un nouvel élément dans la pile
    '
    ' Arguments   : ENTRYVALUE : (Variant) élément à charger dans pile STCK_PILE
    '
    ' Tables          : (aucune)
    '
    '  Objets         : STCK_ENTRY (Cl_StackElement)
    '
    ' Variables      :
    '
    '-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Public Function push(ByVal EntryValue)
        Dim STCK_Entry  As ClREGISTRE
        If StackSize + Len(EntryValue) < SizeAllowed Then
            Set STCK_Entry = New ClREGISTRE
        Else
            Set STCK_Entry = PtrSTACK
        End If
     
        If IsObject(EntryValue) Then
            Set STCK_Entry.ElementValue = EntryValue
        Else
             STCK_Entry.ElementValue = EntryValue
        End If
        Set STCK_Entry.NextItem = PtrSTACK
        Set PtrSTACK = STCK_Entry
        StackSize = StackSize + Len(STCK_Entry.ElementValue)
    End Function
    '-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    'Fonction       : POP (Variant)
    'Créée le         : 02-06-2008          Modifée le :
    '
    'Rôle              : Retire de la pile le dernier élément chargé
    '
    ' Arguments   : (aucun)
    '
    ' Tables          : (aucune)
    '
    '  Objets         : (aucun)
    '
    ' Variables      :
    '
    '-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Public Function pop()
        Dim STCK_Entry As Object
        If (PtrSTACK Is Nothing) Then Exit Function
        Set STCK_Entry = PtrSTACK.NextItem
        If IsObject(PtrSTACK.ElementValue) Then
            Set pop = PtrSTACK.ElementValue
        Else
            pop = PtrSTACK.ElementValue
        End If
        StackSize = StackSize - Len(PtrSTACK.ElementValue)
        Set PtrSTACK = Nothing
        Set PtrSTACK = STCK_Entry
    End Function
     
    Private Sub Class_Initialize()
        Set PtrSTACK = Nothing
        SizeAllowed = DEFAULT_STACKSIZE
    End Sub

    Dans un module supplémentaire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Private PILE As ClSTACK
     
    Public Sub push (lValeur)
     If (PILE Is Nothing) Then Set PILE=New ClSTACK
     PILE.push lValeur
    End Sub
     
    Public Function pop () 
     If Not (PILE Is Nothing) Then pop=PILE.pop
    End Function
    Le module d'Arkham
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Public Function OpenDialogForm(pFormName as String, pOpenArg as String) As Variant
     Docmd.OpenForm FormName:=pFormName, WindowMode:=acDialog
     OpenDialogForm=pop
    End function
    Pour le formulaire FormDialog1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    Dim lResult As Variant
    '-------------------------------------------------
    ' Click sur bouton Yes
    '-------------------------------------------------
    Private Sub btnYes_Click()
    lResult = vbYes
    DoCmd.Close acDataForm, Form.Name
    End Sub
     
    '-------------------------------------------------
    ' Click sur bouton No
    '-------------------------------------------------
    Private Sub btnNo_Click()
    lResult = vbNo
    DoCmd.Close acDataForm, Form.Name
    End Sub
     
    Private Sub Form_Close()
        push lResult
    End Sub
     
    Private Sub Form_Load()
        lResult = vbCancel
    End Sub

  5. #5
    Expert confirmé Avatar de nico84
    Homme Profil pro
    Consultant/développeur ERP
    Inscrit en
    Mai 2008
    Messages
    3 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant/développeur ERP
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 3 087
    Points : 5 203
    Points
    5 203
    Par défaut
    Bonjour,

    Merci, c'est clair, élégant et ça peut me servir

    Il y a des solutions discutables avec des variables globales ou des boucles d'attente.
    En quoi l'utilisation d'une variable globale est-elle discutable ? Y a-t-il des risques de conflit si plusieurs utilisateurs utilisent la même variable au même moment (dans le cas d'un exécutable sur le serveur) ???
    Utilisez Planet, gestion d'entreprise gratuite pour TPE / PME

  6. #6
    Responsable Access

    Avatar de Arkham46
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    5 865
    Détails du profil
    Informations personnelles :
    Localisation : France, Loiret (Centre)

    Informations forums :
    Inscription : Septembre 2003
    Messages : 5 865
    Points : 14 524
    Points
    14 524
    Par défaut
    Citation Envoyé par nico84 Voir le message
    En quoi l'utilisation d'une variable globale est-elle discutable ? Y a-t-il des risques de conflit si plusieurs utilisateurs utilisent la même variable au même moment (dans le cas d'un exécutable sur le serveur) ???
    Non pas de risque en cas d'utilisation multi-utilisateurs, les variables sont propres à l'environnement d'exécution, donc à chaque utilisateur.

    Là où on peut discuter c'est que les variables globales ont une durée de vie ... globale.
    C'est à dire qu'en cas d'utilisation de telles variables, il faut bien les initialiser avant chaque appel au formulaire dialogue, et même les vider ensuite si on ne veut pas qu'elles occupent de la mémoire inutilement (même si c'est souvent qu'une petite quantité de mémoire) ou soient réutilisées à tort.
    Si on ajoute une variable et qu'on oublie de l'initialiser à un endroit (on peut utiliser une même variable pour plusieurs appels du formulaire) on risque le bug.
    Et on se retrouve vite avec un module qui contient beaucoup de variables et il faut commenter chacune pour savoir à quoi elle sert et dans quelles fonctions elles sont utilisées.
    Bien codé ça marche quand même bien.

    Pour moi l'avantage de la méthode ci-dessus c'est que les variables ont automatiquement une durée de vie égale à la durée de vie du formulaire dialogue.
    Et en plus on peut ajouter autant de propriétés qu'on souhaite pour faire un formulaire qui retourne plusieurs valeurs.
    Tout ce qui concerne un formulaire de dialogue est intégré à ce formulaire, c'est plus facile à maintenir : pas besoin d'aller chercher des variables dans un autre module, pas besoin de parcourir toute l'appli pour penser à bien initialiser chaque variable.

  7. #7
    Expert confirmé Avatar de nico84
    Homme Profil pro
    Consultant/développeur ERP
    Inscrit en
    Mai 2008
    Messages
    3 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant/développeur ERP
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 3 087
    Points : 5 203
    Points
    5 203
    Par défaut
    Merci pour cette réponse détaillée

    Ce qui est magique dans cette affaire c'est que si je comprends bien rend la main au formulaire appelant

    J'utilise aussi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Me.parent.monchamp=resultat
    dans la fenêtre de dialogue mais c'est lourd
    Utilisez Planet, gestion d'entreprise gratuite pour TPE / PME

Discussions similaires

  1. [Article] Créez des formulaires fabuleux avec HTML5
    Par Bovino dans le forum Publications (X)HTML et CSS
    Réponses: 2
    Dernier message: 26/05/2014, 12h24
  2. [HTML 5] Créez des formulaires fabuleux avec HTML5
    Par Bovino dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 21/05/2012, 20h46
  3. Créez des formulaires sans table avec le Data Shaping ADO
    Par Lou Pitchoun dans le forum Contribuez
    Réponses: 5
    Dernier message: 26/01/2009, 21h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo