Compréhension code

Bonjour à tous,

J'essaie de comprendre le code d'un fichier bien fait, avec des formulaires et variables tableaux , mais je m'y perd.

Cà concerne le formulaire inscription qui s'ouvre en page Inscription, avec le bouton nouvelles inscriptions. L'étape concerne la validation de 3 concurrents pour la partie.

image

2 ou 3 points pour commencer :

- Le premier dans la macro initialize de l'UF Inscription. Je comprends qu' application est pour l'écran, et Me pour l'UF, mais un exemple de calcul serait plus parlant.

  'Positionnement du formulaire: application pour l'écran, Me pour l'UF
'Window.UsableHeight (Excel). Renvoie la hauteur maximale de l'espace pouvant être occupé par une fenêtre dans la zone de la fenêtre d'application
  Me.Top = Application.Top + (Application.UsableHeight / 2) - (Me.Height / 2)
  Me.Left = Application.Left + (Application.UsableWidth / 2) - (Me.Width / 2)

- Le 2eme point dans la macro valid. Je comprends que tbins cadre un 'tableau à 6 lignes et 3 colonnes (Alors qu'il y a 3 lignes de participants pour 6 colonnes)

 'tableau à 6 lignes et 3 colonnes ou ?
  ReDim tbIns(1 To 6, 1 To 3)
  For i = 0 To 5
    For j = 0 To ListBox2.ListCount - 1
      tbIns(i + 1, j + 1) = ListBox2.List(j, i)
    Next j
  Next i

- Le 3eme point dans la même macro. 2 c'est bien le numéro de colonne ? Pourtant dans l'onglet Inscription, le n° d'emplacement est en 1ere colonne.

  tbEmp = Range("tb_inscriptions").Value
'Contrôle places disponibles
  For i = 1 To UBound(tbEmp)
    If tbEmp(i, 2) = "" Then nbDispo = nbDispo + 1
  Next i

Merci

5concours-peche.xlsm (197.37 Ko)

Bonjour,

Juste une petite chose vite fait : en effet Tab(i,j) on a bien i ligne du tableau VBA et j colonne du tableau VBA.

Mais ce n'est pas forcément représentatif des données d'une feuille Excel. Pourquoi ? Une des raison est l'utilisation de Redim Préservé qui ne redimensionne que la dernière dimension du tableau, donc dans ce cas on définie les colonnes "fixes" du tableau comme des lignes et inversement ce qui fait qu'à l'ajout "d'une ligne" on peut agrandir le tableau VBA d'une colonne. L'injection de ce tableau sur la feuille se fera avec un Application.Transpose afin de "redresser" les lignes et colonnes.

Maintenant je suis sur tel, et je n'ai pas regardé votre fichier.

@ bientôt

LouReeD

re,

première question = la position de l'USF sur l'écran (unité de mesure = points)

* Application.top, Application.left, Application.UsableHeight et Application.UsableWidth sont la position actuel du top et gauche (dans le worksheet), l'hauteur et la largeur de l'écran

* Me.Height et Me.Width sont les dimensions de l'hauteur et la largeur de l'USF

bon, si on veut l'USF bien au centre horizontallement de l'écran, le bordure gauche doit se trouver à la position = bordure gauche de l'écran (application.left) + largeur de l'écran (Application.UsableWidth) /2 - largeur de l'USF (Me.Width) /2

même chose pour positioner l'USF au centre verticallement.

3eme question, souvent excel commence à compter à partir de 0 (=premier élément) au lieu de 1. Pourquoi ??? C'est comme çà ...

Pour le point trois BsAlv, vous allez dans le "mauvais sens" ! Cela aurait été colonne 1 alors que sur la feuille c'est colonne 2.

Pour répondre à votre question je dirait que celui qui à fait l'application à créer un tableau avec 40 emplacements, et pour chacun d'eux des personnes peuvent être inscrites ou pas voir se désinscrire, ce qui peut provoquer des emplacement "au milieu" du tableau avec aucun nom en colonne 2. Donc la boucle teste la colonne NOM et si c'est vide alors il y a au moins un emplacement de dispo. C'est une manière de faire... A la fin d ela boucle on connait alors le nombre de ligne disponible pour les futurs inscription.

