excel vba code error(subscript out of range) - excel

Hi all I had a code in excel vba that makes me able to change sheet name according to cell value i right click on sheet name then select (view code ) then paste the code it worked well with the sheet i did a simple macro that copy the sheet content into another new sheet then paste the code that changes the sheet name with the cell value but i got an error i just need a macro that add new sheet and copy the current sheet content into the new and make the sheet name dependent on cell value (b3)
i have 0 experience in visual basic
here is some screenshots
thanks for helping me
this the sheet name code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("B3")) Is Nothing Then
ActiveSheet.Name = ActiveSheet.Range("B3")
End If
End Sub
i have already explained that THAT

Create a Copy of the Active Sheet
Copy this code into a standard module, e.g. Module1.
Option Explicit
Sub CopyActiveSheet()
' In the worst case scenario, you'll end up with an additional worksheet
' that could not be renamed. If you want to keep this worksheet,
' set DeleteIfCannotRename to False.
Const DeleteIfCannotRename As Boolean = True
' Invalidate the active sheet.
Dim sh As Object: Set sh = ActiveSheet
If sh Is Nothing Then Exit Sub ' no visible workbooks open
If Not TypeOf sh Is Worksheet Then Exit Sub ' not a worksheet
' Reference the source worksheet.
Dim sws As Worksheet: Set sws = ActiveSheet
' Create a copy.
sws.Copy After:=sws
' Reference the copy.
Dim dws As Worksheet: Set dws = ActiveSheet
' Write the value form 'B3' to a variable.
Dim dName As String: dName = CStr(dws.Range("B3").Value)
Dim ErrNumber As Long
' Prevent error if a sheet with the same name already exists
' or the value in 'B3' doesn't contain a valid worksheet name.
On Error Resume Next ' turn on error-trapping
' Attempt to rename.
dws.Name = dName
ErrNumber = Err.Number ' store the error number in a variable
On Error GoTo 0 ' turn off error trapping
' Delete and inform. Out-comment or delete the 'MsgBox' line(s)
' if the message box is too annoying.
If DeleteIfCannotRename Then ' will delete
If ErrNumber <> 0 Then
Application.DisplayAlerts = False
dws.Delete
Application.DisplayAlerts = True
MsgBox "Could not rename to '" & dName & "' so it got deleted.", _
vbCritical, "CopyActivesheet"
End If
Else ' will not delete
MsgBox "Could not rename to '" & dName & "'.", _
vbCritical, "CopyActivesheet"
End If
End Sub

Related

Selecting a worksheet based on a cell value in Excel VBA

