VBA - Copy a template worksheet and rename with user entered text - vba

VBA novice here - I've combed the interwebs and can't seem to get this to work, it's got me stumped.
I would like to have a button on a form that will allow a user to generate a copy of a worksheet "Template", in the same workbook - to the right of "Template". I've figured it out enough that I can generate a copy that renames itself as Template(2) OR generate a blank worksheet named with the text entered in the prompt, but I can't do both.
As is below - it currently returns an "Object Required" error. Thanks in advance for your help, it's much appreciated!
Private Sub NewSheet()
Dim NewSheet As Worksheet
Dim newName As String
Do
newName = Application.InputBox("What do you want to name the new sheet?", Type:=2)
If newName = "False" Then Exit Sub: Rem cancel pressed
Set NewSheet = ThisWorkbook.Worksheets("Template").Copy(After:=Worksheets("Template"))
On Error Resume Next
NewSheet.Name = newName
newName = Error
On Error GoTo 0
If newName <> vbNullString Then
Application.DisplayAlerts = False
NewSheet.Delete
Application.DisplayAlerts = True
MsgBox newName
End If
Loop Until newName = vbNullString
End Sub

Or you can try this:
Sub Test()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Sheets("Template")
Dim newws As Worksheet, sh As Worksheet, newname
Dim query As Long, xst As Boolean, info As String
retry:
xst = False
newname = Application.InputBox("Enter a new sheet name.", info, , , , , , 2)
If newname = "False" Then Exit Sub
For Each sh In wb.Sheets
If sh.Name = newname Then
xst = True: Exit For
End If
Next
If Len(newname) = 0 Or xst = True Then
info = "Sheet name is invalid. Please retry."
GoTo retry
End If
ws.Copy after:=ws: Set newws = ActiveSheet: newws.Name = newname
End Sub
This will continuously ask for a valid sheet name unless the user cancels it.
To avoid deleting a newly added sheet, check first if the name is valid.
Also, I don't think you can copy and assign in one go since there's no documentation that the Copy Method returns the object that was copied. So you copy first and use Activesheet to assign it to a variable.

Related

Require a cancel option for code that copies a worksheet and renames it using Application.inputbox.

I have the following code that copies a Master worksheet and renames it using Application.Inputbox.
'Generates input box to name the new Sheet and checks duplicate names
Set wks = ActiveSheet
Do While sName <> wks.Name
sName = Application.InputBox _
(Prompt:="Enter New Year")
On Error Resume Next
wks.Name = sName
On Error GoTo 0
Loop
Set wks = Nothing
This works fine except when the user clicks cancel.
Current out comes are;
User inputs something and clicks 'ok' = master sheet copied and renamed to input value.
User inputs nothing and clicks 'ok' = Input box loops until value entered and 'ok' clicked or cancel clicked.
User clicks 'cancel' = master sheet copied and renamed to 'False'.
Desired Out come for user clicks 'cancel' = sub exited and nothing copied or altered.
Any help?
I would change your code in the following way.
Dim sname As Variant
Dim wks As Worksheet
Set wks = ActiveSheet
Do While sname <> wks.Name
sname = Application.InputBox _
(Prompt:="Enter New Year")
If sname = vbFalse Then
MsgBox "You pressed Cancel"
Else
On Error Resume Next
wks.Name = sname
On Error GoTo 0
End If
Loop
Set wks = Nothing
In case user presses Cancel sname becomes a boolean with value False
You can detect a cancel by looking for an vbNullString (empty) string
Set wks = ActiveSheet
Do While sName <> wks.Name
sName = Application.InputBox _
(Prompt:="Enter New Year")
If sName = vbNullString Then
MsgBox ("Cancel button clicked!")
Exit Sub
End If
On Error Resume Next
wks.Name = sName
On Error GoTo 0
Loop
Set wks = Nothing
Using above help added this to my code;
'Generates input box to name the new Sheet and checks duplicate names
Set wks = ActiveSheet
Do While sname <> wks.Name
sname = Application.InputBox _
(Prompt:="Enter New Year")
If sname = vbFalse Then
MsgBox "You pressed Cancel"
Application.DisplayAlerts = False
Sheets("MASTER (2)").Delete
Application.DisplayAlerts = True
Sheets("MASTER").Visible = False
Exit Sub
Else
On Error Resume Next
wks.Name = sname
On Error GoTo 0
End If
Loop
Set wks = Nothing
The help above allowed the code to accept a valid input, detect a duplicate input, check for no input and loop as needed, and if the 'cancel' button was clicked then it informed the user. I added further code to exit the sub after deleting the unwanted worksheet (copied from a master sheet earlier in the code).
Thank you all for your help.

