Macro problème avec formule concatenation

Bon ! On amorce une petite révision, à l'occasion de laquelle je vais apporter une toute petite modification à ce qui a été défini...

Dès le départ on avait placée la feuille traitée sous instruction With, et on y est toujours. Mais une fois la mise en forme réalisée, on n'intervient plus sur cette feuille, il n'y a donc pas lieu d'y rester? On va donc clore l'instruction par un End With, prenant place juste après qu'on ait prélevé les données modifiées dans un tableau (on travaillera alors sur le tableau, plus sur la feuille).

En outre, dans cette première partie, on a opéré de multiples interventions sur la feuille, lesquelles vont produire autant de mises à jour de l'affichage qui ralentiront l'exécution de la procédure. On a donc intérêt à interrompre ces mises à jour de l'écran par Application.ScreeUpdating = False.

Il est sans doute logique de mettre sous les yeux de l'utilisateur le résultat de cette première opération. On le rétablira donc à True avant de poursuivre avec la préparation de la 2e phase. Cette préparation ne se traduit par aucun affichage, mais lorsqu'on passera à la création des feuilles des mises à jour d'affichage vont reprendre, on va donc remettre la propriété à False à ce moment, et ce jusqu'à la fin. Et on ne la rétablira pas à True alors, car Excel le fait automatiquement à l'issue d'une macro, on le laisse donc faire.

Rappel du code intégrant ces modifications :

Sub Macro()
    Dim c As Range, i%, n%, dln%, Col, Tbl, k, Tmp(), d As Object
    With Worksheets(" Listes des pointages")
        dln = .Range("A1").CurrentRegion.Rows.Count - 4
        Application.ScreenUpdating = False
        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
        MiseEnForme .Range("A1").CurrentRegion
        Tbl = .Range("A1").CurrentRegion
        Application.ScreenUpdating = True
    End With
    ReDim Tmp(1): n = 2
    Tmp(0) = WorksheetFunction.Index(Tbl, 1, 0)
    Tmp(1) = WorksheetFunction.Index(Tbl, 2, 0)
    Set d = CreateObject("Scripting.Dictionary")
    For i = 3 To UBound(Tbl) - 2
        k = Tbl(i, 3): d(k) = d(k) & ";" & i
    Next i
    Application.ScreenUpdating = False
    For Each k In d.keys
    '...
    Next k
End Sub

Je ferai une remise en mémoire de la 2e partie pour la compléter avant de poursuivre, là j'ai juste ajouté la boucle sur les clés du dico établi, lesquelles sont constituées par les noms d'instit. Il ne reste plus qu'à remplir cette boucle par ce qu'il y a lieu de faire pour chaque instit.

(Pour l'instant j'ai diverses tâches urgentes ...)

La structure de la procédure est en principe définitivement établie.

@+

OK, merci de prendre du temps pour t'occuper de tout ça!

Pour ma part semaine prochaine c'est vacances scolaires, mes deux trolls partent en colo, j'aurai du temps pour potasser tout ça

Très bien ! Tu vas pouvoir finir d'assimiler tout ça.

Je résume le passage de la partie 1 à la partie 2 : avant de quitter la feuille sur laquelle on a travaillé, on récupère les données telles qu'elles ont été modifiées en tableau. C'est sur ce tableau qu'on va ensuite travailler, faire les extractions de lignes par instit. On met à jour l'affichage : l'utilisateur peut ainsi voir ce qui a été fait pendant qu'on poursuit.

