2
votes

Exécuter la macro lorsque le résultat de la cellule change par formule

Ce dont j'ai besoin: Une macro à déclencher, appelons la macro "MacroRuns", chaque fois que la cellule C3 renvoie une valeur différente de celle qu'elle a actuellement, basée sur sa FORMULE, PAS basée sur la saisie manuelle d'une valeur différente.

J'ai passé toute la journée à lire et à essayer toutes les «solutions» des deux premières pages de ma recherche Google sur ce sujet. Jusqu'à présent, rien ne semble fonctionner pour moi. Veuillez aider !!! Je l'apprécierais beaucoup!

Exemple:

J'ai maintenant essayé cela mais cela corrompt mon fichier après avoir fonctionné plusieurs fois.

Private Sub Worksheet_Calculate()
    If Range("E3") <> Range("C3").Value Then
        Range("E3") = Range("B3").Value
        MsgBox "Successful"
    End If
End Sub


9 commentaires

Vous utiliseriez l'événement Worksheet_Calculate


Merci Scott, mais chaque fois que j'utilise des solutions avec Worksheet_Calculate, mon code est exécuté à chaque fois que les cellules de la même feuille ou des cellules différentes sont accédées et que l'on appuie sur Entrée. J'ai vu dans d'autres articles que, parce que j'utilise une formule indirecte dans mon classeur, cela fait que Worksheet_Calculate fonctionne de cette manière.


oui, vous devrez enregistrer la valeur quelque part et vérifier la nouvelle valeur par rapport à l'ancienne, si elle est différente, exécutez le code et mettez à jour la cellule dans laquelle vous avez enregistré la valeur, en l'amorçant pour le test suivant.


J'ai lu plusieurs solutions comme celle-ci, donc je suis d'accord, mais pour une raison quelconque, je ne peux faire fonctionner aucune d'elles. Avez-vous un exemple de code que je pourrais essayer? Il me manque peut-être quelque chose lorsque je copie-collez leurs solutions et les modifie pour répondre à mes besoins.


Si je mets du code de test, il aura probablement le même problème que ceux que vous avez copiés, collés et modifiés. Sur ce site, la personne qui pose la question montre son code et explique les erreurs qui sont reçues, et non l'inverse.


Ça a du sens. J'essaye actuellement ceci: Private Sub Worksheet_Change(ByVal target As Range) If Not Intersect(target.Address, Range("C3:C4")) Is Nothing Then MsgBox "I ran" End If End Sub - I get a " Erreur de compilation - Incompatibilité de type "sur la ligne target.address


La modification de feuille de calcul ne prendra pas en compte la modification en raison de la formule, veuillez montrer comment vous avez essayé d'enregistrer la valeur et de la comparer dans l'événement Worksheet_Calculate.


Et ne postez pas de clarifications sur la question dans les commentaires, modifiez plutôt votre question d'origine avec le code / les clarifications


je suppose que la raison pour laquelle le code actuel n'est pas en cours d'exécution est que vous avez une target comme variable globale ou un sous-nom ou un nom de fonction. Le fait qu'il soit en minuscules indique que vous l'avez utilisé de cette manière quelque part et qu'il prend le pouvoir sur l'état naturel.


3 Réponses :


2
votes

Module1, Sheet1 (Calculer), Ce classeur (Ouvrir)

Points forts

  • Lorsque le classeur s'ouvre, la valeur de C3 est lue dans la variable publique TargetValue via TargetStart .
  • Lorsque la valeur dans C3 est en cours de calcul, TargetCalc est activé via l'événement de calcul.Si la valeur actuelle dans C3 est différente de TargetValue , MacroRuns est déclenché et TargetValue est mis à jour avec la valeur dans C3 .

Le code

Module 1

Option Explicit

Private Sub Worksheet_Calculate()
    TargetCalc Me
End Sub

Ce classeur

Option Explicit

Private Sub Workbook_Open()
    TargetStart
End Sub

Feuille1

