Protection feuille (sauf cellules déverrouillées) avec VBA

Bonjour à tout le forum,

Je viens vers vous à la recherche d'une solution VBA!

Je souhaite faire évoluer mon projet et j'ai besoin de vous ! Dans le fichier joint, j'ai 2 colonnes A et B qui prennent soit la couleur verte ou rouge en fonction du double click gauche sur la case. Dans la colonne C j'ai du texte que j'aimerais protéger et ce pour toute la colonne C pour éviter les fausses manip. Et dans la colonne D la saisie est libre

J'ai pour cela modifié le verrouillage des cellules renseignées "Libre saisie" par click droit=> Propriétés...

J'ai essayé de protéger ma feuille en espérant pouvoir modifier les cellules "déverrouillées" mais le souci c'est que le reste du code vba (fonction double-click gauche qui permet de colorer les cases en colonne A ou B) ne fonctionne plus :/

Avez-vous une proposition ? L'idéal serait de pouvoir adapter le code du double click gauche

Bonne dimanche et merci à ceux qui pourront m'aider :)

J-Baptiste

103test1.xlsm (18.20 Ko)

Bonjour,

Eventuellement rajoute ce code aux extrémités

ActiveSheet.Unprotect ("")
ActiveSheet.Protect ("")

Bonne journée.

Bonjour Ergotamine,

Merci pour votre proposition. J'avais déjà essayé cette solution mais cela ne fonctionne pas :/

Il faudrait pouvoir adapter le code que vous m'avez proposé aux cellules déverrouillées et je ne sais ps si cela est possible ?

Bonne journée et merci quand même :)

J-Baptiste

Bonjour à tous,

Les évènements clic droit et double clic fonctionnent même sur des cellules verrouillées et protégées.

Et, si je ne dis pas de bêtise, la protection n'empêche pas de mettre en forme, tant qu'on peut sélectionner les cellules.

Edit : Lors de la protection, il faut autoriser la modification du format de cellule peut-être.

Cdlt,

Bonjour,

Avec un code comme celà ça fonctionne chez moi :

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
ActiveSheet.Unprotect ("")
If Target.Column < 3 And Target.Row > 7 And Target.Text = "" Then Range("A" & Target.Row & ":B" & Target.Row).Interior.Pattern = xlNone Else Exit Sub
Target.Interior.ColorIndex = IIf(Target.Column = 1 And Target.Column < 3, 43, 3)
Cancel = True
ActiveSheet.Protect ("")
End Sub

Mais la solution de 3GB est beaucoup plus simple, merci à lui :

select

Merci à vous tous, effectivement cocher la case "Format de cellule" suffit à répondre à mon problème !

J'en profite pour que vous puissiez m'aider sur une autre problématique: j'aimerais effacer tout le contenu et la mise en forme des cellules non verrouillées en cliquant sur un bouton uniquement pour les feuilles qui commencent par un "V". Je pensais à un début de code suivant mais je ne sais pas comment le faire fonctionner:

Dim ws As Worksheet
For Each ws In Worksheets
    If ws.Name Like "V*"and Range.Locked=False then 
'instructions.ClearContents.ClearFormats
    End If
Next ws

Le souci c'est que certaines cellules que je souhaite effacer sont fusionnées :/

Merci à vous si vous avez des propositions !

J-Baptiste

Bonjour,

Sans fichier compliqué ..

Je pense qu'il faut que tu le fasses en plusieurs étape :
1- Boucler comme tu l'as fait
2- Activer la feuille si débute par V*
3- Déprotéger la feuille
4- Sélectionner les cellules avec une constante via la sélection avancée équivalente en VBA
5- Nettoyer leur contenu
6- Supprimer le fond
7- Reprotéger

Tu conserves ainsi la fusion des cellules mais les nettoie de leur contenu.

Bonne journée

Merci Ergotamine mais je débute en VBA et je ne sais pas comment coder notamment pour l'étape 4 "Sélectionner les cellules avec une constante via la sélection avancée équivalente en VBA". Est-ce que tu pourrais m'aider stp ? :)