On amorce la préparation de l'extraction :

  • redimensionnement tableau Tmp à 1 (tableau de base 0, donc 2 éléments d'indice 0 et 1),
  • on place les 2 lignes d'en-tête dans ces 2 éléments du tableau,
  • on incrémente une variable (n) à 2, indice suivant du tableau lorsqu'on aura à l'incrémenter,
  • on crée un objet dictionnaire,
  • on consigne dans ce dictionnaire des éléments clé-valeur dont la clé est un nom d'instit, la valeur une liste de numéros de lignes (séparés par des points-virgules) correspondant à cet instit., en opérant une boucle sur le tableau (partie correspondant aux données, à l'exclusion des 2 lignes d'en-tête [qu'on a d'ailleurs déjà prélevées pour pouvoir les mettre sur toutes les feuilles] et des 2 lignes de totaux à la fin).

Chaque élément instit du dico est unique. Prenons l'exemple de Mme T en ligne 3, il n'y aura qu'un seul élément dico dont la clé sera Mme T, et la valeur sous cette clé sera : ;3;8;9;14;15;20;21;26;27;32;33;38;39;44;45;50;51;56;60;61;65;66;70;71;76;81;87

On va procéder aux extractions par une boucle sur les éléments dico, soit sur chaque instit, c'est à dire sur les clés du dico :

    For Each k In d.keys

A l'invocation des clés d.keys, VBA les renvoie sous forme de tableau, que l'on peut parcourir dans une boucle For Each... Next [Ce type de boucle permet de parcourir des collections d'objets en utilisant une variable objet du type des éléments composant la collection (par exemple un objet Worksheet pour parcourir la collection des feuilles d'un classeur), ou les éléments d'un tableau en utilisant une variable de type Variant, ce qui est notre cas ici].

A chaque tour de boucle, k sera un élément du tableau de clés, soit une clé, sa valeur sera donc un nom d'instit.

A partir de la clé k on va appeler l'élément dictionnaire correspondant à cette clé, d(k) et en récupérer la valeur sous forme de tableau en utilisant la fonction Split :

        Col = Split(d(k), ";")

On a déjà vu cette fonction en opérant les suppressions de colonnes. Elle permet donc de transformer une chaîne-texte en tableau en la scindant selon un séparateur qu'on indique, ici le point-vigule. Et simultanément on affecte ce tableau à une variable de type Variant qui va nous permettre de l'utiliser.

La variable Col que nous avons déjà utilisé était disponible et n'avait plus d'autre utilisation prévue. On en profite donc pour la réutiliser (et éviter de créer une nouvelle variable alors que celle-ci resterait sur le carreau). J'espère que le fait qu'on l'ait nommée Col ne te déstabilisera pas... ! Y pensant plus tôt, j'aurais pris un nom plus parlant pour un type d'utilisation mixte, mais après coup j'ai pensé que changer le nom pourrait t'induire en erreur plus facilement, et le fait qu'on ait une variable appelée Col pour un tableau de numéros de lignes ne gêne en rien VBA. Et toi tu peux plus facilement voir qu'une variable représentant une occupation d'espace mémoire, même si on n'en manque pas, il est souhaitable de l'économiser en ayant le nombre de variables nécessaires pour opérer, en les utilisant au mieux et sans en créer un surplus qui resterait sous-utilisé.

Disposant ainsi de l'instit et de ses numéros de lignes, on va parcourir notre tableau de lignes en utilisant une boucle !

        For i = 1 To UBound(Col)

Le tableau est de base 0, mais comme on l'a vu la chaîne qui a permis de le constituer débute par un ";", c'est à dire un séparateur. Cela signifie que notre premier élément de tableau, d'indice 0, sera vide. On va donc l'ignorer et démarrer notre boucle à 1, jusqu'à la fin du tableau.

A chaque tour de cette boucle, on aura une ligne à récupérer, on incrémente donc le tableau Tmp avec la variable n préparée pour cela, en préservant le contenu déjà dans le tableau, on affecte une ligne entière du tableau Tbl en utilisant Index, et on incrémente n pour le tour suivant.

            ReDim Preserve Tmp(n)
            Tmp(n) = WorksheetFunction.Index(Tbl, CInt(Col(i)), 0)
            n = n + 1

La ligne du tableau Tbl à prélever est fournie par l'élément de Col sur lequel on boucle, Col(i). Ces éléments sont de type String, à la fois en provenant d'un dico qui les stocke dans ce type, et générés par Split qui produit un tableau de type String, donc on les convertit en Integer pour les utiliser comme valeur numérique.

Une fois achevée la constitution du tableau Tmp pour un instit donné, on n'a plus qu'à passer à l'ajout de feuille pour y insérer les données. Jusque là, rien ne se voit...

Je récapitule le code de la 2e partie, jusqu'à ce point :

Sub Macro()
    Dim c As Range, i%, n%, dln%, Col, Tbl, k, Tmp(), d As Object
    With Worksheets(" Listes des pointages")
        '...
        Tbl = .Range("A1").CurrentRegion
        Application.ScreenUpdating = True
    End With
    ReDim Tmp(1): n = 2
    Tmp(0) = WorksheetFunction.Index(Tbl, 1, 0)
    Tmp(1) = WorksheetFunction.Index(Tbl, 2, 0)
    Set d = CreateObject("Scripting.Dictionary")
    For i = 3 To UBound(Tbl) - 2
        k = Tbl(i, 3): d(k) = d(k) & ";" & i
    Next i
    Application.ScreenUpdating = False
    For Each k In d.keys
        Col = Split(d(k), ";")
        For i = 1 To UBound(Col)
            ReDim Preserve Tmp(n)
            Tmp(n) = WorksheetFunction.Index(Tbl, CInt(Col(i)), 0)
            n = n + 1
        Next i
        '...
    Next k
End Sub

@+ pour le dernier bout de chemin.

Bonjour ehlana24 ,salut à tous,

@ehlana24

un début de piste,

remplacer les lignes du style

Columns("O:P").Select
Range("O2").Activate
Selection.Delete Shift:=xlToLeft

par

Range("O:P").Delete Shift:=xlToLeft

c'est à dire, appliquer l'action directement à l'objet

les lignes

ActiveWindow.SmallScroll Down:=

sont inutile, vous pouvez les effacer.

remplacer les lignes du style

Range("H2").Select
ActiveCell.FormulaR1C1 = "S1"

par

Range("H2") = "S1"

toujours appliquer l'action directement à l'objet

ect...

en espérant que cela vous sera utile pour débuter un grand ménage,

n'hésiter pas à revenir poser des questions,

bonne continuation!

Bonjour,

Ne laissons pas refroidir ! Parvenus à l'étape précédente, l'avant-dernière, nous avons traité une instit. :

  • nous disposons de son nom à partir de la clé de dico, dans la variable k,
  • nous avons monté un tableau des lignes du tableau initial (incluant les deux lignes d'en-tête qui seront communes pour tous les instit.) relevant de l'instit. traité : tableau Tmp à une dimension dont chaque élément est constitué par une ligne entière de données, soit un tableau,
  • nous connaissons le nombre de lignes à insérer dans la nouvelle feuille dédiée à l'instit. par la variable n ayant servi au redimensionnement progressif du tableau Tmp (la variable était incrémentée à la fin de chaque tour de boucle pour redimensionnement du tableau au tour suivant, sa valeur est donc toujours l'indice atteint par le tableau +1, le tableau étant de base 0, cette valeur coincide avec le nombre de lignes).

Il ne nous reste plus qu'à mettre ces données dans une nouvelle feuille.

Pour cela nous allons ajouter une feuille au classeur, en utilisant la méthode Add (dont disposent presque toutes les collections d'objets Excel que l'on est amené à manipuler en VBA, qui consiste à ajouter un élément, soit une feuille, à la collection constituées par les feuilles du classeur).

Lors de cet ajout, on définit l'emplacement de la nouvelle feuille. Cela se fait avant ou après une autre feuille existante désignée. Sauf avis contraire de ta part, si tu dois placer les nouvelles feuilles à un autre emplacement (auquel cas on modifiera...), on les place après la feuille sur laquelle nous avons travaillé au cours de la première partie.

Et comme ensuite c'est sur cette feuille que nous allons opérer pour y faire diverses choses, on la place en l'ajoutant sous instruction With, ce qui nous permettra d'y faire référence sans avoir à répéter la référence.

        With Worksheets.Add(after:=Worksheets("Listes des pointages"))

[Dernier commentaire au sujet de cette ligne : l'indication de la feuille après laquelle nous plaçons la nouvelle dans le classeur est un argument de la méthode Add de la collection Worksheets. Les arguments (ou paramètres de l'action à réaliser) peuvent être passés aux méthodes de deux façons : soit par nom (nom de l'argument suivi de ":=", suivi de la valeur de l'argument), soit par position (ils doivent alors être passés dans l'ordre défini par le programmeur de la méthode, en laissant en blanc ceux qui ne sont pas utilisés, entre les virgules séparant chaque argument et indiquant sa position).

Je suis partisan de les placer autant que possible par position, parce que c'est la méthode la plus générale (il est des cas où ils ne peuvent être passés par nom, mais peuvent toujours l'être par position), parce que cela raccourcit le code et qu'on a moins à écrire, c'est donc plus clair à la lecture, et on assimilera vite le positionnement des principaux arguments des méthodes les plus utilisées au bout d'un petit nombre d'utilisation...

Note qu'à l'inverse, l'enregistreur les passe par nom, mais dans l'ordre d'inscription, et répète ceux qui, laissés à leur valeur par défaut n'ont pas besoin d'être définis. C'est un des points sur lesquels on doit épurer le code enregistré.

Par exception à ce que je viens de dire, tu auras remarqué que j'ai passé ici l'argument par nom : after:=...

Les 2 premiers arguments de la méthode sont before et after, pour les passer par position on débuterait par une virgule... Outre qu'il est toujours possible qu'on ait un doute sur l'ordre de ces deux arguments proches, on peut facilement louper la virgule initiale... Dans un tel cas le passage par nom offre une sécurité (il y a quelques cas de ce type) et à la relecture on n'aura pas à s'interroger sur la signification puisqu'on la lit...

On peut aussi opérer un passage mixte, passer les premiers arguments par nom puis, au lieu d'avoir 7 ou 8 virgules entre lesquelles on n'aura rien à mettre, et facile de faire une erreur dans ce cas, on poursuit par nom...]

