Delete sheets if their names belong to an array - arrays

I have a workbook with multiple sheets named like dates e.g 12-01-2015, 12-02-2015, .... etc. I would like to create a code that deletes specific sheets if their names are listed in an array.
I created a code but it does not work. My guess is it is related to incorrect statement listed in line starting with "If".
I would really appreciate any tip where I am going wrong
Sub DeleteSelectedSheets()
Dim i As Long
Dim Holidays() As Variant
Holidays = Array("12-3-2015", "12-4-2015")
For Each Worksheet In ActiveWorkbook
If Worksheet(i).Name = Holidays(i) Then
Application.DisplayAlerts = False
Sheets(i).Delete
Application.DisplayAlerts = True
End If
Next
End Sub

Sub DeleteSelectedSheets()
Dim Holidays As Variant
Holidays = Array("Sheet1", "Sheet3", "Sheet5")
For Each Sheet In ThisWorkbook.Sheets
If UBound(Filter(Holidays, Sheet.Name)) > -1 Then
Application.DisplayAlerts = False
Sheet.Delete
Application.DisplayAlerts = True
End If
Next
End Sub

This should work just fine!
With the exception, that will happen regardless the code you are using, where there is only one sheet left and you are trying to delete it, it'll throw an error message!
See the use of LBound() and UBound() :
Sub DeleteSelectedSheets()
Dim i As Long
Dim Holidays() As Variant
Dim wS As Worksheet
Holidays = Array("12-3-2015", "12-4-2015")
For Each wS In ActiveWorkbook
For i = LBound(Holidays) To UBound(Holidays)
If wS.Name <> Holidays(i) Then
Else
Application.DisplayAlerts = False
wS.Delete
Application.DisplayAlerts = True
Exit For
End If
Next i
Next wS
End Sub

It may be better to simply try and delete the worksheet(s) named in the array. Of course, you will need to operate under an On Error Resume Next to guard against the condition where a worksheet named does not exist.
Sub DeleteSelectedSheets()
Dim h As Long, Holidays() As Variant
Holidays = Array("12-3-2015", "12-4-2015")
On Error Resume Next
Application.DisplayAlerts = False
For h = LBound(Holidays) To UBound(Holidays)
Worksheets(Holidays(h)).Delete
Next h
'alternate delete entire array (they need to be all there, fail on partial)
'Worksheets(Holidays).Delete
Application.DisplayAlerts = True
On Error GoTo 0
End Sub

This seems to work:
Sub DeleteSelectedSheets()
Dim i As Long
Dim Holidays() As Variant
Holidays = Array("12-3-2015", "12-4-2015")
For i = Sheets.Count To 1 Step -1
If Sheets(i).Name = Holidays(0) Or Sheets(i).Name = Holidays(1) Then
Application.DisplayAlerts = False
Sheets(i).Delete
Application.DisplayAlerts = True
End If
Next
End Sub

Related

Copy Iteration Issue

The script below triggers every couple milliseconds due to the Worksheet Calculate event and then copies from my Pivot Table to the Chart Helper. Script works great but when it copies the next iteration of data it pastes it after the original data set it just copied.
I need it to continuously paste over the original data set. Example if the original data set copies to A1:A15 I want it to replace A1:A15 not keep A1:A15 then add the new refreshed data set to A16:A30.
I suspect this line is the culprit Offset(1).Resize(.Rows.Count, .Columns.Count).Value = .Value
Private Sub Worksheet_Calculate()
If Not Worksheets("Dashboard").ToggleButton1.Value Then Exit Sub
Dim chPivot As PivotCache
On Error GoTo SafeExit
Application.EnableEvents = False
Application.ScreenUpdating = False
For Each chPivot In ActiveWorkbook.PivotCaches
chPivot.Refresh
Next chPivot
With ThisWorkbook.Sheets("Data Breakdown").PivotTables("PivotTable1").PivotFields("Price").DataRange
ThisWorkbook.Sheets("Chart Helper").Cells(Rows.Count, 1).End(xlUp). _
Offset(1).Resize(.Rows.Count, .Columns.Count).Value = .Value
With ThisWorkbook.Sheets("Data Breakdown").PivotTables("PivotTable1").PivotFields("Cost").DataRange
ThisWorkbook.Sheets("Chart Helper").Cells(Rows.Count, 2).End(xlUp). _
Offset(1).Resize(.Rows.Count, .Columns.Count).Value = .Value
End With
End With
SafeExit:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Assuming your data either gets larger or stays the same size then you just always need to paste data into the exact same cell to overwrite prior pastes.
i.e. replace .Cells(Rows.Count, 1).End(xlUp).Offset(1) with Range("A1")
You also need to separate your with statements. It can become ambiguous which object is being referenced when many are nested. Lastly, remove the column resize. You only need to resize the row here.
Your code could also be cleaned up a little by creating some Worksheet variables
Private Sub Worksheet_Calculate()
If Not Worksheets("Dashboard").ToggleButton1.Value Then Exit Sub
Dim db As Worksheet: Set db = ThisWorkbook.Sheets("Data Breakdown")
Dim ch As Worksheet: Set ch = ThisWorkbook.Sheets("Chart Helper")
Dim chPivot As PivotCache
On Error GoTo SafeExit
Application.EnableEvents = False
Application.ScreenUpdating = False
For Each chPivot In ActiveWorkbook.PivotCaches
chPivot.Refresh
Next chPivot
'Value transfer 'PRICE' to A1
With db.PivotTables("PivotTable1").PivotFields("Price").DataRange
ch.Range("A1").Resize(.Rows.Count).Value = .Value
End With
'Value transfer 'COST' to B1
With db.PivotTables("PivotTable1").PivotFields("Cost").DataRange
ch.Range("B1").Resize(.Rows.Count).Value = .Value
End With
SafeExit:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub

