Delete Excel worksheets if not in array - vba

I am having problem to solve the error "time execution error #13: incompatible type". If user creates some worksheet that is not stated in the array, it will be deleted. Can anyone help?
sub DeleteNewSheets()
Dim ws, wsP As Worksheet
Dim ArrayOne As Variant
Application.DisplayAlerts = False
ArrayOne = Array("SheetA", "SheetB", "SheetC", "Sheet_n")
Set wsP = ThisWorkbook.Worksheets(ArrayOne) ' <--- ERROR #13
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> wsP.Name Then ws.Delete
Next ws
Application.DisplayAlerts = True
end sub

Your line of code saying:
Set wsP = ThisWorkbook.Worksheets(ArrayOne)
is trying to set a Worksheet object to an array of many Worksheets. That's like trying to set a single Integer to be an array of Integers.
Try using the following code
Sub DeleteNewSheets()
Dim ws As Worksheet
Dim ArrayOne() As Variant
Dim wsName As Variant
Dim Matched As Boolean
ArrayOne = Array("SheetA", "SheetB", "SheetC", "Sheet_n")
Application.DisplayAlerts = False
For Each ws In ThisWorkbook.Worksheets
Matched = False
For Each wsName In ArrayOne
If wsName = ws.Name Then
Matched = True
Exit For
End If
Next
If Not Matched Then
ws.Delete
End If
Next ws
Application.DisplayAlerts = True
End Sub

If you add an extra For ... Next or For Each ... Next statement to loop through every element in ArrayOne and conditional IFs statement then it should do the work. So your code should be like this
Sub DeleteNewSheets()
Dim ws As Worksheet
Dim ArrayOne As Variant, iSheet As Integer
Application.DisplayAlerts = False
ArrayOne = Array("SheetA", "SheetB", "SheetC", "Sheet_n")
For Each ws In ThisWorkbook.Worksheets
For iSheet = LBound(ArrayOne) To UBound(ArrayOne)
If ws.Name = ArrayOne(iSheet) Then Exit For
If iSheet = UBound(ArrayOne) Then
ws.Delete
End If
Next
Next
Application.DisplayAlerts = True
End Sub
or alternatively
Sub DeleteNewSheets()
Dim ws As Worksheet
Dim ArrayOne As Variant
Application.DisplayAlerts = False
ArrayOne = Array("SheetA", "SheetB", "SheetC", "Sheet_n")
For Each ws In ThisWorkbook.Worksheets
For Each Element In ArrayOne
If ws.Name = Element Then Exit For
If Element = ArrayOne(UBound(ArrayOne)) Then
ws.Delete
End If
Next
Next
Application.DisplayAlerts = True
End Sub

