I need the VBA code to select ALL sheets (number and sheet names will vary from time to time) in a workbook except two specific sheets named "Overview" and "Index" (which also happens to be the left-most sheets on the tab list)
Is there "generic" code that can do this without naming each sheet (other than the two sheets that I do NOT want selected)
I tried the below code first to see if I could select all sheets except one:
Sub Macro1()
Dim i As Long
Sheet1.Select
For i = 2 To ThisWorkbook.Sheets.Count
If Sheets(i).Name <> "Overview" Then Sheets(i).Select Replace:=False
Next i
End Sub
but I kept getting a run-time error '1004; message and when I clicked debug it would highlight the "sheet1.slecet" line of code.
Here's an option.
Sub SelectWS()
Dim WS As Worksheet
Dim I As Long
Dim N As Long
Dim Fnd As Boolean
Dim Vis As Boolean
N = 0
For Each WS In ThisWorkbook.Worksheets
Vis = (WS.Visible = xlSheetVisible)
If Vis = False Then N = N + 1
If WS.Name <> "Overview" And WS.Name <> "Index" And Vis Then
Fnd = True
If ActiveSheet.Name = "Overview" Or ActiveSheet.Name = "Index" Then
WS.Activate
WS.Select
Else
WS.Select (False)
End If
End If
Next WS
If Not Fnd Then
MsgBox "No suitable WS found.", vbInformation + vbOKOnly, "Error:"
ElseIf N > 0 Then
MsgBox "Found " & N & " hidden Worksheet(s) - not selectable.", vbInformation + vbOKOnly, "Notice:"
End If
End Sub
Try this:
Sub Macro1()
Dim iSel As Long, ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If IsError(Application.Match(ws.Name, _
Array("Overview", "Index"), 0)) Then
ws.Select Replace:=(iSel = 0) 'only Replace for first-selected sheet
iSel = iSel + 1 'increment selected sheet count
End If
Next ws
End Sub
(assumes no hidden sheets)
Related
Wondering why I can't do :
For i = 1 To ThisWorkbook.Sheets.Count
If ThisWorkbook.Sheets(i).Name <> "DO NOT SAVE" Then ThisWorkbook.Sheets(i).Select Replace:=False
Next i
Selection.Copy
what would be the best way to save all sheets which does not match DO NOT SAVE name in another wb ?
Try this:
Sub Tester()
Dim ws As Worksheet, arr(), i As Long
ReDim arr(0 To ThisWorkbook.Worksheets.Count - 2)
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> "DO NOT SAVE" Then
arr(i) = ws.Name
i = i + 1
End If
Next ws
Worksheets(arr).Copy
End Sub
A Reflection on the Sheets' Visibility
To export a single sheet to a new workbook, the sheet has to be visible.
To export multiple sheets (using an array of sheet names) to a new workbook, at least one of the sheets has to be visible, while very hidden sheets will not get exported (no error though).
In a given workbook, the following procedure will copy all its sheets, except the ones whose names are in a given array (Exceptions), to a new workbook if at least one of the sheets is visible.
Before copying, it will 'convert' the very hidden sheets to hidden and after the copying, it will 'convert' the originals and copies to very hidden.
Option Explicit
Sub ExportSheets( _
ByVal wb As Workbook, _
ByVal Exceptions As Variant)
Dim shCount As Long: shCount = wb.Sheets.Count
Dim SheetNames() As String: ReDim SheetNames(1 To shCount)
Dim sh As Object
Dim coll As Object
Dim Item As Variant
Dim n As Long
Dim VisibleFound As Boolean
Dim VeryHiddenFound As Boolean
For Each sh In wb.Sheets
If IsError(Application.Match(sh.Name, Exceptions, 0)) Then
Select Case sh.Visible
Case xlSheetVisible
If Not VisibleFound Then VisibleFound = True
Case xlSheetHidden ' do nothing
Case xlSheetVeryHidden
If Not VeryHiddenFound Then
Set coll = New Collection
VeryHiddenFound = True
End If
coll.Add sh.Name
End Select
n = n + 1
SheetNames(n) = sh.Name
End If
Next sh
If n = 0 Then
MsgBox "No sheet found.", vbExclamation
Exit Sub
End If
If Not VisibleFound Then
MsgBox "No visible sheet found.", vbExclamation
Exit Sub
End If
If n < shCount Then ReDim Preserve SheetNames(1 To n) ' n - actual count
If VeryHiddenFound Then ' convert to hidden
For Each Item In coll
wb.Sheets(Item).Visible = xlSheetHidden
Next Item
End If
wb.Sheets(SheetNames).Copy ' copy to new workbook
If VeryHiddenFound Then ' revert to very hidden
Dim dwb As Workbook: Set dwb = Workbooks(Workbooks.Count)
For Each Item In coll
wb.Sheets(Item).Visible = xlSheetVeryHidden
dwb.Sheets(Item).Visible = xlSheetVeryHidden
Next Item
End If
MsgBox "Sheets exported: " & n, vbInformation
End Sub
Sub ExportSheetsTEST()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
ExportSheets wb, Array("DO NOT SAVE")
End Sub
Alternatively you could use the following snippet:
Sub CopyWorkbook()
Dim i As Integer
For i = 1 To ThisWorkbook.Sheets.Count
If ThisWorkbook.Sheets(i).Name <> "DO NOT SAVE" Then
Dim rng As Range
Windows("SOURCE WORKBOOK").Activate
rng = ThisWorkbook.Sheets(i).Cells
rng.Copy Before:=Workbooks("TARGET WORKBOOK").Sheets(i)
End If
Next i
End Sub
I am working with an EXCEL file with 11 worksheets, in this configuration:
VOL_CODE = The code that I look for. If present in a worksheet, the entire line containing VOL_CODE should be deleted.
Worksheets:
“NEW VOL DATA” –This is the worksheet that “stays on” (‘Active’ or ‘Selected’) during the whole process.
Also, here are in range K1:K10 the indications (“X”) if the destination worksheets are selected or not.
“DESTINATION1”, “DESTINATION2”, “DESTINATION3” ... “DESTINATION10”
“Target” worksheets where if VOL_CODE appears AND worksheet is indicated as ‘selected’ (in “NEW VOL DATA” worksheet), it’s line should be removed.
Code:
Private Sub CommandButton3_Click()
'--- Remove VOL_CODE line from all worksheets -----
Dim ws1, ws2 As Worksheet
Dim VOL_CODE As String
Dim PLA, LIN As Integer
Set ws1 = Worksheets("NEW VOL DATA") '--- This is the Working Worksheet -----
VOL_CODE = “RS_123456” ‘--- This is the code to search for -----
For PLA = 1 To 10
If UCase(Range("K" & PLA)) <> "X" Then GoTo JUMP_PLA:
Set ws2 = Worksheets("DESTINATION" & Trim(Str(PLA)))
Do While True
On Error GoTo JUMP_PLA:
LIN = Application.WorksheetFunction.Match(VOL_CODE, ws2.Range("B:B"), 0)
ws2.Cells(LIN, 1).EntireRow.Delete
Loop
JUMP_PLA:
Next PLA
End Sub
The problem is, when I execute the code, it goes fine in DESTINATION1 worksheet, containing or not VOL_CODE (if it does, it loops deleting VOL_CODE’s lines until there are no more), then, when finding no more entries for VOL_CODE, it goes to “JUMP_PLA:” and “Next PLA”... There it starts over, now going to next “DESTINATIONx” worksheet (the next selected)... And there’s an error (finding or not a valid entry) when the Application.WorksheetFunction.Match command executes :
Error in execution: 1004
Application definition or Object definition error
I know it must be a stupid error, but as I am a newbie, I cannot visualize it. And it is driving me crazy...
Can anyone give me a light? It would be very appreciated, and I thank you in advance.
Application.WorksheetFunction.Match to Delete Rows
The procedure doDest is best copied into a standard module (e.g. Module1) and then called in your button code:
Private Sub CommandButton3_Click()
doDest
End Sub
I left your code inside it, so you could see the mistakes and some options.
The rest of the code is just some toys a created to play with, since I've never seen Match used for deleting rows.
IF you wanna play, copy the complete code into a standard module in a new workbook and rename a worksheet to NEW VOL DATA. In range K1:K10 of it, enter an x in a few cells and you're good to go.
The Code
Option Explicit
Sub doDest()
'--- Remove VOL_CODE line from all worksheets -----
' Speed up the code (you won't see what the macro is doing).
Application.ScreenUpdating = False
Dim ws1 As Worksheet, ws2 As Worksheet 'Dim ws1, ws2 As Worksheet
Dim VOL_CODE As String
Dim PLA As Long, LIN As Long ' Dim PLA, LIN As Integer
Dim wb As Workbook: Set wb = ThisWorkbook ' The workbook with this code.
Set ws1 = wb.Worksheets("NEW VOL DATA") 'Set ws1 = Worksheets("NEW VOL DATA") '--- This is the Working Worksheet -----
VOL_CODE = "RS_123456" '--- This is the code to search for -----
For PLA = 1 To 10
'If StrComp(ws1.Range("K" & PLA).Value, "X", vbTextCompare) <> 0 _
Then GoTo JUMP_PLA
If UCase(ws1.Range("K" & PLA).Value) <> "X" Then GoTo JUMP_PLA ' If UCase(Range("K" & PLA)) <> "X" Then GoTo JUMP_PLA:
Set ws2 = wb.Worksheets("DESTINATION" & PLA) ' Set ws2 = Worksheets("DESTINATION" & Trim(Str(PLA)))
Do ' Do While True
' On Error GoTo JUMP_PLA:
' LIN = Application.WorksheetFunction.Match(VOL_CODE, ws2.Range("B:B"), 0)
' ws2.Cells(LIN, 1).EntireRow.Delete
On Error Resume Next ' Turn ON error trapping.
' "ws2.Columns("B")" is just an option, you can stick with
' "ws2.Range("B:B")".
LIN = Application.WorksheetFunction _
.Match(VOL_CODE, ws2.Columns("B"), 0)
If Err.Number <> 0 Then
On Error GoTo 0 ' Turn OFF error trapping.
'Debug.Print "Done with worksheet '" & ws2.Name & "'."
Exit Do ' or: GoTo JUMP_PLA
Else
On Error GoTo 0 ' Turn OFF error trapping.
ws2.Cells(LIN, 1).EntireRow.Delete
End If
Loop
JUMP_PLA:
Next PLA
Application.ScreenUpdating = True
MsgBox "Deleted rows containing '" & VOL_CODE & "'.", _
vbInformation, "Success"
End Sub
' Deletes all sheets named "DESTINATIONx", where x is from 1 to 10.
Sub deleteDest()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim i As Long
For i = 1 To 10
Application.DisplayAlerts = False ' To prevent Excel from 'complaining'.
On Error Resume Next ' If a sheet does not exist.
wb.Sheets("DESTINATION" & i).Delete
On Error GoTo 0
Application.DisplayAlerts = True
Next i
End Sub
' Adds worksheets named "DESTINATIONx", where x is from 1 to 10.
' In each of those worksheets, adds "RS_123456" to up to 100 cells
' in 'random' rows from 1 to 1000 in column 'B'.
Sub createDest()
' Speed up the code (you won't see what the macro is doing).
Application.ScreenUpdating = False
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet, i As Long, j As Long, CurrName As String
For i = 1 To 10
CurrName = "DESTINATION" & i
On Error Resume Next ' Turn ON error trapping.
Set ws = wb.Worksheets(CurrName)
If Err.Number <> 0 Then
' Sheet with current name does not exist.
Set ws = wb.Worksheets _
.Add(After:=wb.Worksheets(wb.Worksheets.Count))
ws.Name = CurrName
'Else ' Sheet with current name exists.
End If
On Error GoTo 0 ' Turn OFF error trapping.
ws.Columns("B").Clear ' Ensures new data if sheets already exist.
For j = 1 To 100
ws.Cells(Application.WorksheetFunction.RandBetween(1, 1000), "B") _
.Value = "RS_123456"
Next j
Next i
wb.Sheets(1).Select
Application.ScreenUpdating = True
End Sub
' Counts the number of cells in column 'B' containing a value.
Sub countDest()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim i As Long
For i = 1 To 10
On Error Resume Next
Debug.Print "DESTINATION" & i, wb.Worksheets("DESTINATION" & i) _
.Columns("B") _
.SpecialCells(xlCellTypeConstants) _
.Cells.Count
If Err.Number <> 0 Then
Debug.Print "DESTINATION" & i, "No cells found."
End If
Next i
End Sub
' Ultimate test
Sub testDest()
deleteDest ' Deletes the sheets.
createDest ' Creates the worksheets with random data.
countDest ' Counts the cells containing "RS_123456" (Debug.Print).
doDest ' Deletes the rows containing "RS_123456" in column 'B'.
countDest ' Counts the cells containing "RS_123456" (Debug.Print).
MsgBox "Ultimate: deleted, created, counted, done and counted again."
End Sub
' Initialize
Sub initCreateAndCount()
deleteDest ' Deletes the sheets.
createDest ' Creates the worksheets with random data.
countDest ' Counts the cells containing "RS_123456" (Debug.Print).
MsgBox "Initialized: Sheets deleted and created, and cells counted."
End Sub
' Shows how even when the 'dest' sheets exist, new values are generated.
Sub testCreateCount()
createDest ' Creates the worksheets with random data.
countDest ' Counts the cells containing "RS_123456" (Debug.Print).
MsgBox "Sheets created and cells counted."
End Sub
Here's a slightly re-worked version.
See comments for notes about changes
Private Sub CommandButton3_Click()
Dim ws1 As Worksheet, ws2 As Worksheet '<< need type for every variable,
' not just the last one...
Dim VOL_CODE As String
Dim PLA As Long, LIN As Long, m '<< use Long, not Integer
Set ws1 = Worksheets("NEW VOL DATA") 'Working Worksheet
VOL_CODE = "RS_123456" '<<< no smart quotes...
For PLA = 1 To 10
If UCase(ws1.Range("K" & PLA)) = "X" Then
Set ws2 = Worksheets("DESTINATION" & PLA)
m = Application.Match(VOL_CODE, ws2.Range("B:B"), 0)
Do While Not IsError(m) '<<< Test return value instead of
' trapping run-time error
ws2.Rows(m).Delete
m = Application.Match(VOL_CODE, ws2.Range("B:B"), 0)
Loop
End If
Next PLA
End Sub
Hi everyone! I'm trying to write a method in VBA to keep 2 worksheets and delete others at the same time.
I already did the one that will keep one worksheet and delete others like this:
Sub delete_all_pages_except_main()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Application.DisplayAlerts = False
If ws.Name <> "Home Page" Then
ws.Delete
End If
Next ws
End Sub
And I try to write it like this
If (ws.Name <> "Home Page" Or ws.Name <> "Data")
But VBA would accept it.
Can you guys help? Thank you.
This should do
Sub delete_all_pages_except_main()
Dim ws As Worksheet
Dim arr As Variant
Dim boo As Boolean
Application.DisplayAlerts = False
arr = Array("Home Page", "Data")
For Each ws In ThisWorkbook.Worksheets
boo = NoDel(ws.Name, arr)
If boo <> True Then ws.Delete
Next ws
Application.DisplayAlerts = True
End Sub
Function NoDel(ws As String, warr As Variant) As Boolean
NoDel = False
For i = LBound(warr, 1) To UBound(warr, 1)
If warr(i) = ws Then NoDel = True
Next i
End Function
Delete Sheets With Exceptions
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: In a specified workbook, writes all the sheet names '
' not specified in an Exceptions array to a Result array, and '
' using the Result array deletes all the sheets in one go. '
' Remarks: This solution applies to worksheets and chartsheets. '
' Since there is no Sheet object, the For Next loop (instead '
' of the For Each Next loop) and the Object type have '
' to be used. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub deleteSheets(Book As Workbook, Exceptions As Variant)
' Program
Dim SheetsCount As Long: SheetsCount = Book.Sheets.Count
Dim Result As Variant: ReDim Result(SheetsCount)
Dim sh As Object, i As Long, j As Long
j = -1
For i = 1 To SheetsCount: GoSub checkName: Next i
If j = -1 Then GoTo NothingToDelete
If j = SheetsCount - 1 Then GoTo NoExceptions
GoSub deleteSheetsInOneGo
MsgBox "Deleted '" & j + 1 & "' sheets.", vbInformation, "Success"
Exit Sub
' Subroutines
checkName:
Set sh = Book.Sheets(i)
If IsError(Application.Match(sh.Name, Exceptions, 0)) Then
j = j + 1
Result(j) = sh.Name
End If
Return
deleteSheetsInOneGo:
ReDim Preserve Result(j)
Application.DisplayAlerts = False
Book.Sheets(Result).Delete
Application.DisplayAlerts = True
Return
' Labels
NothingToDelete:
MsgBox "Sheets already deleted.", vbCritical, "Nothing to Delete"
Exit Sub
NoExceptions:
MsgBox "Cannot delete all sheets.", vbCritical, "No Exceptions"
Exit Sub
End Sub
' Usage Example
Sub runDeleteSheets()
Dim SheetNames As Variant: SheetNames = Array("Home Page", "Data")
deleteSheets ThisWorkbook, SheetNames
End Sub
I have 15 sheets, of which I need to loop through all but four sheets named graphs, print, summary and print.
My code only excludes the first sheet and not the other three.
Dim Current As Worksheet
For Each Current In Worksheets
If Current.Name <> "Summary" And Current.Name <> "Model" And Current.Name <> "Print" And Current.Name <> "Graphs" Then
MsgBox Current.Name
Next
End Sub
I am looking to be able to exclude the four sheets in the output. TIA
This should work:
Sub whatever()
Dim Current As Worksheet, c As String
For Each Current In Worksheets
c = Current.Name
If c <> "Summary" And c <> "Model" And c <> "Print" And c <> "Graphs" Then
MsgBox c
End If
Next
End Sub
Sub Sheets_Walk()
Dim ws As Worksheet
For Each ws In Worksheets
If s_in_A1(ws.Name, a1_Names) = False Then
MsgBox ws.Name
End If
Next
End Sub
Function s_in_A1( _
s As String, _
a1 As Variant) _
As Boolean
Dim lCol As Long
For lCol = LBound(a1) To UBound(a1)
If a1(lCol) = s Then
s_in_A1 = True
Exit For
End If
Next
End Function
Function a1_Names() _
As Variant
a1_Names = Array("Summary", "Model", "Print", "Graphs")
End Function
I have the below code I use to jump to sheets. It requires the exact name to typed in order to be found. Is there a way to have it jump to a sheet by typing in part of the sheet name?
For example, I have a large workbook with sheets named by their ID and currency. If I know the ID but not the currency I would like to be able to jump to the sheet.
My code:
Sub SelectSheet()
Dim i As Variant
Dim ws As Worksheet
i = Application.InputBox("Enter worksheet name", "Select sheet")
'Cancel was pressed
If i = False Or Trim(i) = "" Then Exit Sub
'Check if sheet exist
On Error Resume Next
Set ws = Sheets(i)
On Error GoTo 0
If ws Is Nothing Then
MsgBox "Worksheet " & i & " not found!"
Else
Sheets(i).Select
End If
End Sub
Any ideas?
This will do a partial name match on the beginning of each sheet name. Adjust accordingly to fit your needs.
It works by matching the first x number of characters of each sheet name, where the value of x is determined by the number of characters you entered. You may need to handle case-conversion (e.g., converting the input to uppercase to remove case-sensitivity).
Sub SelectSheet()
Dim Temp As Variant
Dim ws As Worksheet
Temp = Application.InputBox("Enter worksheet name", "Select sheet")
'Cancel was pressed
If Temp = False Or Trim(Temp) = "" Then Exit Sub
'Check if sheet exist
On Error Resume Next
For i = 1 To Sheets.Count
If Left(Sheets(i).Name, Len(Temp)) = Temp Then ' Match first letters
Set ws = Sheets(i) ' Found it
End If
Next
Set ws = Sheets(i)
On Error GoTo 0
If ws Is Nothing Then
MsgBox "Worksheet " & Temp & " not found!"
Else
ws.Select
End If
End Sub