Coping a worksheet without it being activated - vba

I'd like to copy a worksheet at the end of my workbook without it becoming active.
I use this code to copy my "Template" sheet at the end:
ThisWorkbook.Sheets("Template").Copy after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
But then my new sheet "Template(2)" become the active sheet.
I'd like to remain on "Template" even after the copy.
Is it possible ?

Is it possible?
It's not. .Copy activates the new sheet, that's just how it is. However nothing stops you from (re-)activating the original sheet after:
With ThisWorkbook.Worksheets("Template")
.Copy after:=ThisWorkbook.Workheets(ThisWorkbook.Worksheets.Count)
.Activate
End With
Notice I'm using the Worksheets collection here. The Sheets collection can contain non-worksheet objects, such as a Chart sheet, which is typically not what you're looking for - the Worksheest collection only contains actual Worksheet object.
Note that finding your template sheet in the ThisWorkbook.Worksheets collection everytime you need to use it is not a necessity, and makes your code more frail than it needs to be.
Each Excel object (VBA object actually) has a (Name) property (on top of the Name property which refers to whatever the worksheet is labelled as) that you can edit in the Properties pane (press F4 in the editor) - that name must be a legal VBA identifier, and what VBA does with it is pretty nifty: it declares a global-scope object variable with that name, so if you name your "Template" sheet TemplateSheet, then you can do this:
With TemplateSheet
.Copy after:=ThisWorkbook.Workheets(ThisWorkbook.Worksheets.Count)
.Activate
End With
And so on for every "static" worksheet (i.e. sheets that aren't generated by code). By referring to worksheets by their Name property (the tab label), your code will start failing as soon as a user decides to name the tab something else. By referring to the corresponding global-scope identifier, you can label the worksheet tab whatever you like, the code won't care at all.

Related

Variable name of a worksheet

I want to name a worksheet in excel as the value inside cell "C6" in the tab named "Control". I am new to VBA and what I tried was typing this on a module.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'
' Macro2 Macro
'
'
Dim month As String
month = Sheet2.Range("C5")
Sheets("Month").Name = month
End Sub
Moreover, I do not know whether the name will be updated automatically. I do not want to have to run a macro to change the worksheet name...
Thanks!
It sounds like you want to be able to always refer to the same worksheet, regardless of the worksheet's name changing (as shown on the worksheet's tab) .
This is where the worksheets' CODENAME Property comes in handy.
Let's say you have an object variable declare for your worksheet like Dim ws As Worksheet. You can refer to a worksheet three basic ways.
...by Name :
Set object variable:
Set ws = Sheets("Sheet1")
The worksheet name is the only worksheet identifier that can be changed to whatever you want, which (as you're probably aware) is done like:
ws.Name = "NewSheetname"
...or alternatively, like:
Sheets("Sheet1").Name = "NewSheetName"
...by Index Number :
The index number identifies the position of the worksheet's "tab", compared to the others (and cannot be changed without changing the order of the worksheets)
Set object variable:
Set ws = Sheets(1)
...then you could (still) change the worksheets name like:
ws.Name = "NewSheetname"
...or you could change the name by referring to the worksheet index number like:
Sheets(1).Name = "NewSheetName"
NOTE: If the worksheet is moved (or another worksheet is inserted before it), the Index number will change! Therefore, it's usually not the preferred method of referring to a worksheet.
...by CodeName :
The CodeName is how Excel refers to the worksheets internally. It is the original name that Excel gave the worksheet, and it does not change since it is a read-only property.
Set object variable:
Set ws = Sheet1
...then you could (still) change the worksheets name like:
ws.Name = "NewSheetname"
...or you could change the name by referring to the worksheet codename like:
Sheet1.Name = "NewSheetName"
You can check a worksheets' CodeName property like:
MsgBox Sheets("YourSheetName").CodeName
...or, if ws is already referencing the worksheet:
MsgBox ws.CodeName
So, in your case, you could change the name of your worksheet as often as you like, with:
Sheet2.Name = "NewNameHere"
...just keep referring to it as Sheet2.
One more example to clarify the difference:
Create a new workbook. (It will automatically have worksheet named Sheet1.)
Change the worksheet name to "Sheet1999", either manually (by double-clicking the name on it's tab) or programmatically (with Sheet1.Name="Sheet1999")
Now, if you want to find out how many rows on that sheet have been used, you use use either:
MsgBox Sheets("Sheet1999").UsedRange.Rows.Count
...or:
MsgBox Sheet1.UsedRange.Rows.Count
A note about Sheets versus Worksheets:
When referring to a worksheet Sheets and Worksheets can usually be used interchangeably, so for example these two lines do the same thing:
Worksheets("mySheet").Calculate
Sheets("mySheet").Calculate
The difference is that:
the Worksheets object searches the Worksheets Collection for a matching Name, Index, or CodeName.
the Sheets object searches the Worksheets Collection **and the Charts Collection** for a matching Name, Index, or CodeName.
Therefore, the only time it would be a problem is if you have a chart and a worksheet with the same name.
So, don't ever name a chart the same as a worksheet, and then you won't have to worry about it, and can go on saving 4 keystrokes any time you refer to a Sheet... :)
More Information:
MSDN : Worksheet Object
MSDN : Worksheet Properties
MSDN : Worksheet Methods
MSDN : Sheets Object

Excel keeps crashing when I set a certain worksheet

The workbook keeps crashing when it gets to the
Set wsEDF = Worksheets("edf master") line. I have tried to delete the sheet and then reinstate it and the same thing happens. Am a bit confused.
Sub CopyGroups()
Application.ScreenUpdating = False
Set wsMarex = Worksheets("marex master")
Set wsMQ = Worksheets("macquarie master")
Set wsEDF = Worksheets("edf master")
There is an end sub plus all the variables were declared at the top. Also at one point the macros worked fine. So have gone back to an old version and will look at changing that based on some advice below.
There's no sheet named edf master in the active workbook. Watch for whitespace (leading and/or trailing).
If the active workbook is ThisWorkbook (i.e. the workbook that contains the code that's running), then you don't need any of this.
Look at the Project Explorer (Ctrl+R). Under "Microsoft Excel Objects" you'll find a class module for every single sheet in your workbook. Click one, then hit F4 to display the Properties box.
In the sheet's properties, you'll see it has a (Name) property, which is probably saying something like Sheet1. Change it to something meaningful, e.g. MarexMasterSheet, or MacquarieMasterSheet, or EDFMasterSheet.
Then you don't need wsMarex, wsMQ and wsEDF anymore - they're already declared for you, as global-scope Worksheet instances. So, say the next line of code was this:
Debug.Print wsMarex.CodeName
Now you can do this instead:
Debug.Print MarexMasterSheet.CodeName

Non-existent Excel Worksheet, but Formulas and Defined names still work?

I have an Excel file that is referencing a non-existent worksheet. But the formulas and stuff still work just like nothing is broken (no "#REF" appear). How is this possible?
E.g. Worksheet A! has a VLOOKUP formula referencing a Defined Name in Worksheet B! which is a table range. Except Worksheet B! is nowhere to be found. Yet, the formula still works even as other variables in the formula are updated.
Some additional info:
1) All workbook / worksheet / macros are unprotected
2) There are no hidden worksheets
3) When you open the VBA editor, under MS Excel Objects, the other "ghost" worksheets appear. If you right click on them, you can "View Code". But "View object" option is blanked out. But there are no VBA code for these "ghost" worksheets
4) When you open name manager, the defined names still show Worksheet B! as if it was still there and nothing was wrong.
Anyone knows how this happened?