Après cette digression, reprenons le fil : notre intervention sur la feuille.

On va commencer par la nommer, du nom de l'instit.

            .Name = k

Simple ! On réfère à la feuille mise sous With et on affecte la propriété Name.

Ensuite, on va devoir affecter les données, soit affecter les valeurs contenues dans le tableau que nous avons préparé à la plage de la feuille destinée à les accueillir.

On va donc dimensionner cette plage, en la plaçant aussi sous With pour continuer à s'y référer (un With plage, inséré dans le With feuille). On sait que sa dimension en lignes est n et en colonnes, 15.

            With .Range("A1").Resize(n, 15)

Pas de problème jusqu'ici. Abordons la partie plus difficile : affecter les valeurs à la plage.

Une plage étant définie, à la dimension d'un tableau, s'il s'agit d'un tableau à 2 dimensions, dont la première représente les lignes et la seconde les colonnes, on affecte simplement : plage.Value = tablo

Si lignes et colonnes sont inversées dans le tablo (cas qui peut survenir fréquemment, on transpose lors de l'affectation : plage.Value = WorksheetFunction.Transpose(tablo)

Si le tableau est unidimensionnel, il se comporte comme une ligne. On l'affectera directement à un plage horizontale, et en le transposant à une plage verticale.

Notre situation est un peu plus compliquée : notre tableau est unidimensionnel et la dimension correspond à une plage verticale, il faudrait donc le transposer, mais ses éléments sont également des tableaux unidimensionnels, donc affectables directement à des plages horizontales (qui en transposant ne vont plus se trouver dans le bon sens et devront à leur tour être transposés) : effectivement, une double transposition rétablira nos données dans le bon sens dans la plage.

C'est un peu difficile à visualiser mentalement, mais lorsqu'on a un tableau unidimensionnel dont les éléments correspondent à des lignes, ces éléments étant eux-mêmes des tableaux unidimensionnels correspondant chacun à une ligne, retenir qu'on doit alors opérer une double transposition lors de l'affectation.

              .Value = WorksheetFunction.Transpose(WorksheetFunction.Transpose(Tmp))

Voilà donc ! On a opéré ainsi pour gagner en rapidité dans la constitution des tableaux, et dès lors qu'on peut opérer l'affectation on conserve ce gain de rapidité.

Il ne reste plus que la mise en forme, que notre procédure annexe va accomplir. Il faut donc l'appeler en lui passant la plage à traiter (sous forme d'objet Range, et l'argument True pour que la proc. assure la totalité de la mise en forme pour une nouvelle feuille.

               MiseEnForme .Cells, True

N'oublions pas que l'on est sous une instruction With référant justement à la plage que l'on doit passer comme argument à la fonction. La propriété Cells nous permet de le faire simplement en renvoyant toutes les cellules de la plage, soit un objet Range qui n'est autre que la plage elle-même.

Si l'on avait voulu utiliser la propriété Range pour renvoyer la plage, cette propriété comportant des arguments obligatoires, on aurait dû redéfinir la plage par rapport à elle-même... Pusiqu'on peut l'éviter, on l'évite !

On en a fini avec la feuille ajoutée, on peut donc passer à la suivante pour répéter l'opération (nous sommes dans une boucle), mais auparavant il nous faut réinitialiser notre variable tableau Tmp et notre variable d'incrémentation du tableau n pour le tour suivant :

  • pour cela on redimensionne le tableau à 1 en préservant ces 2 premières lignes d'en-tête qui demeurent valides pour l'instit. suivant,
  • et on redéfinit n à 2 comme on l'avait fait au départ,
on aborde ainsi le tour suivant dans les mêmes conditions que lorsqu'on est entré dans la boucle.

Résumons le code ajouté, en reprenant la totalité de la boucle sur les instit. :

'...
    For Each k In d.keys
        Col = Split(d(k), ";")
        For i = 1 To UBound(Col)
            ReDim Preserve Tmp(n)
            Tmp(n) = WorksheetFunction.Index(Tbl, CInt(Col(i)), 0)
            n = n + 1
        Next i
        With Worksheets.Add(after:=Worksheets("Listes des pointages"))
            .Name = k
            With .Range("A1").Resize(n, 15)
                .Value = WorksheetFunction.Transpose(WorksheetFunction.Transpose(Tmp))
                MiseEnForme .Cells, True
            End With
        End With
        ReDim Preserve Tmp(1): n = 2
    Next k
End Sub

Cordialement.

NB- Je vais tout de même sous peu tester ce code, ce que je n'ai toujours pas fait jusqu'ici... !

MFerrand, je te suis... à peu près, impressionnant quand même !

Du coup, pour la liste des instits, la liste pourra être modifiable facilement ? Parce qu'elle évolue quand même régulièrement.

Je n'ai pas vu, dans ton code, où tu déterminais la liste de noms ?

Bonjour,

Ici :

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

Tbl est un tableau qui reproduit ton tableau initial modifié sur la feuille, dont la colonne 3 est la colonne Classes (dans laquelle figurent les noms des instits).

On parcourt les lignes de données de ce tableau à partir de la ligne 3 (1 et 2 étant des entêtes) jusqu'à l'avant-avant-dernière (ou antépénultième !) (les 2 dernières lignes étant des totaux).

A chaque tour de boucle, on affecte à k le nom de l'instit figurant en col. 3. Et on ajoute à l'élément de dico d(k) [k étant la clé de l'élément] le numéro de ligne précédé par un ";" au contenu qu'il a déjà (ou à rien s'il n'en avait pas et qu'on vient alors de le créer).

Les clés n'admettant pas de doublons, chaque élément dico correspondra à un instit différent.

Et c'est la liste des clés du dico qui constitue notre liste d'instits.

Cette opération étant faite sur le tableau actuel, que les noms changent ou varient en nombre n'aura aucune incidence, on aura à chaque fois une liste des instits en place, sans doublon.

Et ensuite on va boucler sur la liste des clés du dico :

    For Each k In d.keys

donc sur la liste des instits.

Dans cette boucle, k sera à chaque tour le nom d'un instit différent.

Ce qui nous permet dans chaque tour, après ajout d'une nouvelle feuille, de la nommer au nom de l'instit :

            .Name = k

Cordialement.

OK, c'est trop bien, ça veux dire que la macro sera pérenne même si les instits changent !

Merci merci !

Bonsoir,

Oui bien sûr ! Excuse mon délai de réponse, j'attendais d'avoir testé, pour répondre et envoyer le fichier pour confirmation.

Je viens de le faire et j'ai dû opérer quelques petites rectifications :

1) A la 2e utilisation du nom de feuille j'avais mentionné "Listes de pointage" au lieu de " Listes de pointage", ce qui bien sûr provoquait une erreur. J'ai donc supprimé cette espace parasite dans le nom et aligné les noms dans le code.

A toi de vérifier le nom de la feuille à traiter par la suite...

2) Un problème affectait les dates en lignes 1 : on ne voit sur la ligne que : LU 24, MA 25... En réalité la date est sur 2 lignes dans la cellule, et sur la 2e ligne on trouve : 09/2018 qui n'apparaît pas en raison de la hauteur de ligne. Le slash qui suit l'indication du jour a été remplacé par un saut de ligne.

J'ai donc ajouté une ligne de code pour substituer un slash au saut de ligne :

            If i Mod 3 = 1 Then
                .Cells(1, i) = Replace(.Cells(1, i), Chr(10), "/")
                .Cells(dln + 2, i) = WorksheetFunction.Sum(.Cells(dln + 1, i).Resize(, 3))
            End If

C'est la première ligne dans l'instruction conditionnelle ci-dessus.

Il faudra donc que tu vérifies si cette façon de faire est permanente dans les fichiers que tu reçois (mais s'il n'y a pas de saut de ligne, rien ne sera remplacé...)

3) Dans la ligne qui précède l'instruction ci-dessus :

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