Une fois le fichier ouvert je trouve une chose étrange : ReDim Preserve tbEmp(1 To UBound(tbEmp), 1 To 7)
Pour moi on ne pouvez modifier que la dernière dimension avec ReDim Preserve...

Alors du coup...

Toujours est-il que pour inscrire 3 personnes, avec votre tableau actuel vous devez supprimer trois noms de la colonne nom afin que vous ayez trois dispo pour les 3 inscriptions.

@ bientôt

LouReeD

En fait après un petit test, si vous faites "nouveau concours" l'application vous demande combien d'emplacement, vous indiquez 15, alors le tableau d'inscription contient 15 emplacements dispo, d'où la boucle qui permet, avant l'enregistrement de 1, 2 ou 3 personnes, de vérifier le nombre d'emplacement disponibles restant.

@ bientôt

LouReeD

Bonjour Bsalv, lou Reed,

Pour le positionnement du formulaire, çà me parait clair, merci Bsalv.

Lou reed, our les variables tableaux l'info des emplacements vides m'est bien utile, comme celle des 40 emplacements que j'avais pas vu.

Ensuite je suis pas encore au preserve, "préserver la derniére dimension", c'est du chinois, j'ai vu des tableaux à 3 dimensions, c'est pour faire des cubes ?

Je comprends bien le cours sur les Redim https://www.excel-pratique.com/fr/vba/tableaux_vba_suite

Pourquoi tbins(x to y, a to b) et pas tbins(6,3) comme dans le cours.

j'aimerais comprendre comment vous passez du tableau à 3 lignes et 6 colonnes qu'est le formulaire au tableau à 6 lignes et 3 colonnes de ReDim tbIns(1 To 6, 1 To 3)

Private Sub valid_Click()
'validation inscription de l'équipe de pecheurs
  Dim tbIns(), tbEmp()
  Dim i As Integer, j As Integer
  Dim inscrit As String
  'ctrl liste
  If ListBox2.ListCount = 0 Then MsgBox "Aucun concurent selectionné": Exit Sub
  'tableau à 6 lignes et 3 colonnes ou ?
  ReDim tbIns(1 To 6, 1 To 3)
  For i = 0 To 5
    For j = 0 To ListBox2.ListCount - 1
      tbIns(i + 1, j + 1) = ListBox2.List(j, i)
    Next j
  Next i
  Call TriInscriptions
...
Plus bas je vois
Dim arEmp(): ReDim arEmp(1 To UBound(tbIns)) 
For i = 1 To UBound(tbIns, 2)
 
Pourquoi pas Ubound(tbins,2) dans les 2 cas ?

Merci

Bonsoir,

Si on regarde ici on voit bien qu'un tableau à 2 voir plus de dimensions ne peut être redimensionner sur sa dernière dimension si l'on veut conserver les données.

Donc un tableau qui est dimensionné comme ceci : Tablo(1 to 5, 1 to 10) et que ce dernier contient des données que l'on souhaite garder, et qu'en plus nous aimerions l'agrandir en (1 to 6, 1 to 20) cela n'est pas possible. On ne peut modifier que la dernière dimension, on a donc : ReDim Preserve Tablo(1 to 5, 1 to 20) par exemple.

Sous VBA une variable tableau contient une seule dimension si il est dimensionné dans ce sens : Dim Tablo(1 to 10) par exemple, ici on a une seule dimension qui comporte 10 "cases" où l'on peut inscrire une donnée. Par exemple Tablo(5) = "LouReeD", dans la case 5 du tableau on y inscrit la valeur LouReeD.
Maintenant sous VBA on peut créer un tableau à deux dimensions : Dim Tablo(1 to 3, 1 to 10) c'est à dire un tableau à 3 lignes qui comportent 10 colonnes. En reprenant la valeur "LouReeD" si l'on veut l'inscrire en case 5 de la ligne 2 : Tablo(2,5) = LouReeD. C'est un peu comme si nous avions regrouper dans un seul tableau 3 tableaux de 10 cases