I am trying to select a particular page based on cell value U2. I am using the backend Excel names not the display names for the sheets. "Sheet11" is the sheet I am currently trying to connect to. I have tried the following codes, but getting run-time error 9, out of range.
What could I try next?
Thanks
'#1
Dim ws As Worksheet
ws = Range("U2")
Set ws = ActiveSheet
'#2
(Range("U2").Activate
'#3
Sheet11.Activate
Works but no variable
'#4
Sheets(Range("U2").Text).Activate
'#5
Sheets(Range("U2").Value).Activate
'#6
Dim GetString As String
GetString = Range("U2")
GetString.Activate
Is this what you are looking for?
Sheets(ActiveSheet.Range("U2").Value).Select
Reference a Worksheet By Its Code Name
Option Explicit
Sub RefByCodeName()
' Write the code name to a string variable ('wscName').
' Adjust the worksheet!
Dim wscName As String: wscName = CStr(Sheet1.Range("U2").Value)
' Using the 'RefWorksheetByCodeName' function, attempt to reference
' the worksheet ('ws') by its code name.
Dim ws As Worksheet: Set ws = RefWorksheetByCodeName(wscName, ThisWorkbook)
' Validate the worksheet.
If ws Is Nothing Then
MsgBox "No worksheet with the code name '" & wscName & "' found.", _
vbCritical
Exit Sub
End If
' Continue, e.g.:
'MsgBox "Name: " & ws.Name & vbLf & "Code Name: " & ws.CodeName, _
vbInformation
' Make sure the workbook is active.
If Not ThisWorkbook Is ActiveWorkbook Then ThisWorkbook.Activate
' Select the worksheet.
ws.Select
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: In a workbook ('wb'), references a worksheet
' by its code name ('WorksheetCodeName').
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefWorksheetByCodeName( _
ByVal WorksheetCodeName As String, _
ByVal wb As Workbook) _
As Worksheet
Dim ws As Worksheet
For Each ws In wb.Worksheets
If StrComp(ws.CodeName, WorksheetCodeName, vbTextCompare) = 0 Then
Set RefWorksheetByCodeName = ws
Exit Function
End If
Next ws
End Function
Sheets have 3 ways of referring to them:
Name (What you see on the tab at the bottom)
Index (A number representing the sheet's position in the workbook, i.e. this will change if you change the position of a sheet)
CodeName (This is what you refer to as the back end excel name)
You can select a sheet using any of these. If I had a workbook with tabs named after months in Jan to Dec order and I haven't changed the code names the code to select November using each would be as follows:
1.Name Worksheets("November").Select
2.Index Worksheets(11).Select
3.CodeName Sheet11.Select
Unlike name and index you can refer to the codename directly as it is an object.
the following code uses the index to loop through the sheet codenames comparing them to the value in U2 when it is the same as U2 it will select the sheet.
Dim lCodeName As String
Dim lWSCount, lCount As Integer
lCodeName = ActiveSheet.Range("U2").Value
lWSCount = ActiveWorkbook.Worksheets.Count
For lCount = 1 To lWSCount
If Worksheets(lCount).CodeName = lCodeName Then
Worksheets(lCount).Select
Else
End If
Next

Filtering multiple worksheets in excel based on the cell value

I am using below code to filter all my worksheets based on the selections from the drop down list.
I am using inbuilt auto-filter function but somehow the code is not working.
The list I want to use to filter is in Sheet 2 and I have several worksheets
Any reason??
Sub apply_autofilter_across_worksheets()
Dim xWs As Worksheet
On Error Resume Next
For Each xWs In Worksheets
xWs.Range("A1").AutoFilter 3, Sheet2.Range("C4")
Next
End Sub
A Worksheet Change: Dropdown AutoFilter
Copy the code into the sheet module of Sheet2.
The code runs automatically on each change of the dropdown value.
The code filters all worksheets except the one with the dropdown.
If you clear the dropdown cell, all filters will be cleared (hopefully you don't need to filter blanks).
Feel free to download the file from my Google drive.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
' Define constants.
' Source
Const sddCellAddress As String = "C4"
' Destination
Const dFilterColumn As Long = 3
Const dFirstCellAddress As String = "A1"
' Reference the source dropdown cell ('sddCell').
Dim sddCell As Range: Set sddCell = Me.Range(sddCellAddress)
' Check if the value in the dropdown cell was not changed.
If Intersect(sddCell, Target) Is Nothing Then Exit Sub
' Write the source worksheet's name ('sName') to a variable.
Dim sName As String: sName = Me.Name
' Write the criterion converted to a string to a variable ('sCriterion').
Dim sCriterion As String: sCriterion = CStr(sddCell.Value)
' Determine if the dropdown is not blank and write the information
' to a boolean variable ('DropDownIsNotBlank').
' This will be used to clear the filters when the dropdown is blank.
Dim DropDownIsNotBlank As Boolean
If Len(sCriterion) > 0 Then DropDownIsNotBlank = True
' Reference the workbook ('wb').
Dim wb As Workbook: Set wb = Me.Parent ' (or 'Set wb = ThisWorkbook')
' Declare additional variables.
Dim dws As Worksheet ' Destination Worksheet
Dim drg As Range ' Destination Range
' Loop through all worksheets in the workbook...
' (Reference each worksheet in the workbook...)
For Each dws In wb.Worksheets
' Check if the current worksheet is not the source worksheet.
If dws.Name <> sName Then ' is not the source worksheet
' Clear any previous filters.
If dws.FilterMode Then dws.ShowAllData
' Check if the dropdown is not blank
If DropDownIsNotBlank Then
' Reference the destination range ('drg').
Set drg = dws.Range(dFirstCellAddress).CurrentRegion
' Check if the destination range has enough columns.
If drg.Columns.Count >= dFilterColumn Then ' enough columns
' Apply the filter.
drg.AutoFilter dFilterColumn, sCriterion
'Else ' not enough columns; do nothing
End If
'Else ' dropdown is blank (previous filters cleared); do nothing
End If
'Else ' is the source worksheet; do nothing
End If
Next dws
End Sub

creating new worksheet from workbook in VBA (Excel)

If WSheetFound Then 'if WSheetFound = True
'copy and paste the record to the relevant worksheet, in the next available row
internal_numberName.Offset(0, -3).Resize(1, 10).Copy Destination:=Worksheets(internal_numberName.Value).Range("A1").End(xlDown).Offset(1, 0)
Else 'if WSheetFound = False
Set NewWSheet = Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)) ' insert a new Worksheet
NewWSheet.Name = internal_numberName 'named after that branch
DataWSheet.Range("A1", DataWSheet.Range("A1").End(xlToRight)).Copy Destination:=NewWSheet.Range("A1") 'and copy the headings to it
internal_numberName.Offset(0, -3).Resize(1, 10).Copy Destination:=NewWSheet.Range("A2") ' then copy and paste the record to i
End If
while Heading is getting created, its failing when trying to add content from A2, can anyone help me on this
Adding a New Worksheet If It Doesn't Exist
The only error I could produce was when internal_numberName contained a number, then the first line in the 'If' statement would fail which is easily avoided with ...Worksheets(CStr(internal_numberName.Value))....
These 'unexplained' errors often happen when there is an On Error Resume Next placed somewhere before the code. If that is the case, remove it because it 'hides' one or several errors previously occurring.
If the posted code doesn't help, you will need to reveal more of the code, best all of it.
The following code eliminates the need for a function or whatever you're using to determine if the destination worksheet already exists.
Option Explicit
Sub Test()
Dim DataWSheet As Worksheet ' Source Worksheet
Set DataWSheet = ThisWorkbook.Worksheets("Sheet1")
Dim internal_numberName As Range
Set internal_numberName = DataWSheet.Range("D2")
' The above is irrelevant for your code, it's just for testing purposes.
Dim NewName As String: NewName = CStr(internal_numberName.Value)
Dim NewWSheet As Worksheet ' Destination Worksheet
Dim srg As Range ' Source Range
Dim dfCell As Range ' Destination First Cell
' Reference the destination worksheet.
' Attempt to reference the worksheet.
Set NewWSheet = Nothing ' necessary if in a loop
On Error Resume Next ' defer error trapping
Set NewWSheet = ThisWorkbook.Worksheets(NewName)
On Error GoTo 0 ' stop error trapping
If NewWSheet Is Nothing Then ' worksheet doesn't exist
Set NewWSheet = ThisWorkbook.Worksheets _
.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
NewWSheet.Name = NewName
DataWSheet.Range("A1", DataWSheet.Cells(1, DataWSheet.Columns.Count) _
.End(xlToLeft)).Copy Destination:=NewWSheet.Range("A1")
'Else ' worksheet exists; do nothing
End If
' Copy
Set srg = internal_numberName.Offset(0, -3).Resize(1, 10)
Set dfCell = NewWSheet.Cells(NewWSheet.Rows.Count, "A") _
.End(xlUp).Offset(1, 0)
srg.Copy dfCell
End Sub

VBA - Unable to Set Worksheet Variable

I'm new to VBA but I'm not new to scripting languages. I have a problem with setting a worksheet variable for some reason in this routine. The same syntax works in other routines but for some reason it won't in this one.
Can someone explain why my worksheet variable 'wks' will NOT populate? I'm not getting any errors but it will not populate. It remains empty.
The problem is this line "Set wks = .Sheets(strTemplate)". The variable 'strTemplate', when mousing over it DOES indicate the proper template sheet name but the worksheet variable 'wks' never populates.
Here's the subroutine that creates a copy of a template sheet, then renames it in order to be populated with data from the 'Main' sheet. I even put in 'Debug' commands but the one that prints "Sheet =" never executes due to 'wks' being empty.
' REPLACE MAIN WORKSHEET AFTER COPYING
'
Public Sub SheetReplace(strSheetName As String, strTemplate As String)
Dim wks As Worksheet
Debug.Print "Entered SheetReplace"
' We don't want screen updating
Application.ScreenUpdating = False
' Delete the existing Main - Copy if it exists
Application.DisplayAlerts = False 'turn off alerts
On Error Resume Next 'continue execution
Worksheets("Main - Copy").Delete 'delete the worksheet
Err.Clear 'clear error
Application.DisplayAlerts = True 'turn on alerts
With ThisWorkbook
' Duplicate the Main - Tmplt sheet
' Duplicate the template sheet
Set wks = .Sheets(strTemplate)
Debug.Print "Sheet = [" & wks & "]"
' Check sheet visibility
isVisible = (wks.Visible = xlSheetVisible)
' Make the sheet visible if not
If Not isVisible Then wks.Visible = xlSheetVisible
' Copy duplicate to the end of the sheets
wks.Copy After:=.Sheets(strSheetName)
' Change the name of the sheet
ActiveSheet.Name = strSheetName & " - Copy"
' Make the sheet invisible
If isVisible Then ws.Visible = xlSheetHidden
' BEGIN COPYING MAIN SHEET INFO
With Worksheets("Main")
Set srcWorkSheet = Worksheets(ActiveSheet.Name) ' Duplicate the Copy name
lastRowMain = .Cells(.Rows.Count, "A").End(xlUp).Row ' Find the last row used in "Main" sheet
' Copy the ranges that contain daily data.
' Copy the Month
.Range("$C$8").Copy Destination:=Worksheets(ActiveSheet.Name).Range("$C$8")
.Range("$I$11").Copy Destination:=Worksheets(ActiveSheet.Name).Range("$I$11")
.Range("$B15:$I51").Copy Destination:=Worksheets(ActiveSheet.Name).Range("$B15:$I51")
srcWorkSheet.Visible = xlSheetHidden ' Make the copy sheet invisible
' Clear cells (including formatting)
.Range("$C15:$H51").ClearContents
End With
' THIS IS THE END OF THE MAIN COPY
End With
End Sub
Any info would be appreciated. Thanks.
Well apparently I had a syntax error & the 'wks' variable WAS being set, I just needed to reference the 'wks.Name' property. Once I did that the execution continued.
Set wks = .Sheets(strTemplate)
Debug.Print "Sheet = [" & wks.Name & "]" <------ OUTPUT: Sheet = [Main - Copy]
#VBasic2008 : Yep. I didn't see your post until now but thanks for responding with that. You've all been a great help.
Update Workbook
Use Option Explicit.
Use ThisWorkbook if you're doing stuff in the workbook containing the code.
On Error Goto 0 turns off error handling (This was the fatal mistake).
A Quick Fix
Option Explicit
Public Sub SheetReplace(strSheetName As String, strTemplate As String)
Dim wb As Workbook
Set wb = ThisWorkbook
' We don't want screen updating
Application.ScreenUpdating = False
' Delete the existing Main - Copy if it exists
On Error Resume Next 'continue execution
Application.DisplayAlerts = False 'turn off alerts
wb.Worksheets("Main - Copy").Delete 'delete the worksheet
Application.DisplayAlerts = True 'turn on alerts
On Error GoTo 0 'disable error handling
' Duplicate the Main - Tmplt sheet
' Duplicate the template sheet
Dim wks As Worksheet
Set wks = wb.Worksheets(strTemplate)
' Check sheet visibility
Dim isVisible As Boolean
isVisible = (wks.Visible = xlSheetVisible)
' Make the sheet visible if not
If Not isVisible Then
wks.Visible = xlSheetVisible
End If
' Copy duplicate to the end of the sheets
wks.Copy After:=wb.Worksheets(strSheetName)
' Change the name of the sheet
Dim src As Worksheet
Set src = wb.ActiveSheet
src.Name = strSheetName & " - Copy"
' Make the sheet invisible
If isVisible Then wks.Visible = xlSheetHidden
' BEGIN COPYING MAIN SHEET INFO
Dim LastRowMain As Long
With wb.Worksheets("Main")
' Find the last row used in "Main" sheet
LastRowMain = .Cells(.Rows.Count, "A").End(xlUp).Row
' Copy the ranges that contain daily data.
' Copy the Month
.Range("$C$8").Copy Destination:=src.Range("$C$8")
.Range("$I$11").Copy Destination:=src.Range("$I$11")
.Range("$B15:$I51").Copy Destination:=src.Range("$B15:$I51")
' If you only need values, this is more efficient (faster).
'src.Range("$C$8").Value = .Range("$C$8").Value
'src.Range("$I$11").Value = .Range("$I$11").Value
'src.Range("$B15:$I51").Value = .Range("$B15:$I51").Value
' Make the copy sheet invisible
src.Visible = xlSheetHidden
' Clear cells (including formatting)
.Range("$C15:$H51").ClearContents
End With
' THIS IS THE END OF THE MAIN COPY
End Sub

Excel - How to reset the default Table name when copying a sheet with a table

I have a workbook with one worksheet Sheet1. On that Sheet I have one table with its default name Table1.
When I copy the worksheet Right-Click > Move or Copy in the same workbook I get sheet Sheet1 (2).
The Table on this sheet is automatically named Table13.
I do some processing in that copied sheet and subsequently remove it. Leaving the workbook with only its original Sheet1.
Each time I make a copy of Sheet1 the table in the copied sheet is incremented by one.
Also if I remove the sheet and add a new one. It keeps incrementing.
I use the workbook and Sheet1 as a template and I create via a macro a lot of copies.
The new Table Name has now Incremented to Table21600.
I found out that Excel will give an overflow when I reach approximately Table21650.
So, I need a way to reset the Name counter of the added table.
Does anyone know how to achieve this?
You can access (and alter) the names of each table ("ListObject") from your macro-code as shown in this example:
Sub ListAllListObjectNames()
Dim wrksheet As Worksheet
Dim lstObjct As ListObject
Dim count As Integer
count = 0
For Each wrksheet In ActiveWorkbook.Worksheets
For Each lstObjct In wrksheet.ListObjects
count = count + 1
lstObjct.Name = "Table_" & CStr(count)
Debug.Print wrksheet.Name, ": ", lstObjct.Name
Next
Next
End Sub
Reset Table 'Counter'
Allthough the 'counter' will not stop incrementing, when you close
the workbook and open it the next time, it will again start from
Table13.
In the Immediate window CRTL+G you will see the table name
before and after the renaming. When done testing just out comment the
lines containing Debug.Print.
The First Code
' Copies a sheet and renames all its tables.
Sub CopySheetWithTable(Optional SheetNameOrIndex As Variant = "Sheet1", _
Optional NewTableName As String = "Tbl")
Dim MySheet As Worksheet
Dim MyCopy As Worksheet
Dim MyTable As ListObject
Dim i As Long
Set MySheet = ThisWorkbook.Worksheets(SheetNameOrIndex)
'MySheet.Copy MySheet ' Before e.g. Sheet1)
MySheet.Copy , MySheet ' After e.g. Sheet1
Set MyCopy = ActiveSheet
For Each MyTable In MyCopy.ListObjects
i = i + 1
Debug.Print "Old Table Name = " & MyTable.Name
MyTable.Name = NewTableName & i
Debug.Print "Old Table Name = " & MyTable.Name
Next
End Sub
Usage
Copy the previous and the following sub into a module. Run the
following sub to copy a new worksheet. Adjust if you want it before
or after the sheet to be copied.
You don't need to copy the worksheet manually anymore.
The Second Code
' You can create a button on the worksheet and use this one-liner in its code.
Sub CopySheet()
CopySheetWithTable ' Default is CopySheetWithTable "Sheet1", "Tbl"
End Sub
Delete all Sheets After Worksheet
This is just a testing tool.
' Deletes all sheets after the selected sheet (referring to the tab order).
Sub DeleteSheetsAfter(DeleteAfterSheetNameOrIndex As Variant) 'Not tested.
Dim LastSheetNumber As Long
Dim SheetsArray() As Variant
Dim i As Long
' Try to find the worksheet in the workbook containing this code.
On Error Resume Next
LastSheetNumber = _
ThisWorkbook.Worksheets(DeleteAfterSheetNameOrIndex).Index
If Err.Number <> 0 Then
MsgBox "There is no Sheet '" & DeleteAfterSheetNameOrIndex & "' " _
& "in (this) workbook '" & ThisWorkbook.Name & "'."
Exit Sub
End If
With ThisWorkbook
ReDim SheetsArray(.Sheets.Count - LastSheetNumber - 1)
For i = LastSheetNumber + 1 To .Sheets.Count
SheetsArray(i - LastSheetNumber - 1) = i
Next
End With
Application.DisplayAlerts = False
ThisWorkbook.Sheets(SheetsArray).Delete
Application.DisplayAlerts = True
MsgBox "Deleted " & UBound(SheetsArray) & " worksheets after worksheet '" _
& ThisWorkbook.Worksheets(DeleteAfterSheetNameOrIndex).Name & "'.", _
vbInformation, "Delete Successful"
End Sub
Sub DeleteAfter()
DeleteSheetsAfter "Sheet1"
End Sub

Resources