简体   繁体   English

删除所有包含指定数值范围之外的值的行

[英]Delete all rows containing values outside of a specified numeric range

I am completely new to visual basic.我对视觉基础完全陌生。 I have a few spreadsheets containing numbers.我有一些包含数字的电子表格。 I want to delete any rows containing numbers outside of specific ranges.我想删除任何包含特定范围之外的数字的行。 Is there a straightforward way of doing this in visual basic?在visual basic中是否有一种简单的方法来做到这一点?

For example, in this first spreadsheet (image linked) I want to delete rows that contain cells with numbers outside of these two ranges: 60101-60501 and 74132-74532.例如,在第一个电子表格(图像链接)中,我想删除包含数字超出这两个范围的单元格的行:60101-60501 和 74132-74532。

Can anyone give me some pointers?谁能给我一些指示? Thanks!谢谢!

电子表格的图像

Code代码

You need to call it for your own needs as shown on the routine "Exec_DeleteRows".您需要根据自己的需要调用它,如例程“Exec_DeleteRows”所示。 I assumed that you needed if it is equals or less to the one that you state on your routine.我假设你需要它是否等于或小于你在例行程序中的 state。 In this example, I will delete the rows where values are between 501-570 and then the ones between 100-200在此示例中,我将删除值介于 501-570 之间的行,然后删除值介于 100-200 之间的行

Sub Exec_DeleteRows()
    Call Exec_DeleteRowsInRangeBasedOnNumberValue(Range("C8:H11"), 501, 570)
    Call Exec_DeleteRowsInRangeBasedOnNumberValue(Range("C8:H11"), 100, 200)
End Sub

Sub Exec_DeleteRowsInRangeBasedOnNumberValue(RangeToWorkIn As Range, NumPivotToDeleteRowBottom As Double, NumPivotToDeleteRowTop As Double)
Dim RangeRowsToDelete As Range
Dim ItemRange As Range
    For Each ItemRange In RangeToWorkIn
    If IsNumeric(ItemRange.Value) = False Then GoTo SkipStep1
    If ItemRange.Value >= NumPivotToDeleteRowBottom And ItemRange.Value <= NumPivotToDeleteRowTop Then ' 1. If ItemRange.Value >= NumPivotToDeleteRowBottom And ItemRange.Value <= NumPivotToDeleteRowTop
    If RangeRowsToDelete Is Nothing Then ' 2. If RangeRowsToDelete Is Nothing
    Set RangeRowsToDelete = RangeToWorkIn.Parent.Rows(ItemRange.Row)
    Else ' 2. If RangeRowsToDelete Is Nothing
    Set RangeRowsToDelete = Union(RangeToWorkIn.Parent.Rows(ItemRange.Row), RangeRowsToDelete)
    End If ' 2. If RangeRowsToDelete Is Nothing
    End If ' 1. If ItemRange.Value >= NumPivotToDeleteRowBottom And ItemRange.Value <= NumPivotToDeleteRowTop
SkipStep1:
    Next ItemRange
    If Not (RangeRowsToDelete Is Nothing) Then RangeRowsToDelete.EntireRow.Delete
End Sub

Demo演示

在此处输入图像描述

Delete Rows Containing Wrong Numbers删除包含错误数字的行

在此处输入图像描述

  • It is assumed that the data starts in A1 of worksheet Sheet1 in the workbook containing this code ( ThisWorkbook ) and has a row of headers ( 2 ).假设数据从包含此代码 ( ThisWorkbook ) 的工作簿中的工作表Sheet1A1开始,并具有一行标题 ( 2 )。
  • This is just a basic example to get familiar with variables, data types, objects, loops, and If statements.这只是熟悉变量、数据类型、对象、循环和If语句的基本示例。 It can be improved on multiple accounts.它可以在多个帐户上进行改进。
Option Explicit

Sub DeleteWrongRows()
    
    Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
    Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1") ' worksheet
    Dim rg As Range: Set rg = ws.Range("A1").CurrentRegion ' range
    
    Application.ScreenUpdating = False
    
    Dim rrg As Range ' Row Range
    Dim rCell As Range ' Cell in Row Range
    Dim rValue As Variant ' Value in Cell
    Dim r As Long ' Row
    Dim DoDelete As Boolean
    
    ' Loop backwards through the rows of the range.
    For r = rg.Rows.Count To 2 Step -1
        Set rrg = rg.Rows(r)
        ' Loop through cells in row.
        For Each rCell In rrg.Cells
            rValue = rCell.Value
            If IsNumeric(rValue) Then ' is a number
                If rValue >= 60101 And rValue <= 60501 Then ' keep
                ElseIf rValue >= 74132 And rValue <= 74532 Then ' keep
                Else ' delete (outside the number ranges)
                    DoDelete = True
                End If
            Else ' is not a number
                DoDelete = True
            End If
            If DoDelete Then ' found a cell containing a wrong value
                rCell.EntireRow.Delete
                DoDelete = False
                Exit For ' no need to check any more cells
            'Else ' found no cell containing a wrong value (do nothing)
            End If
        Next rCell
    Next r
    
    Application.ScreenUpdating = True
    
    MsgBox "Rows with wrong numbers deleted.", vbInformation
    
