Repérer le passage d'une cellule vide à une cellule renseignée et inversement da [Résolu]

Signaler
Messages postés
9
Date d'inscription
jeudi 29 janvier 2009
Statut
Membre
Dernière intervention
6 novembre 2009
-
Messages postés
9
Date d'inscription
jeudi 29 janvier 2009
Statut
Membre
Dernière intervention
6 novembre 2009
-
Bonjour,

J'essaie de réaliser des opérations qui s'éxécutent dans une feuille Excel (2003) après avoir modifié la valeur d'une cellule. J'utilise donc la procédure Worksheet_Change. Jusque là, tout va bien (grâce à d'autres discussions sur ce forum)! Si la cellule en question n'est pas vide, je réalise la 1ère opération, sinon j'en fais une autre (j'ai mis le code en bas pour info).

Concrêtement, je veux que lorsqu'on met ses initiales dans la colonne Vérificateur initialement vide, cela affiche la date et protège la ligne contre tous les utilisateurs, et qu'au contraire, lorsque les vérificateurs retirent leurs initiales, la date et la protection disparaissent pour pouvoir faire des modifs.

En fait mon pb, c'est que je ne veux pas seulement repérer si une cellule est vide ou pas après l'avoir modifiée, mais plutôt savoir si on passe de vide à rempli ou l'inverse. C'est vraiment ça qui conditionnerait mes 2 opérations. En effet, la procédure Worksheet_Change va éxécuter la 1ère opération même si je ne fais que modifier le texte d'une cellule, et la 2è opération même si j'active une cellule vide et passe à la suivante. Cela va générer des pbs (2 fois la même protection sur la même plage...)


J'espère que c'est à peu près clair...!
Merci d'avance pour vos conseils!
GoodWeath'


Private Sub Worksheet_Change(ByVal Target As Range)

    Dim j As Long
    j = 1 'Compteur de colonnes

    Do While Cells(1, j) <> "Vérificateur"
        j = j + 1
    Loop
    
    'Opérations à réaliser si on RENSEIGNE une cellule de la colonne Vérificateur    
    If Target.Column = j And Target.Value <> "" Then
        'Ajout de la date dans la colonne suivante
        Cells(Target.Row, j + 1).Value = "le " & Format(Date, "dd/mm/yyyy")
        
        'Déprotection de la feuille pour définir une nouvelle zone protégée
        ActiveSheet.Unprotect Password:="jb"
        ActiveSheet.Protection.AllowEditRanges.Add Title:="Ligne" & Target.Row, _
        Range:=Range(Cells(Target.Row, j - 3), Cells(Target.Row, j - 1)), Password:="bloque"

        ActiveSheet.Protect Password:="jb", ...    

    'Opérations à réaliser si on VIDE une cellule de la colonne Vérificateur
    ElseIf Target.Column j And Target.Value "" Then
        Cells(Target.Row, j + 1).Value = ""
        
    End If
    
End Sub

6 réponses

Messages postés
9
Date d'inscription
jeudi 29 janvier 2009
Statut
Membre
Dernière intervention
6 novembre 2009

Bonjour Us,

C'est pas grave, ce qui compte, ce sont les idées, et le memo dans Selection_Change est exactement ce qu'il me fallait donc merci! Ensuite j'ai pu l'adapter à ce que je cherchais à faire (voir en dessous).

Par contre, j'ai vu que tu utilisais une méthode différente pour repérer la position de la colonne Vérificateur : quel est son intérêt? et tu utilises UCase uniquement pour ne pas avoir de pb avec les accents dans le fichier Excel?

Voilà, maintenant je vais pouvoir me prendre la tête avec des histoires de protection/déprotection... Il y a bien des chances pour que j'ai de nouveau recours au forum!

Bonne journée!
GW

Option Explicit

' Déclaration valable pour l'ensemble des subs de la feuille
Dim memo As String


Private Sub Worksheet_Change(ByVal target As Range)

    Dim j As Long
    j = 1 'Compteur de colonnes
    Do While Cells(1, j) <> "Vérificateur"
        j = j + 1
    Loop
    
    
    If target.Column = j Then
    
        'Opérations à réaliser si on RENSEIGNE une cellule initialement vide de la colonne Vérificateur
        If memo = vbNullString And target.Value <> vbNullString Then
        
            'Ajout de la date dans la colonne suivante
            Cells(target.Row, j + 1).Value = "le " & Format(Date, "dd/mm/yyyy")
        
            '...
                
        'Opérations à réaliser si on VIDE une cellule de la colonne Vérificateur
        ElseIf memo <> vbNullString And target.Value = vbNullString Then
            Cells(target.Row, j + 1).Value = vbNullString
            
        'Pour empécher la modification des initiales sans raison
        ElseIf memo <> vbNullString And target.Value <> memo And target.Value <> vbNullString Then
            MsgBox ("blabla")
            Cells(target.Row, j).Value = memo
            
        End If
        
    End If
    
End Sub

Private Sub worksheet_selectionchange(ByVal target As Range)
    
    'Retient le contenu de la cellule
    memo = target.Value
    
End Sub
Messages postés
2065
Date d'inscription
lundi 11 avril 2005
Statut
Membre
Dernière intervention
14 mars 2016
8
Bonjour,