UserForm.Show within a prior Initial User form causes blank grey un-closeable workbook to open

Below is the excerpt of code where the "error(more like an unwanted occurrence)" happens. My code is running in a userform (not userform1) after a command button click. The initial form shows on workbook open. The second userform - UserForm1 in the code below - is a check box that I want to present to the user upon my IF condition. When the program gets there, it opens the UserForm1, but also opens a blank grey excel workbook. The workbook cannot be closed until I close the Userformm1 interface.
Note: the second msgbox does not display until AFTER I close the userform.
I tried searching for this problem, but couldn't find the issue in regards to UserForm stuff. Thanks in advance for any help.
Private Sub CommandButton1_Click()
Dim wbName As String, wb As Workbook, ws As Worksheet
Dim sht As Worksheet
Dim myValue As Variant
Dim counter As Integer
Dim EstNumAttempt As Boolean
EstNumAttemp = False
counter = 0
Dim ThisNum As String
Dim EstNum As String
Dim CopyFromBook As Workbook
Dim CopyToWbk As Workbook
Dim ShToCopy As Worksheet
Set CopyToWbk = ThisWorkbook
Application.ScreenUpdating = False
ThisUserPath = Application.ActiveWorkbook.Path
userDataPath = ThisUserPath & "\SBNBidDataSet01112018.xlsx"
Dim StartDate As String
Dim EndDate As String
StartDate = TextBox1.Value
EndDate = TextBox2.Value
EstNum = TextBox3.Value
Set wb = Workbooks.Open(userDataPath)
Set CopyFromWbk = wb
WSCount = wb.Worksheets.Count
If EstNum <> "" Then
EstNumAttempt = True
For X = 1 To WSCount
Set ws = wb.Sheets(X)
ThisNum = ws.Cells(2, 2)
If ThisNum = EstNum Then
counter = counter + 1
Set ShToCopy = CopyFromWbk.Worksheets(X)
ShToCopy.Copy After:=CopyToWbk.Sheets(CopyToWbk.Sheets.Count)
End If
Next X
If counter = 0 Then
MsgBox " That's probably not a valid EST# in SmartBidNet"
End If
End If
If IsDate(StartDate) = True And IsDate(EndDate) = True And EstNumAttempt = False Then
MsgBox "h"
wb.Application.Visible = False
UserForm1.Show
wb.Application.Visible = True
MsgBox "h"
'BLANK GREY SHEET HERE
For X = 100 To 101
Set ws = wb.Sheets(X)
lastrow = ws.Cells(Rows.Count, 1).End(xlUp).Row
'future code
Next X
End If
wb.Close
Application.ScreenUpdating = False ' from before also!
End Sub
THIS IS NOT A SOLUTION, I tested a piece of your code and here is my feedback below.
I ran just this code in a workbook named testbook.xslm and I created a form (myForm that is just a grey layout, nothing on it):
Private Sub CommandButton1_Click()
Dim wb As Workbook
Dim anotherbook As Workbook
Dim anotherbook2 As Workbook
Dim anotherbook3 As Workbook
Set wb = Workbooks.Add
Set anotherbook = wb
Set anotherbook2 = wb
Set anotherbook3 = wb
MsgBox "h"
wb.Application.Visible = False
myForm.Show
wb.Application.Visible = True
MsgBox "h"
wb.Close
Application.ScreenUpdating = False ' from before also!
End Sub
From the user standpoint:
1) testbook opens
2) click the button -> book# opens on top of testbook
3) msgbox "h" pops up
4) x out of msgbox "h" -> Both workbooks disappear (testbook and book1)
5) my grey user form pops up (its empty)
6) x out of userform
7) testbook shows again on top of the new book created which is behind it
8) msgbox "h" #2 pops up
9) x out of msgbox
10) the book# behind testbook disappears
That's it. No grey box residue. How are you closing the userforms (the first one and the second one)? obviously I used the terminate with the x. I did not add any code. So how are you closing your form with no code?
Adding the same behavior occurs if I make multiple workbook references to wb.
So this code area is not your problem . . . .
Second test, still no problems, adding worksheets, running through the number of worksheets, copying them to the testbook.
Option Explicit
Private Sub CommandButton1_Click()
Dim wb As Workbook
Dim wb2 As Workbook
Dim ws As Worksheet
Dim anotherbook As Workbook
Dim anotherbook2 As Workbook
Dim anotherbook3 As Workbook
Dim X As Double
Dim lastrow As Double
Dim thisNum As String
Set wb = Workbooks.Add
Set anotherbook = wb
Set anotherbook2 = wb
Set anotherbook3 = wb
Set wb2 = ThisWorkbook
wb.Worksheets.Add
wb.Worksheets.Add
wb.Worksheets.Add
wb.Worksheets.Add
wb.Worksheets.Add
wb.Worksheets.Add
myForm2.Show
MsgBox "h"
wb.Application.Visible = False
myForm.Show
wb.Application.Visible = True
MsgBox "h"
For X = 1 To wb.Worksheets.Count
Set ws = wb.Sheets(X)
thisNum = ws.Cells(2, 2)
lastrow = ws.Cells(Rows.Count, 1).End(xlUp).Row
ws.Copy After:=wb2.Worksheets(wb2.Worksheets.Count)
'future code
Next X
wb.Close
Application.ScreenUpdating = False ' from before also!
End Sub
Perhaps you have a lot of data being acted upon. Clear the clipboard after the paste? With:
Application.CutCopyMode = False
Digging - WWC