Une plage de cellule injectée dans un tableau VBA crée automatiquement un tableau à deux dimensions même si vous injectez une seule ligne ou une seule colonne, et le tableau sous VBA prendra alors en premier paramètre les lignes et en deuxième paramètre les colonnes. VBA comprendra alors que votre variable "deviens" un tableau à deux dimension:

Dim Tablo1, Tablo2
Tablo1 = Range("A1:J1")
Tablo2 = Range("A1:J3")

Ici par exemple on pourrait croire que Tablo 1 est à 1 dimension du fait qu'il n'y ait qu'une ligne, mais si vous faites : MsgBox Tablo1(5) il y aura une erreur, si l'on veut la cinquième valeur alors dans ce cas il faut préciser la ligne 1 même s'il y en a qu'une : MsgBox Tablo(1,5).
Donc suite à une injection de plage de cellule dans VBA on a un tableau à deux dimensions, dans nos exemple cela revient à dire que Tablo1 = Dim Tablo1(1 to 1,1 to 10) et pour le deuxième Dim Tablo2(1 to 3,1 to 10)

Ici je stipule le plus petit index à 1 car dans une feuille Excel la ligne 0 et la colonne 0 d'une plage n'existe pas, c'est forcément la première colonne de la plage ou la première ligne. Sinon sous VBA par défaut les tableaux commencent à l'index 0, donc un DIM Tablo(5) demande à VBA de créer un tableau de 5 cases dont les index vont de 0 à 4 ! 0, 1, 2, 3 et 4 on a bien les 5 cases !

Pour votre question des UBound, cette instruction sert à connaitre le plus haut indice d'un tableau, donc UBound(Tablo2) = 3 ! Et non pas 10 !
Pourquoi ? parce que UBound à un deuxième paramètre en plus du nom du tableau : c'est le numéro de la dimension en sachant que la première est "par défaut" donc en l'absence de paramètre c'est la première dimension qui est renvoyé. Pour obtenir 10 il aurait fallut écrire UBound(Tablo2,2) et là oui on a 10 !

Donc ici :

Dim arEmp(): ReDim arEmp(1 To UBound(tbIns))
For i = 1 To UBound(tbIns, 2)

on crée un variable tableau : DIM arEmp(), qu'on redimensionne en fonction de la première dimension de tbIns, par contre pour travailler dessus on utilise une boucle qui va tourner sur la quantité de la deuxième dimension de tbIns

  ReDim tbIns(1 To 6, 1 To 3)
  For i = 0 To 5
    For j = 0 To ListBox2.ListCount - 1
      tbIns(i + 1, j + 1) = ListBox2.List(j, i)
    Next j
  Next i

Ici on crée un tableau avec 6 lignes et 3 colonnes, on boucle de 0 à 5 avec la variable i et qui correspond aux colonnes de la ListBox2, on boucle en même temps de 0 à "le nombre de ligne de données de la ListBox2 - 1" avec la variable j. On remplie le tableau en croisant les références ligne/colonne, si vous regardez bien on inscrit dans le tableau en ligne i+1 et colonne j+1 la données se trouvant dans la ListBox en ligne j et colonne i !

Pourquoi i+1 et j+1 : Parce que le tableau est dimensionné avec le premier index à 1 tbIns(1 to 6, 1 to 3), par contre la première ligne d'une ListBox est en index 0 tout comme ses colonnes ! On voit bien qu'il y a renversement des données entre la ListBox2 et le tableau tbIns().

Là je me demande pourquoi mettre en variable la boucle du j vu qu'on dimensionne le tableau à 6 la boucle du j aurait pu être For j=0 to 5

@ bientôt

LouReeD

Bonjour à tous,

Merci lou Reed pour tes longues explications, mais j'ai plus besoin de savoir ce que chaque partie fait vu qu'il n'y avait aucun commentaire.

