Forum Discussion
VBA Delete all sheets excluding a few known
- Jan 10, 2024
Lorenzo The snippet you found can be applied as follows:
Sub DeleteOtherSheets() Dim tbl As ListObject, arr() As Variant, i As Long Set tbl = ThisWorkbook.Worksheets("HIDDEN_DEV_SHEET").ListObjects(1) ReDim arr(1 To tbl.ListRows.Count) For i = 1 To tbl.ListRows.Count arr(i) = tbl.DataBodyRange(i, 1).Value Next i Dim Item As Worksheet Application.ScreenUpdating = False Application.DisplayAlerts = False On Error Resume Next For Each Item In ThisWorkbook.Worksheets If UBound(Filter(arr, Item.Name)) = -1 Then Item.Delete Next Item Application.DisplayAlerts = True Application.ScreenUpdating = True End Sub
I was working on something similar with arrays, using the Filter function to reduce the list of sheet names upon each iteration by setting the optional Include parameter to False...
Sub DeleteOtherSheets() 'Load all worksheet names into an array Dim sheetList() As Variant, wsCount As Long, i As Long wsCount = ThisWorkbook.Worksheets.Count ReDim sheetList(1 To wsCount) For i = 1 To wsCount sheetList(i) = ThisWorkbook.Worksheets(i).Name Next i 'Remove HIDDEN_DEV_SHEET from the sheet list Dim ws As Worksheet, removeList As Variant Set ws = ThisWorkbook.Worksheets("HIDDEN_DEV_SHEET") removeList = Filter(sheetList, ws.Name, False) 'Remove each name in the table from the sheet list Dim tbl As ListObject, rowCount As Long Set tbl = ws.ListObjects(1) rowCount = tbl.ListRows.Count If rowCount > 0 Then Dim arr As Variant arr = tbl.ListColumns(1).DataBodyRange.Value If rowCount = 1 Then ' single item If Len(arr) > 0 Then removeList = Filter(removeList, arr, False) End If Else ' multiple items For i = LBound(arr, 1) To UBound(arr, 1) If Len(arr(i, 1)) > 0 Then removeList = Filter(removeList, arr(i, 1), False) End If Next i End If End If 'Delete each worksheet in the filtered list On Error Resume Next Application.ScreenUpdating = False Application.DisplayAlerts = False For i = LBound(removeList) To UBound(removeList) ThisWorkbook.Worksheets(removeList(i)).Delete Next i Application.DisplayAlerts = True Application.ScreenUpdating = True End Sub
EDIT: I discovered a few little quirks with this method (ie: if the table contains blank rows), so the code has been updated to handle those scenarios.
FYI: I believe the 'Type Mismatch" error is caused when using a 2-dimensional array in the SourceArray parameter. An array created directly from a range (ie: arr = rg.Value) is automatically 2-dimensional, even if it's a single column. Cheers!
Not what you asked, but a macro to delete all sheets except those in the list:
Sub DeleteSomeSheets()
Dim rng As Range
Dim found As Range
Dim i As Long
Application.ScreenUpdating = False
Application.DisplayAlerts = False
On Error GoTo ErrHandler
Set rng = Worksheets("HIDDEN_DEV_SHEET").ListObjects("TableDontDel").DataBodyRange
For i = Worksheets.Count To 1 Step -1
Set found = rng.Find(What:=Worksheets(i).Name, LookAt:=xlWhole)
If found Is Nothing Then
Worksheets(i).Delete
End If
Next i
ExitHandler:
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Exit Sub
ErrHandler:
MsgBox Err.Description, vbExclamation
Resume ExitHandler
End Sub
- LorenzoJan 10, 2024Silver Contributor
I can do what I want with your snippet - Thanks again
For the record I found this before posting:
For Each ws In ActiveWorkbook.Worksheets If UBound(Filter(arr, ws.Name)) = -1 Then ws.Delete Next ws
in https://stackoverflow.com/questions/46326943/how-to-delete-all-sheets-except-those-in-list but I couldn't adapt it - type mistmatch I couldn't resolve 😞
- djclementsJan 10, 2024Silver Contributor
Lorenzo The snippet you found can be applied as follows:
Sub DeleteOtherSheets() Dim tbl As ListObject, arr() As Variant, i As Long Set tbl = ThisWorkbook.Worksheets("HIDDEN_DEV_SHEET").ListObjects(1) ReDim arr(1 To tbl.ListRows.Count) For i = 1 To tbl.ListRows.Count arr(i) = tbl.DataBodyRange(i, 1).Value Next i Dim Item As Worksheet Application.ScreenUpdating = False Application.DisplayAlerts = False On Error Resume Next For Each Item In ThisWorkbook.Worksheets If UBound(Filter(arr, Item.Name)) = -1 Then Item.Delete Next Item Application.DisplayAlerts = True Application.ScreenUpdating = True End Sub
I was working on something similar with arrays, using the Filter function to reduce the list of sheet names upon each iteration by setting the optional Include parameter to False...
Sub DeleteOtherSheets() 'Load all worksheet names into an array Dim sheetList() As Variant, wsCount As Long, i As Long wsCount = ThisWorkbook.Worksheets.Count ReDim sheetList(1 To wsCount) For i = 1 To wsCount sheetList(i) = ThisWorkbook.Worksheets(i).Name Next i 'Remove HIDDEN_DEV_SHEET from the sheet list Dim ws As Worksheet, removeList As Variant Set ws = ThisWorkbook.Worksheets("HIDDEN_DEV_SHEET") removeList = Filter(sheetList, ws.Name, False) 'Remove each name in the table from the sheet list Dim tbl As ListObject, rowCount As Long Set tbl = ws.ListObjects(1) rowCount = tbl.ListRows.Count If rowCount > 0 Then Dim arr As Variant arr = tbl.ListColumns(1).DataBodyRange.Value If rowCount = 1 Then ' single item If Len(arr) > 0 Then removeList = Filter(removeList, arr, False) End If Else ' multiple items For i = LBound(arr, 1) To UBound(arr, 1) If Len(arr(i, 1)) > 0 Then removeList = Filter(removeList, arr(i, 1), False) End If Next i End If End If 'Delete each worksheet in the filtered list On Error Resume Next Application.ScreenUpdating = False Application.DisplayAlerts = False For i = LBound(removeList) To UBound(removeList) ThisWorkbook.Worksheets(removeList(i)).Delete Next i Application.DisplayAlerts = True Application.ScreenUpdating = True End Sub
EDIT: I discovered a few little quirks with this method (ie: if the table contains blank rows), so the code has been updated to handle those scenarios.
FYI: I believe the 'Type Mismatch" error is caused when using a 2-dimensional array in the SourceArray parameter. An array created directly from a range (ie: arr = rg.Value) is automatically 2-dimensional, even if it's a single column. Cheers!
- LorenzoJan 17, 2024Silver Contributor
Hi HansVogelaar & djclements
I finally opted for something similar to:
Sub DeleteOtherSheets() ... ReDim arr(1 To tbl.ListRows.Count) For i = 1 To tbl.ListRows.Count arr(i) = tbl.DataBodyRange(i, 1).Value Next i ... On Error Resume Next For Each Item In ThisWorkbook.Worksheets If UBound(Filter(arr, Item.Name)) = -1 Then Item.Delete Next Item ... End Sub
because it was more appropriate for what I really needed to do and the performance aspect is not a priority for what ultimately needs to be achieved
Many thanks again - Highly appreciated
Cheers guys
- LorenzoJan 10, 2024Silver Contributor
Not exactly what I asked but this does the job 🙂
The actual scenario is a bit more complex, I'll see if I can adapt it on my own...
THANK YOU