Je conçois un rapport de temps pour mes collègues. Il existe des cellules qui contiennent une formule (masquée) mais qui ne sont pas protégées car j'ai besoin que l'utilisateur puisse toujours remplacer manuellement la formule.
Maintenant, si un utilisateur entre son propre contenu et le supprime à nouveau, la cellule est vide, ce que je ne veux pas, car cela ne fera que prêter à confusion.
Je veux écrire une macro VBA qui reconnaît si le contenu de la cellule dans une plage précédemment déclarée est supprimé / vide et s'ils sont supprimés / vides, alors une formule d'une autre cellule (protégée par mot de passe et masquée) doit être copiée dans la cellule vide.
Private Sub Worksheet_Change(ByVal Target As Range) Dim myRange As Range Set myRange = Intersect(Range("F9:I108"), Target) If Not myRange Is Nothing Then 'I'm guessing something with WorksheetFunction and possibly CountA, 'but I don't know how to make it work End If End Sub
Les formules à saisir si le contenu d'une cellule (ou de plusieurs cellules) est supprimé est toujours à la ligne 117 (même feuille de calcul). Par exemple, si l'utilisateur supprime G50, la formule de G117 doit être copiée dans G50 de la même manière que vous copiez habituellement les formules dans Excel (donc s'il y a une référence non - $ - dans G117 qui pointe vers A117, elle doit alors pointer vers A50 après la copie de la formule dans G50).
Si possible, je veux travailler sans boucles - elles prennent toujours tellement de temps à s'exécuter.
Merci d'avance!
3 Réponses :
Voici un exemple très simple qui n'implique que des cellules 3 , A1 , A2 et A3 . Vous devez le modifier pour accueillir vos cellules de formule.
Nous créons d'abord une feuille de calcul secrète (appelée secret
) . Nous plaçons les formules de A1 à A3 de la feuille de calcul principale dans la feuille secrète, mais nous les stockons sous forme de chaînes plutôt que de formules :
Ensuite, nous mettons la macro d'événement de feuille de calcul suivante dans la feuille principale:
Private Sub Worksheet_Change(ByVal Target As Range) Dim rng As Range Set rng = Range("A1:A3") If Intersect(Target, rng) Is Nothing Then Exit Sub If Target.Count <> 1 Then Exit Sub If Target.Value <> "" Then Exit Sub Application.EnableEvents = False Target.Formula = Sheets("secret").Range(Target.Address).Value Application.EnableEvents = True End Sub
Le sous-contrôleur surveille les modifications apportées aux trois cellules et si l'une d'entre elles est effacée, cette formule sera restaurée à partir de la feuille de calcul secrète.
Comme il s'agit du code de la feuille de calcul, très facile à installer et à utiliser automatiquement:
Si vous avez des doutes, essayez-le d'abord sur une feuille de calcul d'essai.
Si vous enregistrez le classeur, la macro sera enregistrée avec lui. Si vous utilisez une version d'Excel postérieure à 2003, vous devez enregistrer le fichier au format .xlsm plutôt que .xlsx
Pour supprimer la macro:
Pour en savoir plus sur les macros en général, consultez:
http://www.mvps.org/dmcritchie/excel/getstarted.htm
et
http://msdn.microsoft.com/en-us/library/ee814735 (v = office .14) .aspx
Pour en savoir plus sur les macros d'événements (code de la feuille de calcul), voir:
http://www.mvps.org/dmcritchie/excel/event.htm
Les macros doivent être activé pour que cela fonctionne!
Merci et @PeterT! J'ai utilisé une combinaison de vos deux idées :)
Voici une autre réponse possible. Afin de copier la formule et de conserver «l'adressage relatif» de la formule, vous devez copier en utilisant la notation R1C1. Donc, un sous-marin rapide pour cela pourrait ressembler à
Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) Dim checkRange As Range Set checkRange = ActiveSheet.Range("A1:A9") If Not Intersect(checkRange, Target) Is Nothing Then Dim changedCell As Range For Each changedCell In Target If IsEmpty(changedCell) Then RestoreFormula changedCell End If Next changedCell End If End Sub
La ligne importante ici est la partie emptyCell.FormulaR1C1 = formulaCell.FormulaR1C1
.
Ensuite , dans l'événement Worksheet_Change
, cela pourrait ressembler à ceci
Option Explicit Sub RestoreFormula(ByRef emptyCell As Range) Dim formulaWS As Worksheet Dim formulaCell As Range Set formulaWS = ThisWorkbook.Sheets("Sheet1") Set formulaCell = formulaWS.Range("A17") emptyCell.FormulaR1C1 = formulaCell.FormulaR1C1 End Sub
Merci et à l'étudiant de @ Gary! J'ai utilisé une combinaison de vos deux idées :)
Si quelqu'un d'autre a le même problème et veut peut-être utiliser ma solution, qui est une combinaison des suggestions de PeterT et Gary's Student (merci beaucoup à tous les deux):
J'ai d'abord créé une nouvelle feuille de travail dans laquelle je copié toutes les formules que je souhaite conserver. Je me suis assuré de les copier exactement dans la même cellule que dans la feuille d'origine.
J'ai ensuite ajouté ce code à la feuille de calcul d'origine:
Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) Dim Bereich1 As Range Set Bereich1 = Range("F9:I108") 'Do NOT enter multiple, non-contiguous ranges here! It crashes Excel! If Not Intersect(Bereich1, Target) Is Nothing Then Dim changedCell1 As Range For Each changedCell1 In Target If changedCell1 = "" Then changedCell1.Formula = Sheets("Tagebuch_secret").Range(changedCell1.Address).Formula End If Next changedCell1 End If Dim Bereich2 As Range Set Bereich2 = Range("E112") 'instead duplicate the code snippet If Not Intersect(Bereich2, Target) Is Nothing Then Dim changedCell2 As Range For Each changedCell2 In Target If changedCell2 = "" Then changedCell2.Formula = Sheets("Tagebuch_secret").Range(changedCell2.Address).Formula End If Next changedCell2 End If End Sub
fonctionne bien pour tous les scénarios dans lesquels le contenu d'une cellule est supprimé, à la fois si l'utilisateur supprime le contenu d'une ou de plusieurs cellules!
Ma prochaine étape consiste à rendre la feuille _secret très cachée, à protéger par mot de passe la structure du classeur puis protégez par mot de passe mon projet vba. Ensuite, seules les personnes qui connaissent le mot de passe (moi) peuvent détruire mon fichier :)
Pourriez-vous simplement avoir une colonne de remplacement utilisateur, puis utiliser par défaut cette valeur sur votre colonne calculée et protégée? Quelque chose du genre:
= IF (Sheet! UserColumn1 = "", Sheet! CalculatedColumn1, Sheet! UserC olumn1)