Débutant en VBA, j'utilise un code permettant de protéger l'ensemble des Feuils de mon workbook avec un mot de passe.
En double cliquant, l'utilisateur déprotège et peut de nouveau modifier le contenu de la dite cellule.
Ma problématique, il m'arrive périodiquement de devoir réaliser un copier/coller d'un groupe de colonnes d'un autre classeur.
Le mode copier/coller est bloqué de part la protection de l'ensemble des Feuils qui s'activent systématiquement a chaque changement de sélection.
J'ai essayé de solutionner mon problème avec le code :
Bonsoir,
Il ne faut pas utiliser Wait car il bloque l'exécution mais Application.OnTime qui déclenche une macro dans Xs.
En PJ un exemple avec :
VB:
Sub Attente()
ActiveSheet.Unprotect
Application.OnTime Now + TimeValue("00:00:05"), "MacroArret"
End Sub
Sub MacroArret()
MsgBox "5 secondes se sont écoulées." & Chr(10) & "La feuille est de nouveau vérouillée."
ActiveSheet.Protect
End Sub
Un appui sur GO lance Attente qui déprotège la feuille et lance un compteur de 5s.
Au bout de 5s MacroArret reprotège la feuille.
C'est la structure de votre code qui ne colle pas. A force de protéger tout on finit par être coincé.
Dès qu'on sélectionne une cellule de Feuil1 elle se reprotège, donc c'est sans issue.
Oui c'est exactement là que se situe ma problématique.
Ayant rencontré dans le passé des problèmes de suppression involontaire de données j'ai pris la décision de tout protéger avec cette méthode => Protection intégrée dans l'évènement :
VB:
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
Et là je ne vois pas de solution malheureusement ...
Une solution efficace serait de gérer une variable public qui permettrait d'invalider les macros Workbook_SheetSelectionChange, de cette façon lorsque vous voulez intervenir par macros vous positionnez cette variable et être tranquille pour bosser. a la fin vous ré autorisez cette fonction.
Dans les macros événementielles vous testez d'abord le Flag :
VB:
Private Sub Workbook_Open()
Flag = True ' Autorisation accordée
End Sub
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If Flag = False Then Exit Sub
Application.DisplayAlerts = False
ActiveSheet.Unprotect Password:="sandman"
Application.CutCopyMode = True
ActiveSheet.Protect Password:="sandman", AllowFormattingCells:=True
End Sub
Private Sub Workbook_SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
If Flag = False Then Exit Sub
MsgBox "Cellule Déprotégée"
ActiveSheet.Unprotect Password:="sandman"
End Sub
Private Sub Workbook_Activate()
If Flag = False Then Exit Sub
'Autorise le collage suite à une copie venant d'un autre classeur
Application.CutCopyMode = True
End Sub
Et dans votre macro vous positionnez ce flag à False ce qui interdit aux autres de bosser, vous faites ce que vous voulez, puis à la fin vous ré autorisez :
Code:
Sub MacroEssai()
'-------------------------------------
' Interdiction à toute macro d'agir
Flag = False
' Déprotection feuilles
Sheets("Feuil1").Unprotect Password:="sandman"
Sheets("Feuil2").Unprotect Password:="sandman"
'-------------------------------------
' Je peux bosser tranquille
Columns("H:H").Copy
Sheets("Feuil2").Activate
Columns("G:G").Select
ActiveSheet.Paste
Sheets("Feuil1").Activate
Range("A1").Select
MsgBox "La colonne H de Feuile1 a été copiée en colonne G de feuil2"
'-------------------------------------
' Autorisation accordée aux macros d'intervenir
Flag = False
' Reprotection des feuilles
Sheets("Feuil1").Protect Password:="sandman"
Sheets("Feuil2").Protect Password:="sandman"
End Sub
Sans oublier de déclarer ce Flag en Public :
Code:
Public Falg As Boolean ' Flag=True autorisation accordée, = False interdiction d'agir
Voir PJ pour essai. Un appui sur le bouton copie la colonne H en G feuil2.
Merci beaucoup pour ce code et la réponse très détaillée !
ça fonctionne parfaitement.
Seul bémol dans mon cas, il n'y a pas de code à exécuter mais une action manuelle de l'utilisateur à savoir copier des données manuellement depuis un autre workbook. Vu les types d'actions réalisées je peux difficilement les inscrire dans un code VBA.
Du coup, ce que je recherche depuis cette fin d'après-midi c'est le moyen de bloquer temporairement l'exécution de la macro afin de laisser une fenêtre de tire suffisante à l'utilisateur pour copier/coller manuellement les cellules qu'il a besoin depuis l'autre workbook vers celui-ci.
Je pensais avoir trouver la solution avec la méthode :
VB:
Application.Wait (Now + TimeValue("00:00:05"))
Qui bloque l'execution du code pendant une durée déterminé, seul problème c'est que le fichier n'est pas utilisable durant cet intervalle de temps. Impossible de réaliser la moindre action car la macro reste "figée" dans son execution.
Code:
Public Falg As Boolean ' Flag=True autorisation accordée, = False interdiction d'agir
Sub Protection()
Application.EnableEvents = False
ActiveSheet.Unprotect Password:="sandman"
Application.EnableEvents = True
End Sub
Sub MacroEssai()
'-------------------------------------
' Interdiction à toute macro d'agir
Flag = False
Application.ScreenUpdating = False
' Déprotection feuilles
Sheets("Feuil1").Unprotect Password:="sandman"
Sheets("Feuil2").Unprotect Password:="sandman"
'-------------------------------------
' Je peux bosser tranquille
MsgBox "Vous disposez de 5sec pour copier vos données depuis le classeur XXX"
Application.Wait (Now + TimeValue("00:00:05"))
MsgBox "Votre classeur est de nouveau vérrouillé"
'-------------------------------------
' Autorisation accordée aux macros d'intervenir
Flag = False
' Reprotection des feuilles
Sheets("Feuil1").Protect Password:="sandman"
Sheets("Feuil2").Protect Password:="sandman"
Application.ScreenUpdating = True
End Sub
Ce qu'il me manque c'est le moyen de réaliser des actions (type copier/coller) durant le laps de temps ou est figée la macro.
La méthode ScreenUpdating = False ne suffit pas.
Bonsoir,
Il ne faut pas utiliser Wait car il bloque l'exécution mais Application.OnTime qui déclenche une macro dans Xs.
En PJ un exemple avec :
VB:
Sub Attente()
ActiveSheet.Unprotect
Application.OnTime Now + TimeValue("00:00:05"), "MacroArret"
End Sub
Sub MacroArret()
MsgBox "5 secondes se sont écoulées." & Chr(10) & "La feuille est de nouveau vérouillée."
ActiveSheet.Protect
End Sub
Un appui sur GO lance Attente qui déprotège la feuille et lance un compteur de 5s.
Au bout de 5s MacroArret reprotège la feuille.
Désolé pour cette réponse tardive. Un grand merci pour cette aide ! Effectivement, c'est bien Application.On.Time qu'il me faut.
Cela fonctionne parfaitement et répond complètement à mon besoin.
Je partage le code en dessous ainsi que mon fichier.
Ce dernier paraîtra peut-être trop sécurisé pour certains, mais pour du travail sur fichier partagé avec données sensibles, cela réduit grandement le risque de suppression de données par erreur.
Seul point qui me dérange actuellement :
Pour déclencher la déprotection, plutôt que d'avoir un bouton intégré dans une des Feuils du workbook, j'ai plutôt opté pour un raccourci dans le ruban.
En l'occurrence, j'ai choisi un picto de clef sur laquelle l'utilisateur n'aura qu'a cliquer pour déclencher la déprotection.
Seul souci, lorsque je partage mon fichier avec d'autres utilisateurs, ces derniers n'ont pas ce raccourci qui apparaît par défaut dans leurs ruban.
Est-il possible à votre connaissance de forcer cela ?
Merci d'avance et bonne fin de journée
VB:
Public Flag As Boolean
Sub Protec()
Flag = True
MsgBox "classeur protégé"
ActiveSheet.Protect Password:="sandman", AllowFormattingCells:=True
End Sub
Sub ArrêtProtec()
Flag = False
Application.ScreenUpdating = False
Application.EnableEvents = False
ActiveSheet.Unprotect Password:="sandman"
ActiveWorkbook.Unprotect Password:="sandman"
Application.OnTime Now + TimeValue("00:00:10"), "Protec"
MsgBox "classeur déprotégé, vous disposez de 10 sec"
Flag = False
Application.ScreenUpdating = False
Application.EnableEvents = True
End Sub
Bonsoir,
... votre PJ est protégé avec un autre mdp que celui que je connais. Ca, c'est sur il est bien protégé.
Concernant le ruban j'ai juste jouer un peu avec, mais ça m'a semblé trop complexe, je préfère mettre un icone sur les feuilles, c'est plus transportable.
Ooops oubli de ma part. Effectivement là je suis dans l'excès
Je ne sais pas si vous voyez mon icône du coup en ouvrant le fichier ?
Si tel n'est pas le cas je me contenterai d'un bouton par défaut dans les différentes feuils cela suffira.
En tout cas merci pour tout !
Non, pas de clef à l'horizon.
Je ne pense pas que ce soit si simple de toucher au ruban d'autrui.
Connaissant MS, je pourrais très bien refuser qu'on touche à mon ruban puisque je l'ai personnalisé.
Il doit donc falloir une procédure bien particulière pour y parvenir, au minimum l'autorisation de l'utilisateur.