I'm trying to change the name of a sheet after it is created under and Intersect method. The code I have below give Error 424. The code works when only creating a new sheet.
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
Set Active_Range = Range("B6:F11")
If Not Application.Intersect(Target, Active_Range) Is Nothing Then
Sheets("Employee Details").Copy after:=Sheets("Job Schedule")
Sheets("Employee Details (2)").Name.Value = "Name One"
End If
End Sub
I have tried creating a trigger for the workbook that renames the new sheet when it is created but that does not work either.
Private Sub Workbook_NewSheet(ByVal Sh As Object)
Sh.Name.Value = "Name One"
End Sub
Is this what you are trying? (Not fully tested)
Option Explicit
Private Sub Workbook_NewSheet(ByVal Sh As Object)
'~~> This is the name that you want to give
Dim Nm As String
Nm = "Name One"
'~~> Check if this name is already taken
Dim ws As Worksheet
On Error Resume Next
Set ws = ThisWorkbook.Sheets(Nm)
On Error GoTo 0
If Not ws Is Nothing Then
'~~> Name the new worksheet
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count).Name = Nm
Else
'~~> Alert user and delete the newly created sheet
MsgBox "This name is already taken"
Application.DisplayAlerts = False
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count).Delete
Application.DisplayAlerts = True
End If
End Sub
sticking to your "Workbook_NewSheet" approach
in any Module code pane, put this at the very top
Option Private Module ' make the Public variables "local" to current VBA project only
Public newSheetName As String ' this variable will be available to any other Sub, Function of this Project
in ThisWorkbook code pane, put this
Private Sub Workbook_NewSheet(ByVal Sh As Object)
Sh.Name = newSheetName
End Sub
in your relevant Worksheet code pane, put this
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
Dim Active_Range As Range
Set Active_Range = Range("B6:F11")
If Not Application.Intersect(Target, Active_Range) Is Nothing Then
newSheetName = "Name One" ' set the public variable
Sheets("Employee Details").Copy after:=Sheets("Job Schedule")
End If
End Sub
After that, you may want to add code (I'd do that in "Workbook_NewSheet()" to ensure the new worksheet name:
a) matches the sheet name rules
b) isn't already used for another sheet in the same workbook
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
Dim Active_Range As Range
Set Active_Range = Range("B6:F11")
If Not Application.Intersect(Target, Active_Range) Is Nothing Then
Name2 = ActiveCell().Value
Sheets("Employee Details").Copy After:=Sheets("Job Schedule")
Worksheets("Employee Details (2)").Name = "Employee Details - " + Name2
End If
End Sub
Above is what I came up with after digging and reading a little more.
A Worksheet BeforeRightClick: Copy and Rename Template Worksheet
Sheet Module e.g. Sheet1
Option Explicit
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
AddNewEmployeeDetails Target, Cancel
End Sub
Standard Module e.g. Module1
Option Explicit
Sub AddNewEmployeeDetails(ByVal Target As Range, ByRef Cancel As Boolean)
Const PROC_TITLE As String = "Add New Employee Details Sheet"
Const TARGET_RANGE As String = "B6:F11"
Const SRC_SHEET_NAME As String = "Employee Details"
Const AFTER_SHEET_NAME As String = "Job Schedule"
Const DST_SHEET_NAME_PREFIX As String = "Employee Details - "
Dim tws As Worksheet: Set tws = Target.Worksheet
Dim trg As Range: Set trg = Intersect(tws.Range(TARGET_RANGE), Target)
If trg Is Nothing Then Exit Sub
Dim eName As String: eName = CStr(Target.Value) ' for the message boxes
Dim dName As String: dName = DST_SHEET_NAME_PREFIX & eName
Dim wb As Workbook: Set wb = tws.Parent
Dim dsh As Object
On Error Resume Next ' to prevent error if sheet doesn't exist
Set dsh = wb.Sheets(dName)
On Error GoTo 0
If dsh Is Nothing Then ' sheet doesn't exist
Dim sws As Worksheet: Set sws = wb.Sheets(SRC_SHEET_NAME)
Dim aws As Worksheet: Set aws = wb.Sheets(AFTER_SHEET_NAME)
sws.Copy After:=aws
Dim dws As Worksheet: Set dws = aws.Next
Dim ErrNumber As Long, ErrDescription As String
On Error Resume Next ' to prevent error if invalid sheet name
dws.Name = dName
ErrNumber = Err.Number
ErrDescription = Err.Description
On Error GoTo 0
If ErrNumber <> 0 Then ' sheet name is invalid
Application.DisplayAlerts = False ' to delete without confirmation
dws.Delete
Application.DisplayAlerts = True
tws.Select
MsgBox "Run-time error '" & ErrNumber & "':" & vbLf & vbLf _
& ErrDescription & vbLf & vbLf & "Could not rename to """ _
& dName & """.", vbCritical, PROC_TITLE
Else ' sheet name is valid
MsgBox "Employee Details sheet for " & eName & " added.", _
vbInformation, PROC_TITLE
End If
Else ' sheet exists
MsgBox "The Employee Details sheet for " & eName _
& " already exists.", vbCritical, PROC_TITLE
End If
Cancel = True
End Sub
Related
I have a survey with health data from patients. I have a sheet with all the data named "data",
This is how the data sheet looks like, each column being some category from the patient (there are more rows):
I am creating a macro where the user has to select a Health Authority from a drop-down box, and that will create a new sheet named as the health authority selected. The button assigned to the macro is on another sheet called "user".
This is my code so far:
EDIT: I added sub demo () to try and paste it but it did not work. It says variable not defined in the part " With Sheets(sName)"
Option Explicit
Sub createsheet2()
Dim sName As String, ws As Worksheet
sName = Sheets("user").Range("M42").Value
' check if already exists
On Error Resume Next
Set ws = Sheets(sName)
On Error GoTo 0
If ws Is Nothing Then
' ok add
Set ws = Sheets.Add(after:=Sheets(Sheets.Count))
ws.Name = sName
MsgBox "Sheet created : " & ws.Name, vbInformation
Else
' exists
MsgBox "Sheet '" & sName & "' already exists", vbCritical, "Error"
End If
End Sub
Sub demo()
Const COL_HA = 6 ' F
Dim id As Long, rng As Range
id = 20 ' get from user dropdown
With Sheets("user")
.AutoFilterMode = False
.UsedRange.AutoFilter field:=COL_HA, Criteria1:=id
Set rng = .UsedRange.SpecialCells(xlVisible)
End With
' new sheet
'here is the problem
With Sheets(sName)
rng.Copy .Range("A1")
.Range("A1").Activate
End With
End Sub
I need to write the code that inserts in the new sheet only the data of the patients of the chosen Health Authority. Each Health Authority corresponds to a number
"sha" column is the health authority that the user previously selected.
Does anyone know how to insert the data I need to this new created sheet?
I think that I need to filter the data first and then paste it inside the sheet. I am very new at VBA and I'm lost.
Replace your code with this
Option Explicit
Sub createsheet()
Const COL_HA = 6 ' F on data sheet is Health Auth
Dim sName As String, sId As String
Dim wsNew As Worksheet, wsUser As Worksheet
Dim wsIndex As Worksheet, wsData As Worksheet
Dim rngName As Range, rngCopy As Range
With ThisWorkbook
Set wsUser = .Sheets("user")
Set wsData = .Sheets("data")
Set wsIndex = .Sheets("index")
End With
' find row in index table for name from drop down
sName = Left(wsUser.Range("M42").Value, 30)
Set rngName = wsIndex.Range("L5:L32").Find(sName)
If rngName Is Nothing Then
MsgBox "Could not find " & sName & " on index sheet", vbCritical
Else
sId = rngName.Offset(, -1) ' column to left
End If
' create sheet but check if already exists
On Error Resume Next
Set wsNew = Sheets(sName)
On Error GoTo 0
If wsNew Is Nothing Then
' ok add
Set wsNew = Sheets.Add(after:=Sheets(Sheets.Count))
wsNew.Name = sName
MsgBox "Sheet created : " & wsNew.Name, vbInformation
Else
' exists
MsgBox "Sheet '" & sName & "' already exists", vbCritical, "Error"
Exit Sub
End If
' filter sheet and copy data
Dim lastrow As Long, rngData As Range
With wsData
lastrow = .Cells(.Rows.Count, COL_HA).End(xlUp).Row
Set rngData = .Range("A10:Z" & lastrow)
.AutoFilterMode = False
rngData.AutoFilter Field:=COL_HA, Criteria1:=sId
Set rngCopy = rngData.SpecialCells(xlVisible)
.AutoFilterMode = False
End With
' new sheet
With wsNew
rngCopy.Copy .Range("A1")
.Range("A1").Activate
End With
MsgBox "Data for " & sId & " " & sName _
& " copied to wsNew.name", vbInformation
End Sub
I have created a button that would create a new sheet which works just fine. However, when I created a new sheet with the function, it relocates or redirect me to that new sheet which make. I also have a delete button in which it just accepts the sheet name and delete it instantly with no redirection or relocating. Is there a way to prevent the redirecting from happening? I am still a beginner so if I am doing something wrong, pls kindly correct me! Thanks in advance.
Here is the code.
Option Explicit
Public sheetName As Variant
Sub AddSheet()
On Error Resume Next
sheetName = InputBox("New Sheet Name", "Prototype 01")
If sheetName = "" Then
MsgBox "Sheet name cannot be empty!"
Exit Sub
End If
Sheets.Add(After:=Sheets(Sheets.Count)).Name = sheetName
MsgBox "" & sheetName & " was successfully created!"
End Sub
Sub DeleteSheet()
On Error Resume Next
sheetName = InputBox("Sheet Name", "Prototype 01")
If sheetName = "" Then Exit Sub
Sheets(sheetName).Delete
MsgBox """" & sheetName & """ was successfully removed!"
End Sub
Yo can switch sheets via Worksheet.Activate function of vba.
Sheets("YourSheetName").Activate
Once you create the new sheet, add this code to return back to your original sheet.
Add a Worksheet or Delete a Sheet
It is assumed that the delete code will be called by a button so the active sheet (the one with the button) cannot accidentally be deleted.
Add
Option Explicit
Sub AddSheet()
Const PROC_TITLE As String = "Add Sheet"
If ActiveSheet Is Nothing Then Exit Sub ' no visible workbooks open
If Not TypeOf ActiveSheet Is Worksheet Then Exit Sub ' not a worksheet
Dim aws As Worksheet: Set aws = ActiveSheet
Dim wb As Workbook: Set wb = aws.Parent
Dim SheetName As String
SheetName = InputBox("Enter name of sheet to be ADDED", PROC_TITLE)
If Len(SheetName) = 0 Then
MsgBox "Sheet name cannot be empty!", _
vbCritical, PROC_TITLE
Exit Sub
End If
Dim nws As Worksheet
Set nws = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count))
Dim ErrNum As Long
On Error Resume Next ' invalid or existing sheet name
nws.Name = SheetName
ErrNum = Err.Number
On Error GoTo 0
Dim IsSuccess As Boolean
If ErrNum = 0 Then
IsSuccess = True
Else
Application.DisplayAlerts = False
nws.Delete
Application.DisplayAlerts = True
End If
aws.Select
If IsSuccess Then
MsgBox "Worksheet """ & SheetName & """ successfully added.", _
vbInformation, PROC_TITLE
Else
MsgBox "Could not rename to """ & SheetName & """.", _
vbCritical, PROC_TITLE
End If
End Sub
Delete
Sub DeleteSheet()
Const PROC_TITLE As String = "Delete Sheet"
If ActiveSheet Is Nothing Then Exit Sub ' no visible workbooks open
If Not TypeOf ActiveSheet Is Worksheet Then Exit Sub ' not a worksheet
Dim aws As Worksheet: Set aws = ActiveSheet
Dim wb As Workbook: Set wb = aws.Parent
Dim SheetName As String
SheetName = InputBox("Enter name of sheet to be DELETED", PROC_TITLE)
If Len(SheetName) = 0 Then
MsgBox "Sheet name cannot be empty!", _
vbCritical, PROC_TITLE
Exit Sub
End If
Dim dsh As Object ' allowing charts to be deleted
On Error Resume Next
Set dsh = wb.Sheets(SheetName)
On Error Resume Next
If dsh Is Nothing Then
MsgBox "There is no sheet named """ & SheetName & """!", _
vbCritical, PROC_TITLE
Exit Sub
End If
' Don't delete the ActiveSheet, the one with the buttons.
If dsh Is aws Then
MsgBox "Cannot delete the 'button' worksheet """ & aws.Name & """!", _
vbCritical, PROC_TITLE
Exit Sub
End If
' A very hidden sheet cannot be deleted. There is no error though.
If dsh.Visible = xlSheetVeryHidden Then
MsgBox "Cannot delete the very hidden sheet """ & SheetName & """!", _
vbCritical, PROC_TITLE
Exit Sub
End If
Application.DisplayAlerts = False
dsh.Delete
Application.DisplayAlerts = True
aws.Select
MsgBox "Sheet """ & SheetName & """ successfully deleted.", _
vbInformation, PROC_TITLE
End Sub
I'm currently trying to detect duplicated sheet name using "CheckSheet" function. And I want to call this function to run in "Add Sheet" to prevent users from creating duplicate sheet names. However, I ran into error "Compile Error: Expected function or variable" and still not succeeding in solving the problem. Kindly enlighten me where I am doing it wrong and feel free to point out if there are any weakness and better optimization to my code. Thanks in advance.
Option Explicit
Public sheetName As Variant
Public cS As Variant
Sub CheckSheet(cS) 'To check duplicate sheet name - used in AddSheet function.
Dim wS As Worksheet
Dim wsName As String
wsName = wS(sheetName)
On Error GoTo 0
If wS Is Nothing Then
cS = False
Exit Sub
End Sub
Sub AddSheet()
Dim cSheet As Variant
cSheet = CheckSheet(cS).Value
On Error Resume Next
sheetName = Application.InputBox(prompt:="New Sheet Name", Left:=(Application.Width / 2), Top:=(Application.Height / 2), Title:="Add Sheet", Type:=2)
If sheetName = "" Then
MsgBox "Sheet name cannot be empty!"
Exit Sub
ElseIf cSheet = False Then
MsgBox "Duplicate Name! Please try again!"
Exit Sub
Else
Application.ScreenUpdating = False
Sheets.Add(After:=Sheets(Sheets.Count)).Name = sheetName
MsgBox """" & sheetName & """ was successfully created!"
Sheets("Sheet1").Activate
End If
End Sub
Two things.
1. Your code can be simplified. You do not need a function to check if a worksheet exists.
Option Explicit
Sub AddSheet()
Dim sh As Object
Dim sheetName As Variant
'~~> Accept user input
sheetName = Application.InputBox(prompt:="New Sheet Name", _
Left:=(Application.Width / 2), _
Top:=(Application.Height / 2), _
Title:="Add Sheet", Type:=2)
'~~> User presses cancel
If sheetName = False Then Exit Sub
'~~> Check if the sheet name is empty
If sheetName = "" Then
MsgBox "Sheet name cannot be empty!"
Exit Sub
End If
'~~> Check if the sheet exists
On Error Resume Next
Set sh = ThisWorkbook.Sheets(sheetName)
On Error GoTo 0
If Not sh Is Nothing Then
MsgBox "Duplicate Name! Please try again!"
Exit Sub
End If
'~~> Create the worksheet
With ThisWorkbook
.Sheets.Add(After:=.Sheets(.Sheets.Count)).Name = sheetName
MsgBox """" & sheetName & """ was successfully created!"
End With
End Sub
2. Even if you want to use a function, your code has lot of errors. (One of them is pointed out by #braX above.
Is this what you are trying?
Option Explicit
Sub AddSheet()
Dim sheetName As Variant
'~~> Accept user input
sheetName = Application.InputBox(prompt:="New Sheet Name", _
Left:=(Application.Width / 2), _
Top:=(Application.Height / 2), _
Title:="Add Sheet", Type:=2)
'~~> User presses cancel
If sheetName = False Then Exit Sub
'~~> Check if the sheet name is empty
If sheetName = "" Then
MsgBox "Sheet name cannot be empty!"
Exit Sub
End If
'~~> Check if the sheet exists
If DoesSheetExists(CStr(sheetName)) = True Then
MsgBox "Duplicate Name! Please try again!"
Exit Sub
End If
'~~> Create the worksheet
With ThisWorkbook
.Sheets.Add(After:=.Sheets(.Sheets.Count)).Name = sheetName
MsgBox """" & sheetName & """ was successfully created!"
End With
End Sub
'~~> Function to check if sheet exists
Private Function DoesSheetExists(wsName As String) As Boolean
Dim sh As Object
'~~> Check if the sheet exists
On Error Resume Next
Set sh = ThisWorkbook.Sheets(wsName)
On Error GoTo 0
If Not sh Is Nothing Then DoesSheetExists = True
End Function
My code is as below:
Sub NewWorksheetTest()
Dim wsname As String
wsname = InputBox("Enter a name for the new worksheet")
On Error GoTo BadEntry
Sheets.Add
ActiveSheet.Name = wsname
Exit Sub
BadEntry:
MsgBox Err.Number & " :" & Err.Description, vbInformation, "There is an error...."
End Sub
My understanding is if I input a bad name (e.g. duplicate or containing ?/), there is a message explaining the reasons and at the same time the system stops a new sheet from being added.
An error msg is there but a new sheet is added.
As Tim Williams said, On Error GoTo BadEntry only works when the error appears, and sheets.add has no error so it will run normally.
This is another version you can use
vs1-no error checking
Option Compare Text
Sub NewWorksheetTest()
Dim wsname As String
wsname = InputBox("Enter a name for the new worksheet")
If Not (Checks_Sheetname (wsname)) Then Exit Sub 'check correct name
If Check_SheetExists(wsname) Then Exit Sub 'check dulicate
Sheets.Add
ActiveSheet.Name = wsname
End Sub
'https://learn.microsoft.com/en-us/office/vba/excel/concepts/workbooks-and-worksheets/name-a-worksheet-by-using-a-cell-value
Private Function Checks_Sheetname (wsname As String) As Boolean
If Len(wsname) > 31 Then Checks_Sheetname = False:exit function 'check sheetname length
Dim lst_str As Variant, item As Variant
lst_str = Array("/", "\", "[", "]", "*", "?", ":")
For Each item In lst_str
If InStr(wsname, item) > 0 Then
'...
Checks_Sheetname = False: Exit Function
End If
Next item
Checks_Sheetname = True
End Function
'https://stackoverflow.com/questions/6688131/test-or-check-if-sheet-exists
Private Function Check_SheetExists(wsname As String) As Boolean
For Each ws In Worksheets
If wsname = ws.Name Then
MsgBox ("exist")
Check_SheetExists = True
Exit Function
End If
Next ws
End Function
vs2: error checking
Sub NewWorksheetTest()
Dim wsname As String
wsname = InputBox("Enter a name for the new worksheet")
On Error GoTo BadEntry
Dim Act_wsname As String: Act_wsname = ActiveSheet.Name
ActiveSheet.Name = wsname: ActiveSheet.Name = Act_wsname 'checksyntax
Dim ws As Worksheet: Set ws = Sheets(wsname) 'check dulicate
If Not (ws Is Nothing) Then Exit Sub
Sheets.Add
ActiveSheet.Name = wsname
Exit Sub
BadEntry:
MsgBox Err.Number & " :" & Err.Description, vbInformation, "There is an error...."
End Sub
If the rename fails then you need to remove the added sheet
Sub NewWorksheetTest()
Dim wsname As String, ws As Worksheet
wsname = InputBox("Enter a name for the new worksheet")
On Error GoTo BadEntry
Set ws = Sheets.Add()
ws.Name = wsname
Exit Sub
BadEntry:
MsgBox Err.Number & " :" & Err.Description, vbInformation, "There is an error...."
If Not ws Is Nothing Then
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End If
End Sub
I am trying to get the user to enter sheet name and based on the input I want selected cell value to be copied from one sheet to another sheet to a new row.
This is for a basic excel functioning system
Set nextCellInColumn = Worksheets("Summary").Cells(Rows.Count, 4).End(xlUp).Offset(1, 0)
strName = Application.InputBox("Please enter")
nextCellInColumn.Value = Worksheets.Application.InputBox("Please enter").Range("I5").Value
Worksheets.Application.InputBox("Please enter").Range("I5").Copy Worksheets("Summary").Range("D6")
You need to test if the worksheet name exists that the user entered otherwise the copy will fail. Also if the user presses the Cancel button the InputBox will return a boolean False. You need to check for that and eg exit, or your code fails too.
Option Explicit
Public Sub Test()
Dim wsSummary As Worksheet
Set wsSummary = ThisWorkbook.Worksheets("Summary")
Dim NextCellInColumn As Range
Set NextCellInColumn = wsSummary.Cells(wsSummary.Rows.Count, 4).End(xlUp).Offset(1, 0)
Dim strName As Variant 'if user presses cancel it will return a boolean false
strName = Application.InputBox("Please enter")
If VarType(strName) = vbBoolean And strName = False Then Exit Sub 'user pressed cancel so exit
If WorksheetExists(strName) Then
NextCellInColumn.Value = ThisWorkbook.Worksheets(strName).Range("I5").Value
ThisWorkbook.Worksheets(strName).Range("I5").Copy wsSummary.Range("D6")
Else
MsgBox "Worksheet '" & strName & "' not found.", vbCritical
End If
End Sub
'check if a worksheet exists
Public Function WorksheetExists(ByVal WorksheetName As String, Optional ByVal wb As Workbook) As Boolean
If wb Is Nothing Then Set wb = ThisWorkbook 'default to thisworkbook
Dim ws As Worksheet
On Error Resume Next
Set ws = wb.Worksheets(WorksheetName)
On Error GoTo 0
WorksheetExists = Not ws Is Nothing
End Function