Macro problème avec formule concatenation

Bonjour,

Il me semblait avoir répondu à toutes les questions non ? Désolée si j'ai zappé quelque chose

Du coup, sur le fin du code, pourquoi avoir rajouté :

Col = Split("B:C H L P T")
        For i = UBound(Col) To 0 Step -1
            .Columns(Col(i)).Delete
        Next i
        .Rows(dln + 3 & ":" & dln + 4).Delete
        '...
      

et pas seulement le delete column comme on l'avait vu plus tôt ?

Bonjour,

Je n'ai peut-être pas posé explicitement la question .

Dans la mesure où tu as en fin de tableau 4 lignes de totaux, doublonnées 2 à 2, il me semblait souhaitable de confirmer que l'on avait toujours bien ces 4 lignes de façon systématique, car si l'on n'est pas assuré de les avoir en permanence, il faut alors se dimensionner avec une méthode plus classique sur une colonne qui sera remplie intégralement sur la partie liste des élèves sans l'être sur les lignes totaux, afin d'éviter tout décalage.

La dernière ligne de code supprime les deux lignes parasites en trop (qui ne font que reproduire les deux lignes qui précèdent).

NB- Et si on modifie le dimensionnement en l'opérant sur la colonne E, qu'il y ait 2 ou 4 lignes à la suite n'aura aucune incidence, le suppression des 2 lignes en trop tombera sur des lignes vides si ces 2 lignes supplémentaires ne figuraient pas.

Quant au code de suppression des colonnes, il procède en listant les colonnes à supprimer que l'on connait dans un tableau :

variable Col (ajoutée dans les déclarations) de type Variant, à laquelle on affecte un tableau des lettres de colonnes à supprimer en utilisant la fonction Split.

Cette fonction transforme une chaîne (texte) en tableau en la scindant sur un séparateur qui par défaut est l'espace (dans ce cas on peut l'omettre) ou n'importe quel autre séparateur indiqué composé de un ou plusieurs caractères. On obtient donc un tableau de base 0 des lettres de colonnes (dans lequel on a regroupé B:C parce que ces deux colonnes sont contiguës).

On procède à la suppression en boucle, en partant de la fin pour aller vers le début (car dans l'autre sens on modifierait l'identification des colonnes à chaque suppression, comme on l'a déjà indiqué...)

Pourquoi cette méthode ? Elle est plus sûre et te donnera le résultat attendu dans tous les cas...Je te ferai une explication plus détaillée des particularités de l'objet Range (à la fois objet et collection confondues, dont les principales propriétés qui le renvoient réfèrent à un objet parent qui peut être un objet Worksheet ou un objet Range, et qui peut être renvoyé par d'autres propriétés...) Mais trop long maintenant.

Bon dimanche.

Bonjour et bon dimanche à toi et à tous !

Ici, il pleut, temps idéal pour le bricolage de macros

Bonjour,

Je n'ai peut-être pas posé explicitement la question .

Dans la mesure où tu as en fin de tableau 4 lignes de totaux, doublonnées 2 à 2, il me semblait souhaitable de confirmer que l'on avait toujours bien ces 4 lignes de façon systématique, car si l'on n'est pas assuré de les avoir en permanence, il faut alors se dimensionner avec une méthode plus classique sur une colonne qui sera remplie intégralement sur la partie liste des élèves sans l'être sur les lignes totaux, afin d'éviter tout décalage.

Alors oui, j'ai toujours ces quatre lignes en fin de tableau

