Deleting Specific Worksheets - vba

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

Related

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

Hide excel worksheet via VBA

I have a workbook that has a number of worksheets each one with a colaborator name on it (Windows login username).
I've tried via VBA to loop through all Worksheets to match the actual Windows Logged On username with the matching Worksheet, and after the match is done, only that Worksheet is kept visible (with all the others being hiden).
I've managed to do this partially but i can only do it untill it finds the matching worksheet. For example, if the matching username is the third worksheet (in a total of ten for example) the code stops there. I want it to run through all worksheets and only then hide the non matching Worksheets.
First i have the following module:
Sub WorksheetFilter()
Dim Username As String
Dim Worksheetname As String
Worksheetname = ActiveWorkbook.ActiveSheet.Name
Username = Environ("Username")
If Worksheetname <> Username Then
ActiveSheet.Visible = False
End If
End Sub
Then, i call the previous module on the Workbook_Open() event:
Option Explicit
Dim WS As Worksheet
Private Sub Workbook_Open()
For Each WS In ActiveWorkbook.Worksheets
WorksheetFilter
Next
End Sub
Any hints on how this can be achieved?
Thanks,
Vítor
Use the code below, and put it in the Workbook module under the Workbook_Open event.
Just loop through all sheets and compare each one with the username.
Option Explicit
Public Sht As Worksheet
Private Sub Workbook_Open()
For Each Sht In ThisWorkbook.Sheets
If Sht.Name = Environ("Username") Then
Sht.Visible = xlSheetVisible
Else
Sht.Visible = xlSheetHidden
' option 2: use very hidden, only able to unhide through code (unable to unhide using right-click)
'Sht.Visible = xlSheetVeryHidden
End If
Next Sht
End Sub
Please see below: chopped your code around a bit. You do not need to defien the worksheets name. This is for the module level, you can call it in the workbook open event as per usual
Option Explicit
Dim ws As Worksheet
Dim Username As String
Sub WorksheetFilter()
Username = Environ("Username")
For Each ws In ActiveWorkbook.Worksheets
If ws.Name <> Username Then
ws.Visible = False
Else
ws.Visible = True
End If
Next ws
End Sub
Please let me know how this works for you! :)

Loop through worksheets with a specific name

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

Comparing two Sheet objects (not contents)

In the context of an error handling code, I would like to verify if the user has given to the current sheet the same name of another one into the same workbook (action forbidden, of course). So the way I intuitively tried to verify this was simply to loop through all the sheets and comparing the names:
For Each sh In ThisWorkbook.Sheets
If sh.Name = ThisWorkbook.ActiveSheet.Name Then
'error handling here
End If
Next sh
However, this is a huge logic fall in the case when:
1) The user is editing, let's say, the sheet number 3;
2) The sheet with the same name is at the position number 5;
In that case, the condition sh.Name = ThisWorkbook.ActiveSheet.Name would be met for sure because the sheet is compared to itself.
So, I wonder: how to understand if sh is not ThisWorkbook.ActiveSheet?
I had thought the task it could have simply been solved with a simple object comparison:
If (sh Is Not ThisWorkbook.ActiveSheet) And (sh.Name = ThisWorkbook.ActiveSheet.Name) Then
but this raises a compile error, namely Object does not support this property or method. Could anyone please help me finding the lack of logic in my code's structure?
OTHER INFORMATION
I have tried to manage the case through the Err.Description and the Err.Number, but the first is OS-language dependent and the second is the same for other types of error I need to handle differently.
Moreover, the sheets (names and contents) are contained into a .xlam add-in so the user can change the contents through custom user-forms but not through the Excel Application.
More in general, let's say that I would like to know how can I perform the comparison, even if a work-around in this specific case is possible, in order to use this method for future developments I already plan to do and that cannot be managed through the default VBA error handler.
Just check the index of the worksheet along with the name.
Only error (or whatever) if the name matches, but the index doesn't.
Option Explicit
Public Sub test()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.ActiveSheet
Dim wsToCheck As Worksheet
For Each wsToCheck In wb.Worksheets
If ws.Name = wsToCheck.Name And ws.Index <> wsToCheck.Index Then
'do something
End If
Next
End Sub
Of course, you could always just test for object equality using the Is operator too, or inequality in your specific case.
Public Sub test2()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.ActiveSheet
Dim wsToCheck As Worksheet
For Each wsToCheck In wb.Worksheets
If Not ws Is wsToCheck Then
'do something
Debug.Print ws.Name
End If
Next
End Sub
You've got an incorrect syntax with "Not"; it should be this:
If (Not sh Is ThisWorkbook.ActiveSheet) And (sh.Name = ThisWorkbook.ActiveSheet.Name) Then
There's no reason to loop through the collection of sheets. Use this:
Function IsWshExists(ByVal wbk As Workbook, ByVal wshName As String) As Boolean
Dim wsh As Worksheet
On Error Resume Next
Set wsh = wbk.Worksheets(wshName)
IsWshExists = (Err.Number = 0)
Set wsh = Nothing
End Function
Usage:
If Not IsWshExists(ThisWorkbook, "Sheet2") Then
'you can add worksheet ;)
'your logic here
End If

VBA - Delete rows in another worksheet

Function DeleteRows()
Dim wb As Workbook
Set wb = Workbooks(ThisWorkbook.Name)
Debug.Print wb.Name
Dim wsName As String
Dim ws As Worksheet
wsName = "SheetX"
Set ws = wb.Worksheets(wsName)
Debug.Print ws.Name
With ws
Debug.Print "ws.name = " & ws.Name
Rows("3:31").Select
Selection.Delete Shift:=xlUp
End With
End Function
I have this function, DeleteRows, that deletes the the rows 3:31 from the worksheet "SheetX".
This only works when "SheetX" is the sheet that is displayed on the screen.
I want it to work when another sheet, lets say "SheetY", in the workbook is displayed. How can I do this?
One way would be to:
1-activate "SheetY"
2-delete the rows
3-activate "SheetX"
But this would not be transparent to the user. Appreciate the help.
You should always try to avoid Select statements. They are almost always unnecessary. That function should be a Sub (because it doesn't have an output) and can be rewritten as a one-liner:
Sub DeleteRows()
ThisWorkbook.Sheets("SheetX").Range("3:31").Delete xlUp
End Sub