删除行组

时间:2016-04-16 12:05:38

标签: excel vba excel-vba

我想删除sheet3中的所有行,其中sheet3列'N'值不在工作表“Main”单元格B12和D12值之间。所以我尝试使用以下代码

With ActiveSheet
     Lvl = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row
     .AutoFilterMode = False
     .Range("N1").AutoFilter Field:=14, Criteria1:="<" & _
      Format(Sheets("Main").Cells(12, 2), "DD-MM-yyyy")
     .Offset(1).SpecialCells(12).EntireRow.Delete
     .AutoFilterMode = False
end with 

但是它在 偏移 上给出错误。对象不支持此属性或方法

2 个答案:

答案 0 :(得分:1)

在这里结交一些事情。一个好的做法是避免ActiveSheet。定义工作表对象并将其设置为该工作表。这使得以后在代码中更容易引用。

Dim wsMain as Worksheet
Set wsMain = thisworkbook.sheets("Main")

然后,在该工作表中定义一个您自动过滤的范围,并删除符合条件的行。 修改:您需要撤消过滤器以显示符合条件的单元格,然后删除该选择。

wsMain.AutoFilterMode = false
'format wsMain however you'd like in here
Dim lRow, lCol as Integer
    lRow = wsMain.Cells(Rows.Count, 1).End(xlUp).Row
    lCol = wsMain.Cells(1, Columns.Count).End(xlToLeft).Column
Dim rngTar as Range
    Set rngTar = wsMain.Range(wsMain.Cells(1, 1), wsMain.Cells(lRow, lCol))
With rngTar  'filter to show everything that matches the values in the range you specified
     .AutoFilter Field:=14, Criteria1:=">=wsMain.Range("B12:D12")
     .Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
wsMain.AutoFilterMode = false

修改:如果您想要多个过滤器,只需添加另一条.Autofilter行!

With rngTar
     .AutoFilter Field:=14, Criteria1:=">=wsMain.Range("B12:D12")
     .AutoFilter Field:=17, Criteria1:="Inactive"
     .Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With

希望这有帮助!

答案 1 :(得分:0)

有一些问题是错误的,可以在该代码段中改进一些。

a)With ... End With statement

With ActiveSheet
     ...
End With

你应该知道你在做什么工作表。如果您打算在一个工作表上执行它然后再激活另一个工作表并再次执行它,那么上述内容可能会很有用。但是您也可以遍历工作表。

b)冗余地引用工作表

     Lvl = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row

您已在With ... End With statement中定义了要处理的工作表。只要您在.Range对象前添加 .AutoFilterMode = False ... .AutoFilterMode = False (DOT)¹,就无需继续引用它。

c)从新的Range.Cells

开始
if .AutoFilterMode then .AutoFilterMode = False

这里的代码很好。我亲自检查是否有自动过滤器(例如 .Range("N1").AutoFilter Field:=14, Criteria1:="<" & _ Format(Sheets("Main").Cells(12, 2), "DD-MM-yyyy") ),然后关闭它,但无论原始值如何,直接覆盖都没有错。除非用户需要,否则在退出之前一定要关闭它。

值得注意的是,如果在Range.AutoFilter Method.CurrentRegion property中的单元格中使用,.UsedRange property需要添加为Range.Parent property,则属性为.AutoFilterMode {3}},而不是Worksheet Object。 (见下面的例子)

d)设置Range object的列是什么?

.Range("N1")