Option Explicit

Public TargetValue As Variant
Private Const cTarget As String = "C3"

Sub TargetCalc(ws as Worksheet)
    If ws.Range(cTarget) <> TargetValue Then
        MacroRuns
        TargetValue = ws.Range(cTarget).Value
    End If
End Sub

Sub TargetStart()
    TargetValue = Sheet1.Range(cTarget).Value
End Sub

Sub MacroRuns()
    MsgBox "MacroRuns"
End Sub

9 commentaires

Merci beaucoup pour votre temps! Je vais essayer ça maintenant.


Le "C3" dont j'ai besoin qu'il se souvienne se trouve sur une feuille cachée appelée "CALC_CompStatus". Comment puis-je ajouter cela au code que vous avez fourni ci-dessus?


@soundship: Je ne sais pas ce que vous demandez. cTarget est une chaîne qui contient "C3", ce n'est pas une plage. TargetCalc est utilisé dans n'importe quelle feuille où vous le souhaitez (je ne sais pas sur hidden) et TargetStart est utilisé dans Sheet1. Vous devez donc ajuster Sheet1 et mettre le code de Sheet1 sur votre code de feuille réel.


@ VBasic2008 Range(cTarget) va faire référence à la feuille active et non à la feuille qui l'appelle. Vous voudrez peut-être passer la feuille de calcul dans le sous: Sub TargetCalc(ws as Worksheet) vous pouvez alors ajouter l'objet range avec le parent correct: ws.Range(cTarget) et vous l'appelleriez TargetCalc me


Merci à vous deux. @ScottCraner, Cela fonctionne parfaitement à partir d'une autre feuille, même lorsque la feuille avec C3 est masquée. Merci!


Cela fonctionnerait de manière cohérente jusqu'à ce que je remplace la MsgBox par Call MyMacro. Pour une raison quelconque, il exécuterait continuellement ma macro et gèlerait le fichier, ce qui en faisait un fichier corrompu qui devait être réparé chaque fois que je l'ouvrais. Curieusement, lorsque j'ai essayé le code ci-dessous par @Ferdinando, j'ai pu installer et exécuter ma macro sans aucun problème. Je suis sûr que le problème vient de ma part et du manque de connaissances sur ce qui en était la cause, mais j'apprécie vraiment votre aide Scott.


Après des tests supplémentaires, le code utilisé par Ferdinando fonctionnait la plupart du temps, mais parfois non. J'ai essayé d'implémenter votre code une fois de plus et j'ai testé tout au long de la journée et cela fonctionne très bien, mis à part le problème de la boucle.


@ScottCraner J'ai fait besoin de poster une autre question pour celle-ci, mais maintenant je dois dire à votre code d'arrêter d'exécuter mon code "MacroRuns" après que MacroRuns ait exécuté 1 fois. J'utilise actuellement une MsgBox pour demander si je souhaite l'exécuter, me donnant un moyen de l'empêcher de se mettre en boucle, mais toute suggestion serait appréciée.


bien merci pour votre aide. Je posterai une autre question à ce sujet.



0
votes

Si j'ai compris votre question, vous pouvez essayer ce code:

1) Cliquez avec le bouton droit sur l'onglet Feuille, puis cliquez sur Afficher le code

  1. copiez ce code:

    Private Sub Worksheet_Change (ByVal Target As Range)

    Dim Value1 As Variant Static Value2 As Variant

    Value1 = Range ("C3"). Value

    Si Value1 <> Value2 Then MsgBox "La cellule a changé." Fin si

    Value2 = Range ("C3"). Value

    End Sub

j'ai essayé celui-ci:

dans la cellule C3, j'ai écrit = SUM (A1: B1) lorsque j'essaie de changer la valeur dans ces cellules, C3 change également et j'obtiens la msgBox

J'espère que cela t'aides

MODIFIEZ le code pour répondre @ MD Ismail Hosen

