Vba 在单元格不包含“@”时删除整行的有效方法
我正在创建一个快速子来检查电子邮件的有效性。我想删除在“E”列中不包含“@”的整行联系人数据。我使用了下面的宏,但它运行得太慢,因为Excel在删除后会移动所有行 我尝试过另一种类似的技术:set rng=unionrng,c.EntireRow,然后删除整个范围,但我无法阻止错误消息 我还尝试过将每一行添加到一个选择中,在按ctrl+select选择所有内容之后,随后将其删除,但我找不到合适的语法 有什么想法吗Vba 在单元格不包含“@”时删除整行的有效方法,vba,excel,Vba,Excel,我正在创建一个快速子来检查电子邮件的有效性。我想删除在“E”列中不包含“@”的整行联系人数据。我使用了下面的宏,但它运行得太慢,因为Excel在删除后会移动所有行 我尝试过另一种类似的技术:set rng=unionrng,c.EntireRow,然后删除整个范围,但我无法阻止错误消息 我还尝试过将每一行添加到一个选择中,在按ctrl+select选择所有内容之后,随后将其删除,但我找不到合适的语法 有什么想法吗 Sub Deleteit() Application.ScreenUpda
Sub Deleteit()
Application.ScreenUpdating = False
Dim pos As Integer
Dim c As Range
For Each c In Range("E:E")
pos = InStr(c.Value, "@")
If pos = 0 Then
c.EntireRow.Delete
End If
Next
Application.ScreenUpdating = True
End Sub
这样做不需要循环。自动过滤器的效率要高得多。类似于SQL中的游标vs.where子句 自动筛选所有不包含@的行,然后按如下方式删除它们:
Sub KeepOnlyAtSymbolRows()
Dim ws As Worksheet
Dim rng As Range
Dim lastRow As Long
Set ws = ActiveWorkbook.Sheets("Sheet1")
lastRow = ws.Range("E" & ws.Rows.Count).End(xlUp).Row
Set rng = ws.Range("E1:E" & lastRow)
' filter and delete all but header row
With rng
.AutoFilter Field:=1, Criteria1:="<>*@*"
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
' turn off the filters
ws.AutoFilterMode = False
End Sub
注:
.Offset1,0阻止我们删除标题行
.SpecialCellsxlCellTypeVisible指定应用自动筛选后保留的行
.EntireRow.Delete删除除标题行以外的所有可见行
逐步浏览代码,您可以看到每一行的作用。在VBA编辑器中使用F8。使用用户shahkalpesh提供的示例,我成功创建了以下宏。我仍然很想学习其他技术,比如Fnostro引用的技术,在该技术中,您可以清除内容、排序,然后删除。我是VBA新手,所以任何例子都会非常有用
Sub Delete_It()
Dim Firstrow As Long
Dim Lastrow As Long
Dim Lrow As Long
Dim CalcMode As Long
Dim ViewMode As Long
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
With ActiveSheet
.Select
ViewMode = ActiveWindow.View
ActiveWindow.View = xlNormalView
.DisplayPageBreaks = False
'Firstrow = .UsedRange.Cells(1).Row
Firstrow = 2
Lastrow = .Cells(.Rows.Count, "E").End(xlUp).Row
For Lrow = Lastrow To Firstrow Step -1
With .Cells(Lrow, "E")
If Not IsError(.Value) Then
If InStr(.Value, "@") = 0 Then .EntireRow.Delete
End If
End With
Next Lrow
End With
ActiveWindow.View = ViewMode
With Application
.ScreenUpdating = True
.Calculation = CalcMode
End With
End Sub
您是否尝试过使用@作为标准的简单自动筛选,然后使用
specialcells(xlcelltypevisible).entirerow.delete
注意:@前后都有星号,但我不知道如何阻止它们被解析出来 处理多行和多个条件时,最好使用这种行删除方法
Option Explicit
Sub DeleteEmptyRows()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim i&, lr&, rowsToDelete$, lookFor$
'*!!!* set the condition for row deletion
lookFor = "@"
Set ws = ThisWorkbook.Sheets("Sheet1")
lr = ws.Range("E" & Rows.Count).End(xlUp).Row
ReDim arr(0)
For i = 1 To lr
If StrComp(CStr(ws.Range("E" & i).Text), lookFor, vbTextCompare) = 0 then
' nothing
Else
ReDim Preserve arr(UBound(arr) + 1)
arr(UBound(arr) - 1) = i
End If
Next i
If UBound(arr) > 0 Then
ReDim Preserve arr(UBound(arr) - 1)
For i = LBound(arr) To UBound(arr)
rowsToDelete = rowsToDelete & arr(i) & ":" & arr(i) & ","
Next i
ws.Range(Left(rowsToDelete, Len(rowsToDelete) - 1)).Delete Shift:=xlUp
Else
Application.ScreenUpdating = True
MsgBox "No more rows contain: " & lookFor & "or" & lookFor2 & ", therefore exiting"
Exit Sub
End If
If Not Application.ScreenUpdating Then Application.ScreenUpdating = True
Set ws = Nothing
End Sub
不要逐个循环和引用每个单元格,而是抓住所有内容并将其放入一个变量数组中;然后循环变量数组 起动器:
Sub Sample()
' Look in Column D, starting at row 2
DeleteRowsWithValue "@", 4, 2
End Sub
真正的工人:
Sub DeleteRowsWithValue(Value As String, Column As Long, StartingRow As Long, Optional Sheet)
Dim i As Long, LastRow As Long
Dim vData() As Variant
Dim DeleteAddress As String
' Sheet is a Variant, so we test if it was passed or not.
If IsMissing(Sheet) Then Set Sheet = ActiveSheet
' Get the last row
LastRow = Sheet.Cells(Sheet.Rows.Count, Column).End(xlUp).Row
' Make sure that there is work to be done
If LastRow < StartingRow Then Exit Sub
' The Key to speeding up the function is only reading the cells once
' and dumping the values to a variant array, vData
vData = Sheet.Cells(StartingRow, Column) _
.Resize(LastRow - StartingRow + 1, 1).Value
' vData will look like vData(1 to nRows, 1 to 1)
For i = LBound(vData) To UBound(vData)
' Find the value inside of the cell
If InStr(vData(i, 1), Value) > 0 Then
' Adding the StartingRow so that everything lines up properly
DeleteAddress = DeleteAddress & ",A" & (StartingRow + i - 1)
End If
Next
If DeleteAddress <> vbNullString Then
' remove the first ","
DeleteAddress = Mid(DeleteAddress, 2)
' Delete all the Rows
Sheet.Range(DeleteAddress).EntireRow.Delete
End If
End Sub
首先,限制要遍历的单元格数量。i、 e.不要使用范围e:e,在itI中使用包含数据的范围我一直想知道如何做到这一点-如何选择包含第一个单元格直到包含数据的最后一个单元格的范围?-看看这个。我相信,它会为你解答的。注册您的问题,假设您位于包含数据的单元格A1上,现在按ctrl+向下箭头键。这将选择从A1开始的所有单元直到包含数据的最后一个单元格注释:中间不应该有空白单元格。使用VBA,您可以lastCell=RangeA1.EndXLDown也-不删除。清除行,然后在end@Fnostro-有关于如何做的参考吗?我得到一个“下标超出范围”错误。你能解释两件事吗?'设置rng=ws.RangeA1:A和lastRow的作用是什么?为什么是A1:A?那么.Offset1,0.SpecialCellsxlCellTypeVisible.EntireRow.Delete做什么呢?我刚刚意识到您正在使用的列是E。错误是因为我搜索了错误的列。将A更改为E,它应该会工作。设置范围指定要自动筛选A1:A的范围,以及最后一行的值。.Offset1,0使我们无法删除标题行。请立即尝试-我编辑了该列。我看到另一个答案将过滤后的答案复制到临时工作表中,然后删除并复制回,但使用更干净!抱歉,我最初发帖时你的答案不在那里。不过,我确实把标准搞砸了!选择会减慢任何代码,应始终避免。我怀疑这是否能达到过滤效率。在让代码正常工作方面做得很好,但在可能的情况下避免范围循环-在较大的数据集上它们可能非常慢。尽可能使用自动筛选、特殊单元或变体阵列。