Name Already exist error for newly created tab using VBA

I tried to create VBA macro in excel where one excel sheet tracks a path and creates a new tab in another sheet. It works well but when I create another tab "accidentally" with same name it gives me error as "Name already taken try another one". I don't want to create one more tab with same name. Instead it should stop me from creating tabs with same name
Is there anyway if there that name already exist it gives me a pop up saying name already exist I get only one option as ok to click. I click Ok and the additional sheet that is created doesn't get saved (or if already created deletes itself or save as same name with (2) next to it as excel usually do for repeated sheets). I am trying something like this
If wb.ActiveSheet.Name = sName Then wb.ActiveSheet.Delete
Here is my code
Private Sub Filling_List()
Dim sPath As String
Dim sFile As String
Dim wb As Workbook
Dim sName As String 'add sName declaration
Dim wb1 As Workbook
Dim ws1 As Worksheet
Set wb1 = ThisWorkbook
Set ws1 = ThisWorkbook.Worksheets("S0")
Application.ScreenUpdating = False
sPath = "C:\Users\arp\Desktop\Filling list macro\"
sFile = sPath & "ArF Filling List.xlsm"
Set wb = Workbooks.Open(sFile)
wb.Worksheets("ArF Templete").Copy After:=Worksheets(Worksheets.Count)
sName = ws1.Range("A1") & " " & ws1.Range("T2")
wb.ActiveSheet.Name = sName
'If wb.ActiveSheet.Name = sName Then wb.ActiveSheet.Delete "I am trying this but it doesn't work"
If sName = vbNullString Then Exit Sub 'compare against vbNullstring not empty string literal
With wb.Worksheets(sName)
.Cells(3, "E") = InputBox("Your Initials:")
'.Cells(5, "E") = InputBox("Col?:")
.Cells(6, "E") = InputBox("I:")
.Cells(7, "E") = InputBox("ET1 B:")
.Range("B03") = wb1.Worksheets("Que").Range("B02").Value2
.Range("B04") = wb1.Worksheets("Que").Range("E01").Value2
.Range("B05") = wb1.Worksheets("Que").Range("B01").Value2
.Cells(3, "E") = wb1.Worksheets("Que").Range("E02").Value2
.Cells(5, "E") = "Yes"
'Filling order
.Range("B38:B43") = wb1.Worksheets("Que & Tsc Cal").Range("B04:B09").Value2
.Range("C38:C43") = wb1.Worksheets("Que & Tsc Cal").Range("C04:C09").Value2
.Range("D38:D43") = wb1.Worksheets("Que & Tsc Cal").Range("A04:A09").Value2
'Retains
End With
Application.ScreenUpdating = True
End Sub
I developed above version with the help of you guys here and joining bits and pieces from other threads.Any suggestions to make it better are very welcome.
I use a check if the named tab/sheet is available:
If IsError(Evaluate("SHEETNAME!A1")) Then
'Nothing
Else
Sheets("SHEETNAME").Delete
End If
Sheets.Add(After:=Sheets(Sheets.Count)).Name = "SHEETNAME"
Or as suggested by Scott to have it be simpler and cleaner:
If Not IsError(Evaluate("SHEETNAME!A1")) Then Sheets("SHEETNAME").Delete
Sheets.Add(After:=Sheets(Sheets.Count)).Name = "SHEETNAME"
Edit 1:
Application.DisplayAlerts = False
If IsError(Evaluate("SHEETNAME!A1")) Then Sheets.Add(After:=Sheets(Sheets.Count)).Name = "SHEETNAME"
Application.DisplayAlerts = True
[W]hen I create another tab "accidentally" with same name it gives me error . . . I don't want to create one more tab with same name. Instead it should stop me from creating tabs with same name
This is not an uncommon problem with macros that create tabs--it is easy to accidentally run them twice. To prevent this, first check to see if the tab already exists and only after verifying that it doesn't exist, call the Worksheets.Copy method.
Private Sub Filling_List()
Dim sPath As String
Dim sFile As String
Dim wb As Workbook
Dim sName As String 'add sName declaration
Dim wb1 As Workbook
Dim ws1 As Worksheet
Set wb1 = ThisWorkbook
Set ws1 = ThisWorkbook.Worksheets("S0")
Application.ScreenUpdating = False
sPath = "C:\Users\arp\Desktop\Filling list macro\"
sFile = sPath & "ArF Filling List.xlsm"
Set wb = Workbooks.Open(sFile)
sName = ws1.Range("A1") & " " & ws1.Range("T2")
On Error Resume Next
Dim wslTest As Worksheet
Set wslTest = wb.Worksheets(sName)
If Err.Number = 0 Then
MsgBox "Tab: " & sName & " already exists.", vbInformation
wslTest.Activate
Exit Sub
End If
On Error GoTo 0
wb.Worksheets("ArF Templete").Copy After:=wb.Worksheets(wb.Worksheets.Count)
wb.ActiveSheet.Name = sName
' rest of code
End Sub
The code below should do what you want, you may need to adapt it for your project.
Option Explicit
Sub addsheet()
Dim sht As Worksheet
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets.add
On Error Resume Next 'Prevent Excel from stopping on an error but just goes to next line
ws.Name = "Sheet1"
If Err.Number = 1004 Then
MsgBox "Worksheet with this name already exists"
Application.DisplayAlerts = False 'Prevent confirmation popup on sheet deletion
ws.Delete
Application.DisplayAlerts = True 'Turn alerts back on
On Error GoTo 0 'Stop excel from skipping errors
Exit Sub 'Terminate sub after a failed attempt to add sheet
End If
On Error GoTo 0 'Stop Excel from skipping errors.
End Sub

