Nettoyage macro

Bonjour Mr MFerrand,

J'aurai encore besoin de votre aide sur un point : est ce possible que lorsque dans la colonne D (type activité) les codes sont PSMC,PSYC,ERGC,KINC,ceux ci soient remis dans la colonne M (car avec les infos transmises à l'époque, la macro reprend les trois premières lettres),

Mais pour ces codes il me faudrait les quatre lettres,

Merci d'avance pour votre aide ,

Cordialement,

9test.xlsm (636.86 Ko)

Bonjour,

Tu vas ajouter une petite fonction, après la fonction ActEnc :

Function Act(ByVal txact As String) As String
    Select Case txact
        Case "PSMC", "PSYC", "ERGC", "KINC"
            Act = txact
        Case Else
            Act = Left(txact, 3)
    End Select
End Function

Et tu remplaces :

                .Cells(i, 13) = Left(.Cells(i, 9), 3)

par :

                .Cells(i, 13) = Act(.Cells(i, 9))

Il y en a 2 sauf erreur...

Cordialement.

Bonjour Mferrand,

J'ai testé la modification mais mon fichier excel plante, le sablier ne pars pas.

Savez vous pourquoi?,

Cordialement,


Merci pour votre retour,

J'ai du mal renseigner quelque chose sur la macro,

Après rectification elle fonctionne maintenant avec les modifs apportées,

Merci beaucoup ,

Cordialement,

Bonjour Mr MFerrand,

Pouvez vous me dire ce que je dois modifier pour que lorsqu'il n'y a pas d'usagers renseigné dans la colonne E, la durée d'activité (colonne J) reste positive (cf fichier joint filtre sur les durées négatives)

