Why wont VBA Next go to next Worksheet - excel

So I've been looking on here for a while and I'm trying to make code that goes through every sheet in the workbook unless the sheets are named Summary, Archive, or Template. When running the code it seems to skip the code when I start on a sheet with any of these three names but never goes to the next sheet. (It may be important to mention that my code involves going to another workbook to gather data).
Here's what I have:
For Each rs In ActiveWorkbook.Worksheets
If rs.Name <> "Summary" And rs.Name <> "Archive" And rs.Name <> "Template" Then
'my Code to do
End If
Next rs
Any help would be greatly appreciated.
Thanks

You are using Activesheet or no parent worksheet at all in the actual processing code that you omitted from your question. Use rs instead.
For Each rs In ActiveWorkbook.Worksheets
WITH RS '<~~ use rs
select case lcase(.Name)
case "summary", "archive", "template"
'do nothing
case else
rs.Select '<~~ not considered 'best practice'
'my Code to do with stuff .Range("A1") or .Cells(1, "A") on rs
end select
END WITH
Next rs
Notice that when in a With ... End With you precede all the worksheet members with a . that pushes the parent worksheet to the one described in the With ... End With.

When you meet something unexpected like what you describe, I find it is best to get a visual check of what's going on. Try this:-
Sub Ryan_S()
Dim Ws As Worksheet
For Each Ws In ActiveWorkbook.Worksheets
Debug.Print Ws.Name
If Ws.Name <> "Summary" And Ws.Name <> "Archive" And Ws.Name <> "Template" Then
Debug.Print , "Executing my code"
'my Code to do
End If
Next Ws
End Sub
Except for my little revolt against calling a Worksheet "rs" (which would be a row in my book :-)) the code is exactly like yours. However, I added two lines of code which print something to the Immediate window (Ctl+G if it isn't visible by default). The first line just prints the name of each sheet being called, the second prints only on one of the selected sheets.
This test will guide you toward the error. You might find that you are looping through the wrong workbook (as someone did suggest above), or that your code actually runs but doesn't do what you expect. A common error for beginners is to have On Error Resume Next in it which prevents the code from crashing but doesn't force it to do as instructed.

Related

Vba code works at times, and at times fails miserably

I have written a pretty elaborate code to automate 2 hours of work into less than 1 min. It works, on most days, somedays like today, the code wont work, or parts of the code wont work.
Its the most obviously simple parts of the code that doesn't work.
This is frustrating me.
To get the code to work, what I have to do would be to restart the system.
Please understand, I dont change the code at all. either before or after the error happens.
the is the code, where the error happens.
Range("Table1_2[[#Headers],[Bag No]:[Batch Making]]").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
On Error Resume Next
Application.DisplayAlerts = False
Worksheets("Batch Making").Delete
Sheets.Add(After:=Sheets("Sheet1")).Name = "Batch Making"
Range("A1").Select
ActiveSheet.Paste
Cells.Select
Cells.EntireColumn.AutoFit
Today the error was that it would not paste what the code had selected.
please note:
It selected the set of rows and columns
It created the new sheet and selected the first cell
It tried pasting the value also, but nothing happened.
After restarting the system, code worked like a dream.
Why does this happen?? any clue ??
EDIT: Biggest issue is replicating the error, as I mentioned on some days, the code will crash, else it will run smoothly.
Every day new data is fed to the program, and its cleaned to ensure that only what the program can take is given to it and this involves removing #N/A's, #VALUE's and #Ref (this was done today also, I double checked the data after the crash)
Yet at times it fails.
I'll remove the Error Handlers and have separate code to check for availability of sheet, incase the error pop's up again, then I'll update here.
You can try below code. Using select is not the best idea in 99% of time. Also, when referencing a cell it is always good to precisely tell VBA which worksheet to use.
I would suggest to replace on error resume next clause - it disables all errors in your code and you will not be notified if something went wrong.In this case you can write a bit more code to check whether the specific worksheet exist and then remove/add it.
Sub copytable()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("worksheet_with_table_you_want_to_copy")
On Error Resume Next
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("Batch Making").Delete
ThisWorkbook.Sheets.Add(After:=Sheets("Sheet1")).Name = "Batch Making"
Application.DisplayAlerts = True
ws.ListObjects(1).Range.Copy
With ThisWorkbook.Worksheets("Batch Making")
.Range("a1").PasteSpecial xlPasteAll
.Cells.EntireColumn.AutoFit
End With
End Sub
edit: Code without on error but with check wheather worksheet "Batch Making" exists and delete it if it's true
Sub copytable()
Dim wsTable As Worksheet
Set wsTable = ThisWorkbook.Worksheets("worksheet_with_table_you_want_to_copy")
Dim ws As Worksheet
Application.DisplayAlerts = False
For Each ws In ThisWorkbook.Worksheets
If ws.Name = "Batch Making" Then ThisWorkbook.Worksheets("Batch Making").Delete
Next ws
Application.DisplayAlerts = True
ThisWorkbook.Sheets.Add(After:=Sheets("Sheet1")).Name = "Batch Making"
ws.ListObjects(1).Range.Copy
With ThisWorkbook.Worksheets("Batch Making")
.Range("a1").PasteSpecial xlPasteAll
.Cells.EntireColumn.AutoFit
End With
End Sub
Unfortunately, you don't say what your code is supposed to do but it seems that you have a template and try to create a new worksheet with a table from this template.
The problem is that the source isn't qualified. Your code copies a "Table_2" from an unspecified source sheet, then deletes the "Batch Making" tab, creates a new sheet by that name and pastes the clipboard to this new sheet. The process is slightly illogical because if the source is a sheet by the name of "Batch Making" then it takes a lot of confidence to delete the original before the copy is safely in place. But I think you have a template. Therefore there is no danger of losing data but the question arises why you make the copy before you need it. Either way, if the copy on the clipboard is lost while deleting and inserting sheets "nothing will happen", as you say.
But what should happen? I presume that you just get a fresh copy of the template, and that means that you retain the structure of the table. Therefore my code below takes a radically different approach. It doesn't delete a sheet (with the table in it) and doesn't create a new sheet. Instead it simply deletes the content of the table in the existing sheet.
Sub Snippet()
' 295
Const WsName As String = "Batch Making"
Dim Ws As Worksheet ' Sheets(WsName)
Dim Tbl As ListObject
On Error Resume Next
Set Ws = Worksheets(WsName)
If Err Then
MsgBox "Sorry, there is no tab """ & WsName & """ in this workbook.", _
vbInformation, "Missing worksheet"
Else
Set Tbl = Ws.ListObjects(1)
If Err Then
MsgBox "Sorry, there is no table on the specified worksheet.", _
vbInformation, "Missing table"
Else
Tbl.DataBodyRange.ClearContents
End If
End If
End Sub
This is done by a single line of code, to wit, Tbl.DataBodyRange.ClearContents. You could take more or different action at that point. For example, you could delete unwanted rows or add default cell content. If there is a lot of such default you might get those data (or formulas) from a template. Otherwise just add it to the code. Headers and totals aren't deleted. The table's structure remains unchanged.
Before that, in the above code, the sheet is qualified and the table. In place of the error messages you could insert code to create the tab and/or create the table.
Please observe the name of the worksheet at the top of the code. You can change that string to any other name. The code doesn't specify the name of the table. Instead, it presumes that there is only one table on that sheet and clears that one.

VBA conflicting sheet name checking via an IF function

I have two subroutines that seem to conflict one with each other. Each one of them is for creating and formatting a new worksheet if it doesn't already exist and I ran into a problem where I can only create one of them and not the other (whichever one is the first one I call to create). I found taht it seems to skip the end sub function in an if function:
For Each Worksheet In Application.ActiveWorkbook.Worksheets
Application.DisplayAlerts = False
If Worksheet.Name = "Machine Layout" Then
Exit Sub
Else:
Sheets.Add.Name = "Machine Layout"
End If
Next
And gives an error that sheet with such name already exists.
Both subroutines use this same code except the worksheet name changes.
I'm wondering what's teh problem with that? Could someone, please, help?
Logic is wrong.
set wb = ActiveWorkbook
For Each ws In wb.Worksheets
If ws.Name = "Machine Layout" Then Exit Sub
next ws
Sheets.Add.Name = "Machine Layout"
I did not test my answer...

Copy formatting to macro

I have a workbook that the workbook formatting is changed regularly, however once changed (maybe weekly or monthly) then going forward until it is changed again a macro needs to replicate that format. Changing the VBA to account for the new formatting each time is very time consuming. Is it possible to format a workbook and then copy the formatting easily to VBA (after the fact not like a macro record) for future use?
In the past I have since used a hidden sheet within the workbook where the macro runs and I essentially copy/paste that into the sheet I am working with. This works but has the downside of when making changes I first need to copy data over to the "template" sheet to ensure everything is correctly aligned with new data.
Possibly some kind of macro that iterates through all cells of a range and outputs to the immediate window the VBA code needed to re-create the formatting?
Basically any ideas will help :)
There are so many formatting options that simply storing them as separate options will take far more space than just a duplicate template sheet. Just run the first code to update your template, and the second to copy it back:
option Explicit
Const TemplatesheetName = "mytemplate"
Sub CopyFormatting
dim ws as worksheet
dim source as worksheet
set source = activesheet
for each ws in worksheets
if ws.name = templatesheetname then
exit for
end if
next ws
if ws is nothing then
set ws = worksheets.add
ws.name = templatesheetname
end if
ws.usedrange.clearformats
source.usedrange.copy
ws.range("a1").pastespecial xlpasteformats
ws.visible = xlveryhidden
end sub
Sub BringBackFormats
dim ws as worksheet
for each ws in worksheets
if ws.name = templatesheetname then
exit for
end if
next ws
if ws is nothing then
msgbox "No template found",vbokonly,"Unabl;e to run"
else
ws.cells.copy
activesheet.range("a1").pastespecial xlpasteformats
end if
exit sub
(written on my phone, can't check the code, there may be typos)

PivotTable Show Details Destination

I know this may be solved with a more complicated script, but I simply want to have the .ShowDetails action for any PivotTable in my workbook (I have 15+) to send the associated data for a particular Pivot Item to a designated worksheet every time. I have this script, but I believe I have coded something incorrectly (I am receiving a procedure declaration compiling error when I attempt to execute it).
Sub Workbook_SheetBeforeDoubleClick()
Dim WS As Worksheet
If Application.Range(ActiveCell.Address).PivotCell.PivotCellType = xlPivotCellValue Then
For Each WS In ThisWorkbook.Worksheets
If WS.Name = "PivotTable Details" Then
WS.Delete
End If
Next WS
Selection.ShowDetails
ActiveSheet.Name = "PivotTable Details"
End If
End Sub
Couple things...
I believe it should be ShowDetail, not ShowDetails.
ShowDetail
is a property that needs to be set to True if you want to display
the data for the selected cell.
The following line should work.
Selection.ShowDetail = True

VBA: Errors with IF loop to rename worksheets (specific errors)

I am trying to have the program search the workbook to CHECK if there is a "Sheet1" and/or "Sheet2". IF there is, I would like them to be renamed "Results" and "DataEntries" (see code below). IF the sheets are already named from previous runs) THEN continue the code with the new names. [the first time a user runs the program, the workbook may have sheet1 and sheet2 as default. My program stores the previous run, so if the user has run the program previously, sheet1 and sheet2 may already have the new and correct names)
The first lines of my code are as follows:
Dim ws As Excel.Worksheet
For Each ws In ActiveWorkbook.Sheets
If ws.Name = Sheet1 Then
Sheet1.Name = Results
ElseIf ws.Name = Sheet2 Then
Sheet2.Name = DataEntries
End If
Exit For
Next ws
Results.Cells.Clear
DataEntries.Cells.Clear
I receive the following errors in this exact order when trying to run the program:
1) object doesnt support this property or method
2) Method 'Name' of object '_Worksheet' failed
3) Object required
4) Object required
Then the program continues to run (although NOT performing the actions I would like). It must be simple syntax confusion but I cannot solve this issue. Can somebody point me in the right direction please? Will post remaining code if needed, but it might not be necessary.
First, you should use Option Explicit which is a result of Require Variable Declaration option set to true in VBA editor options. If you did so I think some/all of your problems you could solve on your own.
Second, your Results and DataEntries are recognised as empty variables. If so you try to change sheets names into empty string which is not allowed. So you need to make the following changes (adding some quotation marks):
If ws.Name = "Sheet1" Then
Sheet1.Name = "Results"
ElseIf ws.Name = "Sheet2" Then
Sheet2.Name = "DataEntries"
End If
Third, your loop will be run only once as you have Exit For line executed during first iteration- you should remove it as I can't find the reason to place it there.
Fourth, there could be some more problems but not seeing all the code it's difficult to recognise them all.
You are missing quotes around your strings, and the Exit For was in the wrong place:
Dim ws As Excel.Worksheet
For Each ws In ActiveWorkbook.Sheets
If ws.Name = "Sheet1" Then
Sheet1.Name = "Results"
ElseIf ws.Name = "Sheet2" Then
Sheet2.Name = "DataEntries"
Exit For
End If
Next ws
Putting the Exit For in the proper location will stop the loop after "Sheet2" has been found and renamed.

Resources