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

  1. #1
    Nouveau Candidat au Club
    Créer un compteur de lignes dans un formulaire
    Bonjour,
    J'ai crée un formulaire qui permet de remplir un tableau.
    Dans ce formulaire, j'ai besoin d'y faire apparaître un compteur automatique qui me donne le nombre de lignes remplies que contient mon tableau.
    Ce compteur doit donc s'incrémenter ou se décrémenter à chaque fois que je saisi une nouvelle ligne, ou que j'en efface une.
    merci pour votre aide !

  2. #2
    Expert éminent sénior
    Citation Envoyé par Man's Voir le message

    Bonjour,

    Si votre tableau est un tableau structuré, vous pourriez facilement trouver le nombre de lignes :

    Soit un tableau structuré nommé MaTable dans l'onglet Feuil1 :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Sub Test()
        With Sheets("Feuil1").ListObjects("Matable")
             Debug.Print .ListRows.Count
        End With
    End Sub
    Eric KERGRESSE
    https://sites.google.com/site/erickergresseeirl/
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter

  3. #3

  4. #4
    Membre chevronné
    Bonjour,


    Exemple:



    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Private Sub UserForm_Initialize()
      nomtableau = "tableau1"
      Me.ListBox1.List = Range(nomtableau).Value
      Me.Label1.Caption = Range(nomtableau).Rows.Count & "Lignes"
    End Sub



    Boisgontier

  5. #5
    Responsable
    Office & Excel

    Salut

    Citation Envoyé par Eric KERGRESSE Voir le message
    [...]
    Perso, je préfère passer par la référence structurée : range("tableau1").ListObject.ListRows.Count qui fonctionne même après déplacement du tableau sur une autre feuille ou renommage de la feuille...



    Citation Envoyé par boisgontierjacques Voir le message
    [...]
    Piège classique du débutant: Range("Tableau1").Rows.Count renvoie 1 même si le tableau est vide. Il faut passer par le listobject, comme Eric l'a montré. Ne pas confondre la plage "Tableau1" avec le Tableau Structuré "Tableau1". Ce ne sont pas les mêmes objets ^^


    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Une fois pour toutes, je donne mon avis. Je ne vais pas le répéter à chaque message...
    Si je propose une solution générique sur votre solution spécifique, c'est parce que, fainéant de nature, je privilégie le réutilisable...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  6. #6
    Expert éminent sénior
    Citation Envoyé par Man's Voir le message
    J'ai crée un formulaire qui permet de remplir un tableau.
    Quelle est la nature de ce "tableau" ? Une ListBox dans le UserForm ? Une liste de valeurs dans Excel (quelle colonne) ? Un tableau structuré dans Excel (Quel est son nom et celui de la colonne de référence) ?

    Dans ce formulaire, j'ai besoin d'y faire apparaître un compteur automatique
    Sous quelle forme ? Une TextBox ?

    Ce compteur doit donc s'incrémenter ou se décrémenter à chaque fois que je saisi une nouvelle ligne, ou que j'en efface une.
    Comment sont créées/effacées les lignes ?
    Des boutons dans le UserForm ? Quel est leur code ?
    Les effacements peuvent-il être parfois "à la main" ?
    Merci de cliquer sur pour chaque message ayant aidé puis sur pour clore cette discussion.

  7. #7
    Responsable
    Office & Excel

    Citation Envoyé par Man's Voir le message
    Bonjour,
    J'ai crée un formulaire qui permet de remplir un tableau.
    Dans ce formulaire, j'ai besoin d'y faire apparaître un compteur automatique qui me donne le nombre de lignes remplies que contient mon tableau.[...]
    En 2020, j'ose espérer que c'est un tableau structuré. Si ce n'est pas le cas, la première chose à réaliser est de convertir ta plage en tableau structuré (voir mon tuto).

    Tu pourrais aussi t'inspirer de ma contribution sur les échanges entre un formulaire et un tableau structuré.

    Il te suffira alors d'intégrer la ligne d'Eric ou mienne à l'ouverture du userform et après l'ajout ou la suppression d'une ligne du tableau.
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Une fois pour toutes, je donne mon avis. Je ne vais pas le répéter à chaque message...
    Si je propose une solution générique sur votre solution spécifique, c'est parce que, fainéant de nature, je privilégie le réutilisable...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  8. #8
    Membre averti
    Bonjour …

    «Piège classique du débutant : Range("Tableau1").Rows.Count renvoie 1 même si le tableau est vide. »
    Un piège, c’est quoi ?
    Une lecture souvent approximative d’une demande, peut se transformer en ‘piège’ !
    Un tableau (structuré ou pas) vide, c’est quoi ?


    « Dans ce formulaire, j'ai besoin d'y faire apparaître un compteur automatique qui me donne le nombre de lignes remplies que contient mon tableau. »
    Des lignes remplies, c’est quoi ? Si ce sont toutes les cellules d’une même ligne, piste :



    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Private Sub UserForm_Initialize()
        Dim c As Byte, n As Byte, s As String, k As Long
        c = [Tb].Columns.Count
        Lst.ColumnCount = c
        For n = 1 To c: s = s & 20 & ";": Next
        Lst.ColumnWidths = s: Lst.Width = 30 * c: Lst.Height = 18 * c
        Lst.RowSource = [Tb].Address             ‘c’est mon Plaisir de voir les titres
        For n = 1 To [Tb].Rows.Count
            If Application.CountA([Tb].Rows(n)) = [Tb].Columns.Count Then k = k + 1
        Next
        s = IIf(k < 2, "", "s")
        Label1 = k & " ligne" & s & " complète" & s & " sur " & [Tb].Rows.Count & " ligne" & s
    End Sub

  9. #9
    Expert éminent sénior
    Citation Envoyé par OrDonc Voir le message

    Bonjour,

    Tu ajoutes une colonne qui totalise les cellules non vides des colonnes T1 à T9 et tu décomptes avec une formule NB.SI.
    Eric KERGRESSE
    https://sites.google.com/site/erickergresseeirl/
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter

  10. #10
    Responsable
    Office & Excel

    Il ne faut pas réinventer à sa sauce les définitions communément admises.

    Une ligne d'une base de données n'est jamais totalement vide, sinon elle n'a pas lieu d'exister. C'est d'ailleurs impossible dans des systèmes tels qu'Access ou SQL Server. C'est impossible car cela n'aurait aucun sens. Ca n'en a donc pas plus en Excel. Par définition, une ligne existe dans un tableau dès que l'on y remplit au moins une cellule, et sauf demande expresse disant "je veux compter les lignes dont toutes les cellules sont remplies", une ligne remplie est à opposer à une ligne vide, c'est-à-dire à la présence d'un enregistrement. D'ailleurs, en présence d'une colonne formulée, il n'y aura plus aucune ligne totalement vide dans le tableau, ce qui me conforte dans l'idée qu'il est inutile et absurde de placer des lignes vides dans un tableau.

    Quoi qu'il en soit, lorsque tu as vidé ton tableau, range("Tableau1").Rows.count (qui ne compte pas la ligne d'entête car range("Tableau1") renvoie à la plage de données) renvoie 1 alors que Range("Tableau1").Listobject.ListRows renvoie 0. Et c'est en cela que je dis que compter les lignes d'un tableau avec range("tableau").Rows.Count est un piège de débutant. Il est donc erroné et dangereux de se baser sur Range("Tableau1") pour compter les lignes d'un tableau. Sur base de cela, il serait assez farfelu d'essayer de compter les cellules non vides de la ligne renvoyée pour déterminer si elle est vide et donc s'il n'y a pas de lignes dans le tableau, puisque le ListObject le permet.

    Dans mon tuto sur les tableaux structurés, j'explique pourquoi cela n'a pas de sens de placer des lignes vides dans son tableau. Dès lors, il est très facile de compter les lignes d'un tableau en VBA en utilisant l'objet adéquat, c'est-à-dire le ListObject. Le reste, ce sont des élucubrations qui ne tiennent pas la route.

    En Excel, on pourra compter le nombre de lignes d'un tableau avec la formule suivante








    En VBA, comme illustré précédemment, la seule bonne façon de faire est de passer par le listobject.






    Et on retrouve encore dans l'exemple d'OrDonc les adressages via Evaluate qui n'ont aucun sens et empêchent de savoir avec quoi on travaille exactement...
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Une fois pour toutes, je donne mon avis. Je ne vais pas le répéter à chaque message...
    Si je propose une solution générique sur votre solution spécifique, c'est parce que, fainéant de nature, je privilégie le réutilisable...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  11. #11
    Membre averti
    Re …


    Merci Eric pour ta proposition.

    Quand je lis construire un formulaire, je pense sans doute à tort à Userform.

    Maintenant, bien que pas énoncé ci-dessus, on peut se contenter d’une MFC (comme sur ma seconde image, dans mon fichier) et ce, sans colonne supplémentaire.

  12. #12
    Expert éminent sénior
    Citation Envoyé par OrDonc Voir le message

    Si tu cherches le nombre de lignes remplies, ce n'est pas incompatible. Tu n'es pas obligé de te créer une procédure, si une fonction te donne directement le résultat. Il te suffit de remonter la valeur dans ton Userform.
    Eric KERGRESSE
    https://sites.google.com/site/erickergresseeirl/
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter

  13. #13
    Responsable
    Office & Excel

    Lorsque l'on a besoin de compter les lignes pleines (toutes cellules remplies en VBA), voici la fonction à utiliser, et dont on utilise le résultat où on le souhaite (formule Excel, userform, procédure ou autre fonction vba):
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Function CountOfFullRows(TableName As String) As Long
      Dim lr As ListRow
     
      For Each lr In Range(TableName).ListObject.ListRows
        CountOfFullRows = CountOfFullRows - (Application.CountA(lr.Range) = lr.Range.Columns.Count)
      Next
    End Function




    Citation Envoyé par OrDonc Voir le message
    [...]

    Maintenant, bien que pas énoncé ci-dessus, on peut se contenter d’une MFC (comme sur ma seconde image, dans mon fichier) et ce, sans colonne supplémentaire.
    Une MFC pour compter des lignes vides? On en apprend tous les jours. Je rappelle le sujet de la discussion: Compter les lignes d'un tableau... ^^
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Une fois pour toutes, je donne mon avis. Je ne vais pas le répéter à chaque message...
    Si je propose une solution générique sur votre solution spécifique, c'est parce que, fainéant de nature, je privilégie le réutilisable...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  14. #14
    Responsable
    Office & Excel

    Citation Envoyé par OrDonc Voir le message
    [...]
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    ...
        Lst.RowSource = [Tb].Address             ‘c’est mon Plaisir de voir les titres...[...]
    La ligne Lst.RowSource = [Tb].Address ‘c’est mon Plaisir de voir les titres, à elle seule, ne permet pas de voir les entêtes. Encore faut-il avoir correctement défini la propriété de la listbox.

    Mais au fait, que viennent faire ici tes considérations sur la MFC et sur un listbox avec ta préférence d'entête dont on se fout un peu, en fait? Où est-il question, dans la demande initiale, de mfc, de listbox, d'entête? Pourquoi polluer une discussion dont la question est simple et formulée de façon claire avec des considérations qui n'ont strictement rien à voir avec le problème posé.

    Les bonnes pratiques suivantes, qu'elles soient Excel ou VBA, permettent normalement de répondre rapidement à une question telle que celle posée dans cette discussion:
    1. Côté Excel, jamais de lignes vides dans un tableau structuré. J'explique pourquoi c'est une bonne pratique dans mon tuto. Si tu n'es pas d'accord avec cela, j'attends tes arguments techniques et il faudra qu'ils soient en béton;
    2. Côté VBA,on travaille avec les bons objets, qui permettent d'écrire du code de qualité. Par exemple, si l'on veut dénombrer les lignes d'un tableau structuré (listobject), on utilise le listobject, et pas la "plage nommée";
    3. Côté VBA toujours, lorsque le code permettant de réaliser ce qui est demandé fait plus qu'une ligne, on l'encapsule dans une procédure/fonction réutilisable, comme c'est d'ailleurs demandé ici puisqu'il faudra dénombrer les lignes à la suite de différentes manipulations.
    4. Côté VBA encore, une procédure ou une fonction ne doit viser qu'un objectif, n'avoir qu'une seule responsabilité. La lisibilité du code, sa compréhension par un autre programmeur, sa maintenance et sa réutilisation seront facilitées par cette approche de code. Pas question, par respect des bonnes pratiques, d'avoir une procédure qui dénombre et qui affiche. Ce sont deux responsabilités différentes.


    On peut ne pas être d'accord avec ces bonnes pratiques, qui ne sont pas bonnes parce que ce sont les miennes, mais qui sont miennes parce qu'elles sont bonnes, mais il faut venir avec de solides arguments pour les contester. On n'est pas au cours de philo ou de morale où a priori, tout peut être discuté. La conception de classeurs Excel et la programmation, c'est de la technique ou toutes les solutions ne se valent pas, quand bien même elles donneraient le même résultat.


    La question de départ revient à trouver la façon de dénombrer les lignes d'un tableau structuré après certaines manipulations de formulaire. Le forum étant Excel-VBA, il est raisonnable d'imaginer que le demandeur attend une réponse VBA et parle d'un userform. Si vraiment il y a doute, il ne sert à rien d'envisager d'autres choses, et il est préférable de demander des précisions.

    Vu les "bonnes pratiques avec les tableaux structurés", la question est clairement "comment savoir le nombre de lignes d'un tableau structuré", et la seule réponse possible est celle que j'ai donnée avec le listobject, la solution de boisgontier étant erronée lorsque le tableau est vide (je l'ai démontré en Excel et en VBA). S'il y a des lignes vides, la solution ne revient pas à imaginer un bidule pour compter les vides ou les pas vides, mais de revenir aux bonnes pratiques, seules garantes d'une solution pérenne, évolutive, portable, réutilisable, compréhensible par les autres utilisateurs ou futurs personnes qui devront maintenir le classeur et/ou la solution VBA.

    Si la question était modifiée par le demandeur et qu'elle devenait "combien de lignes complètement remplies", il conviendrait alors de lui proposer une fonction (cfr bonnes pratiques VBA vues plus haut) qu'il appellerait quand il le souhaite lors des manipulations des données dans le userform. Dans ce cas, la solution de la boucle au sein même de Initialize est une mauvaise pratique, puisqu'elle amènera à devoir pondre à nouveau du code aux autres endroits du formulaire (sur les boutons d'ajout ou de suppression de lignes, par exemple). Cette fonction, telle par exemple celle que j'ai proposée pour compter les lignes complètes, s'intégrera facilement là où il est nécessaire de l'utiliser et, qui plus est, par son caractère générique, pourra être enregistrée dans un module xlTools ou autre pour resservir dans d'autres circonstances, là où le code pondu à l'arrache et très dépendant d'une situation particulière ne saura être réutilisé sans souffrir, alors même qu'il ne correspond pas aux bonnes pratiques citées plus haut. L'initialize initialise le userform et donc prépare les contrôles, mais son rôle n'est pas de compter.

    Quant à savoir où pousser le résultat (le nombre de lignes), on peut supposer que le demandeur, s'il a créé un formulaire lié à un tableau structuré, sait comment mettre du texte dans un label et l'on peut supposer que son problème n'est pas celui-là. A priori, il ne sert donc pas à grand chose de lui demander où il va le mettre ni de lui proposer un label avec un texte de 3 kilomètres de long, et on peut déjà imaginer que ce ne sera pas un textbox comme cela a été proposé par un intervenant, puisque par nature le textbox est utilisé pour modifier le texte qui s'y trouve et que, par nature, l'info que l'on y pousse n'est pas modifiable par l'utilisateur.




    S'ensuit une bonne pratique sur nos forums, qui est d'attendre le retour du demandeur sur les solutions proposées avant de proposer diverses solutions non demandées et qui s'éloignent de plus en plus de la question initiale. C'est une question de
    • respect du demandeur et de son problème;
    • respect des personnes qui ont pris du temps pour répondre et qui voient leurs solutions noyées dans des interventions non pertinentes;
    • respect par rapport au futur lecteur de la discussion, arrivé souvent ici via un moteur de recherche, et qui se retrouve devant une question simple à laquelle il a été apporté une réponse simple, les deux étant noyés dans des supputations et propositions qui n'ont rien à voir avec la question initiale et qui vont "le perdre".
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Une fois pour toutes, je donne mon avis. Je ne vais pas le répéter à chaque message...
    Si je propose une solution générique sur votre solution spécifique, c'est parce que, fainéant de nature, je privilégie le réutilisable...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  15. #15
    Membre averti
    Re...
    Citation Envoyé par Pierre Fauconnier Voir le message
    ...
    S'ensuit une bonne pratique sur nos forums, qui est d'attendre le retour du demandeur sur les solutions proposées avant de proposer diverses solutions non demandées et qui s'éloignent de plus en plus de la question initiale. C'est une question de
    • respect du demandeur et de son problème;
    • respect des personnes qui ont pris du temps pour répondre et qui voient leurs solutions noyées dans des interventions non pertinentes;
    • respect par rapport au futur lecteur de la discussion, arrivé souvent ici via un moteur de recherche, et qui se retrouve devant une question simple à laquelle il a été apporté une réponse simple, les deux étant noyés dans des supputations et propositions qui n'ont rien à voir avec la question initiale et qui vont "le perdre".

    Tu te permets souvent de ne pas pratiquer cette bonne pratique !
    Quelques exemples :
    - pour le « Respect du demandeur… » :
    Pourquoi ne pas avoir donné, dès ta première intervention, seulement ta fonction ?
    - pour le « Respect des personnes… » :
    Pourquoi ne pas avoir donné, dès ta première intervention, seulement ta fonction ?
    Il est donné à chaque intervenant de corriger son discours après coup et cela est très pratique mais si c’est seulement effacer des appréciations dénotant un manque de civilité, ce n’est pas, à mon avis, une bonne pratique.


    Ici, le questionnement n’est qu’un style d’écriture donc ne nécessite aucune réponse !
    Si je ne t’ai pas répondu dans nombre de messages précédents, c’est que je tiens à consacrer mon temps à d’autres personnes, aux demandeurs plus en attente de Pratique que de Théorie dans leur problème. Il en sera de même dans les messages à venir !

  16. #16
    Responsable Systèmes

    Vu la tournure de la discussion, je ferme celle-ci.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutor...s/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

###raw>template_hook.ano_emploi###