Je suis sur la fin de la macro valid et ai rajouté mes commentaires. a voir si je raconte des conneries.

Private Sub valid_Click()
....
    'redimensionnement tablo base (140 lignes)
    Range("tb_inscriptions").Resize(UBound(tbEmp), UBound(tbEmp, 2)) = tbEmp '2 actions: resize et devient tbemp
    ListBox2.Clear
    Exit Sub
  End If
  'redimensionnement tablo inscriptions (40 lignes)
  'Redim Préserve ne redimensionne que la dernière dimension du tableau, pas le nombre de lignes
  ReDim Preserve tbEmp(1 To UBound(tbEmp), 1 To 7) ' 7 colonnes dans tb inscriptions
  For i = 1 To UBound(tbEmp)
    tbEmp(i, 7) = tbEmp(i, 2) & tbEmp(i, 3) & tbEmp(i, 4) & tbEmp(i, 5) & tbEmp(i, 6) 'nom prenom licence club catégorie
  Next i
' Contrôle déjà incrit
  For i = 1 To UBound(tbEmp)
    For j = 1 To UBound(tbIns, 2)
      inscrit = tbIns(1, j) & tbIns(2, j) & tbIns(3, j) & tbIns(4, j) & tbIns(5, j) & tbIns(6, j) 'num nom prenom licence club catégorie
      If tbEmp(i, 7) <> "" And tbEmp(i, 7) = inscrit Then
        MsgBox tbIns(2, j) & " " & tbIns(1, j) & vbLf & " déjà enregistré"
        ListBox2.Clear
        Exit Sub
      End If
    Next j
  Next i

  Call ValideInscription(tbIns, arEmp)

  UF_Emplacements.Show 0
  With UF_Emplacements
    For i = 0 To ListBox2.ListCount - 1
        .Controls("TextBox" & i + 1).Text = ListBox2.List(i, 1) & " " & ListBox2.List(i, 0) & " "
        .Controls("TextBox" & i + 4).Text = arEmp(i + 1)
        UF_Emplacements.Controls("TextBox" & i + 1).Visible = True
        UF_Emplacements.Controls("TextBox" & i + 4).Visible = True
    Next i
  End With
  ListBox2.Clear

End Sub

Le point qui m'intrigue est le début :

  ReDim Preserve tbEmp(1 To UBound(tbEmp), 1 To 7) ' 7 colonnes dans tb inscriptions
  For i = 1 To UBound(tbEmp)
    tbEmp(i, 7) = tbEmp(i, 2) & tbEmp(i, 3) & tbEmp(i, 4) & tbEmp(i, 5) & tbEmp(i, 6) 'nom prenom licence club catégorie
  Next i

Il y a un resize ou tbemp devient la table des inscriptions

Range("tb_inscriptions").Resize(UBound(tbEmp), UBound(tbEmp, 2)) = tbEmp '2 actions: resize et devient tbemp

Dont la 7eme colonne est le sexe
Pour moi tbEmp(i,7) = tbEmp(i,2).. écrit dans une cellule de la colonne sexe, mais je dois me tromper, non ?

Merci

Bonjour,