How can I have excel go down a list and check for certain conditions?

This is code the internet and I came up with. Please could you tell me what I’m doing wrong? I keep getting an error that says “can’t use a loop without a do”
Sub additions ()
Range(“BI1”) = “Comments”
Range(“V2”).Select
Do until IsEmpty(ActiveCell)
If (Range(ActiveCell) = “DM”) Then
ActiveCell.Offset(0,39).Select
Range(ActiveCell) = “Developed Markets”
ActiveCell.Offset(1,-39).Select
End If
Loop
End Sub
Add String to One Column If Another String in Another Column
Option Explicit
Sub Additions()
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
Dim srg As Range
Set srg = ws.Range("V2", ws.Cells(ws.Rows.Count, "V").End(xlUp))
Dim drg As Range: Set drg = srg.EntireRow.Columns("BI")
ws.Range("BI1").Value = "Comments"
Dim sCell As Range
Dim r As Long
For Each sCell In srg.Cells
r = r + 1
If CStr(sCell.Value) = "DM" Then ' is a match
drg.Cells(r).Value = "Developed Markets"
'Else ' is not a match; do nothing
End If
Next sCell
MsgBox "Additions finished.", vbInformation
End Sub

VBA Copy sheets to new workbook - with/without formulas

I use this code to copy 4 sheets to separate workbook. One of them - "1" have formulas inside, method below skips those formulas. Any ideas how to keep three workbook's as value only and one - "1" including the formulas? Part of code responsible for that action below. Thank you in advance.
Sub test()
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Dim Fname As String, ws As Worksheet
Dim InitFileName As String, fileSaveName As String
Fname = Sheets("STRUCTURE").Range("A1").Value
Sheets(Array("STRUCTURE", "2", "3", "1")).Copy
For Each ws In ActiveWorkbook.Worksheets
With ws.UsedRange
.Value = .Value
End With
Next ws
With ActiveWorkbook
fileSaveName = "FILE LOCATION FOLDER " & Sheets("STRUCTURE").Cells(1, 1) & ".xlsx"
.SaveAs fileSaveName
.Close
End With
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
This is what is changing formulas to values:
With ws.UsedRange
.Value = .Value
End With
You have several options to skip the worksheet in question:
Skip the worksheet named 1.
For Each ws In ActiveWorkbook.Worksheets
If ws.Name <> "1" Then
With ws.UsedRange
.Value = .Value
End With
End If
Next
Only loop over the worksheets in question:
Dim sheetNamesToProcess As Variant
sheetNamesToProcess = Array("STRUCTURE", "2", "3")
Dim i As Long
For i = Lbound(sheetNamesToProcess) To Ubound(sheetNamesToProcess)
With ActiveWorkbook.Worksheets(sheetNamesToProcess(i)).UsedRange
.Value = .Value
End With
Next

Passing an array to subroutine VBA

