Loop through worksheets with a specific name - vba

Say I have 10 worksheets and 4 have very similar names:
1.danger tom
2.danger man
3.danger ten
4.danger lan
I want my code to find all worksheets with the text string danger in its name and execute my code
I've tried the following two instances:
Public Sub SubName()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
If ws.Name Like "danger" Then
*Also tried this version: If ws.Name Like "danger" = True Then*
Range("A1").Interior.ColorIndex = 37
End If
Next ws
End Sub
take 2
Sub WorksheetLoop()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
If InStr("danger", ws.Name) > 0 Then
Range("A1").Interior.ColorIndex = 37
End If
Next ws
End Sub
The first code doesn't do anything, even though there's no errors. The second code only does something if the name matches exactly with what I wrote down.
Any help is needed.

I'm pretty sure you just need to add in explicitly which worksheets you're using.
Public Sub SubName()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
If ws.Name Like "danger" Then
' *Also tried this version: If ws.Name Like "danger" = True Then*
ws.Range("A1").Interior.ColorIndex = 37
End If
Next ws
End Sub
Sub WorksheetLoop()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
If InStr("danger", ws.Name) > 0 Then
ws.Range("A1").Interior.ColorIndex = 37
End If
Next ws
End Sub
It's a simple fix (all I did was add ws. before each Range()), but very important when working with multiple sheets. Always be explicit when using multiple ranges. If you were using Cells(), Row(),Column(), etc. you should add the worksheet you're using as well.
An alternative layout is using With (see below for example with your SubName() routine):
Public Sub SubName()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
With ws
If .Name Like "danger" Then
' *Also tried this version: If ws.Name Like "danger" = True Then*
.Range("A1").Interior.ColorIndex = 37
' For illusatration, this will color the range A1:B10
' .Range(.Cells(1,1),.Cells(10,2)).Interior.ColorIndex = 37
End If
End with
Next ws
End Sub
Notice that using With allows you to just use a "placeholder" . to refer to the WS (or whatever follows With). See the line I added that uses Range(Cells(),Cells()) for a good example of this.
Edit: Using If ws.Name like "danger" Then will only run on sheets named danger (lowercase, no spaces). If you want this to work on sheets named like DangerMouse, DangerDoom, Carlos Danger, then you'll need to use ... Like "*danger*" Then

I think Your first code will work if you change this:
If ws.Name Like "danger" Then
*Also tried this version: If ws.Name Like "danger" = True Then*
Range("A1").Interior.ColorIndex = 37
End If
to this :
If ws.Name Like "danger" & "*" Then
ws.Range("A1").Interior.ColorIndex = 37
End If
and simply you can use "danger*".

Or without looping
Sub GetSheets()
Dim strIn As String
Dim X, xArr
strIn = Application.InputBox("Search string", "Enter string to find", "*List*", , , , , 2)
If strIn = "False" Then Exit Sub
ActiveWorkbook.Names.Add "shtNames", "=RIGHT(GET.WORKBOOK(1),LEN(GET.WORKBOOK(1))-FIND(""]"",GET.WORKBOOK(1)))"
X = Filter([index(shtNames,)], strIn, True, 1)
For Each xArr In X
Sheets(xArr).Range("A1").Interior.ColorIndex = 37
Next
End Sub

Add an asterisk * before the like name. e.g. .Name Like "*danger"
Asterisk * is the wildcard for Excel

Related

Display all available sheets in combobox, except the hidden ones, (loop through sheets add to list) VBA

