Comment puis-je obtenir de l'ancienne valeur d'un changement de cellule dans Excel VBA?
Je suis la détection des changements dans les valeurs de certaines cellules dans une feuille de calcul Excel comme ça...
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Range
Dim old_value As String
Dim new_value As String
For Each cell In Target
If Not (Intersect(cell, Range("cell_of_interest")) Is Nothing) Then
new_value = cell.Value
old_value = ' what here?
Call DoFoo (old_value, new_value)
End If
Next cell
End Sub
En supposant que ce n'est pas trop mal une façon de coder cela, comment puis-je obtenir la valeur de la cellule avant de le changer?
Vous devez vous connecter pour publier un commentaire.
essayer cette
déclarer une variable dire
et dans le
SelectionChange
Événementet dans votre
Worksheet_Change
événementVous pouvez utiliser un événement sur la cellule à modifier pour déclencher une macro qui effectue les opérations suivantes:
J'ai une autre solution pour vous. Vous pouvez créer un caché de la feuille de calcul afin de maintenir les anciennes valeurs pour votre intérêt.
Le supprimer lorsque le classeur est fermé...
Et modifier votre Worksheet_Change événement comme si...
Voici un moyen que j'ai utilisé dans le passé. Veuillez noter que vous devez ajouter une référence à Microsoft Scripting Runtime de sorte que vous pouvez utiliser le Dictionnaire d'objet - si vous ne voulez pas d'ajouter que la référence que vous pouvez faire cela avec des Collections mais ils sont plus lents et il n'y a pas de manière élégante à vérifier .Existe (vous avez pour intercepter l'erreur).
Comme toute méthode similaire, cela a ses problèmes - tout d'abord, il ne connaîtra pas les "vieux" de la valeur jusqu'à ce que la valeur a été effectivement changé. Pour y remédier, vous devez intercepter l'événement Open sur le classeur et de passer par Feuille.UsedRange remplissage OldVals. Aussi, il va perdre toutes ses données si vous réinitialisez le projet VBA par arrêt du débogueur ou quelque chose du genre.
CreateObject("Scripting.Dictionary")
sans l'ajout de la bibliothèque de référence. 🙂J'ai eu à le faire aussi. J'ai trouvé la solution de "Chris R" vraiment bon, mais pensé qu'il pourrait être plus compatible en n'ajoutant pas toutes les références. Chris, vous avez parlé de l'utilisation de Collection. Voici donc une autre solution à l'aide de la Collection. Et il n'est pas lent, dans mon cas. Aussi, avec cette solution, en ajoutant de l'événement "_SelectionChange", c'est toujours travailler (pas besoin de "workbook_open").
une idée ...
ThisWorkbook
moduleessayer, ça ne marchera pas pour la première sélection, ensuite, il sera sympa 🙂
J'ai eu un besoin de capturer et de comparer les valeurs anciennes et les nouvelles valeurs saisies dans un complexe de planification de feuille de calcul. J'avais besoin d'une solution générale qui a fonctionné, même lorsque l'utilisateur a changé beaucoup de lignes en même temps. La solution mise en place d'une CLASSE et d'une COLLECTION de classe.
La classe: oldValue
Il y a trois feuilles dans laquelle j'ai suivi les cellules. Chaque feuille a sa propre collection en tant que variable globale dans le module nommé ProjectPlan comme suit:
La InitDictionaries SOUS est appelé hors de la feuille de calcul.ouvrir pour établir les collections.
Il y a trois modules utilisés pour gérer chaque collection de oldValue objets qu'ils sont Ajouter, Existe, et la Valeur.
Le gros du travail est fait dans le Worksheet_SelectionChange de rappel. L'un des quatre est indiqué ci-dessous. La seule différence est la collection utilisée dans les opérations d'AJOUT et EXISTENT appels.
La VALEUR d'appel est appelée hors de code exécuté à partir de la Worksheet_Change de Rappel par exemple. J'ai besoin d'affecter la bonne collection est basée sur le nom de la feuille:
et puis je suis libre pour calculer comparer le courant de la valeur à la valeur d'origine.
Marque
Nous allons d'abord voir comment détecter et enregistrer la valeur d'une seule cellule d'intérêt. Supposons que
Worksheets(1).Range("B1")
est votre cellule d'intérêt. Dans un module, utilisez ceci:Puis dans le module de feuille de calcul(1):
Cela permettra de capturer le changement de la
Worksheets(1).Range("B1")
, si le changement est dû à l'utilisateur activement à la sélection de la cellule dans la Feuille de calcul et la modification de la valeur, ou en raison d'autres codes VBA qui permet de changer la valeur deWorksheets(1).Range("B1")
.Depuis, nous avons déclaré la variable
StorageArray
public, vous pouvez faire référence à sa dernière valeur dans d'autres modules dans le même projet VBA.D'élargir notre champ d'application à la détection et l'enregistrement de la valeur de plusieurs cellules d'intérêt, vous devez:
StorageArray
comme un tableau à deux dimensions, avec le nombre de lignes égal au nombre de cellules que vous êtes suivi.Sub SaveToStorageArray
procédure généraleSub SaveToStorageArray(TargetSingleCell as Range)
et changer lacodes pertinents.
Private Sub Worksheet_Change
procédure pour prendre en charge le suivi de ceux de plusieurs cellules.Annexe:
Pour plus d'informations sur la durée de vie des variables, reportez-vous à: https://msdn.microsoft.com/en-us/library/office/gg278427.aspx
En réponse à Matt Roy réponse, j'ai trouvé cette option, une grande réponse, bien que je ne poste pas en tant que tel avec ma notation actuelle. 🙁
Cependant, tout en profitant de l'occasion pour poster mes pensées sur sa réponse, j'ai pensé que je voudrais profiter de l'occasion pour inclure une petite modification. Il suffit de comparer le code pour voir.
Donc merci à Matt Roy pour avoir ce code à notre attention, et Chris.R pour l'affichage de code d'origine.
J'ai le même problème que vous et heureusement, j'ai lu la solution à partir de ce lien:
http://access-excel.tips/value-before-worksheet-change/
Remarque: vous devez placer
oldValue
variable comme variable globale, de sorte que tous les sous-classes peuvent l'utiliser.J'avais besoin de cette fonctionnalité et je n'aime pas toutes les solutions ci-dessus après avoir essayé la plupart comme ils sont soit
Eh bien, je pense très fort à elle et j'ai obtenu une solution complète DÉFAIRE,REFAIRE l'histoire.
Pour capturer l'ancienne valeur, il est effectivement très facile et très rapide.
Ma solution est de capturer toutes les valeurs une fois à l'utilisateur d'ouvrir la feuille est ouvert dans une variable, et il est mis à jour après chaque modification. cette variable sera utilisée pour vérifier l'ancienne valeur de la cellule. Dans les solutions ci-dessus tous les utilisé pour la boucle. En fait, il est plus facile méthode.
Pour capturer toutes les valeurs que j'ai utilisé cette commande simple
Ouais, c'est juste que, en Fait excel va retourner un tableau si la plage est l'un de plusieurs cellules, donc nous n'avons pas besoin d'utiliser POUR CHAQUE commande et il est très rapide
Le compartiment suivant est le code complet qui doit être appelée dans Workbook_SheetActivate. Un autre sous doit être créée pour enregistrer les modifications. Comme, j'ai un sub appelé "catchChanges" qui s'exécute sur Workbook_SheetChange. Il s'agira de saisir les modifications, puis de les enregistrer sur un autre un changement de l'histoire de la feuille. puis exécute UpdateCache de mettre à jour le cache avec les nouvelles valeurs
maintenant pour obtenir l'ancienne valeur, il est très facile que dans le tableau ont la même adresse de cellules
exemples si nous voulons cellule D12, nous pouvons utiliser la suite
ce sont des extrait de en expliquant la méthode, j'espère que tout le monde comme il
À l'aide de
Static
permettra de résoudre votre problème (avec quelques autres trucs pour initialiserold_value
correctement:Dans le classeur de code, la force de l'appel de
Worksheet_change
pour remplirold_value
:Noter, cependant, que TOUTE solution fondée en VBA variables (y compris les dictionnaire et un autre plus sophistiqué méthodes) échouera si vous vous arrêtez (Reset) de l'exécution de code (par exemple. lors de la création de nouvelles macros, le débogage de code, ...). Pour éviter de telles, envisager l'utilisation d'autres méthodes de stockage (caché de la feuille de calcul, par exemple).
J'ai lu ce vieux post, et j'aimerais donner une autre solution.
Le problème avec l'exécution de l'Application.Annuler est que Woksheet_Change s'exécute à nouveau. Nous avons le même problème lorsque nous restaurer.
Pour éviter cela, j'utilise un morceau de code pour éviter la deuxième étapes à travers Worksheet_Change.
Avant de commencer, nous devons créer un Booléen variable statique BlnAlreadyBeenHere, pour dire à Excel de ne pas exécuter Worksheet_Change nouveau
Ici, vous pouvez voir:
L'avantage de cette méthode est qu'il n'est pas nécessaire d'exécuter Worksheet_SelectionChange.
Si nous voulons que la routine de travail à partir d'un autre module, nous avons juste à prendre la déclaration de la variable blnAlreadyBeenHere sortir de la routine, et de le déclarer avec Dim.
Même opération avec vOldValue et vNewValue, dans l'en-tête d'un module
Juste une pensée, mais Avez-vous essayé d'utiliser l'application.annuler
Ceci permettra de définir les valeurs de retour. Vous pouvez ensuite il suffit de lire la valeur d'origine. Il ne devrait pas être trop difficile à stocker les nouvelles valeurs de la première, de sorte que vous revenir à nouveau si vous le souhaitez.