Conserver l’historique des modifications
Partie identification :
- L'erreur #9 , apparaît toujours lors de l'authentification dans la feuille "Accueil".
- il faut respecter la casse (majuscules/minuscules)
- il faut supprimer Workbook_Open
- j'ai systématiquement une erreur 1004 que je n'avais pas sur le fichier que j'avais proposé
- a contrario, lors de la fermeture, il faut forcer l'enregistrement sans avertissement
ThisWorkbook.Close Savechanges:=True
Cette partie aurait pu faire l'objet d'un autre sujet.
J'aurais traité plus simplement dans la mesure où tout le monde a accès à la BdD (l'intérêt du contrôle d'accès est que les intervenants aient accès chacun à un ou des onglets spécifiques) :
- ne rien faire / pas feuille de login,
- enregistrer l'accès et les modifications selon le username,
- protéger la macro,
- masquer tous les onglets sauf BdD : seul l'administrateur a accès au déverrouillage des onglets masqués par un code
Partie tracer des modifications :
/!\ Le fait que tu aies remplacé le n° de colonne par l'en-tête te fait perdre le lien hypertexte.
- La date ajoutée dans la feuille "Log" est toujours sous forme américaine, mais dans le code elle est sous forme française.
- Je n'ai pas ce soucis, cela dépend peut-être de la configuration excel ? j'ai mis la colonne en jj/mm/aaaa hh:mm et cela passe.
- Dans le code elle n'a aucune forme, c'est Now !
- Pour supprimer une ligne, je procède comme suit :
- Clic gauche, puis, dans le menu contextuel, choisir "Supprimez une ligne du tableau" (la suppression avec la touche Suppr provoque une erreur !)
"Manque identifiant !"- Il y a d'autres erreurs que je n'ai pas enregistrées.
- Clic gauche ou droit ?
- Du coup, cela ajoute autant de lignes que de colonnes en plus de la suppression d'une ligne. Mais au final on trace bien un événement. => on peut néanmoins améliorer ce point
- "la suppression avec la touche Suppr provoque une erreur !" : de quelle erreur s'agit-il ? si c'est le commentaire "impossible d'agir sur une ligne ou une colonne entière" ce n'est pas une erreur mais un message ! c'est normal
- Je n'ai pas de commentaire "Manque identifiant !" sauf si je veux ajouter une ligne avec le clic droit et c'est normal aussi
- Si les autres erreurs ne sont pas identifiées, on ne peut pas les traiter.
A ce stade, je n'ai donc pas compris qu'il y avait des erreurs à corriger, mais il y a un point à améliorer lors de la suppression d'un ligne par clic droit et menu contextuel.
- Du coup, cela ajoute autant de lignes que de colonnes en plus de la suppression d'une ligne. Mais au final on trace bien un événement. => on peut néanmoins améliorer ce point
proposition
et dans la mesure où on restreint le champ à la base de données, on peut autoriser la suppression d'une ligne complète d la feuille
Option Explicit
Private Sub Worksheet_change(ByVal cible As Range)
Dim avant, apres, idavant As Object, idapres As Object, log As Worksheet, cle As Variant
Dim memoire As Range, plage As Range, cel As Range, ecart As String
Dim i%, j%, n%, flag As Boolean
On Error GoTo fin
If Not Intersect(cible, ActiveSheet.ListObjects(1).DataBodyRange) Is Nothing Then
Set memoire = Selection
Set log = Sheets("Log")
' contrôle des identifiants uniques
apres = ActiveSheet.ListObjects(1).ListColumns("ID").DataBodyRange
Set idapres = CreateObject("Scripting.Dictionary")
Set idavant = CreateObject("Scripting.Dictionary")
For i = 1 To UBound(apres)
If apres(i, 1) = "" Then
MsgBox "Manque identifiant !"
Application.EnableEvents = False
Application.Undo
Application.EnableEvents = True
Exit Sub
End If
If idapres.exists(apres(i, 1)) Then
MsgBox "Les identifiants doivent être uniques !"
Application.EnableEvents = False
Application.Undo
Application.EnableEvents = True
Exit Sub
End If
idapres(apres(i, 1)) = ""
Next
' traitement des modifications
Application.EnableEvents = False
With ActiveSheet.ListObjects(1)
Set plage = Intersect(cible, .DataBodyRange)
apres = .DataBodyRange
For i = 1 To UBound(apres)
idapres(apres(i, 1)) = ""
Next
Application.Undo
avant = .DataBodyRange
For i = 1 To UBound(apres)
idavant(avant(i, 1)) = ""
Next
Application.Undo
flag = True
' taille du tableau
If UBound(apres) > UBound(avant) Then
loguer "", "", "", "", "La BdD a augmenté de " & -UBound(avant) + UBound(apres) & " ligne(s)"
For i = UBound(avant) + 1 To UBound(apres)
For j = 1 To UBound(apres, 2)
If apres(i, j) <> "" Then
loguer .DataBodyRange(i, 1), j, "", apres(i, j), ""
End If
Next
Next
End If
If UBound(apres) < UBound(avant) Then
ecart = ""
For Each cle In idavant
If Not idapres.exists(cle) Then ecart = ecart & "/" & cle
Next
loguer "", "", "", "", "La BdD a diminué de " & UBound(avant) - UBound(apres) & " ligne(s)" & vbCrLf & ecart
flag = False
End If
If UBound(apres, 2) > UBound(avant, 2) Then
loguer "", "", "", "", "La BdD s'est élargie de " & -UBound(avant, 2) + UBound(apres, 2) & " colonne(s)"
For i = 1 To UBound(apres)
For j = UBound(avant, 2) + 1 To UBound(apres, 2)
If apres(i, j) <> "" Then
loguer .DataBodyRange(i, 1), j, "", apres(i, j), ""
End If
Next
Next
End If
If UBound(apres, 2) < UBound(avant, 2) Then
loguer "", "", "", "", "La BdD s'est rétrécie de " & UBound(avant, 2) - UBound(apres, 2) & " colonne(s)"
flag = False
End If
' cas standard
n = plage.Cells.Count
If n > 0 And flag Then
For Each cel In plage
i = cel.Row - .HeaderRowRange.Cells(1, 1).Row
j = cel.Column - .HeaderRowRange.Cells(1, 1).Column + 1
If i <= UBound(avant) And i <= UBound(apres) And j <= UBound(avant, 2) And j <= UBound(apres, 2) Then
If avant(i, j) <> apres(i, j) Then
loguer .DataBodyRange(i, 1), j, avant(i, j), apres(i, j), ""
End If
End If
Next
End If
End With
Application.EnableEvents = True
End If
If Not memoire Is Nothing Then memoire.Select
fin:
Application.EnableEvents = True
If Err Then MsgBox "Erreur #" & Err.Number & " !"
End Sub
Sub loguer(id, colonne, avant, apres, commentaire)
Dim ligne%
'Date & heure ID Ligne Colonne Avant Après Commentaire Lien vers … Auteur
With Sheets("Log").ListObjects(1)
.ListRows.Add
ligne = .ListRows.Count
With .DataBodyRange
.Cells(ligne, 1) = Now
.Cells(ligne, 2) = id
.Cells(ligne, 4) = colonne
.Cells(ligne, 5) = avant
.Cells(ligne, 6) = apres
.Cells(ligne, 7) = commentaire
.Cells(ligne, 9) = utilisateur
.Cells(ligne, 10) = Environ("username")
End With
End With
End Sub
pour moi c'est plus un exercice de style, car il y aura de toute façon des situations difficiles à retracer quand on modifie les ID
et puis le code devient trop long, trop complexe
Bonjour,
il faut respecter la casse (majuscules/minuscules)
Même lorsque la casse est respectée, l'erreur #9 est toujours déclenchée.
il faut supprimer Workbook_Open
Je pensais que cela permettrait le lancement de la macro dés l'ouverture du classeur et la feuille de connexion sans intervention de l'utilisateur?
j'ai mis la colonne en jj/mm/aaaa hh:mm et cela passe
Je l'ai trouvé sous le format : m/j/aaaa h:mm
Clic gauche ou droit ?
J'étais désorienté !
Si les autres erreurs ne sont pas identifiées, on ne peut pas les traiter.
J'ai eu l'erreur 1024.
et puis le code devient trop long, trop complexe
Tu as raison, mais j'essaye d'être aussi clair que possible !
Remarques :
- Si la dernière ligne est supprimée ou elle se trouve dans une plage qui sera supprimée, le message "Manque identifiant !" sera toujours affiché.
Pour éviter ce message, on devra toujours avoir une cellule non vide après la cellule qu'on veut supprimer. - Qu'en est-il de l'ajout des commentaires "Création", "Modification" ou "Suppression" ?
Voici le fichier sur lequel je travaille,
- je n'ai plus d'erreur 1004 (et non 1024)
- je n'ai plus d'erreur #9.
- j'ai les dates au format qui me convient.
- je n'ai pas "manque identifiant" sauf si j'ajoute une ligne sans identifiant.
- j'ai les liens hypertexte actifs
Il est clair que workbook_open tel que tu l'as écrit ou conservé plante ! et comme j'ai dit, je ne mettrais même pas cette phase d'identification mais libre à toi.
On traite 2 sujets en même temps, je préfère me focaliser sur ce qui fait le titre de ce fil de discussion au départ, sinon on tournera en boucle.
Je n'avais pas encore retenu les commentaires que tu as ajouté car je n'ai pas eu le temps d'y réfléchir, tu disais du reste "J'ai du mal à ajouter un commentaire approprié lors de la création, de la modification ou de la suppression."
J'ai testé le dernier exemple et j'ai reçu le message "Manque identifiant!" dans le cas :
- d'utilisation de la touche "Suppr" pour supprimer une ligne entière (4 colonnes dans l'exemple).
Si une ligne entière de la feuille est sélectionnée, la suppression avec la touche "Suppr" fonctionne.
Pas de problème avec l'utilisation du menu contextuel, pour supprimer "Lignes de tableau".
Parfois, j'ajoute ou modifie des lignes, mais elles ne sont pas transférées dans la feuille "Log".
Je crois que
Application.EnableEvents
a été désactivée pendant l'exécution et est restée à false.
Pour la suppression, j'aimerais bien que les valeurs supprimées soient enregistrées dans la page "Log".
J'ai testé le dernier exemple et j'ai reçu le message "Manque identifiant!" dans le cas :
- d'utilisation de la touche "Suppr" pour supprimer une ligne entière (4 colonnes dans l'exemple).
Si une ligne entière de la feuille est sélectionnée, la suppression avec la touche "Suppr" fonctionne.
Oui, dans la mesure où on ne s'intéresse qu'à l'intersection avec le tableau, la touche supp fonctionne en dehors du tableau.
Par contre si on fait Supp sur l'identifiant seul, ou sur la ligne, la macro refuse car elle n' a plus l'identifiant pour ensuite permettre le lien hypertexte (c'est cette fonctionnalité qui est très structurante).
Je crois que
Application.EnableEvents
a été désactivée pendant l'exécution et est restée à false.
C'est exact, cela ne se reproduira pas quand on réactivera
'On Error GoTo fin
en début de macro.
J'ai mis l' apostrophe pour justement pouvoir piéger les erreurs et surtout la ligne concernée. S'il n'y a plus d'erreurs, on peut réactiver en supprimant l'apostrophe.
ok. Je regarde pour mémoriser les valeurs supprimées.
J'ai trouvé une tuile : aucun enregistrement si la dernière ligne du tableau est supprimée !
Casse-tête chinois !
Bonjour,
Alors que la formule de création de lien hypertexte est basée sur l'id, j'ai pensé à cette solution qui crée le lien dans VBA sans utiliser l'id:
Set Rg = Sheets("BDD").ListObjects(1).Range(.Cells(ligne, 3), .Cells(ligne, 4))
.Hyperlinks.Add anchor:=.Cells(ligne, 11), Address:="", _
SubAddress:="'" & Rg.Parent.Name & "'!" & Rg.Address
Je l'ai testé dans la colonne 11, car dans la colonne 8, il y a la formule qui écrase le lien créé par VBA.
La question est : est-ce que si tu tries ta base de données, le lien pointe-t-il toujours à la bonne place ?
-
Je souhaite mettre les cellules modifiées en lien dans le code vba, car le tri dans la feuille l'affecte, comme tu l'as mentionné.Après plusieurs essais, le fait de mettre une formule ne fonctionne pas avec le tri, la formule reste accrochée à la même adresse. Donc la seule solution serait de mettre un identifiant unique de ligne dans la ase de donnée.
Bonjour,
Le tri n'est pas necessaire sur la feuille Log, puisqu'elle est déja triée sur la date.
Mais, il l'est sur la feuille BDD.
Ma question est bien : si tu tries ta bdd est-ce que les liens que tu as créés pointent toujours sur les bonnes cellules ?
Tu as raison !
N'y a-t-il pas de solution à cela ? Sinon, on devras garder la base de données telle quelle, sans tri !
La solution c'est celle que je t'ai proposée avec la formule qui suivra l'emplacement de l'ID quand tu auras trié.
Donc, en ayant l'id, on pourra trier la base de données, par exemple, sur le second champ, sans aucun problème ?
oui
c'était ta demande
fais l'essai !
Parfait, les liens changent en fonction de la ligne et de la colonne du tableau "TLog", même si je trouve la formule assez compliquée.
Notamment, ces lignes et colonnes de la feuille "Log", lorsque j'applique le tri à la BDD, leurs valeurs changent !
Génial.
Dans ce cas, peut-on ajouter un tri automatique lors de la saisie d'une nouvelle ligne dans BDD ?
Définis le tri que tu veux dans la base de données, "à la main", exemple ici sur la 3ème colonne, ajoute c
où tu veux ...
Il suffit ensuite d'ajouter au code
ActiveSheet.ListObjects("Tbdd").Sort.Apply
Définis le tri que tu veux dans la base de données, "à la main"
Je ne vois pas le lien avec le tri par code VBA ?
exemple ici sur la 3ème colonne, ajoute c
Pourquoi un c ?