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 :

[FàQ] Comment numéroter les enregistrements d'un [sous-][sous-]formulaire.


Sujet :

Contribuez

  1. #21
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut
    Bonjour,

    Hâtez-vous lentement, et sans perdre courage,
    Vingt fois sur le métier remettez votre ouvrage,
    Polissez-le sans cesse, et le repolissez,
    Ajoutez quelquefois, et souvent effacez.
    (Boileau, L’Art Poétique)
    Autre citation illustre :

    J'ai surtout l'impression que tu sombres dans un piège bien connu : le nez dans le code, on cherche des solutions de plus en plus sophistiquées... et on passe à côté du plus simple. Je te conseillerai simplement de laisser ce sujet de côté pendant une bonne semaine, puis de relire le tout et faire ton choix.
    Il y a longtemps, j'ai dû apprendre la première pas coeur . Un demi siècle plus tard, dire que la seconde m’ait fait plaisir serait grandement exagéré.

    Mais Papy Turbo avait raison !

    Le code de la livraison précédente transpire la douleur. Cela a été enfanté avec peine, et aux forceps !
    Je m’étais imposé d’écrire une fonction publique unique plutôt qu’une privée à recopier dans chaque formulaire.
    Par principe, pour faciliter la maintenance éventuelle.

    J’ai réécrit plus léger :
    - au départ des « en 4 lignes » de Papy Turbo
    - en ajoutant un peu de code pour libérer la contrainte d’une valeur unique obligatoirement numérique
    - et dans une fonction privée.

    J’ai actualisé le texte d’un post précédent, pour faciliter la lecture d'une proposition finale.

    Le but de l'exercice :

    Trouver un moyen « passe-partout » pour numéroter les enregistrements d’un formulaire (souvent en continu),
    - quelle que soit la position de ce formulaire dans la hiérarchie ([sous]-[sous]…[formulaire],
    - quel soit le nombre de formulaires numérotés ouverts,
    - que l’on puisse consulter, mettre à jour, supprimer, ajouter ou modifier les filtres,
    - avec un maximum de facilité pour l’implanter dans une DB existante (en tout cas à partir de [Access2000]).

    Consignes d’utilisation

    Le formulaire doit contenir au moins un contrôle dont la source correspond à une valeur sans doublon.
    Quel qu’en soit le type donc pas nécessairement un autonum ni une clé. Indifféremment du numérique, du texte ou une date. Mais UNIQUE.

    Le contrôle de numérotation aura comme source :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    =NumeroterLignes(NomDuContrôle à ValeurUnique)
    Exemple =NumeroterLignes("ztDENOMINATION")

    Dans tous les événements susceptibles de modifier l’ordre
    Me.Refresh (renuméroter) ou Me.Requery (se repositionner au début) selon l’effet recherché.

    Dans le code associé au formulaire, la fonction privée suivante :
    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
    Private Function NumeroterLignes(CtlValUnique As String) As Long
    Dim TypeDonnee As Integer
       'déterminer le type du RecordSource de CtlValUnique
            'pour choisir la bonne syntaxe de comparaison
        With Me.RecordsetClone
              If IsNumeric(Me(CtlValUnique)) Then
                .FindFirst "[" & Me(CtlValUnique).ControlSource & "] = " & Me(CtlValUnique)
                GoTo Attribuer
              ElseIf IsDate(Me(CtlValUnique)) Then
                .FindFirst "[" & Me(CtlValUnique).ControlSource & "] = #" & Format(Me(CtlValUnique), "mm/dd/yy") & "#"
                 GoTo Attribuer
              Else   'c'est donc du texte
                .FindFirst "[" & Me(CtlValUnique).ControlSource & "] = """ & Me(CtlValUnique) & """"
              End If
    Attribuer:
            NumeroterLignes = .AbsolutePosition + 1
        End With
    End Function
    L’idée

    Le numéro d’ordre de chaque enregistrement correspond à sa position (AbsolutePosition) dans le RecordSet du formulaire.
    Le processus consiste à rechercher cette position en localisant la valeur courante du champ à valeur sans doublon.
    La syntaxe de cette recherche diffère selon le type de données (numérique, date, texte).


    En pièce jointe un exemple d’utilisation en [Access2000].
    Les formulaires «ChampUniqueDATE », « ChampUnique NUMERIQUE » et « ChampUniqueTEXTE » montrent que cela fonctionne avec des valeurs uniques de tout type.
    Les formulaires «Ex2emeNiveau» et «Ex3emeNiveau» montrent un sous-formulaire qui évolue en fonction d’un champ dans le formulaire principal. (refresh après MàJ)


    Merci déjà pour vos remarques et suggestions.

  2. #22
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    Bonjour, Claude,

    Super. Ah, que voilà une belle routine super utile

    Juste un bref rappel, puisque tu veux une routine publique donc unique, la recherche du formulaire par Arkham (+ haut) te permet de remplacer Me par le parent du contrôle.
    Sinon, copiée dans chaque formulaire, j'aurais tendance à inclure aussi les 3 .Findfirst selon les types, mais à en mettre 2 en commentaire, au cas par cas. Sans le Select Case ?

  3. #23
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut
    Bonjour à tous,

    C’est mon dernier, sauf si des corrections syntaxiques s’imposaient …

    Cette nouvelle livraison a un air de fromage belge : un peu de tout pour satisfaire le plus grand nombre.
    Eh oui, amis hexagonaux, dans ce pays, il n'y a pas que des blagues, il y a aussi du fromage !

    Cette proposition est un compromis (autre spécialité belge) entre les suggestions de Papy Turbo, Arham46 et mon intention d’origine : une solution passe-partout.

    Pour ceux qui ne sont pas préoccupés par les performances ( ex : leur formulaire à numéroter est tel que la différence est imperceptible pour l’utilisateur), je propose la formule : « Fonction publique ».

    Pour les autres, la formule : « Fonction privée sur mesure ».


    Formule « Fonction publique »


    La source du contrôle de numérotation fait appel à la fonction publique « NumeroterLignes », avec comme paramètre entre crochets le nom du champ sans doublon. Exemple :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    =NumeroterLignes([ztid])
    La fonction publique « NumeroterLignes » est logée dans un module :

    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
    Public Function NumeroterLignes(CtlValUnique As Access.Control) As Long
    Dim loParent As Object
    ' Recherche le formulaire parent
    Set loParent = CtlValUnique
       Do  ' Boucle nécessaire au cas où le parent du contrôle soit un contrôle à onglet par exemple
           Set loParent = loParent.Parent
           If TypeOf loParent Is Access.Form Then
                 Exit Do  'loParent = l'objet formulaire contenant le contrôle donné en paramètre
           End If
       Loop
    With loParent.RecordsetClone
       'déterminer le type du RecordSource de CtlValUnique
            'pour choisir la bonne syntaxe de comparaison
      If IsNumeric(CtlValUnique.Value) Then
          .FindFirst "[" & CtlValUnique.ControlSource & "] = " & CtlValUnique.Value
          GoTo Attribuer
      ElseIf IsDate(CtlValUnique.Value) Then
          .FindFirst "[" & CtlValUnique.ControlSource & "] = #" & Format(CtlValUnique.Value, "mm/dd/yy") & "#"
          GoTo Attribuer
      Else   'c'est donc du texte
          .FindFirst "[" & CtlValUnique.ControlSource & "] = """ & CtlValUnique.Value & """"
      End If
    Attribuer:
     NumeroterLignes = .AbsolutePosition + 1
    End With
    End Function
    Dans l’exemple joint, cette technique est utilisée pour tous les formulaires sauf « ChampUniqueDATE »


    Formule : « Fonction privée sur mesure »

    La source du contrôle de numérotation fait appel à la fonction privée « NumeroterLignesPriv », avec comme paramètre entre double quotes le nom du champ sans doublon. Exemple :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    =NumeroterLignesPriv("ztDATEACHAT")
    La fonction privée est logée dans le code associé au formulaire

    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
    Private Function NumeroterLignesPriv(CtlValUnique As String) As Long
    Dim TypeDonnee As Integer
       'déterminer le type du RecordSource de CtlValUnique
            'pour choisir la bonne syntaxe de comparaison
        With Me.RecordsetClone
        ' Enlevez l'apostrophe de mise en commentaire de la ligne
        '                  .FindFirst qui convient à votre cas spécifique
     
        '' CtlValUnique est une date
                .FindFirst "[" & Me(CtlValUnique).ControlSource & "] = #" & Format(Me(CtlValUnique), "mm/dd/yy") & "#"
        '*
        ''CtlValUnique est numérique
        '        .FindFirst "[" & Me(CtlValUnique).ControlSource & "] = " & Me(CtlValUnique)
        '*
        ''CtlValUnique est du texte
        '        .FindFirst "[" & Me(CtlValUnique).ControlSource & "] = """ & Me(CtlValUnique) & """"
        '*
            NumeroterLignesPriv = .AbsolutePosition + 1
        End With
    End Function
    Dans l’exemple joint, cette technique est utilisée pour le formulaire « ChampUniqueDATE ».

    Merci encore à Papy Turbo, Arkham46 et pier.antoine pour leur contribution.

  4. #24
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut
    Bonjour,
    Une erreur détectée à l'usage (lorsque la fonction tente de numéroter le futur enregistrement à ajouter).
    Voici la correction de la fonction :
    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
    Public Function NumeroterLignes(CtlValUnique As Access.Control) As Long
    Dim loParent As Object
    ' Recherche le formulaire parent
    Set loParent = CtlValUnique
       Do  ' Boucle nécessaire au cas où le parent du contrôle soit un contrôle à onglet par exemple
           Set loParent = loParent.Parent
           If TypeOf loParent Is Access.Form Then
                 Exit Do  'loParent = l'objet formulaire contenant le contrôle donné en paramètre
           End If
       Loop
    With loParent.RecordsetClone
       'déterminer le type du RecordSource de CtlValUnique
            'pour choisir la bonne syntaxe de comparaison
      If IsNull(CtlValUnique.Value) Then   'ce cas survient pour le nouveau record à créer
          NumeroterLignes = 0
          Exit Function
      End If
      If IsNumeric(CtlValUnique.Value) Then
          .FindFirst "[" & CtlValUnique.ControlSource & "] = " & CtlValUnique.Value
          GoTo Attribuer
      ElseIf IsDate(CtlValUnique.Value) Then
          .FindFirst "[" & CtlValUnique.ControlSource & "] = #" & Format(CtlValUnique.Value, "mm/dd/yy") & "#"
          GoTo Attribuer
      Else   'c'est donc du texte
          .FindFirst "[" & CtlValUnique.ControlSource & "] = """ & CtlValUnique.Value & """"
      End If
    Attribuer:
     NumeroterLignes = .AbsolutePosition + 1
    End With
    End Function

  5. #25
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    Bravo pour le test.

    Juste pour être en cohérence avec Access (nouvel enregistrement à la fin), puis je suggérer de mettre le dernier n° + 1 ?
    Éventuellement aussi, utiliser .NewRecord du formulaire...
    Genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    [...]
    With loParent.RecordsetClone
       'déterminer le type du RecordSource de CtlValUnique
            'pour choisir la bonne syntaxe de comparaison
      If loParent.NewRecord Then   'ce cas survient pour le nouveau record à créer
          NumeroterLignes = .RecordCount + 1
          Exit Function
      End If
      [...]
    à tester, bien sûr

  6. #26
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut
    Bonjour PapyTurbo,

    Ce n’est pas la création d’un new qui faisait problème, c’est quand la fonction essayait de numéroter l’emplacement réservé au futur New éventuel, la dernière ligne encore vierge sauf si elle contient des champs avec une valeur par défaut.
    Vois les 3 exemples en pièce jointe.
    ChampUniqueNUMERIQUE fonctionne – correctement – en appelant la version corrigée.
    ChampUniqueNUMERIQUE_AvecErreurxxxxx appellent l’ancienne version.
    Le phénomène se produit à cause du champ Id qui est autonum., ou date qui a une valeur par défaut.
    Malheureusement de tels cas ne faisaient partie de mes jeux de test : errare humanum est.

  7. #27
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut
    Ps J'ai testé "loParent.NewRecord" : il n'est pas détecté, lorsque la Sub tente de numéroter cette ultime "future" ligne.

    Merci pour ton intérêt.

  8. #28
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    Citation Envoyé par ClaudeLELOUP Voir le message
    Ps J'ai testé "loParent.NewRecord" : il n'est pas détecté, lorsque la Sub tente de numéroter cette ultime "future" ligne.
    Autant pour moi ! la ligne du nouvel enregistrement n'est pas active pendant le calcul !

    Sinon, l'idée du .RecordCount, c'était pour continuer l'affichage jusqu'au bout :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      If IsNull(CtlValUnique.Value) Then   'ce cas survient pour le nouveau record à créer
          NumeroterLignes = .RecordCount + 1
          Exit Function
      End If
    et le test dans ton dernier exemple semble bien marcher (voir image).
    Images attachées Images attachées  

  9. #29
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut Co'n'rawète !
    Bonjour,

    Juste pour être en cohérence avec Access (nouvel enregistrement à la fin), puis je suggérer de mettre le dernier n° + 1 ?
    Si c'est Papy Turbo qu'il dit ...

    Voici la version corrigée de la fonction "Public"

    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
    Public Function NumeroterLignes(CtlValUnique As Access.Control) As Long
    Dim loParent As Object
    ' Recherche le formulaire parent
    Set loParent = CtlValUnique
       Do  ' Boucle nécessaire au cas où le parent du contrôle soit un contrôle à onglet par exemple
           Set loParent = loParent.Parent
           If TypeOf loParent Is Access.Form Then
                 Exit Do  'loParent = l'objet formulaire contenant le contrôle donné en paramètre
           End If
       Loop
    With loParent.RecordsetClone
       'déterminer le type du RecordSource de CtlValUnique
            'pour choisir la bonne syntaxe de comparaison
      If IsNull(CtlValUnique.Value) Then   'ce cas survient pour le nouveau record à créer
          NumeroterLignes = .RecordCount + 1
          Exit Function
      End If
      If IsNumeric(CtlValUnique.Value) Then
          .FindFirst "[" & CtlValUnique.ControlSource & "] = " & CtlValUnique.Value
          GoTo Attribuer
      ElseIf IsDate(CtlValUnique.Value) Then
          .FindFirst "[" & CtlValUnique.ControlSource & "] = #" & Format(CtlValUnique.Value, "mm/dd/yy") & "#"
          GoTo Attribuer
      Else   'c'est donc du texte
          .FindFirst "[" & CtlValUnique.ControlSource & "] = """ & CtlValUnique.Value & """"
      End If
    Attribuer:
     NumeroterLignes = .AbsolutePosition + 1
    End With
    End Function
    et pour la fonction "Private" :
    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
    Private Function NumeroterLignesPriv(CtlValUnique) As Long
    Dim TypeDonnee As Integer
       'déterminer le type du RecordSource de CtlValUnique
            'pour choisir la bonne syntaxe de comparaison
        With Me.RecordsetClone
        If IsNull(Me(CtlValUnique)) Then    'ce cas survient pour le nouveau record à créer
          NumeroterLignesPriv = .RecordCount + 1
        End If
        ' Enlevez l'apostrophe de mise en commentaire de la ligne
        '                  .FindFirst qui convient à votre cas spécifique
     
        '' CtlValUnique est une date
                .FindFirst "[" & Me(CtlValUnique).ControlSource & "] = #" & Format(Me(CtlValUnique), "mm/dd/yy") & "#"
        '*
        ''CtlValUnique est numérique
        '        .FindFirst "[" & Me(CtlValUnique).ControlSource & "] = " & Me(CtlValUnique)
        '*
        ''CtlValUnique est du texte
        '        .FindFirst "[" & Me(CtlValUnique).ControlSource & "] = """ & Me(CtlValUnique) & """"
        '*
            NumeroterLignesPriv = .AbsolutePosition + 1
        End With
    End Function
    En pièce jointe l'actuelle "dernière" version.
    Bien à vous.

  10. #30
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 371
    Points : 19 774
    Points
    19 774
    Billets dans le blog
    65
    Par défaut
    Salut Claude,

    Etant d'un tempérament plus que fainéant , je n'ai pas lu la totalité de la discussion.

    Cependant je me posais juste une question :

    S'il s'agit de donner 1 numéro d'ordre à chaque enregistrement d'1 formulaire ou sous-formulaire en mode feuille de données ou mode continu, pourquoi ne pas utiliser une variable IndEnrg déclarée dans le module du formulaire, que l'on initialise à l'ouverture du formulaire.

    Puis utiliser une fonction FunNumero déclarée également dans le module du formulaire et que tu mets comme toi sur la source du contrôle de numérotation: A chaque appel de la fonction on incrémente le compteur d'enrg.

    Voici le code du module du formulaire :

    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
    Option Compare Database
     
    Dim IndEnrg As Long
     
    Function FunNumero(Chp As Variant) As Variant
     
     If (IndEnrg <> -1) Then
     
         If Not IsNull(Chp) Then
         FunNumero = CStr(IndEnrg + 1)
         IndEnrg = IndEnrg + 1
     
          Me.RecordsetClone.MoveLast
     
             If Me.RecordsetClone.RecordCount = IndEnrg Then
                IndEnrg = 0
             End If
     
         End If
     
       Else
          FunNumero = "[Nouvel Enrg.]"
       End If
     
    End Function
     
    Private Sub Form_AfterDelConfirm(Status As Integer)
    IndEnrg = 0
    Me.Numero.Requery
     
    End Sub
     
    Private Sub Form_AfterInsert()
    IndEnrg = 0
    Me.Numero.Requery
     
    End Sub
     
    Private Sub Form_AfterUpdate()
    IndEnrg = 0
    Me.Numero.Requery
     
    End Sub
     
    Private Sub Form_BeforeInsert(Cancel As Integer)
    IndEnrg = -1
     
    End Sub
     
    Private Sub Form_Load()
    IndEnrg = 0
     
     
    End Sub
    Il me semble que l'on peux faire la même chose avec la propriété AbsolutePosition du recordset source du form.

    Mais peut-être que tout cela a déjà été abordé

    C'est juste une idée comme ça et ça n'a rien de très prétentieux

  11. #31
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut
    Hello User,

    Content de te croiser ici.


    La solution que tu proposes ne fonctionne que dans un cas très particulier : la taille du formulaire est telle que tous les enregistrements sont affichés à l’écran.
    Dans ce cas, la fonction est appelée, dans l’ordre, pour chaque enregistrement.
    Par contre, si tu dois faire appel à l’ascenseur, la fonction attribue un numéro aux enregistrements nouvellement affichés. Ce numéro ne représente pas le classement des enregistrements mais correspond à l’ordre d’apparition à l’écran. Et il n’est pas stable : un enregistrement qui n’est plus affiché perd son numéro et s’il revient à l’écran, il sera affecté d’un autre numéro.
    Vois l’exemple du formulaire « ChampUniqueTEXTE_User », je l’ouvre au dernier record. Fais fonctionner l’ascenseur et tu comprendras.

    Etant d'un tempérament plus que fainéant , je n'ai pas lu la totalité de la discussion.
    Lis le poste 23, tout est là.

    Cordialement.
    Fichiers attachés Fichiers attachés

  12. #32
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 371
    Points : 19 774
    Points
    19 774
    Billets dans le blog
    65
    Par défaut
    OK, merci pour le test,

    C'est juste une idée

    Je vais voir si je peux améliorer les choses en gardant la même idée...

    [Edit] C'est vrai que cette solution est trop dépendante de l'affichage...

    A+

  13. #33
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 371
    Points : 19 774
    Points
    19 774
    Billets dans le blog
    65
    Par défaut
    Salut Claude,

    On peut s'en sortir en récupérant la propriété bookmark du formulaire dans la fonction FunNumero:

    La propriété "source contrôle" de la zone de texte "numero" devient alors :

    Et le module:

    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
    Option Compare Database
     
    Public Function FunNumero() As Variant
     
    On Error GoTo err_Numero
     
    Me.RecordsetClone.Bookmark = Me.Bookmark
     
       If Not Me.NewRecord Then
     
          FunNumero = Me.RecordsetClone.AbsolutePosition + 1
     
       Else
     
          FunNumero = Me.RecordsetClone.RecordCount + 1
     
       End If
     
    Exit Function
     
    err_Numero:
     
    FunNumero = ""
     
     
    End Function
     
    Private Sub Form_AfterDelConfirm(Status As Integer)
     
       If Not Me.NewRecord Then
          Me.Numero.Requery
       End If
     
    End Sub
    A+

  14. #34
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut
    Chapeau !


  15. #35
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    Super, le bookmark ! Bravo bis.

    Petit bug (testé sur une copie de DENOMINATIONS, dans la base 2010-09-05 NuméroterLignesFormulaire5.mdb) :
    - [Ctrl +] (nouvel enregistrement) : la mention "[Nouvel enr.]" ne s'affiche pas.
    Et surtout, en restant toujours sur un nouveau :
    - [F9] > "[Nouvel enr.]" s'affiche sur toutes les lignes visibles !

    Pas trouvé de parade, à part supprimer tout le test "If NewRecord..."

  16. #36
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 371
    Points : 19 774
    Points
    19 774
    Billets dans le blog
    65
    Par défaut
    Salut Etienne,

    Tout seul c'est toujours difficile d'arriver à quelque chose

    Voici la fonction corrigée:
    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
     
    Public Function FunNumero() As Variant
     
    On Error GoTo err_Numero
     
    Me.RecordsetClone.Bookmark = Me.Bookmark
     
       If Not Me.NewRecord Then
     
          FunNumero = Me.RecordsetClone.AbsolutePosition + 1
     
       Else
     
          FunNumero = Me.RecordsetClone.RecordCount + 1
     
       End If
     
    Exit Function
     
    err_Numero:
     
    FunNumero = ""
     
     
    End Function
    Le mieux c'est aussi d'enlever les requery dans le module

    On peut garder éventuellement celui-ci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Private Sub Form_AfterDelConfirm(Status As Integer)
     
       If Not Me.NewRecord Then
          Me.Numero.Requery
       End If
     
    End Sub

    Merci...

  17. #37
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut
    Bonjour User, Bonjour Etienne,

    Tout seul c'est toujours difficile d'arriver à quelque chose
    Non Jef, t’es pas tout seul…

    Ce code devrait suffire :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Public Function FunNumero() As Variant
    Me.RecordsetClone.Bookmark = Me.Bookmark
    FunNumero = Me.RecordsetClone.AbsolutePosition + 1
    End Function

    De plus, tous les événements qui peuvent perturber l’ordre d’affichage (donc la numérotation) doivent provoquer un requery, à savoir : Form_AfterDelConfirm, Form_AfterInsert et dans l’exemple annexé, ztDENOMINATION_AfterUpdate (puisque ce champ est l’argument de tri).

    Cette syntaxe a un inconvénient : dans le cas où un ajout est permis, le numéro de la dernière ligne est marqué « Erreur ». Je présume que c’est la raison de ton test sur NewRecord.

    Pour contourner, ajouter ce code en début de la fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    '----------- A adapter ------------------
      '  Choisir un contrôle qui n'est jamais Null
       If IsNull(Me.ZtDENOMINATION) Then
          FunNumero = "[Nouvel Enrg.]"
          Exit Function
       End If
     '----------------------------------------
    En résumé

    1 La source du contrôle de numérotation :

    Un numéro pour le fun ?

    2 Dans le module associé au formulaire, ce code à adapter :

    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
    Option Compare Database
    Option Explicit
    Public Function FunNumero() As Variant
      '----------- A adapter ------------------
      '  Choisir un contrôle qui n'est jamais Null
       If IsNull(Me.ZtDENOMINATION) Then
          FunNumero = "[Nouvel Enrg.]"
          Exit Function
       End If
     '----------------------------------------
    'Cas banal
    Me.RecordsetClone.Bookmark = Me.Bookmark
    FunNumero = Me.RecordsetClone.AbsolutePosition + 1
    End Function
     
     
     
     
    Private Sub Form_AfterDelConfirm(Status As Integer)
    'dans tous les cas
    Me.Requery
    End Sub
     
    Private Sub Form_AfterInsert()
    'dans tous les cas
    Me.Requery
    End Sub
    '------------------------------------------------------------------------------------
    '-------- A adapter ------------------
    'Pour tous les contrôles dont la modif est susceptible de modifier l'ordre d'affichage
    ''------------------------------------------------------------------------------------
    Private Sub ztDENOMINATION_AfterUpdate()
    Me.Requery
    End Sub
    ''------------------------------------------------------------------------------------
    Qu'en pensez-vous ?

  18. #38
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 371
    Points : 19 774
    Points
    19 774
    Billets dans le blog
    65
    Par défaut
    Merci Claude,

    Pour contourner, ajouter ce code en début de la fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    '----------- A adapter ------------------
      '  Choisir un contrôle qui n'est jamais Null
       If IsNull(Me.ZtDENOMINATION) Then
          FunNumero = "[Nouvel Enrg.]"
          Exit Function
       End If
     '----------------------------------------
    Oui, j'ai pensé à cette solution,

    Mais justement, je veux éviter d'avoir à choisir un contrôle jamais null à l'ajout, pour que ma fonction reste indépendante de l'interface ou du formulaire:

    Quelle puisse être fonctionnelle directement par ajout du code et de la zdt "Numero".

    De plus, il faut aussi que ce contrôle n'est pas de valeur par défaut sinon à l'ajout ca va poser un problème.

    Comme tu pourra le constater dans mes derniers messages:
    J'ai enlevé la plupart des requery et j'utilise la même méthode que toi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FunNumero = Me.RecordsetClone.RecordCount + 1
    Si Me.NewRecord=True

    Pour mettre à jour le champ Numero sur ajout d'1 nouvel enregistrement.

    A+

  19. #39
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut
    Qu’elle puisse être fonctionnelle directement par ajout du code et de la zdt "Numero".
    Ce serait l’idéal. Mais je n’ai pas encore trouvé un autre moyen pour déterminer que la fonction est sollicitée pour calculer le numéro d’un futur [éventuel] nouveau record (la dernière ligne, si ajout autorisé)

    A mon avis, le test sur Me.NewRecord n’est pas adéquat : car il n’y aura « Me.NewRecord » qu’à l’instant où on commence à le créer.
    C’est-à-dire trop tard, car si on crée un nouveau record, comme celui-ci est susceptible de remettre l’ordre actuel en question, il faut provoquer le requery… et le problème ne se pose plus : le nouveau est intégré dans l’ensemble et reçoit « naturellement » son numéro parmi ses pairs.

    De plus, vois ce que Etienne signale.
    Dans le fichier joint, dans User2 (ton code), crée un nouveau record, sans le sauver, et actionne l’ascenseur ---> tous les records reçoivent RecordCount + 1 !

    J'ai enlevé la plupart des requery
    A mon avis ce n’est pas une bonne idée.
    pour la raison que je cite plus haut :

    De plus, tous les événements qui peuvent perturber l’ordre d’affichage (donc la numérotation) doivent provoquer un requery, à savoir : Form_AfterDelConfirm, Form_AfterInsert et dans l’exemple annexé, ztDENOMINATION_AfterUpdate (puisque ce champ est l’argument de tri).
    De plus, il faut aussi que ce contrôle n'ait pas de valeur par défaut
    Ça, c’est facile, il suffit d’en créer un avec la bonne source et le rendre invisible pour éviter tout malentendu.
    Fichiers attachés Fichiers attachés

  20. #40
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    Olla,

    D'accord avec Claude : NewRecord est lié à la position dans le recordset et, quoi qu'on fasse, la valeur choisie s'affichera dans tous les enregistrements.

    Ton idée de [Bookmark] m'a tellement plu que j'ai testé directement, dans le contrôle : =IIf([NewRecord];"[Nouv.]";FunNumero([Bookmark]))

    Ça marche, mais pas mieux que le test dans la fonction.

    Du coup, j'ai même testé =[AbsolutePosition] qui ne marche pas (propriété du recordset), et =[CurrentRecord], qui marche, mais qui affiche la valeur du compteur partout !

    Donc, pas mieux que Claude pour l'instant, avec son contrôle spécifique.

Discussions similaires

  1. Réponses: 1
    Dernier message: 29/07/2014, 17h41
  2. comment numéroter les onglets sous excel 2000
    Par PtiteNanou dans le forum Excel
    Réponses: 1
    Dernier message: 17/03/2008, 11h52
  3. [TRichEdit] Comment numéroter les lignes ?
    Par ARDILLER dans le forum Composants VCL
    Réponses: 1
    Dernier message: 27/03/2006, 15h43
  4. comment concaténer les enregistrements d'un champ donné ???
    Par c_moi_c_moi dans le forum SAP Crystal Reports
    Réponses: 7
    Dernier message: 23/03/2006, 16h11
  5. Réponses: 3
    Dernier message: 22/03/2006, 09h47

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