Bonne journée à toi aussi :)

J-Baptiste

Bonjour,

Ne te fis pas aux apparences, je débute aussi !
Quand tu as un doute, le plus simple est de voir comment l'enregistreur de macro interprète l'action et ensuite tu optimises.

Voilà ce que j'obtiens :

Worksheets("Feuil1").Cells.SpecialCells(xlCellTypeConstants, 23).Select

Bonne journée.

Je ne vois pas comment activer la feuille qui débute par "V" :/

Pour le reste du code ça devrait pouvoir donner ça:

Dim ws As Worksheet
For Each ws In Worksheets
    If ws.Name Like "V*" THEN
''.Activate
With Activesheet
.Unprotect
.Cells.SpecialCells(xlCellTypeConstants, 23).Select
.ClearContents
.ClearFormats
.Protect
End With

Merci à vous !

J-Baptiste

Bonjour,

Un petit bout de code comme ça fait l'affaire :

Sub TEST()
For Each Ws In Worksheets
    If Ws.Name Like "V*" Then
    Ws.Activate
    End If
Next Ws
End Sub

Bon dimanche

Je propose une petite alternative parce qu'il peut exister des cellules avec des constantes verrouillées...

Ce genre de code (qui suit) peut prendre un peu de temps. Alors je limite à la zone utilisée :

Sub Cleaner()

application.screenupdating = false
for each ws in worksheets 'pour chaque feuille du classeur
    with ws 'avec feuille en cours
        if .name like "V*" then 'si le nom commence par "V"
            .unprotect 'deprotege
            for each cell in .usedrange 'pour chaque cellule de la zone utilisée
                if cell.locked = false then cell.clear 'si cellule en cours déverrouillée, on efface tout
            next cell 'cellule suivante
            .protect 'protege
        end if
    end with
next ws 'feuille suivante
application.screenupdating = true

end sub

Cdlt,

Bonjour 3GB,

Si je lis et interprète correctement, elle prend du temps car le code "inspecte" chaque cellule de la feuille 1 à 1 ?

Arriverais-tu à m'expliquer comment est défini le usedrange ? C'est la dernière ligne et colonne rempli en partant de A1 ?

Merci et bon dimanche !

Re Ergotamine,

Je ne suis pas un expert mais je vais essayer de répondre en fonction de ce que je crois savoir.