On procède à la suppression en boucle, en partant de la fin pour aller vers le début (car dans l'autre sens on modifierait l'identification des colonnes à chaque suppression, comme on l'a déjà indiqué...)

Dans le code que tu as décrit tu vas bien dans l'autre sens, du début vers la fin non ?

Col = Split("B:C H L P T")

En tout cas, tout fonctionne, j'ai bien les colonnes modifiées comme je le souhaitais, c'est top, merci beaucoup !

J'ai ensuite besoin de trier les enfants par instits. J'avais également créé une macro via enregistrement en faisant un tri par instit, et en copiant la page, une fois le tri appliqué, sur une nouvelle feuille, renommée du nom de l'enseignant. Au total il y a 14 feuilles à créer.

Elles sont dans l'ordre dans le tableau, c'est au niveau boucle qu'on les prend dans l'ordre inverse :

        For i = UBound(Col) To 0 Step -1

J'ai ensuite besoin de trier les enfants par instits. J'avais également créé une macro via enregistrement en faisant un tri par instit, et en copiant la page, une fois le tri appliqué, sur une nouvelle feuille, renommée du nom de l'enseignant. Au total il y a 14 feuilles à créer.

Ça, c'est un élément nouveau ! Pas de problème pour traiter ainsi à la suite. Mais si tu veux bien, on va finir cette première phase : dans la mesure où tu deux lignes de totaux en fin de tableau, et une colonne de totaux à droite, il est logique de rétablir les bons résultats après les modifications apportées...

Ensuite, on aura en fait un nouveau tableau à partir duquel on pourra procéder à une répartition par instit.

NB- Il pleut également à Nice, mais en ce moment accalmie...

Cordialement.

Idem à Lyon, accalmie

La colonne de totaux a droite n'a pas d’intérêt, je l'avais supprimée dans mon essai de code. Seules celles du bas ont un intérêt pour moi.

Ok ! Donc on supprime la colonne V. On l'introduit dans le tableau et elle sera ainsi supprimée.

Sub Macro()
    Dim c As Range, i%, dln%, Col
    With Worksheets(" Listes des pointages")
        dln = .Range("A1").CurrentRegion.Rows.Count - 4
        For i = 0 To 12 Step 4
            For Each c In .Range("H3:H" & dln).Offset(, i)
                If c.Value <> "" Then
                    c.Offset(, -1) = c: c.Offset(, 1) = c
                End If
            Next c
        Next i
        Col = Split("B:C H L P T V")
        For i = UBound(Col) To 0 Step -1
            .Columns(Col(i)).Delete
        Next i
        .Rows(dln + 3 & ":" & dln + 4).Delete
        For i = 15 To 4 Step -1
            .Cells(dln + 1, i) = WorksheetFunction.CountA(.Cells(3, 1).Resize(dln - 2))
            If i Mod 3 = 1 Then
                .Cells(dln + 2, i) = WorksheetFunction.Sum(.Cells(dln + 1, i).Resize(, 3))
            End If
        Next i
        '...
    End With
End Sub

Code prolongé pour inscrire les totaux : une boucle sur toutes les colonnes de 15 à 4 (après suppressions, le tableau ne va plus que jusqu'à O, les jours commençant en D, avec 3 colonnes par journée).

On utilise des fonctions Excel (en VBA) pour calculer le nombre de valeurs permettant de servir la premières ligne de totaux.

On procède de la fin vers le début car sur la première colonne de chaque jour, on peut ainsi faire le total de la journée dans la 2e ligne de totaux.

Ton code se poursuivait par des mises en forme quelque peu nébuleuses, certaines n'étant guère compréhensibles avec le modèle communiqué, laissant penser que la mise en forme du tableau reçu n'est pas celle visible sur le modèle...

Si une mise en forme doit être faite, il convient de la décrire exactement pour que l'on puisse la coder.

Cordialement.

Bonjour, bonjour !

OK jusque là...

Le total me donne le nombre d'enfants total (le nombre de ligne en fait) et pas le nombre de R (enfants présents).

Côté mise en forme, je grisais un jour sur deux pour plus de lisibilité, du coup, 3 colonnes grisées, puis 3 sans couleurs, puis 3 grisées....

Et ensuite, le fameux tri par instit pour avoir une feuille dans le fichier par enseignant

Et ensuite, sur chaque feuille créée, élargir la première colonne (nom de l'enfant) à 25, faire un renvoi à la ligne auto sur cette colonne.

Ajuster également la largeur des colonnes D à O à 11

Et ensuite, ajuster la mise en page à 1 page en largeur et hauteur, en paysage, marges étroites.

ça ça me donne les plannings destinés aux animatrices.

Ensuite, on sort les mêmes pour les instit, en faisant d'autres modifs sur les tableaux, mais je vais voir si on peux leur donner les mêmes, que ce soit plus simple à gérer et qu'on ai moins de travail à faire

Là, normalement on a tout, il me semble.

Encore merci pour votre aide précieuse ! Vous êtes top

Bonjour,

Le total me donne le nombre d'enfants total (le nombre de ligne en fait) et pas le nombre de R (enfants présents).

Ah ! Non ! Ce que je calcule est le nombre de valeurs par colonne (fonction NBVAL qui est utilisée), soit le nombre de présents par plage horaire, qui sont ensuite additionnés pour la 2e ligne de totaux.

Si un souci à cet égard, me le signaler, je testerai...

Pour la mise en forme :

Ok pour griser un jour sur 2 (1er et 3e pour assurer la distinction)

Ok pour colonne Nom à 25 et en saut de ligne auto

Ok pour colonnes jours à 11

Pour Niveau et Classe, pas de changements ?

Et est-ce à dire que pour le reste, tu reçois le fichier tel qu'il se présente dans le modèle : hauteurs de lignes, centrages horizontaux et verticaux, bordures ?

Cordialement.

Ah ! Non ! Ce que je calcule est le nombre de valeurs par colonne (fonction NBVAL qui est utilisée), soit le nombre de présents par plage horaire, qui sont ensuite additionnés pour la 2e ligne de totaux.

Si un souci à cet égard, me le signaler, je testerai...

J'ai 90 en résultat sur toutes les colonnes donc oui soucis

Pour Niveau et Classe, pas de changements ?

Tu as raison, ajustons aussi les largeurs si tu veux bien, niveau à 7, et classe à 13 avec également un renvoi à la ligne automatique pour la classe.

Sinon, tout est extrait centré, pour ce qui est des bordures, c'est correct, et ce sera lisible en grisant un jour sur deux.

Désolé ! Rectifie cette ligne :

            .Cells(dln + 1, i) = WorksheetFunction.CountA(.Cells(3, 1).Resize(dln - 2))

Avec .Cells(3, 1)... ça va toujours compter sur la colonne A ! C'est évidemment .Cells(3, i)...

            .Cells(dln + 1, i) = WorksheetFunction.CountA(.Cells(3, i).Resize(dln - 2))

Nickel, ça y'est le comptage est correct

Bonjour,

Etape suivante :

On va procéder à la mise en forme...

La répartition par feuille instit n'est pas une mise en forme, on y procèdera ensuite, il s'agit d'extraire les lignes correspondant à chaque instit de ton tableau pour les reproduire dans une nouvelle feuille ajoutée par instit, donc extraction des lignes à regrouper par instit, puis pour chaque extraction individualisée on ajoutera une feuille pour l'y placer... et on devra procéder à sa mise en forme.

Lors de notre actuelle mise en forme, on va anticiper en y procédant au moyen d'une procédure secondaire qui sera appelée par la procédure principale, et que l'on pourra appeler par la suite pour chaque feuille ajoutée.

Il faudra indiquer à cette procédure où elle devra intervenir pour opérer sa mise en forme : quoi de plus simple qu'en lui indiquant globalement la plage sur laquelle intervenir ?

On la définit facilement, et on pourra la définir aussi facilement pour chaque feuille par la suite.

La structure de la plage étant identique, hormis le nombre de lignes, mais en passant la plage en argument elle sera à chaque fois dimensionnée sur le nombre de lignes adéquat.

On doit dimensionner différemment la largeur des 3 premières colonnes, en plaçant un saut de ligne auto pour les 1re et 3e, puis pour les autres colonnes, en les regroupant par 3, dimensionner la largeur, et griser les 1er et 3e groupe.

Pour les autres feuilles, on aura un peu plus à faire, mais on la complètera le moment venu.

Sub MiseEnForme(Plg As Range)
    Dim i%
    With Plg
        .WrapText = False
        With .Columns(1)
            .ColumnWidth = 25: .WrapText = True
        End With
        .Columns(2).ColumnWidth = 7
        With .Columns(3)
            .ColumnWidth = 13: .WrapText = True
        End With
        For i = 4 To 13 Step 3
            With .Columns(i).Resize(, 3)
                .ColumnWidth = 11
                If i Mod 2 = 0 Then .Interior.Color = RGB(217, 217, 217)
            End With
        Next i
    End With
End Sub

Quelques remarques à faire pour bien comprendre :

1) Remarque conjoncturelle : .WrapText = False en début de procédure élimine les sauts de lignes automatique (il y en avait de façon un peu désordonnée, dont on ne sait s'ils sont d'origine ou produit par des manipulations lors de la constitution du tableau, on les élémine pour faire place nette).

2) On s'accupe individuellement des 3 premières colonnes. Note, ce qui a déjà été utilisé dans le code précédemment vu, que pour les colonne 1 et 3 pour lesquelles on code 2 commandes (la largeur, et le saut de ligne auto), ces 2 commandes sont placées sur la même ligne mais séparées par un caractère ":". Ce caractère est un séparateur permettant de placer deux lignes de code ou plus sur la même ligne physique.

[NB- A l'inverse, un caractère espace suivi d'un underscore (trait de soulignement) indique une continuité de ligne, la ligne physique qui suit fait partie de la même ligne de code.]

3) On opère en boucle pour les colonne jours, en les regroupant par 3, de façon à pouvoir griser le 1er et le 3e groupe que l'on teste par i Mod 2 = 0, soit si i est pair, on est dans le 1er ou 3e groupe, alors on grise.

