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 ?

Rechercher des sujets similaires à "conserver historique modifications"