j'avais tapé un 1 à la place d'un i... mais je crois que nous avions corrigé cette erreur qui empêchait le calcul. C'est moi qui avait omis de rectifier mon fichier...

4) Dans la procédure de Mise en forme, sur cette ligne :

            If NewF Then .Cells(1, i).Resize(, 3).MergeCells = True

destinée à rétablir les fusions en ligne 1, j'avais inversé ligne et colonne : (i, 1) au lieu de (1, i), ce provoquait la fusion toute les 3 lignes des tableaux avec message d'Excel puisque les colonnes étaient occupées, un beau bazar.

Si tu as testé, tu aurais dû le constater.

S'agissant d'une procédure à n'exécuter qu'une fois sur un même tableau à traiter, si une erreur survient alors que le traitement a été engagé, relève le numéro d'erreur ou le message, et la ligne en erreur, ferme le fichier sans enregistrer, pour le rouvrir dans l'état initial, rectifier l'erreur et enregistrer après rectif avant de relancer.

Là elle est fonctionnelle sur le fichier. Sur un autre fichier, vérifier les points qui pourraient poser problème avant de lancer et si d'autres non prévus apparaissent, faire comme indiqué ci-dessus... Tu signales et on pourra ajuster.

Tu lances la macro à partir de la boîte de dialogue, je n'ai pas mis de bouton, ta feuille à traiter étant destinée à changer.