you can check sheets in one loop and delete "bad" ones in one shot as follows:
Option Explicit
Sub DeleteNewSheets()
Dim ws As Worksheet
Dim sheetsToDelete As String
Const GOODSHEETS As String = "\SheetA\SheetB\SheetC\Sheet_n\" '<--| list of good sheets names, separated by an invalid character for sheet names
For Each ws In ThisWorkbook.Worksheets
If InStr(GOODSHEETS, "\" & ws.Name & "\") = 0 Then sheetsToDelete = sheetsToDelete & ws.Name & "\" '<--| update sheets to be deleted list
Next ws
If sheetsToDelete <> "" Then '<--| if the list is not empty
sheetsToDelete = Left(sheetsToDelete, Len(sheetsToDelete) - 1) '<--| remove last delimiter ("\") from it
Application.DisplayAlerts = False
ThisWorkbook.Worksheets(Split(sheetsToDelete, "\")).Delete '<-- delete sheets
Application.DisplayAlerts = True
End If
End Sub

Related

Adding array to sheet names

I am using the below code to retain sheets that I need and delete the rest.
Sub DeleteSheets1()
Dim xWs As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each xWs In Application.ActiveWorkbook.Worksheets
If xWs.Name <> "Sheet1" And xWs.Name <> "Sheet2" Then
xWs.Delete
End If
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
I have around 6 sheets that I want to retain. I need help modifying the syntax to accommodate multiple sheets. Something like below
if xWs.Name <> ("sheet1", "sheet2"....) then xws.delete
Here arr is an array of the sheets to retain:
Sub DeleteSheets1()
Dim xWs As Worksheet, s As String, i As Long
Dim skp As Boolean
arr = Array("Sheet1", "Sheet2", "Sheet3")
Application.ScreenUpdating = False
Application.DisplayAlerts = False
n = ActiveWorkbook.Worksheets.Count
For i = n To 1 Step -1
s = Sheets(i).Name
skp = False
For Each a In arr
If s = a Then skp = True
Next a
If Not skp Then Sheets(i).Delete
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
The valueInArray boolean function could work the code easier:
Public Function valueInArray(myValue As Variant, myArray As Variant) As Boolean
Dim cnt As Long
For cnt = LBound(myArray) To UBound(myArray)
If CStr(myValue) = CStr(myArray(cnt)) Then
valueInArray = True
Exit Function
End If
Next cnt
End Function
Sub DeleteSheets()
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Dim cnt As Long
cnt = Worksheets.Count
Dim arrWks As Variant
arrWks = Array("Sheet1", "Sheet2", "Sheet3")
For cnt = Worksheets.Count To 1
If Not valueInArray(Worksheets(cnt).Name, arrWks) Then
Worksheets(cnt).Delete
End If
Next cnt
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
The valueInArray function gets value to search for myValue and array where to search for this value myArray. It loops through all elements of the array and if it finds the same String of the passed value, it returns True and exits. If it is not found, it returns False, as this is the default.
Another approach
Sub Test()
Dim ws As Worksheet
Dim arr As Variant
arr = Array("Sheet1", "Sheet2", "Sheet3")
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each ws In ThisWorkbook.Worksheets
If Not IsNumeric(Application.Match(ws.Name, arr, 0)) Then ws.Delete
Next ws
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Ok, this one doesn't quite fulfil the requirement of an array, but it's another way of using a single loop.
It looks for an occurrence of the sheet name in the RetainSheets string. Each sheet name is surrounded by | just in case there's a sheet name within a sheet name eet1Sh as an example.
The code will not attempt to delete the last worksheet in the workbook either.
Sub Test()
Dim wrkSht As Worksheet
Dim RetainSheets As String
RetainSheets = "|Sheet1|Sheet2|"
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each wrkSht In Worksheets
If InStr(RetainSheets, wrkSht.Name) = 0 And Worksheets.Count > 1 Then
wrkSht.Delete
End If
Next wrkSht
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

Deleting specific sheets and those which do not meet a criteria

I have a macro where I create a number of sheets that take their names from the values in column c, cell 7 onwards in a sheet called "Schedule". I am using the following code for that
Sub CreateDataSheets()
'Updateby Extendoffice 20161215
Dim xRg As Variant
Dim wSh As Excel.Worksheet
Dim wBk As Excel.Workbook
Set wSh = ActiveSheet
Set wBk = ActiveWorkbook
Application.ScreenUpdating = False
For Each xRg In wSh.Range("C7", Range("C7").End(xlDown))
If Not IsError(xRg) Then
If xRg <> "" Then
If Not WorksheetExists((xRg)) Then
With wBk
.Sheets.Add after:=.Sheets(.Sheets.Count), Type:="L:\London\General\Reference & Tools\Software\BIM\IiA_Specifications\Excel\Uk Specification Template.xltx"
ActiveSheet.Name = xRg.Value
End With
End If
End If
End If
Next xRg
Application.ScreenUpdating = True
End Sub
Now I need another Macro where if I change or delete any of these values in Column C, I want to create new updated ones and delete all the sheets that are redundant. While doing this, I want to retain the sheets called Schedule, Home and CoverSheet. Below is the code I tried to write but that would not work.
Sub DeleteNewSheets()
Dim ws As Worksheet
Dim ArrayOne() As Variant
Dim wsName As Variant
Dim Matched As Boolean
Dim DirArray As Variant
DirArray = Range("C7:C11")
ArrayOne = Array("Home", "Schedule", "CoverSheet", DirArray.Value)
Application.DisplayAlerts = False
For Each ws In Sheets
Matched = False
For Each wsName In ArrayOne
If wsName = ws.Name Then
Matched = True
Exit For
End If
Next
If Not Matched Then
ws.Delete
End If
Next ws
Application.DisplayAlerts = True
End Sub
Would really appreciate any ideas...
DirArray is beeing created as a Variant and the position 4 of your Array ArrayOne is actually another array and not a string.
To fix it, initialize the ArrayOne just like this:
ArrayOne = Array("Home", "Schedule", "CoverSheet")
Dim Name As Variant
For Each Name In DirArray
If Name <> "" Then
ReDim Preserve ArrayOne(UBound(ArrayOne) + 1)
ArrayOne(UBound(ArrayOne)) = Name
End If
Next
It will also not consider empty values on the range you selected.
Consider changing your removing steps as on Sam's answer
Iterating over a changing set is often a bad idea. Do something like this instead
For i = Sheets.Count to 1 Step -1
If ....
Sheets(i).Delete
End If
Next i

Vlookup on external workbook VBA

I don't know how it isn't working.
I have my active workbook. I want to run macros from active sheet.
1. I want to add 2 more columnes with headers . - works
2. I want to open external file, which is base in my vloop. - works
3. I want to use vloop to find my variable from active sheet in external workbook and save result in my active sheet
Sub ImpFPQ()
Application.ScreenUpdating = False
On Error Resume Next
Dim Imp_Row As Integer
Dim Imp_Col As Integer
Dim Baza1 As Workbook
Dim Baza2 As Workbook
Dim wksheet As Worksheet
Dim plik As Variant
Set wksheet = ActiveWorkbook.ActiveSheet
'add columns with names
wksheet.Columns("A:B").Insert Shift:=xlToRight
wksheet.Columns("A").Cells(1, 1) = "KOD"
wksheet.Columns("B").Cells(1, 1) = "LICZNIK"
'open file
plik = Application.GetOpenFilename(Title:="Wybierz raport")
If plik = False Then Exit Sub
Workbooks.Open Filename:=plik
Set Baza1 = ThisWorkbook 'activesheet
Set Baza2 = Workbooks(plik) 'external workbook
Set lastel = Baza2.Range("F3", Range("F3").End(xlDown)).Select
Set lookFor = Baza1.Cells(2, 4) 'aktualny subsyst do znalezienia
Set srchRange = Baza2.Sheets(1).Range("A3:lastel")
Range("A2").Value = Application.VLookup(lookFor, srchRange, 6, False)
Application.ScreenUpdating = True
MsgBox "Done!"
End Sub
I have these columns, but rows dont have results. Can someone help me?
This should do the trick.
Sub ImpFPQ()
Application.ScreenUpdating = False
On Error Resume Next
Dim Imp_Row As Integer
Dim Imp_Col As Integer
Dim Baza1 As Workbook
Dim Baza2 As Workbook
Dim wksheet As Worksheet
Dim plik As Variant
Dim lastRow As Long
Dim lookfor As Variant
Dim srchRange As Range
Set wksheet = ActiveWorkbook.ActiveSheet
'add columns with names
wksheet.Columns("A:B").Insert Shift:=xlToRight
wksheet.Columns("A").Cells(1, 1) = "KOD"
wksheet.Columns("B").Cells(1, 1) = "LICZNIK"
'open file
plik = Application.GetOpenFilename(Title:="Wybierz raport")
If plik = False Then Exit Sub
Workbooks.Open Filename:=plik
Set Baza1 = ThisWorkbook 'activesheet
Set Baza2 = Workbooks.Open(plik) 'external workbook
With Baza2.Sheets(1)
lastRow = .Cells(.Rows.Count, 6).End(xlUp).Row
End With
lookfor = Baza1.Cells(2, 4) 'aktualny subsyst do znalezienia
Set srchRange = Baza2.Sheets(1).Range("A3:F" & lastRow)
Range("A2").Value = Application.VLookup(lookfor, srchRange, 6, False)
Application.ScreenUpdating = True
MsgBox "Done!"
End Sub
Change this:
If plik = False Then Exit Sub
Workbooks.Open Filename:=plik
Set Baza1 = ThisWorkbook 'activesheet
Set Baza2 = Workbooks(plik) 'external workbook
To this:
If plik = False Then Exit Sub
Set Baza2 = Workbooks.Open(Filename:=plik)
Set Baza1 = ThisWorkbook 'activesheet
since plik is giving you a full filename (including a path) I don't think it can be used as an index for the Workbooks collection
See here: https://msdn.microsoft.com/en-us/vba/excel-vba/articles/workbook-object-excel

excel sheet creation and update

I am looking for a way to create sheets in excel based on a list of cells
problem I have is that I would like the script to check if the list was updated and add the additional sheets and not re create all or delete the old copies
1) is it possible from excel (non VBA)
2) if not the code i have for creating a sheet is :
but it will create new entrys if I re-run (and I am looking for update)
Sub AddSheets()
'Updateby Extendoffice 20161215
Dim xRg As Excel.Range
Dim wSh As Excel.Worksheet
Dim wBk As Excel.Workbook
Set wSh = ActiveSheet
Set wBk = ActiveWorkbook
Application.ScreenUpdating = False
For Each xRg In wSh.Range("A1:A7")
With wBk
.Sheets.Add after:=.Sheets(.Sheets.Count)
On Error Resume Next
ActiveSheet.Name = xRg.Value
If Err.Number = 1004 Then
Debug.Print xRg.Value & " already used as a sheet name"
End If
On Error GoTo 0
End With
Next xRg
Application.ScreenUpdating = True
End Sub
Here's another option. I also added a part where it'll name the sheet the column A value. (You can remove that if needed).
Sub AddSheets()
'Updateby Extendoffice 20161215
Dim xRg As Excel.Range
Dim wSh As Excel.Worksheet
Dim wBk As Excel.Workbook
Set wSh = ActiveSheet
Set wBk = ActiveWorkbook
Application.ScreenUpdating = False
For Each xRg In wSh.Range("A1:A7")
With wBk
If Not sheetExists(xRg.Value) and xRg <> "" Then
.Sheets.Add after:=.Sheets(.Sheets.Count)
ActiveSheet.Name = xRg.Value
End If
End With
Next xRg
Application.ScreenUpdating = True
End Sub
Function sheetExists(sheetToFind As String) As Boolean
'http://stackoverflow.com/a/6040454/4650297
Dim sheet As Worksheet
sheetExists = False
For Each sheet In Worksheets
If sheetToFind = sheet.Name Then
sheetExists = True
Exit Function
End If
Next sheet
End Function
Use this function to check if the worksheet already exists, then let it skip over it.
Function WorksheetExists(sName As String) As Boolean
WorksheetExists = Evaluate("ISREF('" & sName & "'!A1)")
End Function
So your code can be:
Sub AddSheets()
'Updateby Extendoffice 20161215
Dim xRg As Variant
Dim wSh As Excel.Worksheet
Dim wBk As Excel.Workbook
Set wSh = ActiveSheet
Set wBk = ActiveWorkbook
Application.ScreenUpdating = False
For Each xRg In wSh.Range("A1:A7")
If Not IsError(xRg) Then
If xRg <> "" Then
If Not WorkSheetExists((xRg)) Then
With wBk
.Sheets.Add after:=.Sheets(.Sheets.Count)
ActiveSheet.Name = xRg.Value
End With
End If
End If
End If
Next xRg
Application.ScreenUpdating = True
End Sub
Function WorksheetExists(sName As String) As Boolean
WorksheetExists = Evaluate("ISREF('" & sName & "'!A1)")
End Function

If statement to delete tab if there but move on if page is not there

I have a code that deletes a tab in the worksheet then runs another code. I am currently running into an issue that if the sheet is not there the code gives me an error... I'm wondering if I could make an if statement that looks if the tab is there and if not it moves on and if it is there it will delete it. I have the code that I have written already posted below but I have no idea how to do the if in the delete section.
Thanks!
Sub delete()
Dim ws As Worksheet
Set ws = Worksheets("Workbench Report")
Application.DisplayAlerts = False
ws.delete
Call Sorting
End Sub
Check if the sheet exists first:
Sub delete()
Dim ws As Worksheet
If WorksheetExists("Workbench Report") Then
Set ws = Worksheets("Workbench Report")
Application.DisplayAlerts = False
ws.delete
Call Sorting
End If
End Sub
Public Function WorkSheetExists(SheetName As String, Optional WrkBk As Workbook) As Boolean
Dim wrkSht As Worksheet
If WrkBk Is Nothing Then
Set WrkBk = ThisWorkbook
End If
On Error Resume Next
Set wrkSht = WrkBk.Worksheets(SheetName)
WorkSheetExists = (Err.Number = 0)
Set wrkSht = Nothing
On Error GoTo 0
End Function
Try this
Sub delete()
Dim i As Integer
i = 1
Application.DisplayAlerts = False
While i <= ActiveWorkbook.Worksheets.Count
Sheets(i).Select
If ActiveSheet.Name = "Workbench Report" Then
ActiveSheet.delete
End If
i = i + 1
Wend
Call Sorting
Application.DisplayAlerts = True
End Sub