2013-06-03 12 views
8

電子メールの有効性チェックを行うために高速サブを作成しています。 'E'列に '@'が含まれていない連絡先データの行全体を削除したいとします。私は以下のマクロを使用しましたが、Excelが削除後にすべての行を移動するため、動作が遅すぎます。セルに '@'が含まれていない場合、行全体を効率的に削除する

私はset rng = union(rng,c.EntireRow)のような別のテクニックを試してみましたが、その後は全範囲を削除しましたが、エラーメッセージを防ぐことができませんでした。

また、選択に各行を追加するだけで、すべてが選択された後(ctrl + selectのように)、それを削除したが、適切な構文が見つからなかった。

アイデア?

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 
+0

まず、横断する細胞の数を制限します。つまり、範囲(E:E)の代わりにデータが入った範囲を使用してください。 – shahkalpesh

+0

私はいつもその方法を知っていました。最初のセルを含む範囲? – Parseltongue

+1

http://www.rondebruin.nl/win/s4/win001.htm - これを見てください。私は確信しています、それはあなたのためにそれに答えるでしょう。あなたの質問をreged、セルA1のデータが含まれていると言い、今すぐCtrl +下矢印を押してください。 A1からデータを含む最後のセルまでのすべてのセルが選択されます(注:中央には空白のセルはありません)。 VBAを使用すると、 'lastCell = Range(" A1 ")。End(xlDown)' – shahkalpesh

答えて

16

これを行うためのループは必要ありません。オートフィルタははるかに効率的です。

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 

NOTES:

  • "@" が含まれているし、このようにそれらを削除しないでくださいすべての行(カーソルに似対どこSQLのWHERE句)

    オートフィルタ.Offset(1,0)タイトル行を削除できないようにします

  • .SpecialCells(xlCellTypeVisible)は、オートフィルタの適用後に残る行を指定します。
  • .EntireRow.Delete

ステップコードを通じてタイトル行を除くすべての可視行を削除して、あなたは、各行が何をするか見ることができます。 VBAエディタでF8キーを使用します。

+0

「範囲外の添え字」エラーが表示されます。 2つのことを説明できますか? 'Set rng = ws.Range( "A1:A"&lastRow)は何ですか?なぜ「A1:A」ですか? .Offset(1,0).SpecialCells(xlCellTypeVisible).EntireRow.Delete "は何をしますか? – Parseltongue

+0

あなたが作業している列がEであることがわかりました。エラーは間違った列を検索しているためです。 "A"を "E"に変更してください。範囲を設定すると、自動フィルタリングする範囲(A1:A、値の最後の行が何であれ)が指定されます。 .Offset(1,0)はタイトル行を削除しないようにします。 –

+2

今すぐお試しください - 私は列を編集しました。 –

2

ユーザー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 
+0

コードを有効にするためにはうまくいきますが、できる限り範囲ループを避けてください。より大きなデータセットでは非常に遅くなる可能性があります。可能であれば、 'AutoFilter'、' SpecialCells'、またはvariant配列を使用してください。 – brettdj

3

はあなたが判断基準として「 @」を使用して、簡単な自動フィルタを試してみました、その後

specialcells(xlcelltypevisible).entirerow.delete 

ノートを使用しますが、アスタリスクは、@の前後にあるが、私はどのように知りませんそれらが解析されるのを止めなさい!

+0

謝罪 - 私が最初に投稿したときのあなたの答えはなかった。私は基準を台無しにした! – JosieP

1

あなたは多くの行、多くの条件で作業している、すべてのものをつかむと、変種に入れて、行削除するこの方法を使用して

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 
+0

'Select'はコードを遅くするので、常に避けるべきです。私はこれがフィルターの効率に近づくかもしれないとは思わない。 – brettdj

0

の代わりにループして1により各セル1を参照するオフあなたより良いですアレイ;その後、バリアント配列をループします。

スターター:

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 
関連する問題