Okay genius hive mind, what am I doing wrong this time?
'wb and ws dimmed in module level declarations...
Set wb = ThisWorkbook
wb.activate
Dim I As Integer, sheetCount As Integer
sheetCount = wb.Worksheets.Count
Dim sheetNum As Integer
sheetNum = 1
With cboCopyFromSheet 'combobox
For I = 0 To sheetCount - 1
'not sure why the capital 'I' describing an object?
'copied from MS documentation
If wb.Worksheets(sheetNum).Visible = True Then
.AddItem wb.Worksheets(sheetNum).Name, I '<----Error
End If
sheetNum = sheetNum + 1
Next I
End With
Weirdly this only happens when I = 9 and sheetnum = 10
None of the sheets are currently hidden ( but some will be )
sheet 10 happens to be a blank sheet...
We are very confucius.
Error thrown is "invalid argument"
Any Clues?
A similar approach to Fane's answer, using the For Each statement.
Sub Whatever()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Visible Then combo.AddItem ws.Name
Next
End Sub
Try the next (simple) code, please. Creating the habit to use combobox List property, will be helpful when you will need to rapidly load a big range (multi-columns, too):
Sub testLoadComboSheetsNames()
Dim sh As Worksheet, arrSh As Variant, k As Long
ReDim arrSh(1 To ThisWorkbook.Worksheets.count)
For Each sh In ThisWorkbook.Worksheets
If sh.Visible = True Then k = k + 1: arrSh(k) = sh.Name
Next
ReDim Preserve arrSh(k)
cboCopyFromSheet.list = arrSh
End Sub
In order to work, your code must look like the next:
Sub testLoadComboShbis()
Dim i As Long, wb As Workbook
Set wb = ThisWorkbook
For i = 1 To wb.Worksheets.count
If wb.Worksheets(i).Visible = True Then
cboCopyFromSheet.AddItem wb.Worksheets(i).Name
End If
Next i
End Sub

How to loop through only the worksheets included in a list?

I am trying to use VBA to loop through worksheets in my file but only those that are included in a list on a control worksheet, e.g.
Worksheet List
When I try to look up the worksheet name in this list, it does not recognise the worksheet name as a string.
Current code below:
I create a function to vlookup on the list:
Public Function IsInRunList(WsName As Variant, RunList As Range) As Boolean
If Application.VLookup(WsName, RunList, 1, False) = WsName Then
IsInRunList = True
End If
End Function
Then I call this function in my subroutine:
Dim Ws As Worksheet
For Each Ws In ThisWorkbook.Worksheets
If IsInRunList(Ws.Name, Range("Run_List").Columns(j)) Then
I get a mismatch error for Ws.Name here.
Any ideas?
Thanks.
Try the next approach, please:
Sub iterateBetweenSheetInList()
Dim sh As Worksheet
For Each sh In ActiveWorkbook.Worksheets
Select Case sh.Name
Case "Sheet1", "Sheet2", "Sheet4", "Sheet7"
Debug.Print sh.UsedRange.Rows.Count
'your code can do here whatever you need...
End Select
Next
End Sub
Or a version to take the sheets name from a range (in column X:X in the code example). You did not show us in which column the sheets list exists:
Sub iterateBetweenSheetInListBis()
Dim sh As Worksheet, ws As Worksheet, arrSh As Variant, El As Variant
Set sh = ActiveSheet
'adapt the next range with the lettr of your column where the sheets name exists:
arrSh = sh.Range("X2:X" & sh.Range("X" & Rows.Count).End(xlUp).row).Value
For Each El In arrSh
Set ws = Worksheets(El)
Debug.Print ws.UsedRange.Rows.Count
'do here whatever you need...
Next
End Sub
Application.VLookup returns a Range when successful and an error if not (same behavior as in Excel). An error is not a string, it's a special type that you can check with IsError.
Change your checking routine to something like:
Public Function IsInRunList(WsName As Variant, RunList As Range) As Boolean
Dim res As Variant
res = Application.VLookup(WsName, RunList, 1, False)
IsInRunList = Not IsError(res)
End Function

VBA For Loop Only Altering One Sheet

I'm trying to alter the values in a range of cells for specifically named worksheets only.
The workbook I am editing has around 95 sheets, and I only want to change the sheets with the period actual information (named P1W1, P1W2 etc, up to P12W5).
When i execute the below it only alters the first sheet and then exits the macro.
Any help is much appreciated
Option Explicit
Public Sub periodclear()
Dim ws As Worksheet
Dim r As Range
On Error Resume Next
Set r = Range("c10:i30")
For Each ws In Worksheets
If ws.Name Like ("P#W#") Or ws.Name Like ("P##W#") Then
r.Value = ""
End If
Next ws
End Sub
Try this. Your r was defined only in terms of one sheet so needs to be brought inside the loop.
Public Sub periodclear()
Dim ws As Worksheet
For Each ws In Worksheets
If ws.Name Like ("P#W#") Or ws.Name Like ("P##W#") Then
ws.Range("c10:i30").ClearContents
End If
Next ws
End Sub