Par rapport au code que te restitue l'enregistreur dès que tu procèdes à la moindre coloration, revenons à des choses simples ! La couleur peut toujours se définir par la propriété Color, qui est une donnée de type entier Long, que l'on peut renvoyer par la fonction RGB(rouge, vert, bleu) à partir de la valeur (de 0 à 255) des 3 couleurs de base, lesquels sont aisées à trouver dans la boîte de dialogues Couleurs d'Excel.

Selon la façon dont tu détermines la couleur, l'enregistreur te renverra une valeur définie à partir d'un thème de couleur, assortie d'élément correctif (TintAndShade)... Tout cela est à éliminer pour revenir au système de base des couleurs, qui seront toujours les mêmes, lequel est bien plus simple à utiliser et sans inflation de code.

Il convient aussi de privilégier Color par rapport à ColorIndex (qui ne définit que les 56 couleurs de la palette, seules couleurs affichables par Excel jusqu'à la version 2003, et conservée pour compatibilité) pour afficher toutes les couleurs définissables sur 16 bits.

Comme tu vois la procédure est déclarée avec un argument de type Range. Elle devra donc être lancée en lui fournissant l'objet Range sur lequel elle aura à opérer la mise en forme prévue :

        MiseEnForme .Range("A1").CurrentRegion
        '...
    End With
End Sub

La ligne de commande qui la lance consiste simplement à indiquer le nom de la procédure, suivi (après espace) de l'argument qu'elle attend, lequel est aisément renvoyé par la région courante à partir de A1 de la feuille sur laquelle on travaille (dans la proc. principale on est toujours sous instruction With référant à la feuille, et l'on a apporté les modifications souhaitées au tableau, la région courante ciblera le tableau tel que nous l'avons modifié).

Cordialement.

OK, j'ai compris le codage dans les grandes lignes, mais faut-il faire la mise en forme largeur de colonne dès maintenant ?

Quand on va copier dans une nouvelle feuille, les largeurs de colonne sont conservées ?

il faut que je regarde comment on utilise "un argument de type Range", du coup ce sera une partie de la macro, ou une autre procédure ?

Bonsoir,

Ayant fait la mise en forme dans une procédure autonome, elle peut être appelée à n'importe quel moment, celui que tu juges opportun...

Il suffit de déplacer la commande dans la proc. principale. Mais elle peut être faite dès la fin des modifications, tant qu'on est sur le traitement de la feuille, car on va passer ensuite au recueil des données et à leur répartition par instit.

Pour cela on va utiliser des tableaux : 1er tableau pour sortir globalement toutes les données de la feuille et travailler sur ce tableau plutôt que directement sur la feuille (car VBA travaille plus rapidement sur des tableaux que sur des feuilles Excel), on listera ensuite les instits au moyen d'un doctionnaire et on récoltera en même temps les lignes les concernant, puis opération répétée pour chaque instit : on extrait les lignes le concernant dans un 2e tableau, on insère une feuille, on affecte le tableau, on le remet en forme sur la feuille.

Pas de copier ni coller.

Vois-tu comment on structure l'opération pour emprunter la voie la plus rapide ?

Cordialement.

Bonsoir,

MFerrand a écrit :

Vois-tu comment on structure l'opération pour emprunter la voie la plus rapide ?

"j'ai trouvé, moi, quelle est la voie la plus rapide :"
screen
"ou alors :"


screen 2

(si y'a pas de bouchons !)

dhany

Bonjour, [ Dhany]

On va poursuivre puisque tu suis sans problème avec un petit intermède sur la mise en forme..

On sait qu'on aura à la déclencher pour chaque feuille ajoutée, qu'elle devra y faire ce qu'elle fait déjà, mais qu'il faudra ajouter quelques éléments de mise en forme que l'on n'a pas retouché sur le tableau initial, mais qui ne seront pas présent lors d'un transfert de valeurs sur une nouvelle feuille.

Il y a, si j'ai bien compté (mais tu vérifieras ça ! ) 4 mises en forme supplémentaires à rétablir :

  • le centrage horizontal et vertical des données, sauf pour la colonne A,
  • la hauteur de ligne à 53, sauf pour les deux premières lignes,
  • la fusion par 3 colonnes, à partir de la colonne D, des cellules de la ligne 1,
  • et les bordures.

Pour ne faire ces mises en forme que sur les nouvelles feuilles, on va doter la procédure d'un second argument de type booléen, et optionnel, c'est à dire qu'on peut l'omettre (et dans ce cas sa valeur sera False), nous n'avons donc rien à retoucher à la commande de mise en forme dans la proc. principale, et on le lancera pour les nouvelles feuilles avec True comme valeur d'argument, ce qui fera exécuter les commandes de mises en forme sous condition que cet argument soit à True (alors que les mêmes commandes ne le seront pas lorsque la procédure est lancée pour le tableau principal.

Sub MiseEnForme(Plg As Range, Optional NewF As Boolean)
    Dim i%
    With Plg
        If Not NewF Then .WrapText = False
        If NewF Then
            With .Offset(, 1).Resize(, 14)
                .HorizontalAlignment = xlCenter
                .VerticalAlignment = xlCenter
            End With
            .Offset(2).Resize(.Rows.Count - 2).Rows.RowHeight = 53
        End If
        With .Columns(1)
            .ColumnWidth = 25: .WrapText = True
        End With
        .Columns(2).ColumnWidth = 7
        With .Columns(3)
            .ColumnWidth = 13: .WrapText = True
        End With
        For i = 4 To 13 Step 3
            If NewF Then .Cells(i, 1).Resize(, 3).MergeCells = True
            With .Columns(i).Resize(, 3)
                .ColumnWidth = 11
                If i Mod 2 = 0 Then .Interior.Color = RGB(217, 217, 217)
            End With
        Next i
        If NewF Then .Borders.Weight = xlThin
    End With
End Sub

On a donc introduit notre argument booléen optionnel : NewF.

La plage (argument 1) sera fourni à chaque fois, et selon la feuille pour laquelle on lance la procédure.

On commence par ne pas exécuter l'élimination des sauts de ligne auto pour les nouvelles feuilles (car il n'en figurera pas sur des feuilles introduites vierges !)

On redimensionne la plage à traiter pour les centrages, en excluant la première colonne.

On redimensionne autrement, en excluant les 2 premières lignes, pour définir la hauteur de ligne.

On procède aux fusions de la ligne 1 dans la boucle qui nous servait déjà à traiter les colonnes jour.

Et enfin, on rétablit les bordures sur toute la plage.

Les mises en forme ont toujours l'air un peu compliquées à cerner, mais c'est très mécanique dès qu'on a recensé ce qu'il y avait à faire en combinant pour ne pas allonger inutilement le code... Pas de difficulté à suivre, je pense...

On peut donc avancer encore un peu sur la procédure principale au stade où on l'avait laissée :

On attaque une 2e partie, bien distincte de la première, mais qu'il n'y a pas lieu de réaliser dans une procédure distincte, cela n'allongera pas inconsidérément la procédure et les 2e parties vont naturellement s'enchaîner sans difficulté pour réaliser globalemen l'opération qu'on effectue sur le tableau reçu.

On va lui ajouter des déclarations de variables dont on aura besoin :

  • une variable non typée (type Variant, donc) qui nous servira à prélever le tableau de données tel que nous l'avons établi, afin de travailler avec hors Excel : Tbl
  • une variable tableau dynamique (car le nombre de ligne variera pour chaque instit), destinée à accueillir les données à transférer, feuille après feuille, bien que tes données soient systématiquement de type String, on conserve ce tableau de type Variant car on n'y affectera pas des données individuelles mais des lignes entières de données (donc en fait des tableaux !) : Tmp()
  • une variable de type Integer, qui nous servira à incrémenter le tableau précédent : n% (% est ce qu'on appelle un caractère de déclaration de type, qui signifie As Integer, ce qui permet de raccourcir les déclarations de variables numériques et String pour lesquelles des caractères sont utilisables pour déclarer le type)
  • une variable objet, destinée à stocker le dictionnaire à constituer (que j'ai déjà évoqué) : d
  • une dernière variable destinée à manipuler les éléments du dictionnaire qu'on aura constitué : k, variable également de type Variant car elle nous permettra de parcourir le dictionnaire au moyen d'une boucle sur les clés (keys) de chaque élément.

Les variables dont on aura besoin étant définies, on prépare le terrain de notre 2e partie :

1) On affecte notre tableau de données à la variable de type Variant que nous avons prévue pour cela :

        Tbl = .Range("A1").CurrentRegion

Pas de mystère, c'est tout le tableau qui est ainsi affecté à notre variable.

Cette méthode produit un tableau à deux dimensions, correspondant aux (lignes, colonnes) du tableau initial, de base 1, c'est à dire que les indices minimaux lignes et colonnes seront 1, quel qu'ait été l'emplacement initial du tableau sur la feuille. Ainsi, on parcourt toutes les lignes de notre tableau Tbl de 1 à UBound(Tbl, 1) [le 1 peut être omis], la fonction UBound renvoyant l'indice maximal du tableau dans sa première dimension (correspondant au nombre de lignes), et on parcourt toutes les colonnes de Tbl de 1 à UBound(Tbl, 2), la fonction UBound renvoyant ici l'indice maximal du tableau dans sa seconde dimension (puisqu'on a précisé 2 en 2e argument de la fonction, correspondant au nombre de colonnes).

2) On procède à un premier redimensionnement de notre tableau dynamique Tmp, à 1 :

        ReDim Tmp(1): n = 2

C'est à dire que notre tableau Tmp aura ainsi au départ 2 élément, d'indice 0 et 1 (l'option base est par défaut 0 pour les tableaux, le cas vu précédemment y déroge uniquement lorsqu'on affecte les données d'une plage à une variable de type Variant). Et ce tableau n'a qu'une dimension (car on placera dans chaque élément une ligne entière, on se dispense donc d'avoir un tableau à 2 dimensions dont une serait dimensionnée sur le nombre de colonnes (soit 14 puisqu'il y a 15 colonnes).

J'ai inclus sur la même ligne physique, une initialisation de n à la valeur 2, car lorsqu'on rajoutera un élément pour recueillir une ligne instit, il faudra redimensionner le tableau en l'incrémentant à 2 (indice suivant), et on fera alors évoluer n au fur et à mesure (mais on verra ça par la suite, pour l'instant on prépare...)

Pourquoi ce premier dimensionnement à 1 ?

Eh bien ! On a 2 lignes d'en-tête, qu'il faudra reprendre sur tous les tableaux Instit. On va donc les affecter dès maintenant (et on les conservera durant toute l'opération ! ce que l'on verra par la suite).

        Tmp(0) = WorksheetFunction.Index(Tbl, 1, 0)
        Tmp(1) = WorksheetFunction.Index(Tbl, 2, 0)

On affecte donc nos deux lignes. Comment fait-on pour affecter une ligne entière de tableau VBA ?

La question mérite tout à fait le détour, car VBA ne dispose pas d'instruction le permettant, mais Excel si ! C'est la fonction INDEX, qui a quelques ressources insoupçonnées (lorsqu'on se contente de son utilisation classique en feuille de calcul, notamment en la combinant avec EQUIV). INDEX renvoie une valeur d'un tableau à partir d'indices ligne et colonne, soit on lui passe les coordonnées d'une valeur d'un tableau et elle renvoie cette valeur... Mais INDEX travaille sur des matrices et si on lui passe un indice ligne à 0, elle renvoie la colonne entière du tableau en tant que matrice, si on lui passe un indice colonne à 0 elle renvoie la ligne entière.

Et VBA peut utiliser cette fonction d'Excel. C'est ce dernier cas qui est codé ci-dessus : on soumet à INDEX notre tableau Tbl, en lui indiquant la ligne, et 0 pour la colonne, la fonction renvoie alors la ligne entière sous forme de matrice. On obtient donc dans l'élément Tmp initialisé un tableau représentant la ligne entière affectée.

[NB- INDEX peut encore faire mieux ! Elle peut renvoyer une matrice composée de valeurs prélevée sur la ligne (ou la colonne) dans l'ordre qu'on lui indique, si on remplace 0 par un tableau d'indice.

Par exemple : ....Index(Tbl, i, Array(1, 4, 7, 10, 13)) renverrait une ligne ne comprenant que les colonnes indiquées, soit le nom de l'élève et les mentions de présence des colonnes du matin de chaque jour...]

3) On initialise notre dictionnaire :

        Set d = CreateObject("Scripting.Dictionary")

Cette fonction spécifique permet d'invoquer un composant qui n'est ni Excel, ni VBA, et de l'utiliser ensuite.

L'outil Dictionary permet de stocker des éléments par couples : une clé (key) identifiant l'élément et qui sera unique, et une valeur (item). Pour nous la clé sera l'indication de l'instit : on aura donc après constitution un seul élément du dico au nom de chaque instit. Le dico joue ainsi naturellement un rôle de filtre.

Et comme valeur, on va concaténer dans chaque élément les numéros de lignes du tableau où figure l'instit. Ainsi, lorsqu'on traitera chaque instit. en appelant l'élément de dico le concernant, on disposera en même temps de la liste des lignes du tableau à prélever...

4) Dans la foulée, on constitue le dico, en parcourant les lignes du tableau à partir de la ligne 3 (les 2 premières étant des en-têtes) et en excluant les 2 dernières (qui sont des totaux).

        For i = 3 To UBound(Tbl) - 2
            k = Tbl(i, 3): d(k) = d(k) & ";" & i
        Next i

On recueille la valeur de la 3e colonne de chaque ligne dans k (qui sera la clé de notre élément dico). Invoquer d(k) crée automatiquement l'élément. On lui affecte la valeur qu'il a déjà (éventuellement rien s'il n'existait pas encore), qu'on concatène avec un séparateur (point-virgule) et du numéro de ligne où l'on se trouve.

On utilise fréquemment Dictionary en VBA, car c'est l'un des composants les plus rapides dont on puisse disposer.

Arrivés à ce point, on en a fini avec la préparation. On poursuivra par l'insertion d'une nouvelle feuille par instit...

Serais-tu noyée ? Il nous reste encore une opération importante avant d'arriver au bout !

Hello !

Noyée, un peu mais par la quotidien....

Je suis à peu près, même si je pense que je serai incapable de refaire seule

Je n'ai pas trouvé comment exécuter cette partie du coup

Bonjour,

Elle n'est pas encore exécutable, tant qu'elle n'est pas finie... Plus précisément elle peut toujours s'exécuter mais l'exécution se traduira par rien qui deviennent apparent.

Ce code intermédaire (en quelque sorte) ne fait que préparer la mise en place d'une boucle, pour créer de nouvelles feuilles, les alimenter, et les mettre en forme. A ce stade le résultat deviendra visible, avant il reste uniquement dans la mémoire de l'ordinateur.

Content de te voir émerger... Il n'y a pas de raison que tu ne comprennes pas, même si ce n'est pas tout et tout de suite... Il faut comprendre avant de pouvoir refaire ou faire quelque chose d'analogue, mais sache que cela n'ira pas sans erreur au départ, mais c'est à partir des erreurs qu'on améliore la compréhension et qu'on finit par aboutir.

@+

OK, alors ça marche je comprends

Rechercher des sujets similaires à "macro probleme formule concatenation"