Elle peut prendre du temps parce que les boucles sur les collections sont plus lentes que les boucles en mémoire : for each ws in worksheets (on boucle sur la collection des feuilles > mais c'est pas grand-chose en général), for each cell in plage (on boucle sur un ensemble de cellules) et à chaque itération, il y a une affectation d'un objet, contrairement à une boucle for i = 1 to fin où on sonde des infos sur l'objet sans encombrer une variable objet à chaque fois.

Donc, plus la zone à couvrir est grande, plus ça peut ramer.

Ensuite, ici, on a pas seulement une boucle avec une condition par exemple, on applique une méthode sur les cellules (.clear), et ce genre d'opérations, lorsqu'elles sont nombreuses, prend plus de temps. C'est un peu comme (en un peu "moins pire") les .select ou .activate qu'il faut éviter car ils ralentissent.

Je crois que le .usedrange est l'union pleine de toutes les cellules avec du contenu (d'une extrémité à l'autre, la plus en haut à gauche remplie à la plus en bas à droite remplie). Donc pas à partir de A1. Et je ne suis pas sûr mais je crois qu'une bordure suffit pour inclure une cellule dans le .usedrange. Il faudrait que j'essaie.

Cdlt,

Merci pour les précisions et le temps consacré !

Donc en soit :
- Collection = Liste d'objet telle each worksheet ou each cell
- Mémoire = Liste de valeur telle que i = 1 to 10, ou je suppose, un array ?

Désolé je ne viens pas du tout du milieu informatique et apprend en autodidacte car c'est un milieu qui me passionne, donc j'essaie d'accumuler un maximum de connaissances pour aider et optimiser au mieux mes réponses !

Une collection, c'est un ensemble d'objets. Donc typiquement worksheets est la collection de worksheet, Shapes la collection de shape, ... Mais on peut définir ses propres collections.

Je ne suis pas non plus informaticien donc c'est compliqué à expliquer mais en "mémoire" sous-entend en passant par des variables qui ne puisent pas beaucoup de ressources, c'est-à-dire avec des ressources VBA "interne à VBA" et non avec des objets particuliers comme les objets d'applications comme excel. Les array sont clairement un bon exemple.

Je comprend mieux merci beaucoup !

Désolé à l'auteur pour ma pollution :)

Bonsoir Ergotamine et les autres !

Pas de souci pour les échanges, les forums sont faits pour ça !

Un membre du forum m'avait déjà aidé à coder mais je n'ai pas réussi à l'adapter à mon projet

Sub Int_Classeur()
 Application.ScreenUpdating = False
    '********************************************************************
    RAZ.afficher
    '********************************************************************
    Dim Plage As Range, Cel_Trouv As Range, DerLig As Long, i, Sh As Worksheet, Nb_Feuille, Cpt
    Nb_Feuille = ThisWorkbook.Worksheets.Count
    For Each Sh In ThisWorkbook.Worksheets
        Cpt = Cpt + 1
        If Left(Sh.Name, 1) = "V" Then
            With Sh
                .Unprotect
                ' on efface les deux première zone et leur colueur
                .Range("F3:I5,J3:M5").ClearContents
                .Range("F3:I5,J3:M5").Interior.Color = xlNone
                ' on attribue à la variable Plage la colonne A de la feuille que l'on essaie de quitter
                Set Plage = .Columns(1)
                ' on attribue la variable Cel_Trouv la cellule qui contient le mot "fin"
                Set Cel_Trouv = Plage.Cells.Find("fin", lookat:=xlWhole)
                ' si cette cellule est vide on quitte la procédure de test car "fin" n'a pas été trouvé
                If Not Cel_Trouv Is Nothing Then
                    DerLig = Cel_Trouv.Row - 1
                    ' on supprime la couleur des cellules en colonne 1 et 2
                    For i = 9 To DerLig
                        ' on supprime la couleur des cellules en colonne 1 et 2
                        If .Cells(i, 1).MergeArea.Cells.Count = 1 Then .Range("A" & i).Resize(, 2).Interior.Color = xlNone
                        ' on efface les données en colonne D, mais elles sont fusionnées, pour le différencier des autres
                        ' on regarde le nombre de cellules comprise dans la sélection
                        If .Cells(i, 4).MergeArea.Cells.Count = 10 Then .Range("D" & i).Resize(, 10).ClearContents
                        Sheets("Sommaire").Shapes.Range(Sh.Name).Fill.ForeColor.RGB = RGB(255, 0, 0)
                    Next i
                    '**************************************************************************************
                    RAZ.actualiser CInt((Cpt / Nb_Feuille) * 100)
                    '*************************************************************************************
                End If
                .Protect
            End With
        End If
    Next Sh
    Sheets("Sommaire").Activate

End Sub

Le souci avec ce code, c'est que lorsque je protège à nouveau mes feuilles, le format de cellule n'est plus coché dans la protection de la feuille donc il faudrait l'ajouter à la fin du code mais je ne sais pas quoi mettre, auriez-vous une piste?

Merci à vous tous :)

J-Baptiste

Bonsoir,

Normalement c'est ça

Range(Tes cellules).Locked = True

Mais ce code me semble sensiblement moins flexible que celui de 3GB car bloqué sur la plage F3:I5, J3:M5.

Merci pour votre réponse mais je ne sais pas comment coder en VBA:

Protéger à nouveau la feuille (.Protect) avec les conditions suivantes:

Sélectionner les cellules verrouillées
Sélectionner les cellules déverrouillées
Format de cellule

Merci à vous :)

J-Baptiste
Rechercher des sujets similaires à "protection feuille sauf deverrouillees vba"