I'm working on a macro for excel and have a sub that passes an array to another sub, but I keep getting
Run time error '9'
Subscript out of range
below is my code and I left a comment pointing to where this error is occurring. I'm new to VBA so it's possible I'm trying to pass an array incorrectly not sure though.
'Main Driver
Sub Main()
WorkbookSize = size() 'Run function to get workbook size
newbook = False
Call create 'Run sub to create new workbook
Call pull(WorkbookSize) 'Run sub to pull data
End Sub
'Get size of Worksheet
Function size() As Integer
size = Cells(Rows.Count, "A").End(xlUp).Row
End Function
'Create workbook
Sub create()
Dim wb As Workbook
Set wb = Workbooks.Add
TempPath = Environ("temp")
With wb
.SaveAs Filename:=TempPath & "EDX.xlsm" _
, FileFormat:=xlOpenXMLWorkbookMacroEnabled, CreateBackup:=False
.ChangeFileAccess Mode:=xlReadOnly, WritePassword:="admin"
End With
End Sub
'pull data
Sub pull(size)
Dim code() As Variant
For i = 1 To size
'Check code column fo IN and Doctype column for 810
If Cells(i, 18).Value = "IN" Then
code(i) = Cells(i, 18).Value 'store in array
End If
Next i
Call push(code)
End Sub
'push data to new workbook
Sub push(ByRef code() As Variant)
activeBook = "TempEDX.xlsm"
Workbooks(activeBook).Activate 'set new workbook as active book
For i = 1 To UBound(code) ' <---here is where the error is referencing
Cells(i, 1).Value = code(i)
Next i
End Sub
Any help is appreciated.
You're problem is that you don't correctly initialize the code array.
Do so using Redim See the modification below:
'pull data
Sub pull(size)
Dim code() As Variant
Redim code(size-1) '<----add this here minus 1 because 0 index array
For i = 1 To size
'Check code column fo IN and Doctype column for 810
If Cells(i, 18).Value = "IN" Then
code(i-1) = Cells(i, 18).Value 'store in array subtract 1 for 0 index array
End If
Next i
Call push(code)
End Sub
Also, you'll need to update your Push method's code to accommodate the 0-indexed array
'push data to new workbook
Sub push(ByRef code() As Variant)
activeBook = "TempEDX.xlsm"
Workbooks(activeBook).Activate 'set new workbook as active book
For i = 0 To UBound(code) ' <0 to ubound
Cells(i+1, 1).Value = code(i) 'add 1 to i for the cells reference
Next i
End Sub
I will add these other points
You are also working with Rows but have Integer as a return for a function risking overflow
e.g.
Function size() As Integer
Change to a Long.
You have lots of implicit activesheet references. Get rid of those and give a parent sheet. For example, you could set the sheet in a variable called ws and pass, if required, as a parameter.
E.g.
Public Function size(ByVal ws As Worksheet) As Long
With ws
size = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
End Function
As mentioned, put Option Explicit at the top of your code and declare all your variables.

How can I automate populating an array using a named range on a specific worksheet?

The named range is SheetNames, on a worksheet named Consolidation, cell B3 to B101 and the array is Sheets(Array("Sheet1", "Sheet2")).Select:
Sub Insert_Formula()
Dim ws As Worksheet
Application.ScreenUpdating = False
Sheets(Array("Sheet1", "Sheet2")).Select
For Each ws In ActiveWindow.SelectedSheets
ws.Range("F3:F50").Formula = "=SUMIFS(Jul!$K:$K,Jul!$H:$H,$C$1,Jul!$J:$J,$C3)"
Next ws
Application.ScreenUpdating = True
End Sub
Hopefully this answers your question. If you are looking to iterate through every sheet in your workbook, instead of explicitly calling out their names you can just use
Sub Insert_Formula()
Application.ScreenUpdating = false
For Each ws In ActiveWorkbook.Sheets
ws.Range("F3:F50").Formula = "=SUMIFS(Jul!$K:$K,Jul!$H:$H,$C$1,Jul!$J:$J,$C3)"
Next
Application.ScreenUpdating = True
End Sub
Alternatively if you want to use the specific sheet name you specified with the worksheet names you can try this
Sub Insert_Formula()
For Each cell In Range("sheetNames")
Sheets(cell.Text).Range("F3:F50").Formula = "=SUMIFS(Jul!$K:$K,Jul!$H:$H,$C$1,Jul!$J:$J,$C3)"
Next
End Sub

Resources