En sachant que si la date du début (colonne A) est supérieure à la date de fin (colonne B) (et oui cela arrive lol c'est une extraction qui le permet ce qui est bien sûr une erreur), la durée d'activité est donc négative.

Merci d'avance pour votre aide,

Cordialement,

12test.xlsm (639.72 Ko)

Bonjour,

Je m'y penche ! on y arrive !

un nouveau casse-tête ton problème !

Je pense en me remémorant les différentes phases de la construction que le cas sans utilisateur n'a pas du tout été prévu !!!

Ce que semble indiquer la structure décisionnelle liée aux encadrants (e) et utilisateurs (u) :

If e = 0 Then
    If u = 1 Then
        ...
    Else
        ...
    End If
Else
    ...
End If

On a bien le cas sans encadrant et le cas avec, et dans le cas sans encadrant on distingue selon un seul utilisateur ou plusieurs... Le cas 0 utilisateurs n'est implicitement pas prévu car le temps étant divisé par le nombre d'utilisateurs, la division par 0 provoquerait une erreur qui interromprait la procédure.

Pour qu'il n'y ait pas d'erreur, il faut donc que si pas d'utilisateur, le nombre en soit tout de même évalué à 1 ! Je crois savoir pourquoi c'est ainsi, mais je ne vois pas encore pourquoi le résultat en J devient alors négatif !

Quelques cafés de plus et on va voir si ça se décante !

Patience...

A+

Bonjour Mr MFerrand,

Oui c'est lors de son utilisation que je me suis rendu compte de cela.

En effet lorsqu'il n'y a pas d'enfants (usagers), la colonne J indique un temps négatif.

Merci beaucoup pour votre aide,,

Cordialement,

Je te remercierai à la fin d'améliorer ainsi mon approche des tableaux affectés à des variables de type Variant et constitués ainsi, c'est à dire en splittant le contenu d'une cellule.

Dans tous les cas, la variable est identifiée comme tableau de type String, et d'indice minimal 0. C'est pour l'indice maximal que ça se corse...

L'indice maximal (renvoyé par Ubound) est égal au nombre de séparateurs sur lequel on splitte contenus dans la cellule, le fait qu'entre les séparateurs il y ait ou non quelque chose n'a pas d'incidence. On aura le cas échéant un tableau comportant des éléments vides...

Mais dans le cas où il n'y a aucun séparateur, UBound renvoie une valeur différente selon que le texte splitté (contenu de la cellule) existe ou non : s'il y a un contenu UBound renvoie 0, logique, on a donc un tableau à un élément, et l'on peut appeler l'élément unique du tableau. Mais s'il n'y a pas de contenu (cellule vide ou contenant une chaîne vide), là UBound renvoie -1 !

Je n'imagine pas quelle allure pourrait avoir un tableau d'indice minimal 0 et d'indice maximal -1 ! Mais de fait, on peut toujours appeler l'élément 0 ou l'élément -1, dans les deux cas on obtient une erreur (erreur 9, indice...)

Notons que la colonne Utilisateurs que l'on utilise liste les noms d'utilisateurs, chaque nom étant suivi d'une virgule. Dès lors qu'il y a au moins un nom, on obtient un tableau de 2 éléments (en splittant) ou d'autant d'élément que d'utilisateurs listés +1, le dernier élément étant toujours vide. L'indice minimal étant toujours 0, l'indice maximal correspondait au nombre d'utilisateurs.

Ce qui n'avait pas été prévu, c'est l'absence d'utilisateur, il était donc considéré que le nombre en était au minimum de 1...

Il s'agit d'un cas qui avait été omis, à prendre en considération. Le fait que dans ce cas l'évaluation du nombre d'utilisateurs se traduise par -1 au lieu de 0, explique que la procédure se déroule sans erreur et que la valeur temps, divisée par -1 se retrouve négative.

La rectification pose alors une petite question... elle peut être simple ou un peu moins !

Il y a la solution simple et confiante ! Elle consiste à constater que les noms portés dans la colonne Utilisateurs le sont toujours (jusqu'ici, sinon on aurait eu des erreurs !) dans les normes prévues, soit tout nom est toujours suivi d'une virgule, et à considérer que la possibilité qu'un nom ne soit pas suivi de virgule est un cas qui ne se produira pas.

Auquel cas une simple inversion de signe rétablira la situation [je vais tout de même regarder de plus près !]

Et la solution méfiante, qui conduira à tester... mais si on teste sur les utilisateurs en prenant en compte la possibilité nom non suivi de virgule, il est alors logique de tester également sur les encadrants, la même possibilité pouvant alors se produire...

A suivre...

Bonjour Mr MFerrand,

Non, le nom de l'usager sera toujours suivi d'une virgule et donc effectivement il n'y aura jamais de noms d'usagers sans virgule.

Si j'ai bien suivi le raisonnement apporté, il faudrait suivre la solution "simple et confiante " dans ce cas !

Cordialement,

Je vais donc opter pour une solution simple, et toutefois mixte !

Je m'explique :

La résultante négative n'était pas le seul problème, il n'y avait plus également insertion de lignes correspondant au nombre d'encadrants. En effet l'insertion se faisait si : u * e > 1, or u étant égal à -1, le produit ne pouvait être supérieur à 1. Et il n'en résultait pas d'erreur ensuite car la boucle : For j = 1 To u [=-1] ne démarrait tout simplement pas.

Pour que tout se passe bien, il faut donc la présence d'un utilisateur ! S'il n'y en a pas, on va considérer qu'il en existe un virtuel, sans nom, qui permettra à la procédure de se dérouler comme prévu, et qui n'aura pas d'effet encombrant puisque aucun nom ne sera écrit, mais u aura la valeur 1, le tableau Usa aura 2 éléments dont le premier (nom de l'utilisateur) sera vide !

Pour obtenir ce résultat une seule ligne de code à ajouter, surlignée dans le fragment ci-dessous :

            .Cells(i, 20) = Facturable(.Cells(i, 4))
            If Right(.Cells(i, 5), 1) <> "," Then .Cells(i, 5) = .Cells(i, 5) & ","
            Usa = Split(.Cells(i, 5), ","): u = UBound(Usa)
            If u > 1 Then

Je pense que tu n'auras pas de mal à repérer l'emplacement, juste avant de définir Usa en splittant le contenu de la cellule utilisateurs.

Si la cellule est vide on y insère simplement une virgule, ce qui crée l'utilisateur virtuel dont on a besoin...

Cordialement.

Question de l'exception activité SYN...

Rappel pour ordre de la procédure. Dernière modification surlignée. (edit : surlignage ôté car plus pris en charge dans la fenêtre code...)

Sub Activité()
    Dim Tmp, Usa, Enc, t, dln&, i&, j%, k%, e%, u%
    Application.ScreenUpdating = False
    With Worksheets("TB ACTIVITE")
        .Range("A1:J2").MergeCells = False
        .Rows(2).Delete
        Tmp = Split("ACTIVITE TB;DUREE ACT.;USAGERS;ENCADRANTS;ACTES;DUREE MORIO;NB ACTES;JOUR;" _
         & "N° MOIS;MOIS;ANNEE;FACTURABLE", ";")
        .Range("I1:T1").Value = Tmp
        dln = .Range("A" & .Rows.Count).End(xlUp).Row
        With .Range("I1:T" & dln)
            .HorizontalAlignment = xlCenter
            With .Borders
                .LineStyle = xlContinuous: Weight = xlThin
            End With
            With .Rows(1)
                .Interior.Color = RGB(128, 128, 128)
                With .Font
                    .Color = vbWhite: .Size = 16: .Bold = True
                End With
            End With
        End With
        For i = dln To 2 Step -1
            .Cells(i, 9) = Split(.Cells(i, 4), "-")(0)
            .Cells(i, 15) = IIf(.Cells(i, 4) = "SYN", 2, 1)
            .Cells(i, 16) = Day(.Cells(i, 1))
            .Cells(i, 17) = Month(.Cells(i, 1))
            .Cells(i, 18) = StrConv(MonthName(.Cells(i, 17)), vbProperCase)
            .Cells(i, 19) = Year(.Cells(i, 1))
            .Cells(i, 20) = Facturable(.Cells(i, 4))
            If Right(.Cells(i, 5), 1) <> "," Then .Cells(i, 5) = .Cells(i, 5) & ","
            Usa = Split(.Cells(i, 5), ","): u = UBound(Usa)
            If u > 1 Then
                For k = 0 To u - 2
                    For j = k + 1 To u - 1
                        If Trim(Usa(j)) < Trim(Usa(k)) Then
                            Tmp = Usa(j): Usa(j) = Usa(k): Usa(k) = Tmp
                        End If
                    Next j
                Next k
            End If
            e = CInt(.Cells(i, 6)): t = Round(.Cells(i, 3) / 60, 2) * .Cells(i, 15)
            If .Cells(i, 4) = "SYN" Then
                .Cells(i, 13) = "SYN": .Cells(i, 10) = t: .Cells(i, 14) = t * 100
                .Cells(i, 11) = .Cells(i, 5): .Cells(i, 12) = .Cells(i, 7)
            ElseIf e = 0 Then
                .Cells(i, 13) = Act(.Cells(i, 9))
                If u = 1 Then
                    .Cells(i, 10) = t: .Cells(i, 14) = t * 100
                    .Cells(i, 11) = UCase(Trim(Usa(0)))
                Else
                    t = Round(t / u, 2): .Cells(i, 10) = t: .Cells(i, 14) = t * 100
                    .Rows(i + 1 & ":" & i + u - 1).Insert
                    .Range("A" & i & ":T" & i).Copy .Range("A" & i + 1 & ":A" & i + u - 1)
                    For j = 1 To u
                        .Cells(i + j - 1, 11) = UCase(Trim(Usa(j - 1)))
                    Next j
                End If
            Else
                Enc = Split(.Cells(i, 7), ","): Tmp = Enc
                t = Round(t / (u * e), 2): .Cells(i, 10) = t: .Cells(i, 14) = t * 100
                If .Cells(i, 9) Like "[!G]*" Then
                    .Cells(i, 13) = Act(.Cells(i, 9))
                    Tmp(0) = ""
                Else
                    For j = 1 To e
                        Tmp(j - 1) = ActEnc(Enc(j - 1))
                    Next j
                End If
                If u * e > 1 Then
                    .Rows(i + 1 & ":" & i + u * e - 1).Insert
                    .Range("A" & i & ":T" & i).Copy .Range("A" & i + 1 & ":A" & i + u * e - 1)
                End If
                For j = 1 To u
                    For k = 1 To e
                        .Cells(i + (j - 1) * e + k - 1, 11) = UCase(Trim(Usa(j - 1)))
                        .Cells(i + (j - 1) * e + k - 1, 12) = Trim(Enc(k - 1))
                        If Tmp(0) <> "" Then .Cells(i + (j - 1) * e + k - 1, 13) = Tmp(k - 1)
                    Next k
                Next j
            End If
        Next i
        .Columns("I:T").AutoFit
    End With
    If Not d Is Nothing Then d.RemoveAll: Set d = Nothing
End Sub

A vérifier...

Bonjour Mr Ferrand,

J'ai testé la modification, mais il me mets erreur de compilation à "ELSE if e = 0 then",

J'ai tenté de le modifier en remplaçant "Else" par "End if", la macro va au bout de son traitement mais n'applique pas la condition synthèse (ne doit pas insérer de lignes peu importe le nombre d'encadrants),

Avez vous une idée de ce que je dois faire?,

Merci d'avance,

Cordialement,

Tu es victime de la rénovation du Forum !

J'avais surligné le fragment de code ajouté, mais il semble que le surlignage n'opère plus dans la fenêtre Code, depuis que les modifications sont devenues effectives et les balises Surligner apparaissent en texte.

            [Surligner]If .Cells(i, 4) = "SYN" Then
                .Cells(i, 13) = "SYN": .Cells(i, 10) = t: .Cells(i, 14) = t * 100
                .Cells(i, 11) = .Cells(i, 5): .Cells(i, 12) = .Cells(i, 7)
            Else[/Surligner]If e = 0 Then

Je viens de les supprimer dans le post concerné :

            If .Cells(i, 4) = "SYN" Then
                .Cells(i, 13) = "SYN": .Cells(i, 10) = t: .Cells(i, 14) = t * 100
                .Cells(i, 11) = .Cells(i, 5): .Cells(i, 12) = .Cells(i, 7)
            ElseIf e = 0 Then

Tu vois donc qu'il s'agit de ElseIf !

Dans l'instruction décisionnelle, on peut trouver Else ou ElseIf, mais Else If n'existe pas !

Bonjour Mr FERRAND,

Oui j'avais remarqué que le code n'était pas surligné lol et connaissant vos compétences, je me disais que cela peut venir que de moi, enfin la à cause des changements du forum !

Après vérification je pense que c'est OK,

Merci pour tout,

Cordialement,

Bonjour MFerrand,

Je reviens sur le sujet car j'ai essayé de modifier le code comme ceci lors de l'application de la règle synthèse (Nom & prénom en majuscule sans la virgule) :

.Cells(i, 11) = UCase(.Cells(i, 5))

Le problème c'est que la virgule reste au bout de la chaine (j'ai essayé avec split mais je n'y arrive pas

Pourriez vous m'aider une fois de plus !

Merci d'avance,

Pas compris.

Il y a toujours eu une virgule à la fin des listes de noms (Utilisateurs, Encadrants) même si un seul dans la liste !

Et il ne faut surtout pas l'enlever ! Plus rien ne fonctionnerait !

A tel point d'ailleurs qu'un des derniers problèmes a été réglé par l'insertion d'une virgule en cas d'absence de nom !

Oui oui bien sur, je me suis mal exprimé, c'est à la colonne K qu' il ne faut plus avoir de virgule : elle était nécessaire à la colonne E.

Votre code pour régler le problème Synthèse

            If .Cells(i, 4) = "SYN" Then
                .Cells(i, 13) = "SYN": .Cells(i, 10) = t: .Cells(i, 14) = t * 100
                .Cells(i, 11) = .Cells(i, 5): .Cells(i, 12) = .Cells(i, 7)
            ElseIf e = 0 Then

Et je voudrais que les cellules de la colonne K (cells(i,11)) soient égales aux cellules en majuscule et sans la virgule de la colonne E (cells(i,5)). Dans la cas de la synthèse, j'ai obligatoirement qu'un seul nom et prénom.

Avez vous compris ma demande?,

Merci d'avance,

D’où le code suivant :

.Cells(i, 11) = UCase(.Cells(i, 5))

mais il me laisse la virgule au bout !

Tu mets :

.Cells(i, 11) = UCase(Replace(.Cells(i, 5), ",", ""))

Merci beaucoup,

Cordialement,

Rechercher des sujets similaires à "nettoyage macro"