Save Worksheets to new Workbook By Checkbox [Excel Macro/VBA]

So my main goal is to save sheets (depending on if they are selected by a checkbox) to a new workbook.
Here is my code:
Sub saveSheetWorkbook()
Dim exampleName As Variant
Dim exampleSavePath As String
Dim exampleSheet As Variant
exampleName = InputBox("Who will this be sent to?")
exampleSavePath = ActiveWorkbook.Path & "\" & exampleName
If Worksheets("Example Worksheet 1").Range("E29") = True Then
exampleSheet = "Example Worksheet 2"
End If
Sheets(Array("Example Worksheet 1"), exampleSheet).Copy
ActiveWorkbook.SaveAs Filename:=exampleSavePath, FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End Sub
For example, I want to always save Example Worksheet 1, but only save Example Worksheet 2 if the checkbox is ticked. The cell E29 in Example Worksheet 1 is the linked cell for the checkbox.
So this macro works when the checkbox is ticked, but when the checkbox is unticked, I get an error.
I have set it up so that the sheet array either contains the name or nothing. but when containing nothing, that gives me the error.
Any help would be great.
Edit: I need this for 6 different checkboxes/sheets.
you have one parenthesis too much
then
Sub saveSheetWorkbook()
Dim exampleName As Variant
Dim exampleSavePath As String
Dim sheetsArray As Variant
exampleName = InputBox("Who will this be sent to?")
exampleSavePath = ActiveWorkbook.Path & "\" & exampleName
If Worksheets("Example Worksheet 1").Range("E29") Then
sheetsArray = Array("Example Worksheet 1", "Example Worksheet 2")
Else
sheetsArray = Array("Example Worksheet 1")
End If
Sheets(sheetsArray).Copy
ActiveWorkbook.SaveAs Filename:=exampleSavePath, FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End Sub
You can use my example workbook to do this with form:
https://drive.google.com/open?id=0BzFv0oeets6ubHg2bk96SHotdkU
To create this by yourself, here is instructions:
Press ALT+F11 in order to open VBA window;
Create userform with name "Userform1"
Put listbox to form and change its name to "lstSheet"
Change its properties like shown below:
ListStyle: 1-fmListStyleOPtion;
MultiSelect: 1-fmMultiSelectMulti;
Userform code:
Option Explicit
Dim NewName As String
Dim ws As Worksheet
Dim NumSheets As Integer
Private Sub CommandButton1_Click()
Dim Count As Integer, i As Integer, j As Integer
Count = 0
For i = 0 To lstSheet.ListCount - 1
'check if the row is selected and add to count
If lstSheet.Selected(i) Then Count = Count + 1
Next i
For i = 0 To lstSheet.ListCount - 1
If lstSheet.Selected(i) Then Sheets(lstSheet.List(i)).Select True
Next i
For i = 0 To lstSheet.ListCount - 1
If lstSheet.Selected(i) Then Sheets(lstSheet.List(i)).Select False
If lstSheet.Selected(i) Then Sheets(lstSheet.List(i)).Activate
Next i
Unload Me
ActiveWindow.SelectedSheets.Copy
For Each ws In ActiveWorkbook.Worksheets
ws.Cells.Copy
ws.[A1].PasteSpecial Paste:=xlValues
ws.Cells.Hyperlinks.Delete
Application.CutCopyMode = False
Cells(1, 1).Select
ws.Activate
Next ws
Cells(1, 1).Select
' Remove named ranges
' Input box to name new file
NewName = InputBox("Please Specify the name of your new workbook", "New Copy")
' Save it with the NewName and in the same directory as original
ActiveWorkbook.SaveCopyAs ThisWorkbook.Path & "\" & NewName & ".xlsx"
ActiveWorkbook.Close SaveChanges:=False
Application.ScreenUpdating = True
End Sub
Private Sub lstSheet_Click()
End Sub
Private Sub UserForm_Initialize()
Dim Sh As Variant
'for each loop the add visible sheets
For Each Sh In ActiveWorkbook.Sheets
'only visible sheetand exclude login sheet
If Sh.Visible = True Then
'add sheets to the listbox
Me.lstSheet.AddItem Sh.Name
End If
Next Sh
End Sub
Create Module and put this code there:
Sub showForm()
Userform1.Show
End Sub

