Home > Software design >  VBA/ Method Delete of Class Range failed
VBA/ Method Delete of Class Range failed

Time:08-26

I am trying to delete a row if the value I check is 0. So far I did almost the exact same in another set of workbooks, and it went just fine. Both cases involve getting the agency's name from the startup workbook, then opening the first workbook of the set that needs deletion, looping through it and deleting what needs to be deleted, closing it and moving on to the next one (here I go from 2 to 2 because there's no need to go through all of them just yet)

I did my homework and looked it up beforehand. No, not my table nor my sheet nor my workbook nor any range is protected. Yes, I made sure to activate the workbook I want to affect, and it has only one sheet in it. Using .Select works, deleting manually isn't possible. It seems a cell is locked, but even unlocking it doesn't allow me to manually delete the row. here it's unlocked.

Edit - I tried running it with the original set of workbooks, and it worked just fine (the one I'm working with is a copy of the original)

Sub PetitTas()

deb = Now()
For i = 2 To 2
    Workbooks("dimensionnement technos 2").Activate
    Agence = Cells(i, 24)
    Workbooks.Open "C:\Users\QNS691\Documents\Excel\par agence 2\" & Agence & ".xlsx"
    Workbooks(Agence).Activate
    For j = 2 To Cells(Rows.Count, 1).End(xlUp).Row
        If Cells(j, 14) = 0 Then
            Rows(j).EntireRow.Delete
        End If
    Next j
    Workbooks(Agence).Close SaveChanges:=True
Next i
MsgBox deb & " " & Now()
End Sub

I am running out of ideas, please help!

CodePudding user response:

Overall you shouldn't be relying on the active sheet or the .Activate method. You should look at how-to-avoid-using-select-in-excel-vba

With that, explicitly use the Workbook and Worksheet when working with any Range or Cell.

Now your deletion is removing rows that your loop is depending on, so one fix is to loop backwards.

Below is my quick fixes to your code, but note it isn't tested.

Option Explicit

Public Sub PetitTas()
    Dim deb As Date ' Was missing
    deb = Now()
    
    Dim i As Long ' Was missing
    For i = 2 To 2
        
        ' Use the specific worksheet reference.
        ' Using activate isn't reliable and
        ' hurts performance
        Dim agence As Variant
        agence = Workbooks("dimensionnement technos 2") _
            .Worksheets(1) _
            .Cells(i, 24)
        
        ' Capture your workbook into a variable for the
        ' same reason above, activate is not your friend
        ' in most cases. Only time is when you need to display
        ' a user a specific sheet.
        Dim wb As Workbook
        Set wb = Workbooks.Open( _
            "C:\Users\QNS691\Documents\Excel\par agence 2\" & _
            agence & ".xlsx" _
        )
        
        
        ' Use a with statement to capture your
        ' worksheet, that way `.Cells` is pointing
        ' explicitly to the correct sheet.
        With wb.Worksheets(1)
            Dim j As Long ' Was missing
            
            ' When deleting in a loop, either capture
            ' all ranges into a variable a delete after loop
            ' or step backwards. I steped backwards for this demo
            ' for simplicity, but single deletion is more performant
            For j = .Cells(.Rows.Count, 1).End(xlUp).Row To 2 Step -1
                If .Cells(j, 14) = 0 Then
                    .Rows(j).EntireRow.Delete
                End If
            Next j
        End With
        
        wb.Close SaveChanges:=True

    Next i
    MsgBox deb & " " & Now()
End Sub

CodePudding user response:

Delete Entire Rows (Union)

Sub PetitTas()
    
    Const FolderPath As String = "C:\Users\QNS691\Documents\Excel\par agence 2\"

    Dim swb As Workbook: Set swb = ThisWorkbook ' workbook containing this code
    Dim sws As Worksheet: Set sws = swb.Worksheets("Feuil1")
    Dim sfCell As Range: Set sfCell = sws.Range("X2")
    Dim slCell As Range: Set slCell = sfCell.Resize( _
        sws.Rows.Count - sfCell.Row   1).Find("*", , xlFormulas, , , xlPrevious)
    Dim srg As Range: Set srg = sws.Range(sfCell, slCell)
    
    Application.ScreenUpdating = False
    
    Dim sCell As Range
    Dim Agency As String
    Dim FilePath As String
    Dim dwb As Workbook
    Dim dws As Worksheet
    Dim durg As Range
    Dim drg As Range
    Dim dCell As Range
    
    For Each sCell In srg.Cells
        Agency = CStr(sCell.Value)
        If Len(Agency) > 0 Then
            FilePath = FolderPath & Agency & ".xlsx"
            If Len(Dir(FilePath)) > 0 Then ' check if the file exists...
                Set dwb = Workbooks.Open(FilePath) ' ... only then open it
                Set dws = dwb.Worksheets(1) ' the one and only
                Set drg = dws.Range("N2", dws.Cells( _
                    dws.Cells(dws.Rows.Count, "A").End(xlUp).Row, "N"))
                For Each dCell In drg.Cells
                    If IsNumeric(dCell) Then
                        If dCell.Value = 0 Then
                            If durg Is Nothing Then
                                Set durg = dCell
                            Else
                                Set durg = Union(durg, dCell)
                            End If
                        End If
                    End If
                Next dCell
                If durg Is Nothing Then
                    dwb.Close SaveChanges:=False
                Else
                    durg.EntireRow.Delete
                    Set durg = Nothing
                    dwb.Close SaveChanges:=True
                End If
            End If
        End If
    Next sCell
    
    Application.ScreenUpdating = True
    
    MsgBox "'PetitTas' is done.", vbInformation
        
End Sub
  • Related