• Speed up the Worksheet_Change

    Author
    Topic
    #508414

    I’ve got macros from expert in this forum according to my request (purpose 1) which link to a sheet when I change a certain cell in column D and/or E, the related entry (check if same in column C) will auto change the value (either above or below rows).
    (purpose 2) for check duplicate entry in column C by exactly the same entry in (col C, col F & col G) and highlight it.
    The pros is what I want to achieve is working, however the cons is it runs really slow.
    I know it will be reapplied every time the cell is changed. I m ok for the checking made after all entry I made too. Would anyone help please?

    My Question: Is there any way (being able to restrict the cols I want to execute code for checking) / other method to tweak this code to make the run faster?

    Here’s my code below,

    Code:
    Private Sub Worksheet_Change(ByVal Target As Range)
     
    ‘PURPOSE 1: Check duplicate entry in column (C, F and G)
    If Target.Count = 1 And Target.Column = 7 And Len(Trim(Cells(Target.Row, 3).Value)) > 0 Then
     
    For Each Aval In Range(“C:C”).SpecialCells(xlCellTypeConstants, 2)
      If Aval.Row  Target.Row Then
       If UCase(Trim(Cells(Target.Row, 3).Value) & Trim(Cells(Target.Row, 6).Value) & Trim(Cells(Target.Row, 7).Value)) = UCase(Trim(Cells(Aval.Row, 3).Value) & Trim(Cells(Aval.Row, 6).Value) & Trim(Cells(Aval.Row, 7).Value)) Then
       pt = MsgBox(“Duplicate record. Please update the existing record!”, vbCritical, “Duplicate entry”)
       End If
      End If
    Next
    End If
     
    Dim rng As Range, Dn As Range, Txt As String
    Set rng = Range(Range(“C5”), Range(“C” & Rows.Count).End(xlUp))
    If Not Intersect(rng.Resize(, 6), Target) Is Nothing Then
        rng.Resize(, 6).Font.Color = vbBlack
        With CreateObject(“scripting.dictionary”)
            .CompareMode = vbTextCompare
    For Each Dn In rng
        Txt = Dn.Value & Dn.Offset(, 3) & Dn.Offset(, 4)
        If Not .exists(Txt) Then
            .Add Txt, Dn
        Else
            .Item(Txt).Resize(, 6).Font.Color = vbRed
            Dn.Resize(, 6).Font.Color = vbRed
        End If
    Next
    End With
    End If
           
    ‘PURPOSE 2: Autochange for all related data if last entry Text value changed in column D
        Dim lastRow As Long
        Dim myRow As Long
     
    ‘   Exit if more than one cell updated at the same time
        ‘If Target.Count > 1 Then Exit Sub
       
    ‘   Exit if update is not to columns D or E
        If Target.Column  5 Then Exit Sub
       
    ‘   Exit if change is made to rows 1
        If Target.Row < 5 Then Exit Sub
       
        Application.ScreenUpdating = False
       
    '   Find last row in column C with data
        lastRow = Cells(Rows.Count, "C").End(xlUp).Row
       
    '   Loop through all rows in column C
        For myRow = 5 To lastRow
    '       Make sure you aren't checking the target row
            If myRow  Target.Row Then
    ‘           Check to see if column C values match
                If Cells(myRow, “C”) = Cells(Target.Row, “C”) Then
    ‘               Update column D or E
                    Application.EnableEvents = False
                    Cells(myRow, Target.Column) = Target
                    Application.EnableEvents = True
                End If
            End If
        Next myRow
           
        Application.ScreenUpdating = True
    End Sub
    
    Viewing 3 reply threads
    Author
    Replies
    • #1593565

      Have you tried turning off screen updating while the macro runs?
      Application.ScreenUpdating = False

      Don’t forget to turn it back on at the end.
      Application.ScreenUpdating = True

      cheers, Paul

    • #1593601

      So you have. 🙂

      cheers, Paul

      • #1593603

        can rewrite it in other direction?

        • #1593627

          Hi carl

          I haven’t any sample data to test this, but perhaps you could try this with a copy of your own test data..

          Code:
          Private Sub Worksheet_Change(ByVal Target As Range)
          
          c = Target.Column
          r = Target.Row
          
          'Turn calcs, event trapping, and screen updates OFF for speedup..
          With Application
          .ScreenUpdating = False
          .Calculation = xlCalculationManual
          .EnableEvents = False
          End With
          
          '------------------------------------------------------------
          'PURPOSE 1: Check duplicate entry in column (C, F and G)
          '------------------------------------------------------------
          If Target.Count = 1 And c = 7 And Len(Trim(Cells(r, 3).Value)) > 0 Then
              
              zNewText = UCase(Trim(Cells(r, "C").Value) & Trim(Cells(r, "F").Value) & Trim(Cells(r, "G").Value))
              
              '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
              For Each Aval In Range("C:C").SpecialCells(xlCellTypeConstants, xlTextValues)
              j = Aval.Row
              If j  r Then
              zExistingText = UCase(Trim(Cells(j, "C").Value) & Trim(Cells(j, "F").Value) & Trim(Cells(j, "G").Value))
                  If zNewText = zExistingText Then
                  pt = MsgBox("Duplicate record. Please update the existing record!", vbCritical, "Duplicate entry")
                  GoTo exitHere
                  End If
              End If
              Next
              '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          End If
          '------------------------------------------------------------
          'continue processing..
          
          zLastRow = Range("C" & Rows.Count).End(xlUp).Row                'find last row; using column [C]; e.g. 2678
          
          temp = "C5:H" & zLastRow                                        'e.g. "C5:H2678"
          Set rng = Range(temp)
          If Not Intersect(rng, Target) Is Nothing Then
          rng.Font.Color = vbBlack
          With CreateObject("scripting.dictionary")
          .CompareMode = vbTextCompare
          
          For j = 5 To zLastRow
          Dn = Cells(j, "C")
          Txt = Dn & Cells(j, "F") & Cells(j, "G")
          If Not .exists(Txt) Then
          .Add Txt, Dn
          Else
          temp = "C" & j & ":H" & j
          Range(temp).Font.Color = vbRed
          End If
          Next
          End With
          End If
          
          '------------------------------------------------------------
          'PURPOSE 2: Autochange for all related data if last entry Text value changed in column D
          '------------------------------------------------------------
          '   Exit if update is not to columns D or E
          If c  5 Then GoTo exitHere
          
          '   Exit if change is made to rows 1
          If r < 5 Then GoTo exitHere
          
          
          '   Loop through all rows in column C
          For j = 5 To zLastRow
          '       Make sure you aren't checking the target row
          If j  r Then
          '           Check to see if column C values match
          If Cells(j, "C") = Cells(r, "C") Then
          '               Update column D or E
          Cells(j, c) = Target
          End If
          End If
          Next
          
          '---------------------------------------------------------------------
          exitHere:
          
          'Turn calcs, event trapping, and screen updates back ON..
          With Application
          .ScreenUpdating = True
          .Calculation = xlCalculationAutomatic
          .EnableEvents = True
          End With
          
          End Sub
          

          Please let me know if this works, and, especially, if it is faster.

          zeddy

          • #1594076

            um…seems no difference in speed ….
            May I change to not immediately check, lets say press button to check ?

        • #1593628

          Hi carl

          ..for faster vba performance, make sure the vb editor is closed, and make sure your worksheet is not in page-preview mode.

          zeddy

    • #1593838

      It looks to me as though the first two sections are essentially doing the same thing – i.e. checking for duplicates – so there isn’t much point in doing it twice.

      • #1593852

        It looks to me as though the first two sections are essentially doing the same thing – i.e. checking for duplicates – so there isn’t much point in doing it twice.

        AnyAny idea for the code improvement?

    • #1593872

      It seems you check for duplicates in column C and ask the user to fix them, then check again and if they match you change columns D or E.

      What do you want the spreadsheet to do?

      cheers, Paul

      • #1594047

        Hi Paul

        That is not what I assumed the issue to be.
        The checks are:
        1. stop immediately if the User tries to enter a value in column [G] that, combined with existing non-blank value in [C] and existing value in [F], is already there.
        2. If the User makes any entry in columns [C] to [H], change the font colour to red in range [C:H] for any row where C&F&G already exists
        3.If the User makes any change in column [D], then make sure column [E] is the same, and vice versa.

        It would be much easier if a sample file with sample data was posted.

        zeddy

        • #1594074

          Hi Paul

          That is not what I assumed the issue to be.
          The checks are:
          1. stop immediately if the User tries to enter a value in column [G] that, combined with existing non-blank value in [C] and existing value in [F], is already there.
          2. If the User makes any entry in columns [C] to [H], change the font colour to red in range [C:H] for any row where C&F&G already exists
          3.If the User makes any change in column [D], then make sure column [E] is the same, and vice versa.

          It would be much easier if a sample file with sample data was posted.

          zeddy

          Data attached and thanks again for your help~

        • #1594080

          The first part puts up a message but does not exit the routine, so the duplicate check is then done again anyway. It also monitors columns A:G even though many of them are irrelevant to the duplicate check.

          I think it would be useful to have – in words, not code – an explanation of exactly what should happen.

          • #1594092

            Hi

            ..the code I suggested in post#6 is not in the sample file posted in post#13

            carl – did you try my posted code???

            zeddy

            • #1594113

              Hi

              ..the code I suggested in post#6 is not in the sample file posted in post#13

              carl – did you try my posted code???

              zeddy

              Yes I try it but when i upload here just deleted~~~just afraid too large file size here

    Viewing 3 reply threads
    Reply To: Speed up the Worksheet_Change

    You can use BBCodes to format your content.
    Your account can't use all available BBCodes, they will be stripped before saving.

    Your information: