0

I have code to paste a value into all worksheets in a workbook (it does work but its a little slow).

Then it should when a value is deleted, delete that row from every other worksheet, but it does nothing.

Debugging it looks like the Application.CountBlank(irg) = 1 is never met even though IRG upon cell deletion as the target cell should definitely be blank and a delete should run the worksheet change event.

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)

    Const cCol As String = "A"
    Const fRow As Long = 2

    Dim crg As Range
    Dim ddFound As Range
    Dim ws As Worksheet
    Dim sh As Worksheet
    Dim outpt As String

    Dim i As Integer

    Application.EnableEvents = False

    Set crg = Columns(cCol).Resize(Rows.Count - fRow + 1).Offset(fRow - 1)
    Dim irg As Range: Set irg = Intersect(crg, Target)
    Dim sraddress As String
    
    Dim dws As Worksheet
    Dim ddcrg As Range

    For Each ws In ActiveWorkbook.Worksheets
                
        Set ddcrg = ws.Columns(cCol)
        sraddress = irg.Value2
        Set ddFound = ddcrg.Find(sraddress, , xlValues, xlWhole)
                
        Application.ScreenUpdating = False
                
        If Application.CountBlank(irg) = 0 Then

            If ddFound Is Nothing Then
                irg.Select:   ActiveCell = irg.Value2
                irg.Copy
                ws.Range(irg.Address) = irg.Value2
                Application.CutCopyMode = False
                
            ElseIf Application.CountBlank(irg) = 1 And ddFound Is Nothing Then
                Sheets(Array("Statistics", "January")).Select
                ddFound.EntireRow.Delete Shift:=xlShiftUp

            End If
        End If
        
    Next ws
   
    Application.ScreenUpdating = True
    Application.EnableEvents = True
    
End Sub
Community
  • 1
  • 1