End Sub

Using Range.Delete is the built-in way of completely erasing a row in Excel VBA.使用Range.Delete是完全擦除 Excel VBA 中的一行的内置方法。 To check an entire row for numbers meeting a certain criteria, you would need a Loop and an If Statement .要检查一整行是否有符合特定条件的数字,您需要一个Loop和一个If 语句

To evaluate a lot of values at a faster pace, it is smart to first grab the relevant data off the Excel sheet into an Array.为了以更快的速度评估大量值,明智的做法是首先将 Excel 表中的相关数据抓取到一个数组中。 Once in the array, it is easy to set up the loop to run from the first element ( LBound ) to the final element ( UBound ) for each row and column of the array.进入数组后,很容易将循环设置为从数组的每一行和每一列的第一个元素 ( LBound ) 运行到最后一个元素 ( UBound )。

Also, when deleting a lot of Ranges from a worksheet, it is faster and less messy to first collect ( Union ) the ranges while you're still looping, and then do the delete as a single step at the end.此外,当从工作表中删除大量 Ranges 时,在您仍在循环时首先收集( Union )范围,然后在最后作为单个步骤执行删除操作会更快且更简洁。 This way the Range addresses aren't changing during the loop and you don't need to re-adjust in order to track their new locations.这样,范围地址在循环期间不会改变,您无需重新调整以跟踪它们的新位置。 That and we can save a lot of time since the application wants to pause and recalculate the sheet after every Deletion.这可以节省大量时间,因为应用程序希望在每次删除后暂停并重新计算工作表。

All of those ideas put together:所有这些想法放在一起:

Sub Example()
    DeleteRowsOutside Min:=60101, Max:=60501, OnSheet:=ThisWorkbook.Worksheets("Sheet1")
    DeleteRowsOutside Min:=74132, Max:=74532, OnSheet:=ThisWorkbook.Worksheets("Sheet1")
End Sub
Sub DeleteRowsOutside(Min As Long, Max As Long, Optional OnSheet As Worksheet)
    If OnSheet Is Nothing Then Set OnSheet = ActiveSheet
    
    'Find the Bottom Corner of the sheet
    Dim BottomCorner As Range
    Set BottomCorner = OnSheet.Cells.Find("*", After:=OnSheet.Range("A1"), SearchDirection:=xlPrevious)
    If BottomCorner Is Nothing Then Exit Sub
    
    'Grab all values into an array
    Dim ValArr() As Variant
    ValArr = OnSheet.Range(OnSheet.Cells(1, 1), BottomCorner).Value
    
    'Check each row value against min & max
    Dim i As Long, j As Long, DeleteRows As Range
    For i = LBound(ValArr, 1) To UBound(ValArr, 1) 'For each Row
        For j = LBound(ValArr, 2) To UBound(ValArr, 2) 'For each column
            Dim v As Variant: v = ValArr(i, j)
            If IsNumeric(v) Then
                If v < Min Or v > Max Then
                    'v is outside the acceptable range! Mark row for deletion
                    If DeleteRows Is Nothing Then
                        Set DeleteRows = OnSheet.Rows(i)
                    Else
                        Set DeleteRows = Union(DeleteRows, OnSheet.Rows(i))
                    End If
                    Exit For 'skip to next row
                End If
            End If
        Next j
    Next i
    
    If Not DeleteRows Is Nothing Then DeleteRows.EntireRow.Delete
End Sub

Here's some code with Regex and with scripting dictionary that I've been working on.这是我一直在研究的带有正则表达式和脚本字典的一些代码。 I made this for my purposes, but it may be useful here and to others.我这样做是为了我的目的,但它在这里和其他人可能有用。

I found a way for selecting noncontinguous cells based on an array and then deleting those cells.我找到了一种基于数组选择非连续单元格然后删除这些单元格的方法。

In this case, I selected by row number because VBA prevented deletion of rows due to overlapping ranges.在这种情况下,我按行号选择,因为 VBA 由于重叠范围而阻止删除行。

Sub findvalues()

    Dim Reg_Exp, regexMatches, dict As Object
    Dim anArr As Variant
    Dim r As Range, rC As Range
    
    
    Set r = Sheets(3).UsedRange
    Set r = r.Offset(1).Resize(r.Rows.Count - 1, r.Columns.Count)
    Set Reg_Exp = CreateObject("vbscript.regexp")
    
    With Reg_Exp
            .Pattern = "^[6-6]?[0-0]?[1-5]?[0-0]?[1-1]?$|^60501$" 'This pattern is for the 60101 to 60501 range. 
    End With
     
     Set dict = CreateObject("Scripting.Dictionary")
        For Each rC In r
            If rC.Value = "" Then GoTo NextRC ''skip blanks
             Set regexMatches = Reg_Exp.Execute(rC.Value)
                If regexMatches.Count = 0 Then
                    On Error Resume Next
                       dict.Add rC.Row & ":" & rC.Row, 1
                End If
NextRC:
        Next rC
                    On Error GoTo 0

    anArr = Join(dict.Keys, ", ")
 
    Sheets(3).Range(anArr).Delete Shift:=xlShiftUp

End Sub

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM