2013-06-03 14 views
8

Ben e-postalar için bir geçerlilik kontrolü yapmak için hızlı alt yaratıyorum. Ben 'E' Sütun bir '@' içermeyen iletişim verilerinin tüm satırları silmek istiyorum. Aşağıdaki makroyu kullandım, ancak çok yavaş çalışıyor çünkü Excel silmenin ardından tüm satırları hareket ettiriyor. set rng = union(rng,c.EntireRow) ve sonrasında tüm aralığı silme, ama hata iletileri engel olamadı:Verimli yolu tüm satırı silmek için '@'

Böyle başka bir teknik denedim.

Ben de sadece seçime her satır ekleyerek İle denediği ve her şey seçildi sonra (ctrl gibi + seçin), sonradan silme, ama bunun için uygun sözdizimi bulamadık.

Herhangi bir fikrin var mı?

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

Birincisi, hücre sayısı travers sınırlar. yani "range (E: E)" yerine, – shahkalpesh

+0

veri içeren bir aralık kullanın. Bunu her zaman nasıl yapacağımı merak ettim. İçinde veri bulunan son hücreye kadar ilk hücreyi içeren bir aralığı nasıl seçerim ? – Parseltongue

+1

http://www.rondebruin.nl/win/s4/win001.htm - Şuna bir bakın. Eminim, sizin için cevaplayacaktır. Sorunuzu yanıtlayın, veri içeren A1 hücresindesiniz, şimdi ctrl + aşağı ok tuşuna basın. Bu, A1'den başlayarak son hücreye kadar veri içeren tüm hücreleri seçer (Not: ortada boş hücreler olmamalıdır). VBA kullanarak 'lastCell = Range (" A1 ") olabilir. End (xlDown)' – shahkalpesh

cevap

16

Bunu yapmak için bir döngüye ihtiyacınız yoktur. Bir otomatik filtre çok daha verimlidir.

Otomatik filtreleme ardından "@" içeren ve olmayan tüm satırlar şöyle silin (benzer SQL fıkra nerede vs ilerlemek için):

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 

NOTLAR:

  • .Offset(1,0),
  • başlık satırını silmemizi engeller Otomatik filtreden sonra kalan satırları belirtir
  • .EntireRow.Delete

Adım kodu ile başlık satırı hariç görünür satırların siler ve her satır ne yaptığını görebilirsiniz. VBA Düzenleyicisi'nde F8 kullanın. kullanıcı shahkalpesh sağladığı bir örneği kullanarak

+0

'Bir aralık dışı aralık' hatası alıyorum. İki şeyi açıklar mısınız? 'Set rng = ws.Range ("A1: A" & lastRow) nedir? Neden "A1: A"? ve ".Offset (1, 0) .SpecialCells (xlCellTypeVisible) .EntireRow.Delete" ne yapar? – Parseltongue

+0

Sadece çalıştığınız sütunun E. olduğunu anladım. Hata, yanlış sütunu aradığım için. "A" ifadesini "E" olarak değiştirin ve işe yaramalısınız. Aralığın ayarlanması, otomatik filtrelemeye gideceğimiz aralığı belirtir (A1: A ve bir değerle son satır ne olursa olsun). .Offset (1,0) başlık sırasını silmemizi engelliyor. –

+2

Şimdi deneyin - Sütunu düzenledim. –

2

, başarıyla aşağıdaki makro yarattı. (Fnostro tarafından başvurulan gibi hangi net içerik, sıralama ve sonra silin) ​​Hala diğer teknikleri öğrenmek için merak ediyorum. VBA’da yeniyim, bu yüzden her örnek çok yardımcı olabilirdi. yıldız işaretleri öncesi ve @ işaretinden sonraki vardır ama nasıl bilmiyorum:

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

Kodun çalışmasını sağlamak için ama mümkün olduğunda aralık döngülerini önlemek için çok iyi - daha büyük veri kümeleri üzerinde çok yavaş olabilirler. Mümkün olduğunda 'AutoFilter', 'SpecialCells 'veya varyant dizileri kullanın. – brettdj

3

Eğer kriterler sonra

specialcells(xlcelltypevisible).entirerow.delete 

notu kullandıkça " @" kullanarak basit bir oto filtresi denediniz ayrıştırılmayı durdurun!

+0

Özür dilerim-orijinal olarak gönderdiğimde cevabınız yoktu. Yine de kriteri bozdum! – JosieP

1

birçok satır ve birçok koşullara çalışıyoruz, her şeyi kapıp bir varyant koydu, sıra silme bu yöntemi kullanarak

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

'Seç 'herhangi bir kodu yavaşlatır ve her zaman önlenmelidir. Bunun filtre verimliliğine yaklaşabileceğinden şüpheliyim. – brettdj

0

yerine döngü 1'e ve her hücreyi 1 referans kapalı daha iyi dizi; Ardından varyant dizisini döngüleyin.

Starter:

Sub Sample() 
    ' Look in Column D, starting at row 2 
    DeleteRowsWithValue "@", 4, 2 
End Sub 

Gerçek işçi:

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 
İlgili konular