si j'ai compris votre problème, vous pouvez essayer cet exemple de code:

 Range("A1:C1").Select
        Selection.Copy
        Range("F1").Select
        Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False

Si vous avez une formule dans votre plage ("A1: C1"), vous devez utiliser ce code pour copier la nouvelle valeur de plage A1: C1 dans F1: H1 sinon vous obtenez l'erreur (boucle la macro). 'POUR utiliser ce code si vous avez une formule dans les cellules.

Private Sub Worksheet_Change(ByVal Target As Range)

'in this code i have used two range on the same row, but you can change as 
'you want. 
'In my case, the range that i check is Range("A1:C1") and the RANGE that i 'save old value is 
'RANGE("F1:H1") F1 is the sixth column.

Dim counter As Byte
Dim sizeRange As Byte

sizeRange = 3 ' my size range

For counter = 1 To sizeRange
    'on the left i check Range("A1:C1").On the right i check The Range("F1:H1")
    If Cells(1, counter) <> Cells(1, counter + 5) Then 'counter start from 1 
        MsgBox "Range Changed"
        Range("A1:C1").Copy Destination:=Range("F1:H1") ' use other code to copy the range
        Exit For
    End If
Next counter
End Sub

J'espère que cela t'aides.


11 commentaires

Merci beaucoup @Ferdinando! Cela l'a fait pour moi. Jusqu'à présent, je n'ai eu aucun problème et cela fonctionne comme je l'espérais.


Cela ne répond pas à la question. Il parle du moment où le résultat d'une formule change plutôt que d'un changement qui déclencherait cette routine. Comme un changement manuel de valeur de cellule par l'utilisateur. Il ne parle pas de ça.


Cher @Gary Carlyle Cook, je pense que ma réponse est bonne parce que dans le post de Soundhip, il dit que ça marche ... non?


@Ferdinando et s'il y a une plage (B10: B64) .. Est-ce que ça va marcher ..?


Oui, @MD Ismail Hosen, essayez-le. Dans la cellule C3, vous mettez cette nouvelle gamme (B10: B64).


En cas de variante, je dois parcourir chaque élément, non?


Désolé @MD Ismail Hosen, mais avez-vous essayé le code? Les réponses sont dans le code ... si vous avez un problème, postez votre problème ici ... et j'espère vous aider ...


Je l'ai essayé mais cela ne fonctionne pas dans mon cas, j'ai besoin d'appeler un autre sous-marin à partir de cet événement ... Donc, au lieu de la variable statique, je stocke les données dans une plage et compare à la fois la plage ... Merci


@MD Ismail Hosen, j'ai édité mon code dans la réponse. J'espère que cela vous aidera


@Ferdinando J'utilise la même procédure pour comparer les valeurs ... Merci..Mes données étaient dans une colonne ... Cela a fonctionné ... Je pensais qu'il y avait peut-être un moyen de comparer sur une ligne au lieu d'une boucle ...


Nice @MDIsmailHosen, si pour vous il n'y a pas de problème vous pouvez voter ma réponse. Toujours si tu veux.



0
votes

Droite. J'ai une pépite à ajouter ici, quelque chose qui m'a complètement frustré en essayant le code de Ferdinando (qui en soi est très soigné, merci Ferdinando !!)

Le point principal est - si vous comptez utiliser autre chose qu'une simple boîte de message (MsgBox "La cellule a changé."), Vous devez ajouter les lignes suivantes au-dessus ET en dessous de cette ligne (sinon, Excel plantera simplement constamment en raison d'essayer sans fin Faire la même chose). Ne me demandez pas pourquoi, mais j'ai finalement résolu mon problème avec ça. Voici donc les lignes:

If Value1 <> Value2 Then
(ADD THIS:)     Application.EnableEvents = False
                MsgBox "Cell has changed."
(I call a macro running a query from MySQL instead of MsgBox)
(AND ADD THIS:) Application.EnableEvents = True

J'espère que cela aide n'importe qui dans la situation dans laquelle j'étais !!


0 commentaires