2017-08-23 3 views
1

Nous avons une feuille que nous utilisons pour analyser un processus d'appel d'offres détaillé, et que nous voulons supprimer toutes les lignes vides.Excel VBA Autofilter> Supprimer les lignes vides

La plage peut varier d'un projet à l'autre, jusqu'à 170 colonnes et 6000 lignes.

Le code que j'ai testé fonctionne, sur un projet avec env. 40 colonnes & 4750 lignes, et prend juste 10 minutes pour courir.

Vous cherchez des solutions légèrement plus élégantes pour réduire ce temps. Actuellement, le code va automatiquement filtrer chaque colonne pour les blancs, se demandant si même les colonnes vides filtrées ralentissent le tout.

Dans le code ci-dessous j'ai supprimé la plupart des champs de filtre automatique pour faciliter la visualisation, mais il filtre tous les champs de 1-175.

Sub DeleteEmptyRows() 

With Sheets("Detailed Comparison") 
    Application.DisplayAlerts = False 
    .AutoFilterMode = False 
    Application.ScreenUpdating = False 

    With .Range("F24:FY6000") 
     .AutoFilter 
     .AutoFilter Field:=1, Criteria1:="=" 
     .AutoFilter Field:=2, Criteria1:="=" 
     .AutoFilter Field:=175, Criteria1:="=" 
    End With 

    With .Range("F25:FY6000").SpecialCells(xlCellTypeVisible).Rows.Delete 
    End With 

    Application.DisplayAlerts = True 

    .AutoFilterMode = False 
    Application.ScreenUpdating = True 
End With 

End Sub 
+1

Je comprends que vous avez besoin comme optimiser votre code ou quelque chose comme ça; Je pense que vous devriez essayer [CodeReview] (https://codereview.stackexchange.com/) || Je ne comprends pas pourquoi vous utilisez un bloc With vide ('.Range (" F25: FY6000 "). SpecialCells (xlCellTypeVisible) .Rows.Delete') – NatNgs

Répondre

1

Pour rendre les choses plus élégant

  1. Ajouter une colonne qui évalue TRUE lorsque les cellules dans les colonnes 1-175 sont vides. Filtrer sur cette colonne.

  2. Pour mieux définir les lignes que vous devez supprimer, utiliser une fonction pour définir la rangée du bas (plutôt que la mise en rangée du bas pour 6000.

par exemple:

Function LastRowInOneColumn(ws As Worksheet, Optional bool As Boolean) As Long 

'Find the last used row in a Column 
'by default, returns row of column A (FLASE) 
'if bool is TRUE then will return row of column B 

Dim LastRow As Long 
Dim col As String 

If bool = True Then 
    col = "B" 
Else 
    col = "A" 
End If 

With ws 
    LastRow = .Cells(.Rows.Count, col).End(xlUp).row 
End With 

LastRowInOneColumn = LastRow 

End Function 

Vitesse

Je vous recommande de tester pour voir quelle partie de votre code fonctionne si lentement Si c'est le filtrage, que la suggestion 1 (ci-dessus) devrait aider. Si c'est la suppression qu'il est possible que d'autres parties de votre classeur soient liées à cet ensemble de données, la suppression de données ici sera TRÈS lente. Si c'est le cas, je vous recommande de modifier vos autres ensembles de données afin qu'ils se réfèrent à cette feuille de calcul via une plage nommée que vous supprimez en tant que première étape de vos macros DeleteEmptyRows, puis recréez ces plages nommées à la fin de l'exécution. macro

Sub set_named_ranges() 

'creates named ranges needed for this workbook 
'this code is somewhat crude, you may need to modify based on how your data are laid out 

Dim found As Range 
Dim col_lookup_text As String 
dim wks_name As String 

wks_name = "Detailed Comparison" 

Worksheets(wks_name).Select 
Worksheets(wks_name).Range("A1").Select 
Range(Selection, Selection.End(xlToRight)).Select 

'header named range 
ActiveWorkbook.Names.Add _ 
     Name:=("data_Header"), _ 
     RefersTo:=Range(wks_name & "!" & RngAddress(Selection)) 

'main data named range 
Range(Selection, Selection.End(xlDown)).Select 

ActiveWorkbook.Names.Add _ 
     Name:=("dataset"), _ 
     RefersTo:=Range(wks_name & "!" & RngAddress(Selection)) 

End Sub 

Function RngAddress(rng As Range) As String 
RngAddress = rng.Address 
End Function 

et:

Sub delete_these_named_ranges(ParamArray names_of_named_ranges() As Variant) 

'not a very sexy macro 
'feed macro names of named ranges 
'deletes the named range 
'if named range doesn't exist, it creates a named range with 
'that name and deletes it to avoid errors 

Dim nName As Variant 

For Each nName In names_of_named_ranges 

    On Error Resume Next 
    ActiveWorkbook.Names.Add Name:=nName, RefersTo:="temp" 
    ActiveWorkbook.Names(nName).Delete 

Next nName 

End Sub 
+0

Merci pour une réponse détaillée, j'ai pris quelques points à bord. Le code est maintenant d'environ 20 lignes par rapport à> 180 avant la main. Le temps a diminué d'environ une minute, mais je ne suis pas sûr que nous puissions l'obtenir plus rapidement en raison de l'ensemble de données, comme vous l'avez mentionné. Cet ensemble de données est particulièrement lourd, ont essayé le code sur l'ensemble avec 2000 lignes de moins et le temps était d'environ 3 minutes, ce qui n'est pas trop mal pour nos besoins. Encore merci beaucoup! – Shabbash18

2

Vous pouvez ajouter une colonne supplémentaire avec le nombre de tous les champs vides de la ligne - par ex. = COUNTA (F24: FY24) - puis filtrer les lignes de cette colonne où la valeur = 0.

Je n'ai pas testé, mais pense qu'il devrait être beaucoup plus rapide ...

+0

Oui, j'avais pensé à faire cela, je suis sûr que je serai capable pour obtenir ce chemin dans la feuille, applaudissements. – Shabbash18