Drawleeh
  • 297
  • 1
  • 10
  • 1
    re: *"it's a little slow"* - rather than copy/pasting values, it may be quicker to set the cell value directly. For example, instead of using `Range("A1").Copy:Range("B1").PasteSpecial Paste:=xlPasteValues`, it's about 30x faster to just assign the value directly like `Range("B1")=Range("A1")`. Also for this kind of stuff `Application.ScreenUpdating=False` makes a big difference to performance, added just before starting a loop (and don't forget to re-enable it afterwards.) [Here](https://learn.microsoft.com/office/vba/api/excel.application.screenupdating)'s the documentation on that. – ashleedawg Dec 23 '21 at 11:06
  • also re:performance - There's some good info about performance [here](https://techcommunity.microsoft.com/t5/excel/9-quick-tips-to-improve-your-vba-macro-performance/m-p/173687) and [here](https://www.spreadsheetsmadeeasy.com/7-common-vba-mistakes-to-avoid/) and also ["How to avoid using Select in Excel VBA"](https://stackoverflow.com/q/10714251/8112776). – ashleedawg Dec 23 '21 at 11:10
  • Is there any difference between `Target` and `irg`, since is the result of an intersection between `Target` and a column range? Can `Target` contain multiple columns? If so and only one row, the cell on the specific column is set. Counting in a single cell is not the best option... Can it contain more rows? In such a case `sraddress = irg.Value2` will return an error. It makes sense only for a single cell. Can you clarify the above mentioned issues, please? – FaneDuru Dec 23 '21 at 11:17
  • Why do you use `Set dws = Worksheets(i)` and the iteration, since you already have `ws`? If you need excepting some sheets, you can do it conditioning the execution for `ws.Name <> "Sheet to be excepted"`. Then, no selection is necessary to do all operation you try executing. This only consumes Excel resources, makes the code slower and does not bring any benefit. And allocating the value directly, as mentioned in the previous comment, the code will become faster. The rows deletion is tricky in your case. If you firstly delete one row, according to a specific case, the next are messed up. – FaneDuru Dec 23 '21 at 11:24
  • For deletion, since it is done in the same sheet, you should create a `Union` range, let us say, `rngDel` which to delete its `EntireRow` at once, at the end of the code. This will make your code also much faster, instead of each row deletion. If you clarify the issues I put in discussion, I can post a working code. Of course, based on what I will be able to understand about your real need... Please, better explain the context. – FaneDuru Dec 23 '21 at 11:29
  • I wanted to specify to only use the intersection if the target is in column A. Target can't contain multiple columns for that matter, entry will only occur in column A. dws = Worksheets(i) is an oversight on my part because I'm not great at coding, the code has been updated now. – Drawleeh Dec 23 '21 at 12:08
  • Please, test the code I posted. Not tested, of course, not having a similar workbook, but it should work (if my understanding about your need is correct). If any error, please mention the row and the error description... – FaneDuru Dec 23 '21 at 12:28
  • It doesn't seem to delete anything from the other pages, same as before when you delete from one page, no error comes up just doesn't do anything. rngDelS is never not nothing to run the delete IF statement when the value is deleted in column A. – Drawleeh Dec 23 '21 at 12:42
  • I cannot get you... Firstly, please comment on my answer. Secondly, your code tried deleting rows from sheets **"Statistics" and "January"**. Isn't it what you want? If it is, didin't the above code delete the necessary rows? If the range is **Not Nothing** it means that it has been set and the condition is met. The rows should be deleted. Please, add the next testing line after `If Not rngDelS Is Nothing Then`: `Debug.Print rngDelS.Address`. Does it return anything in Immediate Window? – FaneDuru Dec 23 '21 at 12:56

1 Answers1

0

Please, try the next code. It assumes that Target may have more columns, but only one row:

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
  Const cCol As String = "A"
  Const fRow As Long = 2
  Dim crg As Range, ddFound As Range, ws As Worksheet, i As Long

 Application.EnableEvents = False

  Set crg = Columns(cCol).Resize(rows.Count - fRow + 1).Offset(fRow - 1)
  Dim irg As Range: Set irg = Intersect(crg, Target)
  If Target.rows.Count > 1 Then Exit Sub 'no more then one row admitted
  If irg Is Nothing Then Exit Sub
  Dim sraddress As String, ddcrg As Range
  Dim rngDelS As Range, rngDelJ As Range 'ranges to keep rows to be deleted

  For Each ws In ActiveWorkbook.Worksheets
   If ws.Index <= 13 Then
        Set ddcrg = ws.Columns(cCol)
        sraddress = irg.Value2
        Set ddFound = ddcrg.Find(sraddress, , xlValues, xlWhole)
    
         If irg.Value <> "" Then
            If ddFound Is Nothing Then
                ws.Range(irg.Address).Value2 = irg.Value2
            End If
        ElseIf irg.Value = "" And Not ddFound Is Nothing Then
                If rngDelS Is Nothing Then
                    Set rngDelS = Sheets("Statistics").Range(ddFound.Address)
                    Set rngDelJ = Sheets("January").Range(ddFound.Address)
                Else
                    Set rngDelS = Union(rngDelS, Sheets("Statistics").Range(ddFound.Address))
                    Set rngDelJ = Union(rngDelJ, Sheets("January").Range(ddFound.Address))
                End If
          End If
    End If
  Next ws
  If Not rngDelS Is Nothing Then 'delete the necessary rows, at once, per each sheet:
     rngDelS.EntireRow.Delete
     rngDelJ.EntireRow.Delete
  End If
  Application.EnableEvents = True
End Sub
FaneDuru
  • 38,298
  • 4
  • 19
  • 27
  • I added the debug.print nothing comes up in Immediate window. And yes my code is attempting to delete the same entry in January when the entry is deleted in Statistics. The first part is fine, when something is added to statistics it is also added to January. Now it should just delete from January when it is deleted from Statistics. – Drawleeh Dec 23 '21 at 13:02
  • @Drawleeh I still cannot get you... Do you say that it is deleting rows on "January" but not from "Statistics? Does it delete form any of the two sheets? if not, this only mean that the condition `ElseIf irg.Value = "" And Not ddFound Is Nothing Then` is not met... – FaneDuru Dec 23 '21 at 13:07
  • @Drawleeh Please, test the updated code. I followed your code logic, but based on that, the code never reach the line `irg.Value = "" And Not ddFound Is Nothing Then`, since it was inside the `If` statement for the case of `irg.Value <> ""`... – FaneDuru Dec 23 '21 at 13:30
  • Im sorry if I'm not describing this correctly, if I type in 'test' in statistics it should also appear in January. If I then delete the word 'test' in statistics it should also be deleted from January. Currently even with the updated code when 'test' is deleted from statistics it doesn't delete from January. – Drawleeh Dec 23 '21 at 14:13
  • But this code runs for **all Sheets**. Is the situation described above a particular case? Please, place a break point on the line `ElseIf irg.Value = "" And Not ddFound Is Nothing Then` and move the cursor over `ddFound` variable. It probably will be `Nothing`. In such a case, why did you use it in your code? Should the code search for an empty string? Not understanding what exactly you want accomplishing I would recommend to delete `And Not ddFound Is Nothing` and test the code after that... – FaneDuru Dec 23 '21 at 14:21
  • What I was hoping to accomplish is on deletion of cell in column A from statistics page, that cell address is then used to delete all rows in every worksheet with the same address. If cell on statistics page is deleted in A6. On every other page Row (6:6) is deleted. – Drawleeh Dec 23 '21 at 14:28
  • But, your code only tried to delete from from two specific sheets... Does your workbook has more then 13 sheets? Are the two specified ones after the 13th one? i will be in my office for maximum 20 minutes. If I will be able to understand what is to be done, I can try helping. Otherwise, I will be available only after some hours, when I will be at home. But, if not something confidential and you can share your workbook, better explaining (**in words**) what you try accomplishing, I will look at it and try adapting the code to do what (I will understand that) you need... – FaneDuru Dec 23 '21 at 14:35
  • I had only set it up to delete from 2 to test a limited range of information, the code will have 13 sheets, one statistics to enter names, which need to appear in 12 sheets that all contain months of the year. When a name is deleted from statistics it should delete from all 12 month sheets too. Thats the basic idea behind what I was trying to accomplish – Drawleeh Dec 23 '21 at 14:48