是列N是相对于工作表的14 th 列,但是如果您要设置这样的自动过滤器,那么它可能是相对于列N的唯一列。{{1应该是.Range("N:N"),这应该是Field:=1以保持可靠性,因为当您只查看N列时,列N是第一个也是唯一的列。

e)在Range.AutoFilter Method

中设置日期类型标准

您的字符串日期不会被解释为日期,而是字符串。在条件中,<>运算符无法可靠地使用字符串。您成功的最大希望是使用主工作表上日期的原始基础Range.AutoFilter Method小于比较运算符。 (见下面的例子)

f)尝试从工作表中移动(又名Range.Value2 property

     .Offset(1).SpecialCells(12).EntireRow.Delete

您正在使用整个工作表,而不是.OffsetRange.CurrentRegion property。你不能在任何方向上取1048576行×16384列和Worksheet.UsedRange property一个单元格而不先调整它,因为它会尝试从工作表中推出一行或一列。

从理论上讲,只要.Offset Range.Resize .Resize之前.Offset,您就可以Range.Offset property处理您正在使用的单元格块。

'this works
.Resize(.Rows.Count-1, .Columns.Count).Offset(1).SpecialCells(12).EntireRow.Delete
this does not work
.Offset(1).Resize(.Rows.Count-1, .Columns.Count).SpecialCells(12).EntireRow.Delete

此外,Range objectWorksheet Object的属性,而不是Range.Delete method,并且有更好的方法来处理有限的单元格区域。 (见下面的CurrentRegion)

g)Range.SpecialCells methodxlCellTypeVisible

删除行时,使用带有.Offset选项的.SpecialCells并不是必需的,只会添加更多处理。

只需按照SUBTOTAL function命令(可选择调整为少一行)和。删除.EntireRow,即可逐步关闭标题行。

我更喜欢确保使用工作表的原生Range.CurrentRegion property删除单元格。曾经有一个错误,当没有可见的单元格和工作表末尾的所有单元格都包括在内但我相信已经修复了服务包。无论如何,使用SUBTOTAL对可见细胞进行非破坏性测试是一种很好的编码实践。

z)使用.CurrentRegion

  

Range.CurrentRegion property 的示例将处理从A1向外辐射的单元格块,直到它在一个方向上遇到一个完全空白的列并且在一个方向上遇到一个完全空白的行其他。
虽然情况并非总是如此,但它是迄今为止最常见的。如果此数据模式与您自己的数据模式不匹配,则必须进行调整。

With ... End With statement中的Worksheet.UsedRange property将用于将代码集中在从单个单元格辐射出的单元格上。在许多情况下,它就像xlCellTypeLastCell property,但仅由工作表上的值定义,而不是With ... End With statement。实际上,您使用Range("N1").AutoFilter使用以N1为中心的.CurrentRegion作为原点来定义.AutoFilter的范围。

Worksheet.Rows中使用时,With ... End With块中的所有引用都相对于.CurrentRegion;例如Range.Rows成为Filter_Improvement_Before属性。

可以通过选择任何单元格并点击 Ctrl + A 一次来检查任何单元格的.CurrentRegion。它向各个方向延伸(向外辐射);不只是向下和向右,除非原始单元格是A1。

您修改了代码

Dim lvl As Long
With Worksheets("Sheet2")
    'work with the block of cells radiating out from A1
    With .Cells(1, 1).CurrentRegion
        'if the parent worksheet already has an AutoFiltyer, remove it
        If .Parent.AutoFilterMode Then .Parent.AutoFilterMode = False
        lvl = .Rows.Count   '<~~ not sure what LVL is actually used for but this is all that is needed
        With .Range("N:N")
            'filter on the raw numerical .value2 of the date
            .AutoFilter Field:=1, _
                        Criteria1:="<" & Worksheets("Main").Cells(12, 2).Value2, _
                        Operator:=xlFilterValues
        End With
        'step off the header row
        With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0)
            'are there visible cells
            If CBool(Application.Subtotal(103, .Cells)) Then
                'don't need .SpecialCells(xlCellTypeVisible) here
                .EntireRow.Delete
            End If
        End With
    End With
    'remove the AutoFilter
    If .AutoFilterMode Then .AutoFilterMode = False
End With

Filter_Improvement_After ActiveSheet property 程序前的样本数据 程序后的样本数据

虽然你和我不会以同样的方式做所有事情,但我希望这有助于指明你正确的方向。

¹还有Rows.Count没有前缀字符。理论上,如果代码在XLS(65536行)上运行并且this由XLSX(具有1048576行)保存,则可能会遇到麻烦。由于其他原因,我个人并不是一直赞同这种做法(见{{3}})。