Cordialement.

Bonsoir !

C'est super, merci pour tout le travail que tu as fait, et merci pour la formation

Je viens de tester la macro, il y avait un bug car l'onglet liste des inscrits commence pas un espace, j'ai rajouté les deux espaces nécessaires et tout a l'air de fonctionner.

Est-ce qu'on pourrait rajouter pour la mise en forme le centrage dans la colonne des noms des enfants ? Actuellement ils sont alignés en bas et à gauche. Et dernier "peaufinage", est-ce qu'il est possible de définir la zone d'impression à chaque tableau et d'ajuster à une page en hauteur et en largeur ? J'abuse

Pas trop ! J'étais sur un autre genre de question et je vais me désaturer, et me réchauffer un peu , mais je verrais ça.

Bonne journée.

Help !!!! Est-ce que tu as pu te réchauffer un peu ? Pas gagné aujourd'hui avec le temps qu'il fait...

J'avais un peu oublié... Je vais essayer de voir ça avant de avant mon départ (pour rentrer chez moi) mais je ne peux le garantir, je suis déjà dans les préparatifs...

@+

T'inquiète, fait au mieux, le gros du travail est déjà fait et me permet d'économiser un temps certain !

Bon retour du coup !

Bonjour,

Normalement les deux petites modifications dans la proc. de mise en forme devraient répondre à ta demande. Selon les spécifications de départ on excluait la colonne 1 du centrage, il suffit donc de ne plus l'exclure.