Option Explicit

' Declaration valable pour l'ensemble des Subs de la Feuille
Dim Memo As String

Private Sub worksheet_change(ByVal Target As Range)

    ' Paramètres
    Dim j As Long
    Dim MotCle As String
    
    ' Recherche colonne avec mot clé "vérificateur"
    MotCle = "Vérificateur"
    
    j = 1 'compteur de colonnes
    Do While UCase(Cells(1, j).Value) <> UCase(MotCle)
        j = j + 1
    Loop
    
    ' Si Cellule vérificateur non vide => remet le contenu initial de la cellule
    If Cells(Target.Row, j) <> vbNullString Then
        Target.Value = Memo
        Exit Sub
    End If
    
    ' Opérations à réaliser si on renseigne une cellule de la colonne vérificateur
    If Target.Column = j Then
        
        If Target.Value <> vbNullString Then
            'ajout de la date dans la colonne suivante
            Cells(Target.Row, j + 1).Value = "le " & Format(Date, "dd/mm/yyyy")
            
            'opérations à réaliser si on vide une cellule de la colonne vérificateur
        Else
            Cells(Target.Row, j + 1).Value = vbNullString
        End If
    End If
    
End Sub

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    
    'Retient le contenu de la cellule
    Memo = Target.Value
    
End Sub


Amicalement,
Us.
Messages postés
2065
Date d'inscription
lundi 11 avril 2005
Statut
Membre
Dernière intervention
14 mars 2016
8
Euh... non, desole, je viens de voir que mon code n'est pas bon...

Je vais le reprendre plus tard...

Amicalement,
Us.
Messages postés
2065
Date d'inscription
lundi 11 avril 2005
Statut
Membre
Dernière intervention
14 mars 2016
8
Bonsoir,

Cette fois c'est bon. Essai ceci :

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    'désactive la protection
    ActiveSheet.Unprotect
    
    'Trouve la colonne de vérificateur
    j = Cells.Find(What:="vérificateur", After:=ActiveCell, LookIn:=xlFormulas, _
        LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
        MatchCase:=False, SearchFormat:=False).Column
        
    'Trouve le dernier élément de la colonne vérificateur
    dernier = Cells(65536, j).End(xlUp).Row
 
    'déverrouille toutes les cellules
    Cells.Locked = False
    Cells.FormulaHidden = False
    
    'ajout de la date dans la colonne suivante
    If Target.Item(1, 1).Value <> vbNullString Then Cells(Target.Row, j + 1).Value = "le " & Format(Date, "dd/mm/yyyy")
    
    ' verrouille les lignes de la colonne vérificateur non vide
    For t = 1 To dernier
        If Cells(t, j) <> vbNullString Then
            Rows(t).Locked = True
            Rows(t).FormulaHidden = False
        End If
    Next t
    
    'déverrouille la colonne vérificateur => permet les modifs
    Columns(j).Locked = False
    Columns(j).FormulaHidden = False
    
    'active la protection des cellules vérrouillées
    ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True

End Sub


Amicalement,
Us.
Messages postés
2065
Date d'inscription
lundi 11 avril 2005
Statut
Membre
Dernière intervention
14 mars 2016
8
euh... peut-être mieux encore :

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'désactive la protection
ActiveSheet.Unprotect

'Trouve la colonne de vérificateur
j = Cells.Find(What:="vérificateur", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Column

'Trouve le dernier élément de la colonne vérificateur
dernier = Cells(65536, j).End(xlUp).Row

'déverrouille toutes les cellules
Cells.Locked = False

' verrouille les lignes de la colonne vérificateur non vide
For t = 1 To dernier
If Cells(t, j) <> vbNullString Then
Cells(t, j + 1).Value = "le " & Format(Date, "dd/mm/yyyy")
Rows(t).Locked = True
End If
Next t

'déverrouille la colonne vérificateur => permet les modifs
Columns(j).Locked = False

'active la protection des cellules vérrouillées
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True

End Sub

Amicalement,
Us.
Messages postés
9
Date d'inscription
jeudi 29 janvier 2009
Statut
Membre
Dernière intervention
6 novembre 2009

Bonjour,

Merci d'encore penser à mon pb! Ca me permet d'avoir d'autres façons de faire! Par ex remplacer ma boucle Do While pour rechercher la colonne...
Par contre le Cells.Find.Column ne marche plus quand je remplace SelectionChange par Change (pour éviter de faire tourner le code à chaque changement de cellule) dans ta procédure. Par contre ça marche dans la mienne au-dessus... Bizarre!!

Malheureusement, je ne peux pas utiliser la fonction Locked car j'ai défini différents types d'utilisateurs avec Protection par plages.
D'où mon besoin d'aller bricoler la taille des plages protégées en fonction des lignes validées : pour les agrandir, j'ai trouvé, par contre pour retirer des morceaux de plage je bloque! Aurais-tu une idée? J'ai posté une question à cette adresse (http://www.vbfrance.com/forum/sujet-RETIRER-CERTAINE-PLAGE-PLAGE-PROTEGEE-MODIFICATION-RANGE-PROTECTION_1363945.aspx) mais personne ne m'a encore répondu!

Merci!
GW