Code to allow user make range selection to search list in another workbook and return cell value

Info
Workbook A: Has a master worksheet with a list of items, but the values are arranged in month columns
Workbook B: I have two sheets with different list of items I want to use to search Workbook A and return the current or specific month I need.
Note: Workbook B columns is offset, so we may need to account for this.
The code I have so far:
Sub Button()
Dim OpenFileName As String
Dim MyWB As Workbook, wb As Workbook
Dim aRange As Range
'Excel titled, "MODs", contains this module
Set MyWB = ThisWorkbook
'Ignore possible messages on a excel that has links
Application.AskToUpdateLinks = False
Application.DisplayAlerts = False
'Select and Open workbook
OpenFileName = Application.GetOpenFilename '("clients saved spreadsheet,*.xlsb")
If OpenFileName = "False" Then Exit Sub
Set wb = Workbooks.Open(OpenFileName)
Application.DisplayAlerts = True
Application.AskToUpdateLinks = True
If MsgBox("Please select list range to search.", vbExclamation, "Search List") = vbOK Then
On Error Resume Next
Set aRange = Application.InputBox(prompt:="Enter range", Type:=8)
If aRange Is Nothing Then
MsgBox "Operation Cancelled"
Else
aRange.Select
End If
End If
End Sub
I might might be making this harder than I should be, so I am open to suggestions. I can't seem to find the right find function to use my selected range list and target the newly open workbook with the specific master worksheet (something similar to a vlookup).
Version 2: with a set range but I'm still getting not value returns
Sub Button()
Dim OpenFileName As String
Dim MyWB As Workbook, wb As Workbook
Dim MyWs As Worksheet, ws As Worksheet
Dim aRange As Range
'This line of code turns off the screen updates which make the macro run much faster.
'Application.ScreenUpdating = False
'Excel titled, "MODs", contains this module
Set MyWB = ThisWorkbook
Set MyWs = MyWB.Sheets("Sheet")
'Ignore possible messages on a excel that has links
Application.AskToUpdateLinks = False
Application.DisplayAlerts = False
'Select and Open workbook
OpenFileName = Application.GetOpenFilename '("clients saved spreadsheet,*.xlsb")
If OpenFileName = "False" Then Exit Sub
Set wb = Workbooks.Open(OpenFileName)
On Error Resume Next
Set ws = Application.InputBox("Select a cell on the key sheet.", Type:=8).Parent
On Error GoTo 0
If ws Is Nothing Then
MsgBox "cancelled"
Else
MsgBox "You selected sheet " & ws.Name
End If
Application.DisplayAlerts = True
Application.AskToUpdateLinks = True
With MyWs
For Each aCell In .Range("A1:A10" & LastRow)
If Len(Trim(.Range("A19" & aCell.Row).Value)) <> 0 Then
.Cells(aCell.Row, 15) = Application.WorksheetFunction.VLookup( _
aCell.Value, ws.Range("A1:C18"), 2, 0)
End If
Next aCell
End With
'wb.Close (False)
'If MsgBox("Please select list range to search.", vbExclamation, "Search List") = vbOK Then
'On Error Resume Next
'Set aRange = Application.InputBox(prompt:="Enter range", Type:=8)
'If aRange Is Nothing Then
'MsgBox "Operation Cancelled"
'Else
'aRange.Select
'End If
'End If
'Return to default setting of screen updating.
'Application.ScreenUpdating = True
End Sub
I think the problem I'm running into is this code:
With MyWs
For Each aCell In .Range("A1:A10" & LastRow)
If Len(Trim(.Range("A19" & aCell.Row).Value)) <> 0 Then
.Cells(aCell.Row, 15) = Application.WorksheetFunction.VLookup( _
aCell.Value, ws.Range("A1:C18"), 2, 0)
begin declaringaCell as Range and lastRow as long
You seem to miss the definition of lastRow, which could be something like
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
then look carefully at .Range("A1:A10" & LastRow). Assume lastRow were 100 then this would set a range from A1 to A10100: is that what you want? Or may be you'd use
.Range("A1:A" & lastRow)
again .Range("A19" & aCell.Row) would lead to a single cell address such as "A1989" (were aCell.Row = 89): is that what you want?
other than what above I can't grasp the actual scenario of what you're searching where. You may want to provide more info about that