Quant à la zone d'impression, elle se confond avec la plage mise en forme...

Sub MiseEnForme(Plg As Range, Optional NewF As Boolean)
    Dim i%
    With Plg
        If Not NewF Then .WrapText = False
        .HorizontalAlignment = xlCenter
        .VerticalAlignment = xlCenter
        If NewF Then .Offset(2).Resize(.Rows.Count - 2).Rows.RowHeight = 53
        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(1, i).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
        .Worksheet.PageSetup.PrintArea = .Address
    End With
End Sub

Confirme-moi que tout colle... Etant sous l'emprise d'un gros rhume, et dans un état qui s'améliore mais reste semi-comateux, je ne puis être certain de tout voir.

Cordialement.

coucou MFerrand,

t'as attrapé un gros rhume ? voilà c'que c'est d'quitter ton île de prédilection pour aller sur le continent !

t'es allé à Nice pa'c'que t'as été attiré par « la promenade des Anglais » (et les jolies p'tites demoiselles) ?


suggestion : quand tu rentreras chez toi, va t'réchauffer près du volcan en activité !

screen

(c'est plus efficace que n'importe quel radiateur ! )

dhany

C'est nickel, ça marche super bien !

Pour moi tout est OK, merci pour ta patience et ta disponibilité, tu es au top !

Soigne toi bien, et au plaisir

Merci !

Côté rhume ça va. Pour le reste, ms soins attendent que je puisse me déplacer...

Bonne continuation à toi.

Rechercher des sujets similaires à "macro probleme formule concatenation"