VBA logic when using macros from personal.xls

I run a spreadsheet report that holds about 50 columns of data for anywhere from 1 to 5000 rows. I'm only interested in 4 columns, but they are never in the same location as these reports are set-up a bit differently for each client. I then take those 4 columns and paste into a new workbook that I can import into another program.
I have three macros created that accomplish this task flawlessy if ran from the local file. When I load them into the personal.xls for use on various files I have issues. Specifically workbook/worksheet referencing issues.
Parts of the macro run to the sheet I intend from them to result on, while other parts act on the personal.xls file itself. This confuses me because I don't have any lines that use commands such as 'thisworkbook' or 'activeworksheet'.
For example:
- The first line is coded to rename Sheet1. The macro renames Sheet1 in personal.xls.
- The next line is the first of four Find commands that locate where the columns i'm interested are located and then move them. This macro runs perfectly on the sheet I intend.
I think my best course is to begin each macro by naming the active workbook and then breaking out each command to the workbook level instead of starting with Worksheets, Range, etc.
Can anyone help me understand what VBA is thinking when performing macros from personal.xls and how to best avoid the macros being run on that sheet itself?
There are two approaches you can take. I use one or both in my code - it's not a one or the other situations.
Declare Variables
Start by defining each sheet that you want to work on in a variable. I generally stay at the sheet level, but that's just a personal choice. If you'd rather be at the workbook level, that's OK too. A procedure might looks like:
Dim shSource as Worksheet
Dim shDest as Worksheet
Set shSource = Workbooks("SomeBook").Worksheets(1)
Set shDest = ActiveWorkbook.Worksheets("Summary")
then whenever I reference a Range or Cells or anything else on a sheet, I preface it with that sheet object variable. Even if I need to get to the workbook, I start with the sheet. If I needed to, for instance, close the Source workbook from the above example, I would use
shSource.Parent.Close False
I set up the sheet variables I need and then everything I do is in terms of those variables.
Edit
If you're opening or creating workbooks, then variables is definitely the way to go. For example, if you're opening a workbook, you could use one of these two examples
Dim wb As Workbook
Set wb = Workbooks.Open(C:\...)
Dim ws As Worksheet
Set ws = Workbooks.Open("C:\...).Worksheets(1)
or creating new, one of these two examples:
Dim wb As Workbook
Set wb = Workbooks.Add
Dim ws as Worksheet
Set ws = Workbooks.Add.Worksheets(1)
With Blocks
When I'm only trying to get at something one time, it seems like a waste to set up a bunch of variables. In those cases, I use a With Block so I can still have fully qualified references, but without a bunch of clutter in my code.
With Workbook("MyBook")
With .Worksheets("First_Sheet")
.Range("A1").Value = "stuff"
End With
With .Worksheets("Second_Sheet")
.Range("G10").Formula = "=A1"
End With
End With
I probably prefer the variable method, but I use them both.
Edit 2: Implicit Referencing
You should always explicitly reference your workbooks and worksheets, but it's still instructional to know how Excel will behave if you don't. A line of code that starts like Range("A1").Value = ... is called an unqualified reference. You're referencing a range, but you're not saying which sheet its on or which workbook that sheet is in. Excel handles unqualified references differently depending on where your code is.
In a Sheet's Class Module (like where you use sheet events like SelectionChange), unqualified references refer to the sheet represented by that module. If you're in the Sheet1 module working in the Change event and you code x = Range("G1").Value then the G1 you are referring to is on Sheet1. In this case, you should be using the Me keyword rather than relying on Excel.
In any other module (like a Standard Module), unqualified references refer to the ActiveSheet. The same x = Range("G1").Value code in a Standard Module refers to G1 on whichever sheet has the focus.
Excel's treatment of unqualified references is very reliable. You could easily create robust code by relying on Excel to resolve the qualified references. But you shouldn't. Your code will be more readable and easier to debug if you qualify every reference. I qualify every reference. And that's not one of those things I "always" do except when I'm lazy - I really do it 100% of the time.

Vb.net Updating excel formula with references to other workbooks

I am trying to update some formulas from one workbook, to another workbook. Everything is working great until I run into a formula that has a reference to another workbook. For example a formula like this =IF(ISERROR(W!Var1),0,W!Var2) It will prompt me to open this workbook, I am assuming so that it can evaluate the formula. So my question is this. Is there a way for me to handle these situations on the fly, so if there is a workbook reference needed it will prompt me and then save it to memory? Because if I have more than one cell that contains these formulas it will prompt me to open the referenced workbook for every cell that contains the link. Alternatively, is there a way that I can just push my formula into the cell without having excel evaluate it?
So in my code I have this line which works for any value that doesn't contain a workbook reference. TheRange.RefersToRange.FormulaR1C1 = RangeFormula
Any help is greatly appreciated.
I understand that you refer to Worksheets (each of the "tabs" in a given Excel file), the Workbook is the whole file. The popping-up message appears when the referred Worksheet cannot be found. Example: range.Value = "=sheet5!A3" (in a Workbook having just "sheet1", "sheet2" and "sheet3"). If you want to avoid this message (although bear in mind that the Worksheet is not there and thus the calculations will be wrong anyway), you can write:
excelApp.DisplayAlerts = False
Where excelApp is the Excel.Application you are currently using.