IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Macros et VBA Excel Discussion :

worksheet_change seulement lors d'une suppression [XL-2019]


Sujet :

Macros et VBA Excel

  1. #1
    Membre régulier
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Janvier 2020
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes

    Informations forums :
    Inscription : Janvier 2020
    Messages : 129
    Points : 73
    Points
    73
    Par défaut worksheet_change seulement lors d'une suppression
    Bonjour à tous gens du Forum
    Voici le sujet de mes réflexions.
    Je souhaite interdire la suppression de certaines lignes de mon fichier. La position de celles ci peut varier ua gré des insertions/suppressions de lignes. Pour les repérer j'ai mis du texte dans les cellule A.

    J'ai codé ça, dans le code du worksheet:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Private Sub Worksheet_Change(ByVal Target As Range)
     
    If Target.Address = Target.EntireRow.Address Then  'And Cells(ActiveCell.Row, 1).Value <> ""   si toute la ligne sélectionnée et cellule A non vide
       Application.EnableEvents = False 'excel ne détecte plus les nouveaux évènements
       MsgBox "Suppression de ligne interdite."
       Application.Undo
       Application.EnableEvents = True
    End If
    MsgBox ("ok")
    End Sub
    la condition cells.value<>"" est en commentaire pour l'instant : une chose à la fois.
    Grace au message "OK", je sais que je rentre bien dans le macro à chaque fois que j'ajoute/supprime du texte dans une cellule.
    Dès que je sélectionne une ligne complète, que j'insère ou que je supprime, j'ai le message "suppression interdite".
    Je n'arrive pas à trouver la condition qui interdira seulement la suppression, et pas l'insertion.
    Mais peut être que worksheet_change n'est pas la bonne fonction....
    J'ai regardé du côté de before_delete, mais ça ne semble fonctionner que pour la suppression de la feuille.

    Quelqu'un aurait'il la solution? Une piste
    Cordialement
    Benoit

  2. #2
    Rédacteur
    Avatar de Philippe Tulliez
    Homme Profil pro
    Formateur, développeur et consultant Excel, Access, Word et VBA
    Inscrit en
    Janvier 2010
    Messages
    12 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur, développeur et consultant Excel, Access, Word et VBA

    Informations forums :
    Inscription : Janvier 2010
    Messages : 12 754
    Points : 28 605
    Points
    28 605
    Billets dans le blog
    53
    Par défaut
    Bonjour,
    Lorsque l'on protège une feuille, il est possible d'autoriser l'insertion de ligne mais pas la suppression.
    Philippe Tulliez
    Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément. (Nicolas Boileau)
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter
    Mes tutoriels : Utilisation de l'assistant « Insertion de fonction », Les filtres avancés ou élaborés dans Excel
    Mon dernier billet : Utilisation de la fonction Dir en VBA pour vérifier l'existence d'un fichier

  3. #3
    Membre régulier
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Janvier 2020
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes

    Informations forums :
    Inscription : Janvier 2020
    Messages : 129
    Points : 73
    Points
    73
    Par défaut
    Bonjour,
    Je regardé de ce côté là, mais je ne veux pas interdire toute suppression de ligne, mais uniquement la suppression de certaines : celles qui ont du texte en colonne A.
    y'aurait-il une condition "si l'action demandée est suppression"?

    Merci pour ce retour

  4. #4
    Rédacteur
    Avatar de Philippe Tulliez
    Homme Profil pro
    Formateur, développeur et consultant Excel, Access, Word et VBA
    Inscrit en
    Janvier 2010
    Messages
    12 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur, développeur et consultant Excel, Access, Word et VBA

    Informations forums :
    Inscription : Janvier 2010
    Messages : 12 754
    Points : 28 605
    Points
    28 605
    Billets dans le blog
    53
    Par défaut
    Bonjour,
    y'aurait-il une condition "si l'action demandée est suppression"?
    Pas que je sache.
    Pour gérer cela par programmation, je crains que cela devienne rapidement une usine à gaz et je ne vois pas comment empêcher la suppression d'une ligne.
    On ne pourrait que la constater.
    Philippe Tulliez
    Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément. (Nicolas Boileau)
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter
    Mes tutoriels : Utilisation de l'assistant « Insertion de fonction », Les filtres avancés ou élaborés dans Excel
    Mon dernier billet : Utilisation de la fonction Dir en VBA pour vérifier l'existence d'un fichier

  5. #5
    Membre régulier
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Janvier 2020
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes

    Informations forums :
    Inscription : Janvier 2020
    Messages : 129
    Points : 73
    Points
    73
    Par défaut
    Gasp...ça sent le roussi...

    Je ne sais pas si ça pourrait aider, mais avec ce code (pompé sur doc.microsoft.com) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, _ 
     Cancel As Boolean) 
     Dim icbc As Object 
     For Each icbc In Application.CommandBars("cell").Controls 
     If icbc.Tag = "brccm" Then icbc.Delete 
     Next icbc 
     If Not Application.Intersect(Target, Range("b1:b10")) _ 
     Is Nothing Then 
     With Application.CommandBars("cell").Controls _ 
     .Add(Type:=msoControlButton, before:=6, _ 
     temporary:=True) 
     .Caption = "New Context Menu Item" 
     .OnAction = "MyMacro" 
     .Tag = "brccm" 
     End With 
     End If 
    End Sub
    Comme pour supprimer ma ligne, je dois faire un clic droit, je me dis qu'il y a peut être une piste.

    Ce code doit "ajouter un nouvel élément au menu contextuel pour les cellules B1:B10." dixit le site.
    Si on peut ajouter un élément au menu, ne pourrait-on pas en masquer un (la fonction "supprimer" en l’occurrence) ou le rentre inactif?
    Et seulement si les conditions (sélection ligne complète ET case A non vide) sont remplies.

    Bonne ou mauvaise idée?

    Il n'y aura pas de message d'alerte...je m'en contenterais.
    Il y a d'autre méthodes que clic droit pour supprimer une ligne, mais celle ci est la plus courante. Je prends le risque qu'un petit malin puisse supprimer une ligne par un autre biais.

    Merci

  6. #6
    Membre émérite
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 814
    Points : 2 949
    Points
    2 949
    Billets dans le blog
    10
    Par défaut
    Bonjour,

    très complexe ce que vous nous demandez là.
    Il existe plusieurs manières de "détruire" des données.

    Si c'est juste pour éviter des "négligences", le code ci-dessous vous aidera.
    Par contre, il ne peux rien contre des êtres diaboliques et malveillants***.

    Un simple copié/collé d'une ligne vide sur une ligne de données suffit à contourner mon code.
    Dans ce cas, il est également possible d'intercepter le "Coller" (je vous l'ai mis dans le code), mais comment le traiter ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    Private Sub Worksheet_Change(ByVal Target As Range)
    Dim C As String, I As Long
        If Target.Row > 1 And Target.Row < 10 Then    'EMPÊCHE LA SUPPRESSION DES LIGNES 2 à 9
            'on vérifie dans la barre d'outils
            With Application.CommandBars("Standard")
                'recherche de la liste de Undo
                I = .FindControl(ID:=128).Index
                'la dernière action qu'il est possible d'annuler
                C = .Controls(I).List(1)
            End With
            's'il s'agit d'un "Supprimer" ou Effacer (obtenu en faisant Ctrl+X puis Suppr) ==> on annule grâce à Undo
            If C = "Supprimer" Or C = "Effacer" Then
                'on annule
                With Application
                    'on désactive les événements sinon le Undo va déclencher à nouveau Worksheet_Change
                    .EnableEvents = False
                    .Undo
                    'réactivation des événements
                    .EnableEvents = True
                End With
            ElseIf C = "Coller" Then 
    '????????????
            End If
        End If
    End Sub
    Le plus simple est de protéger le classeur...

    Attention aussi à la désactivation des événements.
    Si, pour une raison ou une autre le code plante avant la réactivation (ici je ne vois pas de raison, mais...), les événements resteront inactifs jusqu'à la prochaine ouverture du classeur.

    EDIT :
    ***
    Le simple lancement de ce code va, non seulement effacer la seconde ligne, mais en plus faire un joli bug dans la macro événementielle Worksheet_Change() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Sub Macro1()
        Rows("2:2").Delete Shift:=xlUp
    End Sub
    Si tu penses qu'un utilisateur en est capable, il te faudra gérer l'erreur avant C = .Controls(I).List(1)

    Un code un peu plus compliqué à contourner serait celui-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    Private Sub Worksheet_Change(ByVal Target As Range)
    Dim C As String, I As Long
        If Target.Row > 1 And Target.Row < 10 Then    'EMPÊCHE LA SUPPRESSION DES LIGNES 2 à 9
            'on vérifie dans la barre d'outils
            With Application.CommandBars("Standard")
                'recherche de la liste de Undo
                I = .FindControl(ID:=128).Index
                'Si suppression par macro, la ligne C = .Controls(I).List(1) va créer une erreur
                'En effet, tout déclenchement de macro vide la liste de Undo
                On Error GoTo Exception 'FERME LE CLASSEUR SANS ENREGISTRER
                'la dernière action qu'il est possible d'annuler
                C = .Controls(I).List(1)
                On Error GoTo 0
            End With
            's'il s'agit d'un "Supprimer" ou Effacer (obtenu en faisant Ctrl+X puis Suppr) ==> on annule grâce à Undo
            If C = "Supprimer" Or C = "Effacer" Then
                'on annule
                With Application
                    'on désactive les événements sinon le Undo va déclencher à nouveau Worksheet_Change
                    .EnableEvents = False
                    .Undo
                    'réactivation des événements
                    .EnableEvents = True
                End With
            ElseIf C = "Coller" Then
                GoTo Exception 'FERME LE CLASSEUR SANS ENREGISTRER
            End If
        End If
        Exit Sub
    Exception:
        MsgBox "Manipulation interdite", vbCritical + vbOKOnly, "EJECTION"
        ThisWorkbook.Close False
    End Sub
    Il empêche également la suppression via une macro en "éjectant" l'utilisateur (fermeture du classeur violente, sans enregistrement)...
    Cordialement,
    Franck

  7. #7
    Membre régulier
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Janvier 2020
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes

    Informations forums :
    Inscription : Janvier 2020
    Messages : 129
    Points : 73
    Points
    73
    Par défaut
    Merci Pijaku
    On n'est pas loin !!

    voici le code adapté :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    Private Sub Worksheet_Change(ByVal Target As Range)
    Dim C As String, I As Long
        If Target.Address = Target.EntireRow.Address And Cells(ActiveCell.Row, 1).Value <> "" Then    
            'on vérifie dans la barre d'outils
            With Application.CommandBars("Standard")
                'recherche de la liste de Undo
                I = .FindControl(ID:=128).Index
                'la dernière action qu'il est possible d'annuler
                C = .Controls(I).List(1)
            End With
            's'il s'agit d'un "Supprimer" ou Effacer (obtenu en faisant Ctrl+X puis Suppr) ==> on annule grâce à Undo
            If C = "Supprimer" Or C = "Effacer" Then
                'on annule
                With Application
                    'on désactive les événements sinon le Undo va déclencher à nouveau Worksheet_Change
                    .EnableEvents = False
                    .Undo
                    'réactivation des événements
                    .EnableEvents = True
                    MsgBox ("Ne pas supprimer cette ligne. Vous pouvez la masquer.")
                End With
            ElseIf C = "Coller" Then
    '????????????
            End If
        End If
    End Sub
    je bute sur la 2ème condition du IF (and cell.value <>"").
    Si je ne met pas cette 2ème condition, je peux insérer une ligne, mais pas en supprimer.
    Comme je ne veux interdire la suppression que sur les lignes qui on une valeur en A, j'ajoute la 2ème condition.
    Mais ça ne marche pas. Quand il teste, la ligne est déjà supprimée et donc il teste sur la ligne du dessous.
    La preuve : si je veux supprimer une ligne sans valeur dans A, mais que la ligne du dessous, elle, a une valeur en A, j'ai le message "ne pas supprimer".

    Est ce que attribuer la valeur de Cells(ActiveCell.Row, 1) à une variable à chaque selection_change pourrait être une solution? Si la variable est <>"" au moment du change, alors on est sur une ligne à ne pas supprimer.
    Est ce que ça a une chance de marcher?

    Pour les êtres diaboliques et malfaisants...je postule avoir à faire à des utilisateurs responsables. Mon fichier de base sera en lecture seule. ils feront le leur via enregistrer-sous. Donc si ils le cassent, tant pis pour eux. Je veux bien gérer les fausses manip,le sabotage non.
    Merci pour les avertissements néanmoins.

    C'est l'heure d'aller troquer la tenue de travail pour le short et les tongs... à lundi j'espère
    Benoit

  8. #8
    Membre émérite
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 814
    Points : 2 949
    Points
    2 949
    Billets dans le blog
    10
    Par défaut
    Bonjour,

    Bon.
    Alors c'est facile.
    1- Quoiqu'il arrive, en cas de suppression de ligne entière, on annule la suppression (Undo),
    2- Après Undo, on regarde la cellule colonne A,
    3- Si A est non vide, on supprime, sinon on affiche le message : Ne pas supprimer cette ligne. Vous pouvez la masquer

    J'ai même traité le cas de suppression de plusieurs lignes. Dans ce cas :=> on annule!

    Tu peux supprimer 1 ou des cellules, mais pas de lignes entières, sauf si A est non vide...

    Le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    Option Explicit
     
    Private Sub Worksheet_Change(ByVal Target As Range)
    Dim I As Long
        With Application
            'Si la ligne entière est sélectionnée (ou plusieurs lignes, mais ENTIERES)
            If Target.Columns.Count = Target.Parent.Columns.Count Then
                I = .CommandBars("Standard").FindControl(ID:=128).Index
                'si on supprime
                If .CommandBars("Standard").Controls(I).List(1) = "Supprimer" Or .CommandBars("Standard").Controls(I).List(1) = "Effacer" Then
                    'annulation
                    .EnableEvents = False
                    .Undo
                    .EnableEvents = True
                End If
                'Si une seule ligne entière sélectionnée
                If Target.Rows.Count = 1 Then
                    'Test si A est non vide
                    If Range("A" & Target.Offset(-1, 0).Row).Value <> vbNullString Then
                        'Si A non vide :=> on supprime
                        Target.Offset(-1, 0).EntireRow.Delete
                    Else
                        MsgBox ("Ne pas supprimer cette ligne. Vous pouvez la masquer.")
                    End If
                End If
            End If
        End With
    End Sub
    Cordialement,
    Franck

  9. #9
    Membre régulier
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Janvier 2020
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes

    Informations forums :
    Inscription : Janvier 2020
    Messages : 129
    Points : 73
    Points
    73
    Par défaut
    Bonjour à tous,

    Voila le code que je viens de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    Option Explicit
     
    Public Nosupp As String
     
    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Nosupp = Cells(ActiveCell.Row, 1).Value
    'MsgBox (Nosupp)
    End Sub
     
    Private Sub Worksheet_Change(ByVal Target As Range)
    Dim C As String, I As Long
        If Target.Address = Target.EntireRow.Address And Nosupp <> "" Then    'EMPÊCHE LA SUPPRESSION si selection ligne complète et si A non vide
            'on vérifie dans la barre d'outils
            With Application.CommandBars("Standard")
                'recherche de la liste de Undo
                I = .FindControl(ID:=128).Index
                'la dernière action qu'il est possible d'annuler
                C = .Controls(I).List(1)
            End With
            's'il s'agit d'un "Supprimer" ou Effacer (obtenu en faisant Ctrl+X puis Suppr) ==> on annule grâce à Undo
            If C = "Supprimer" Or C = "Effacer" Then
                'on annule
                With Application
                    'on désactive les événements sinon le Undo va déclencher à nouveau Worksheet_Change
                    .EnableEvents = False
                    .Undo
                    'réactivation des événements
                    .EnableEvents = True
                    MsgBox ("Ne pas supprimer cette ligne. Vous pouvez la masquer.")
                End With
             End If
        End If
     
    End Sub

    A chaque selectionchange, on applique à la variable Nosupp la valeur de la cellule "A,ligne".
    Si cette valeur est <> "" ET que l'on a sélectionné une ligne complète, alors la suppression est interdite : undo et message

    ça fait bien ce que je voulais !

    Merci à vous 2 pour votre aide.
    Bonne semaine
    Benoit

  10. #10
    Rédacteur
    Avatar de Philippe Tulliez
    Homme Profil pro
    Formateur, développeur et consultant Excel, Access, Word et VBA
    Inscrit en
    Janvier 2010
    Messages
    12 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur, développeur et consultant Excel, Access, Word et VBA

    Informations forums :
    Inscription : Janvier 2010
    Messages : 12 754
    Points : 28 605
    Points
    28 605
    Billets dans le blog
    53
    Par défaut
    Bonjour Franck,
    Pas mal

    Attention : Petit bemol toutefois que si tu empêches la suppression de la ligne entière, rien n'empêche de supprimer le contenue d'une ou plusieurs cellules de cette ligne ou de plusieurs lignes et les décaler vers le haut ou vers la gauche
    Philippe Tulliez
    Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément. (Nicolas Boileau)
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter
    Mes tutoriels : Utilisation de l'assistant « Insertion de fonction », Les filtres avancés ou élaborés dans Excel
    Mon dernier billet : Utilisation de la fonction Dir en VBA pour vérifier l'existence d'un fichier

  11. #11
    Membre régulier
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Janvier 2020
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes

    Informations forums :
    Inscription : Janvier 2020
    Messages : 129
    Points : 73
    Points
    73
    Par défaut
    Bonjour Franck,
    Nos réponses se sont croisées.
    Bien vu le cas d'une suppression de plusieurs lignes !

    Bon, par contre, ton code plante :
    Si je supprime une ligne avec rien en A : j'ai le message "ne pas supprimer" et il la remet. Donc l'inverse de ce qu'il est sensé faire.
    Si je supprime une ligne avec qqch en A :
    Erreur d'exécution '-2147467259 (80004005)' :
    la méhode 'List' de l'objet '_commandbarcombobox' a échoué

    A cet endroit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
                If .CommandBars("Standard").Controls(I).List(1) = "Supprimer" Or .CommandBars("Standard").Controls(I).List(1) = "Effacer" Then
    Si je supprime 2 lignes vide en A, ou avec un mixte vide/non vide : il supprime et remet aussitôt, sans message "ne pas supprimer"

    Je vais essayer de comprendre et de corriger, mais je veux bien ton éclairage aussi.

    Benoit


    PS
    Les applaudissements de Maître Philippe me vont droit au coeur !!

  12. #12
    Membre émérite
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 814
    Points : 2 949
    Points
    2 949
    Billets dans le blog
    10
    Par défaut
    Voici le code corrigé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    Option Explicit
     
    Private Sub Worksheet_Change(ByVal Target As Range)
    Dim I As Long
        With Application
            .EnableEvents = False
            'Si la ligne entière est sélectionnée (ou plusieurs lignes, mais ENTIERES)
            If Target.Columns.Count = Target.Parent.Columns.Count Then
                I = .CommandBars("Standard").FindControl(ID:=128).Index
                'si on supprime
                If .CommandBars("Standard").Controls(I).List(1) = "Supprimer" Or .CommandBars("Standard").Controls(I).List(1) = "Effacer" Then
                    'annulation
                    .Undo
                End If
                'Si une seule ligne entière sélectionnée
                If Target.Rows.Count = 1 Then
                    'Test si A est non vide
                    If Range("A" & Target.Offset(-1, 0).Row).Value = vbNullString Then
                        'Si A non vide :=> on supprime
                        Target.Offset(-1, 0).EntireRow.Delete
                    Else
                        MsgBox ("Ne pas supprimer cette ligne. Vous pouvez la masquer.")
                    End If
                End If
            End If
            .EnableEvents = True
        End With
    End Sub
    @Philippe :
    Attention : Petit bemol toutefois que si tu empêches la suppression de la ligne entière, rien n'empêche de supprimer le contenue d'une ou plusieurs cellules de cette ligne ou de plusieurs lignes et les décaler vers le haut ou vers la gauche
    Oui.
    On peut le faire, mais je préfères tout de même laisser ça à l'utilisateur (vu avec le demandeur)
    Cordialement,
    Franck

  13. #13
    Membre régulier
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Janvier 2020
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes

    Informations forums :
    Inscription : Janvier 2020
    Messages : 129
    Points : 73
    Points
    73
    Par défaut
    Désolé, mais c'est encore moi...
    C'est nettement mieux :
    suppression une ligne vide en A : il accepte et supprime
    suppression plusieurs lignes : il annule la commande. J'ai ajouté un message "merci de supprimer ligne à ligne"
    suppression une ligne non vide en A : il annule et message "ne pas supprimer"

    Par contre lorsque je copie une ligne (vide en A) et que je l'insère (insérer les cellules copiées) ça plante.
    Même message et au même endroit que toute à l'heure.
    C'est embêtant car le copier/insérer est un des piliers de l'utilisation de mon fichier

    Et une fois que ça a planté, la macro "change" ne fonctionne plus. Je peux ajouter, insérer, supprimer ce que je veux, c'est comme si le code n'existait plus.
    Il faut que je ferme et ré-ouvre le fichier pour retrouver la fonctionnalité du code.

    Autre point, ça m'embête de ne pouvoir supprimer plusieurs lignes en même temps. Je pensais faire un test sur la somme des valeurs en colonne A de la target. Si cette somme est <>"", c'est qu'au moins une ligne contient une valeur et ne doit pas être supprimer. Auquel cas, on annule. Si somme ="", alors aucune ligne ne contient une valeur et on peut tout supprimer.
    Mais je n'ai pas trouvé comment coder ça. Puis-je abuser encore de tes conniassances?

    Merci
    Benoit

  14. #14
    Membre régulier
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Janvier 2020
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes

    Informations forums :
    Inscription : Janvier 2020
    Messages : 129
    Points : 73
    Points
    73
    Par défaut
    je viens de voir un autre soucis.
    Si j'insère une ligne (clic droit, insertion) il n'insère pas de ligne, mais efface le contenu de la ligne du dessus.

  15. #15
    Membre régulier
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Janvier 2020
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes

    Informations forums :
    Inscription : Janvier 2020
    Messages : 129
    Points : 73
    Points
    73
    Par défaut
    pb similaire lors d'un couper/insérer de ligne
    le couper marche bien, mais lors de l'insertion, au lieu de d'insérer la ligne coupé, le contenu de la ligne du dessus est remplacé par les valeurs coupées.
    Désolé pour ces info par petite touche.
    Cette fois, je crois avoir tout testé

  16. #16
    Membre émérite
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 814
    Points : 2 949
    Points
    2 949
    Billets dans le blog
    10
    Par défaut
    Je regarde tout ça.
    A tout à l'heure.



    ps : je vais me refaire un tit café!
    Cordialement,
    Franck

  17. #17
    Membre émérite
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 814
    Points : 2 949
    Points
    2 949
    Billets dans le blog
    10
    Par défaut
    Bon.
    Normalement, j'ai pris en compte tes demandes. Toutes, il me semble...
    Nouveau code, à tester...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    Option Explicit
     
    Private Sub Worksheet_Change(ByVal Target As Range)
    Dim I As Long
        With Application
            .EnableEvents = False
            'Si la ligne entière est sélectionnée (ou plusieurs lignes, mais ENTIERES)
            If Target.Columns.Count = Target.Parent.Columns.Count Then
                I = .CommandBars("Standard").FindControl(ID:=128).Index
                'si on supprime
                If .CommandBars("Standard").Controls(I).List(1) = "Supprimer" Or .CommandBars("Standard").Controls(I).List(1) = "Effacer" Then
                    'annulation
                    .Undo
                Else
                    .EnableEvents = True
                    Exit Sub
                End If
                'Si une seule ligne entière sélectionnée
                If Target.Rows.Count = 1 Then
                    'Test si A est vide
                    If Range("A" & Target.Offset(-1, 0).Row).Value = vbNullString Then
                        'Si A  vide :=> on supprime
                        Target.Offset(-1, 0).EntireRow.Delete
                    Else
                        MsgBox ("Ne pas supprimer cette ligne. Vous pouvez la masquer.")
                    End If
                Else
                    'Si la colonne A du Target sélectionné ne contient pas de valeurs
                    If .WorksheetFunction.CountA(Target.Offset((Target.Rows.Count * -1), 0).Columns(1)) = 0 Then
                        'SUPPRIME
                        Rows(Target.Offset((Target.Rows.Count * -1), 0).Columns(1).EntireRow.Address).Delete
                    End If
                End If
            End If
            .EnableEvents = True
        End With
    End Sub
    Concernant ce point :
    Et une fois que ça a planté, la macro "change" ne fonctionne plus.
    C'est normal.
    En début de macro on désactive le gestionnaire d'événement : EnableEvents = False.
    Si la macro plante au milieu, elle ne va pas jusqu'à la réactivation : EnableEvents = True

    On pourrait mettre un "pare-feu" à cela, mais, s'agissant de mettre la poussière sous le tapis, je préfères que tu testes en long et en large (voir même en travers), avant de songer à appliquer cette solution...

    Mais, de toutes manières, il te faut y songer.
    Place donc cette procédure dans un module standard. En cas de plantage, lance là pour rétablir le gestionnaire d'événements...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Public Sub SOSevents()
        Application.EnableEvents = True
    End Sub
    Cordialement,
    Franck

  18. #18
    Membre régulier
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Janvier 2020
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes

    Informations forums :
    Inscription : Janvier 2020
    Messages : 129
    Points : 73
    Points
    73
    Par défaut
    Franck, merci pour ce N° retour.
    y'a plein de trucs qui marchent bien, mais... je ne pensais pas que ce serait si tordu comme demande !

    Quand je veux effacer le contenu d'une ligne, y'a un pb d'offset, car, selon les configurations
    -si ma ligne est vide en A et celle du dessus non vide, j'ai le message comme quoi je ne peut pas supprimer (il teste donc la ligne du dessus !)
    -si la ligne du dessus est vide en A, il supprime la ligne du dessus.
    Mais jamais il n'efface le contenu de la ligne sélectionnée
    J'ai viré la condition OR commandBars..."effacer" et ça efface bien la ligne sélectionnée. Même si elle est non vide en A

    Après avoir inséré une ligne ou copier/insérer cellules copiées, si j'annule par ctrl+Z, la macro plante : erreur execution 9, l'indice n'appartient pas à la selection. Au niveau du IF commandbars.
    Je n'ai pas ce pb si je fait un couper/insérer les cellules coupées

    Du coup, et malgré tout le respect que j'ai pour ton code,...j'ai repris celui que j'ai envoyé ce matin. corrigé pour prendre en compte plusieurs lignes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    Option Explicit
     
    Public Nosupp As String
     
    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
     
    Nosupp = WorksheetFunction.CountA(Target.Columns(1))
    End Sub
     
    Private Sub Worksheet_Change(ByVal Target As Range)
     
    Dim C As String, I As Long
       If Target.Address = Target.EntireRow.Address And Nosupp > 0 Then   'EMPÊCHE LA SUPPRESSION si selection ligne complète et si A non vide
            'on vérifie dans la barre d'outils
            With Application.CommandBars("Standard")
                'recherche de la liste de Undo
                I = .FindControl(ID:=128).Index
                'la dernière action qu'il est possible d'annuler
                C = .Controls(I).List(1)
            End With
            's'il s'agit d'un "Supprimer" ou Effacer (obtenu en faisant Ctrl+X puis Suppr) ==> on annule grâce à Undo
            If C = "Supprimer" Or C = "Effacer" Or C = "copiée" Then
                'on annule
                With Application
                    'on désactive les événements sinon le Undo va déclencher à nouveau Worksheet_Change
                    .EnableEvents = False
                    .Undo
                    'réactivation des événements
                    .EnableEvents = True
                    MsgBox ("Vous ne devez pas supprimer cette ligne. Mais vous pouvez la masquer.")
                End With
             End If
        End If
    End Sub
    Plus de pb d'effacement décalé et je peux faire ctrl+Z.
    Le seul point qui manquerai serait d'interdire le "couper" d'une ligne non vide en A. De ce que j'ai déduit, "couper" n'est pas considéré comme un changement et donc de déclenche pas la macro.
    C'est un moindre mal, car ça sort d'une utilisation normal du fichier et je vais donc en resté là.

    Merci beaucoup pour le temps que tu m'as consacré. Je ne serait pas aller aussi loin sans toi.
    Cordialement
    Benoit

  19. #19
    Membre émérite
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 814
    Points : 2 949
    Points
    2 949
    Billets dans le blog
    10
    Par défaut
    Curieusement, j'ai testé et viens de retester, les problèmes que tu signales :
    -si ma ligne est vide en A et celle du dessus non vide, j'ai le message comme quoi je ne peut pas supprimer (il teste donc la ligne du dessus !)
    -si la ligne du dessus est vide en A, il supprime la ligne du dessus.

    ne se produisent pas chez moi.

    As-tu bien copié/collé mon dernier code sans y toucher?

    Après avoir inséré une ligne ou copier/insérer cellules copiées, si j'annule par ctrl+Z, la macro plante : erreur execution 9
    ça oui. La macro plante quand tu fais une seule action et que tu l'annules par Ctrl+z.
    En effet, s'il n'y a rien à annuler, .Controls(I).List(1) n'existe pas...
    Suffit d'ajouter un test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If .CommandBars("Standard").Controls(I).ListCount > 0 Then
    Mais bon, si ton code fonctionne, utilise le.
    Cordialement,
    Franck

  20. #20
    Membre régulier
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Janvier 2020
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes

    Informations forums :
    Inscription : Janvier 2020
    Messages : 129
    Points : 73
    Points
    73
    Par défaut
    Bonjour Franck,
    J'ai retesté ton code d'hier 11h48. En me disant que j'avais peut être bidouillé un truc.
    Ton code tel que me fait les même pb que décrit hier :
    Quand je veux effacer le contenu d'une ligne, y'a un pb d'offset, car, selon les configurations
    -si ma ligne est vide en A et celle du dessus non vide, j'ai le message comme quoi je ne peut pas supprimer (il teste donc la ligne du dessus !)
    -si la ligne du dessus est vide en A, il supprime la ligne du dessus.


    Je viens de voir que j'avais sélectionné Excel 2019 dans ma demande. je suis en 2016. Peut être que ça joue...

    A ta dispo si tu veux que je teste autre chose pour comprendre le pourquoi des choses, mais pour ma part, je vais resté sur mon code.
    Bonne journée

    Benoit

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Message d'erreur inattendue lors d'une suppression
    Par Just-Soft dans le forum Bases de données
    Réponses: 8
    Dernier message: 18/11/2008, 11h42
  2. Réponses: 3
    Dernier message: 13/04/2008, 02h40
  3. [JDOM] Problème d'iterateur lors d'une suppression
    Par romuluslepunk dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 07/01/2006, 15h00
  4. Probleme lors d'une suppression
    Par DrTank dans le forum Langage SQL
    Réponses: 5
    Dernier message: 21/04/2005, 17h38
  5. Combler les trous lors d'une suppression dans une table
    Par Billybongjoe dans le forum PostgreSQL
    Réponses: 5
    Dernier message: 08/04/2004, 14h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo