Get Handle on last worksheet copied by Worksheet.Copy - vba

I'm trying to get a handle to the worksheet that was created by a copy operation. following code used to work:
Dim wsTempl As Worksheet, pageCount as Long
Set wsTempl = Sheets("Template")
For pageCount = 1 To 5
wsTempl.Copy After:=Sheets(Sheets.Count)
Set ws = Sheets(Sheets.Count)
ws.Name = "p" & pageCount
Next
But stopped when adding VeryHidden worksheets to the workbook. now my Sheets(Sheets.Count) is getting the VeryHidden sheet instead of the sheet I added last.
Of course I could use
Set ws = Sheets(wsTempl.Name & " (2)")
ws.Name = "p" & pageCount
But that seems so ugly, is this really the only way? Can somebody think of another way?
to replicate the issue:
Open a New workbook, Name the first Sheet 'Template' & delete the other sheets
alt-f11 - insert code module & paste the above code
F5 should show you that it works.
insert a worksheet, using the worksheet tabs drag it to the end of collection
set it to VeryHidden in VBA IDE
F5 again, the first code listing should fail
Reason seems to be that the Copy After:= does not copy after VeryHidden Sheets, thus the part of the code to rename the sheet always renames the VeryHidden Sheet

The Copy method of a worksheet makes the newly created sheet active so you should be able to do this.
Dim wsTempl As Worksheet, i as int
Set wsTempl = Sheets("Template")
For i = 1 To 5
wsTempl.Copy After:=Sheets(Sheets.Count)
Set ws = ThisWorkbook.ActiveSheet
ws.Name = "p" & pageCount
Next

Related

Create another sheet if only 1 exists and use it VBA

I had a working program that uses Sheet1 and Sheet2 in the code. However, now I realized that if I remove Sheet2 and create new sheet that sheet number is no longer being used. What I actually need to do is to create another sheet if only 1 exists and then use that in my code. However, my trials have not worked so far. I used to have code like this to define variables:
Dim datasheet As Worksheet
Dim reportsheet As Worksheet
Set datasheet = Sheet1
set reportsheet = Sheet2
Of course this doesnt work anymore since I deleted Sheet2 and excel remembers your past mistakes. I tried to circumvent this by doing following:
Set datasheet = Sheet1
'Create reportsheet if it doesnt exist
Dim ws As Worksheet
CreateSheetIf = False
Set ws = Nothing
On Error Resume Next
Set ws = ActiveWorkbook.Worksheets("reportdata")
On Error GoTo 0
If ws Is Nothing Then
CreateSheetIf = True
Worksheets.Add.Name = "reportdata"
End If
Set reportsheet = ws
Unfortunately, here I run into an error in my later code which tries to empty the reportsheet:
reportsheet.Range("A1:H200").ClearContents
What I would like to have is to create a new sheet in addition to sheet1 if there is none. This sheet should be located after the Sheet1 in the sheet listing. My further code would utilize this as the reportsheet (I move data from Sheet1 to Sheet2). Someone has any tips on what I am doing wrong and how to do it better?
You do not need to rename the sheet, or have it called Sheet1 and Sheet2. You could access it dynamically relative to their index. For example:
Set datasheet = Worksheets(1) ' The first sheet in the workbook
set reportsheet = Worksheets(2) ' The second sheet in the workbook
I see lack of focus there, you first try to refer to worksheets by Object name (Sheet1, Sheet2) and then by Tab name ("reportdata").
Set ws = ActiveWorkbook.Worksheets("reportdata") with error supression is a good way to handle it, although you try to do the following after:
Set reportsheet = ws
The problem is that if you go through code, you will notice that at this stage Object ws is Nothing if there was no "reportdata" worksheet prior to running this code.
Use:
Set reportsheet = ActiveWorkbook.Worksheets("reportdata")
You can use the worksheet index number instead of the codename.
Option Explicit
Sub repBuild()
Dim datasheet As Worksheet
Dim reportsheet As Worksheet
Set datasheet = Sheet1
On Error GoTo createSecondWs
Set reportsheet = Worksheets(2)
On Error GoTo 0
'build report here with reportsheet
Exit Sub
createSecondWs:
With Worksheets.Add(after:=Worksheets(Worksheets.Count))
.Name = "Report Sheet"
'perform other basic report template operations here before returning
End With
Resume
End Sub
This uses error control to create a second worksheet if only one exists.

Specifying a [Type] when adding a worksheet

I need an Excel worksheet that has data in every row to run a macro that creates a sheet for every row and has each sheet be created with a custom template I have saved on my computer.
So far, I have the macro working to open each row in a sheet but I do not know how to get the sheet to open with the custom template. Also I'd like to rename every sheet corresponding to a specific cell in each sheet.
The current code I am using to create a new sheet from each row is:
Sub RowToSheet()
Dim xRow As Long
Dim I As Long
With ActiveSheet
xRow = .Range("A" & Rows.Count).End(xlUp).Row
For I = 1 To xRow
Worksheets.Add(, Sheets(Sheets.Count)).Name = "Row " & I
.Rows(I).Copy Sheets("Row " & I).Range("A1")
Next I
End With
End Sub
There is an annoying issue with the Excel object model here. You can't use Worksheets.Add and then use the Type parameter to specify the template. If you use Sheets.Add however, then it'll work.
Try this:
Dim NewSheet As Worksheet
Set NewSheet = Sheets.Add(After:=Sheets(Sheets.Count), Type:=TemplatePath)
NewSheet.Name = "Row " & I.Rows(I)
NewSheet.Copy Sheets("Row " & I).Range("A1")
Set the TemplatePath variable to a suitable path.

Runtime Error 1004 Method "Range" of object "_Worksheet" failed

I am trying to combine numerous sheets into one new sheet. I would really appreciate any comments.
The issue is with the line:
wsSrc.Range("A1", wsSrc.Range("D", lastRow)).Copy Destination:=rngDest
Which causes the error when I try to run it. I have previously been using the code to combine all the sheets into the sheet Summary which is where the button for the macro is created which worked fine.
Sub mcrCombine()
ActiveWorkbook.Sheets.Add.Name = "Combined" 'Create new sheet
'Definitions
Dim wsSrc As Worksheet
Dim wsDest As Worksheet
Dim rngDest As Range
Dim lastRow As Long
Dim destRow As Long
Set wsDest = Worksheets("Combined") 'Destination sheet in same Workbook
Set rngDest = wsDest.Range("B1") 'Destination cell in Combined
Application.DisplayAlerts = False 'suppress prompt worksheet delete
'loop through all sheets
For Each wsSrc In ThisWorkbook.Sheets
If wsSrc.Name <> "Summary" And wsSrc.Name <> "Combined" Then 'all sheets except summary
lastRow = wsSrc.Cells.SpecialCells(xlCellTypeLastCell).Row 'define last row
wsSrc.Range("A1", wsSrc.Range("D", lastRow)).Copy Destination:=rngDest 'copy and paste data in range
Set rngDest = rngDest.Offset(lastRow - 1) 'update destination range
wsSrc.Delete 'delete source file
End If
Next
Application.DisplayAlerts = True 'prompts back on
End Sub
OK, I am not sure that this will get your code to achieve all what it is supposed to do, but since you corrected to issue pointed out by #Jeeped and specified your issue within this line:
wsSrc.Range("A1", wsSrc.Range("D", lastRow)).Copy Destination:=rngDest
The error in this line is because of the comma instead of the ampersand. You should change it into:
wsSrc.Range("A1", "D" & lastRow).Copy Destination:=rngDest
Hope this helps.
I have previously been using the code to combine all the sheets into the sheet Summary which is where the button for the macro is created which worked fine.
That's the clue as to what is occurring. As you cycle through each of the worksheets in the workbook you take care not to process the Summary worksheet; probably because a) it already holds aggregated information from the other worksheets and b) you do not want it deleted with the other worksheets that are processed.
If you have changed the central location to a Combined worksheet you are going to have to include that in the worksheet(s) to skip over. Failure to skip over the Combined worksheet will a) copy its content on top of itself and b) delete the Combined worksheet.
If wsSrc.Name <> "Summary" And wsSrc.Name <> "Combined" Then
If you delete the Combined worksheet, then there is Nothing in the way of a destination.

Excel VBA Create buttons to copy/rename sheets and whole workbook

I am trying to create a roadway design spreadsheet that can be used over and over again for hundreds of alignments. I got the everything working with a master sheet to be copied and two sheets used as lookup tables. I want to add two buttons in the corner that can be used to:
1) Copy the Master Sheet and rename it the alignmentname-##. This will be within the current workbook and will be used for each curve in the roadway alignment. It would be even better if there was a way to delete out these two buttons in the copied sheets.
2) A button to copy just the Master sheet, and two supplement sheets to a new workbook.
So far I have:
Sub Button10_Click()
Worksheets("Master (DO NOT MODIFY)").Copy _
Before:=ActiveWorkbook.Sheets("Master (DO NOT MODIFY)")
End Sub
It works fine for now just creating a copy of the base file, but I have not been able to rename it. The code for renaming the sheet is not working and I am not quite sure why.
Sheets(Count).Name = Range("H7").Value & "-" & Count
Where count is a public variable that goes up by one everytime a new curve is addedand H7 is the name of the alignment.
I have also played with the ActiveSheet. activesheet and Worksheets
Code for the first Button:
Public Count As Integer
Sub Button10_Click()
If Count = 0 Then
Count = 1
End If
Dim ws As Worksheet
Worksheets("Master (DO NOT MODIFY)").Copy _
Before:=ActiveWorkbook.Sheets("Master (DO NOT MODIFY)")
Set ws = ActiveSheet
ws.Name = Range("C2").Value & Count
Count = Count + 1
End Sub
Is this what you are trying? You cannot use count as the sheet is moved before the sheet and if you are incrementing the count then it will refer to the wrong sheet.
Sub Button10_Click()
Dim ws As Worksheet
Worksheets("Master (DO NOT MODIFY)").Copy _
Before:=ActiveWorkbook.Sheets("Master (DO NOT MODIFY)")
Set ws = ActiveSheet
ws.Name = Range("H7").Value & "-" & Count
End Sub
Regarding your 2nd question, you can try it like this. I am assuming that the master is not the last or the 2nd last sheet. Also there are two more sheets after the master.
Sub Button10_Click()
Dim ws As Worksheet
Dim wsMaster As Worksheet
Dim MyArray(1 To 3) As String
Dim n As Long
Set wsMaster = ThisWorkbook.Worksheets("Master (DO NOT MODIFY)")
wsMaster.Copy Before:=wsMaster
Set ws = ActiveSheet
ws.Name = Range("H7").Value & "-" & Count
n = ThisWorkbook.Sheets.Count
MyArray(1) = wsMaster.Name
MyArray(2) = ThisWorkbook.Sheets(n - 1).Name
MyArray(3) = ThisWorkbook.Sheets(n).Name
'~~> This will create a new workbook with the 3 sheets
ThisWorkbook.Sheets(MyArray).Copy
End Sub

Copy an entire worksheet to a new worksheet in Excel 2010

I have found similar questions that deal with copying an entire worksheet in one workbook and pasting it to another workbook, but I am interested in simply copying an entire worksheet and pasting it to a new worksheet -- in the same workbook.
I'm in the process of converting a 2003 .xls file to 2010 .xlsm and the old method used for copying and pasting between worksheets doesn't paste with the correct row heights. My initial workaround was to loop through each row and grab the row heights from the worksheet I am copying from, then loop through and insert those values for the row heights in the worksheet I am pasting to, but the problem with this approach is that the sheet contains buttons which generate new rows which changes the row numbering and the format of the sheet is such that all rows cannot just be one width.
What I would really like to be able to do is just simply copy the entire worksheet and paste it. Here is the code from the 2003 version:
ThisWorkbook.Worksheets("Master").Cells.Copy
newWorksheet.Paste
I'm surprised that converting to .xlsm is causing this to break now. Any suggestions or ideas would be great.
It is simpler just to run an exact copy like below to put the copy in as the last sheet
Sub Test()
Dim ws1 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Master")
ws1.Copy ThisWorkbook.Sheets(Sheets.Count)
End Sub
ThisWorkbook.Worksheets("Master").Sheet1.Cells.Copy _
Destination:=newWorksheet.Cells
The above will copy the cells. If you really want to duplicate the entire sheet, then I'd go with #brettdj's answer.
' Assume that the code name the worksheet is Sheet1
' Copy the sheet using code name and put in the end.
' Note: Using the code name lets the user rename the worksheet without breaking the VBA code
Sheet1.Copy After:=Sheets(Sheets.Count)
' Rename the copied sheet keeping the same name and appending a string " copied"
ActiveSheet.Name = Sheet1.Name & " copied"
I really liked #brettdj's code, but then I found that when I added additional code to edit the copy, it overwrote my original sheet instead. I've tweaked his answer so that further code pointed at ws1 will affect the new sheet rather than the original.
Sub Test()
Dim ws1 as Worksheet
ThisWorkbook.Worksheets("Master").Copy
Set ws1 = ThisWorkbook.Worksheets("Master (2)")
End Sub
'Make the excel file that runs the software the active workbook
ThisWorkbook.Activate
'The first sheet used as a temporary place to hold the data
ThisWorkbook.Worksheets(1).Cells.Copy
'Create a new Excel workbook
Dim NewCaseFile As Workbook
Dim strFileName As String
Set NewCaseFile = Workbooks.Add
With NewCaseFile
Sheets(1).Select
Cells(1, 1).Select
End With
ActiveSheet.Paste
If anyone has, like I do, an Estimating workbook with a default number of visible pricing sheets, a Summary and a larger number of hidden and 'protected' worksheets full of sensitive data but may need to create additional visible worksheets to arrive at a proper price, I have variant of the above responses that creates the said visible worksheets based on a protected hidden "Master". I have used the code provided by #/jean-fran%c3%a7ois-corbett and #thanos-a in combination with simple VBA as shown below.
Sub sbInsertWorksheetAfter()
'This adds a new visible worksheet after the last visible worksheet
ThisWorkbook.Sheets.Add After:=Worksheets(Worksheets.Count)
'This copies the content of the HIDDEN "Master" worksheet to the new VISIBLE ActiveSheet just created
ThisWorkbook.Sheets("Master").Cells.Copy _
Destination:=ActiveSheet.Cells
'This gives the the new ActiveSheet a default name
With ActiveSheet
.Name = Sheet12.Name & " copied"
End With
'This changes the name of the ActiveSheet to the user's preference
Dim sheetname As String
With ActiveSheet
sheetname = InputBox("Enter name of this Worksheet")
.Name = sheetname
End With
End Sub