Private Sub valid_Click()
    'validation inscription de l'équipe de pecheurs

    Dim tbIns(), tbEmp() ' on cré deux variables tableau sans dimensions
    Dim i As Integer, j As Integer
    Dim inscrit As String
    ' on vérifie qu'il y a bien une donnée dans la liste de sélection d'équipe, sinon on quite
    If ListBox2.ListCount = 0 Then MsgBox "Aucun concurent selectionné": Exit Sub

    ' on redimensionne le tableau tbIns avec 6 lignes dont les index vont de 1 à 6
    ' et 3 colonnes dont les index vont de 1 à 3
    ' si on ne stipule pas le 1, alors on aurait bien 6 lignes et 3 colonnes dans le tableau
    ' mais les index irraient de 0 à 5 pour les lignes et de 0 à 2 pour les colonnes
    ReDim tbIns(1 To 6, 1 To 3)
    ' on boucle sur les colonnes de la listbox (les listbox ont les index de colonne allant de 0 à nombre de colonne,
    ' donc ici la boucle commence à 0 pour cibler la première colonne)
    For i = 0 To 5
        ' on boucle sur les lignes de la listbox (les listbox ont les index de ligne allant de 0 à nombre de ligne,
        ' donc ici la boucle commence à 0 pour cibler la première ligne)
        ' comme on sait qu'il n'y aura pas plus de trois données on peut remplacer :
        ' ListBox2.ListCount - 1 par 2 (pour le calcul : ListBox2.ListCount = nombre de ligne de la listbox = 3 ici
        ' mais comme l'index commence à 0 pour avoir le l'index max il faut retrancher 1 : 3-1=2, on a bien 0,1 et 2 comme index
        For j = 0 To ListBox2.ListCount - 1
            ' comme tbIns a été dimensionné de 1 à 6 pour les lignes et que la boucle de i commence à 0, il faut
            ' bien ajouter 1 à i pour arriver à son premier index 1
            ' ici en regardant bien le code inverse le i et j
            ' pour tbIns i = ligne et j = colonne
            ' pour la source de donnée la listbox j = ligne et i = colonne
            tbIns(i + 1, j + 1) = ListBox2.List(j, i)
        Next j
    Next i

    ' à vérifier mais on lance un code qui permet de trier le tableau afin je pense de regrouper les lignes vides de ce tableau
    Call TriInscriptions

    ' une fois trié, on injecte le tableau dans la variable tbEmp
    tbEmp = Range("tb_inscriptions").Value
    ' vu que c'est une injection à partir d'une feuille Excel ce tableau a automatique deux dimensions :
    ' la première correspond au nombre de ligne de la plage injectée, la deuxième au nombre de colonne
    ' dans ce cas les index commence à 1

    ' on boucle sur ce tableau pour vérifier le nombre de place disponible en partant de 1 à la taille de sa première dimension
    For i = 1 To UBound(tbEmp)
        ' si pas de nom en ligne i et colonne 2 alors il y a une place de disponible en plus
        If tbEmp(i, 2) = "" Then nbDispo = nbDispo + 1
    Next i

    ' si le nombre de place disponible est plus faible que le nombre d'inscrit alors on quite
    If nbDispo < ListBox2.ListCount Then MsgBox "Plus assez d'emplacements disponibles": Exit Sub

    ' ici on test si c'est égal
    If nbDispo = ListBox2.ListCount Then

        ' on dimensionne un tableau en deux temps, on aurait pu le faire en une fois : Dim arEmp(1 to Ubound(tbIns))
        ' on le dimensionne avec un nombre des "cases" égal à la taille de la première dimenssion du tableai tbIns = 6
        Dim arEmp(): ReDim arEmp(1 To UBound(tbIns))
        ' on lance une boucle allant de 1 à la taille de la deuxième dimension du tableau tbIns = 3
        For i = 1 To UBound(tbIns, 2)
            ' on lance une boucle allant de 1 à la taille du tableau tbEmp qui est aussi égal à la première dimension de tbIns = 6
            For j = 1 To UBound(tbEmp)
                ' si la ligne j et colonne 2 du tableau tbEmp est vide
                If tbEmp(j, 2) = "" Then
                    ' alors on récupère certaine données de tbIns qu'on inscrit à certain endroit de tbEmp
                    tbEmp(j, 2) = tbIns(1, i): tbEmp(j, 3) = tbIns(2, i): tbEmp(j, 4) = tbIns(3, i)
                    tbEmp(j, 5) = tbIns(4, i): tbEmp(j, 6) = tbIns(5, i): tbEmp(j, 7) = tbIns(6, i)
                    arEmp(i) = j
                    ' si on a entré des données on sort de la boucle en cours c'est à dire j et on continue la boucle i
                    Exit For
                End If
            Next j
        Next i

        ' on affiche le USF des emplacements
        UF_Emplacements.Show 0
        ' avec ce USF
        With UF_Emplacements
            ' on boucle sur les lignes de la listbox
            For i = 0 To ListBox2.ListCount - 1
                ' on modifie la valeur text des textbox et on les rend visibles
                .Controls("TextBox" & i + 1).Text = ListBox2.List(i, 1) & " " & ListBox2.List(i, 0) & " "
                .Controls("TextBox" & i + 4).Text = arEmp(i + 1)
                .Controls("TextBox" & i + 1).Visible = True
                .Controls("TextBox" & i + 4).Visible = True
            Next i
        End With
        ' le tableau structuré du classeur ayant pour nom tb_inscription se fois recevoir les données du tableau VBA tbEmp
        ' pour ce faire on crée une plage ayant en taille de ligne la première dimension de tbEmp et
        ' en colonne la deuxième dimension de tbEmp
        Range("tb_inscriptions").Resize(UBound(tbEmp), UBound(tbEmp, 2)) = tbEmp
        ' on efface la listbox
        ListBox2.Clear
        ' on quitte
        Exit Sub
    End If

    ' si on arrive ici c'est que dispo est supérieur à ListBox2.ListCount
    ' vu que tbEmp est une injection du tableau Tb_Inscriptions qui lui contient beaucoup de colonne
    ' ici en redimensionnat le tableau avec 1 à 7, on en reduit la taille au niveau des colonnes où la 7 correspond au sexe
    ' le nombre de ligne ne change pas mais on ne connait pas sa valeur c'est pour quoi on utilise 1 to ubound(tbEmp)
    ReDim Preserve tbEmp(1 To UBound(tbEmp), 1 To 7)
    ' on boucle sur ses lignes et cela commence à 1 car les données provienne d'une plage de cellules
    For i = 1 To UBound(tbEmp)
        ' on inscrit les données voulues en colonne 7 ce qui effacera les données de sexe
        tbEmp(i, 7) = tbEmp(i, 2) & tbEmp(i, 3) & tbEmp(i, 4) & tbEmp(i, 5) & tbEmp(i, 6)
    Next i

    ' Contrôle déjà incrit
    ' on boucle sur les lignes du tbEmp
    For i = 1 To UBound(tbEmp)
        ' on boucle sur la deuxième dimension de tbIns soit de 1 à 3
        For j = 1 To UBound(tbIns, 2)
            ' on récupère le concatener
            inscrit = tbIns(1, j) & tbIns(2, j) & tbIns(3, j) & tbIns(4, j) & tbIns(5, j) & tbIns(6, j)
            ' si la valeur en colonne 7 est égal au concatener de l'inscription en cours
            If tbEmp(i, 7) <> "" And tbEmp(i, 7) = inscrit Then
                ' on efface tout
                MsgBox tbIns(2, j) & " " & tbIns(1, j) & vbLf & " déjà enregistré"
                ListBox2.Clear
                ' on quitte
                Exit Sub
            End If
        Next j
    Next i

    ' procédure de validation d'inscription
    Call ValideInscription(tbIns, arEmp)

    ' on affiche le USF des emplacements
    UF_Emplacements.Show 0
    With UF_Emplacements
        ' avec les lignes de la listbox
        For i = 0 To ListBox2.ListCount - 1
            ' on modifie le text des boutons et on les rend visibles
            .Controls("TextBox" & i + 1).Text = ListBox2.List(i, 1) & " " & ListBox2.List(i, 0) & " "
            ' ici pour moi il y a erreur car arEmp dans ce cas de figure n'a pas été déclaré...
            .Controls("TextBox" & i + 4).Text = arEmp(i + 1)
            .Controls("TextBox" & i + 1).Visible = True
            .Controls("TextBox" & i + 4).Visible = True
        Next i
    End With
    ' on efface la listbox
    ListBox2.Clear
    ' on quitte
End Sub

Bon, je pense qu'il y a moyen de faire plus simple, mais ceci est ma compréhension du code.

@ bientôt

LouReeD

Rechercher des sujets similaires à "comprehension code"