Deleting Specific Worksheets

I am attempting to delete all worksheets in my workbook except for the two titled: "main" and "dataset". My current code seems to simply delete the last two worksheets.
Option Explicit
Option Base 1
Public Sub DeleteWS()
Dim mySheet As String, mySheet2 As String, ws As Worksheet
mySheet = "main"
mySheet2 = "Dataset"
For Each ws In Worksheets
If ws.Name <> mySheet Or ws.Name <> mySheet2 Then
ActiveWindow.SelectedSheets.Delete
Else
Exit Sub
End If
Next
End Sub
Change this line:
ActiveWindow.SelectedSheets.Delete
to this:
ws.Delete
to fix your If statement
Use And in your If, not Or
and keep in mind that capitalization and extra spaces both matter too in a comparison like that.
I would use something more like this:
If Trim$(UCase$(ws.Name)) <> Trim$(UCase$(mySheet)) And _
Trim$(UCase$(ws.Name)) <> Trim$(UCase$(mySheet2)) Then
You could also go like this:
Option Explicit
Option Base 1
Public Sub DeleteWS()
Dim ws As Worksheet
For Each ws In Worksheets
If InStr(ws.Name, “main,Dataset”) = 0 Then ws. Delete
Next
End Sub

VBA Code to cycle through worksheets starting with a specific sheet (index 3)

I need to cycle through sheets of index 3 tip last sheet and run a code. I tried something like this but its doesn't work.
If (ws.sheetIndex > 2) Then
With ws
'code goes here
End With
End If
I did a search but don't find a solution to this problem. Help would be much appreciated.
I also tried:
Dim i As Long, lr As Long
Dim ws As Worksheet
Windows("Book1").Activate
With ActiveWorkbook
Set ws = .Worksheets("index")
For i = 3 To 10
'code goes here
Next i
End With
You can try the following, which iterates over all worksheets in your workbook and only "acts" for worksheets with index 3 or above.
Dim sheet As Worksheet
For Each sheet In ActiveWorkbook.Worksheets
If sheet.Index > 2 Then
' Do your thing with each "sheet" object, e.g.:
sheet.Cells(1, 1).Value = "hi"
End If
Next
Note that this doesn't put a hard limit on the number of sheets you have (10 or whatever), as it will work with any number of worksheets in your active workbook.
EDIT
If you want the code to run on worksheets with names "Sheet" + i (where i is an index number from 3 onwards), then the following should help:
Dim sheet As Worksheet
Dim i As Long
For i = 3 To ActiveWorkbook.Worksheets.Count
Set sheet = ActiveWorkbook.Worksheets(i)
If sheet.Name = "Sheet" & i Then
' Do your thing with each "sheet" object, e.g.:
sheet.Cells(2, 2).Value = "hi"
End If
Next i
Of course, this means that the names of your worksheets need to always follow this pattern, so it's not best practice. However, if you're sure the names are going to stay like this, then it should work well for you.
Try excluding first and second sheet using name:
Public Sub Sheets3andUp()
Dim ws As Worksheet
Dim nameOfSheet1 As String
Dim nameOfSheet2 As String
nameOfSheet1 = "Sheet1"
nameOfSheet2 = "Sheet2"
For Each ws In ActiveWorkbook.Worksheets
If ws.Name <> nameOfSheet1 And ws.Name <> nameOfSheet2 Then
'Code goes here
Debug.Print ws.Name
End If
Next ws
End Sub
Note that the user can reorder the sheets in the Worksheets Collection, so it is better to refer to the sheets by CodeName (which the user cannot change), and exclude by CodeName the sheets to be skipped, as here:
Public Sub TestLoop()
On Error GoTo ErrHandler
Dim ws As Worksheet, s As String
For Each ws In Worksheets
If ws.CodeName <> "Sheet2" Then
s = s & vbNewLine & ws.CodeName
End If
Next ws
s = "WorksheetList (except Sheet2:" & vbNewLine & vbNewLine & s
MsgBox s, vbOKOnly, "Test"
EndSUb:
Exit Sub
ErrHandler:
Resume EndSUb
End Sub
If I drag Sheet 3 to precede Sheet1, the MsgBox outputs:
WorksheetList (except Sheet2:
Sheet3
Sheet1