Referencing sheets in another workbook by codename using VBA [duplicate] - vba

This question already has an answer here:
How can I get worksheet code name to activate a specific worksheet?
(1 answer)
Closed 3 years ago.
I am attempting to copy data from one workbook to my current workbook using VBA. InputBook is a workbook object referring to the file from which I would like to extract data. The main issue has to do with referencing particular worksheets in the InputBook workbook. In InputBook, I have a worksheet named "Lines" with the codename LINES. I would prefer to reference this worksheet by its codename, for example:
NumItems = WorksheetFunction.CountA(InputBook.LINES.Columns(1))
This clearly doesn't work and I know I can make it function by using either of the following:
NumItems = WorksheetFunction.CountA(InputBook.Sheets("Lines").Columns(1))
NumItems = WorksheetFunction.CountA(InputBook.Sheets(2).Columns(1))
I would, however, rather not use either of those methods as they seem to be less robust. Is there any way to reference the codename of a worksheet object in another open workbook? Thanks.

You can "hack" a reference to another workbook sheet code name by:
Sub UseCodeNameFromOutsideProject()
Dim WS As Worksheet
With Workbooks("InputBook .xls")
Set WS = _
.Worksheets(CStr(.VBProject.VBComponents("Lines").Properties(7)))
debug.print WS.Name
End With
End Sub
Your WS object is now set to the sheet which has the codename "Lines" in this example.
Original inspiration is here.

I could call a workbook "I LIKE TEA" but InputBook.I LIKE TEA.Columns(1) wont cut it.
Abstract the name away with a const or:
public enum InputSheets
LINES = 2,
GARMENTS = 4
end enum
to allow:
InputBook.Sheets(InputSheets.LINES).Columns(1)
or
MyGetSheetFunction(InputBook, InputSheets.LINES)
You could take this further and use a wrapper class.

Related

VBA : How best for multiple subroutines to refer to the same worksheet

I am relatively inexperienced in VBA and don't know how to best structure my code.
I have a number of subs that all operate on an particular sheet, let's say Sheet1.
Each of my subs starts by setting the worksheet as follows:
Set ws = Sheets("Sheet1")
but I am conscious that down the track I may change the name of Sheet1 to something else, and this would require me to make changes to all of my subs. Ideally it is better to set this declaration once so that I only have to change it once.
What would be the best way to do this?
Several ways to do so. Btw, when using Sheet, you should always specify the workbook, else VBA will try to access the sheet from the active Workbook, and that is not always the workbook you want to work with. If the sheets and your code are in the same book, best is to refer to ThisWorkbook
o Define a constant at the top of your code. When sheetname is changed, you just need to change the const definition
Const MySheetName = "Sheet1"
Sub MySub1
Dim ws as Worksheet
Set ws = ThisWorkbook.Sheets(MySheetName)
(...)
o Use the Code name. A code name is a technical name of a sheet that can be changed only in the VBA-environment, so usually it never changes. See https://stackoverflow.com/a/41481428/7599798
o If the sheet is always the first (and maybe the only) sheet of a workbook, you can use the index number instead
Set ws = ThisWorkbook.Sheets(1)
o Use a function that returns the sheet:
Function getMySheet() As Worksheet
Set getMySheet = ThisWorkbook.Sheets("Sheet1")
End Function
Sub MySub1
Dim ws as Worksheet
Set ws = getMySheet
(...)

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

Open a closed workbook to a specific sheet based of a cell value

I've spent to much time trying to figure this out and would appreciate some help.
I would like to open a closed workbook based off a cell value (eg A1) containing a file path and have it open up to the sheet matching another cell (eg A2).
for example A1 = C:\User\TEST.xls
and A2= Sheet3
I would like a button that opens C:\User[TEST.xls]Sheet3
Here's what I've got so far:
Sub OpenSesame()
Dim ClosedBook As Workbook
Set ClosedBook = Workbooks.Open(Filename:=Application.Range("ClosedBookFile").Value)
'ClosedBookFile is a named cell
ClosedBook.Sheets(*DYNAMIC CELL VALUE*).Activate
Range("A1").Select
End Sub
What can I put instead of dynamic cell value to open to a specific sheet or am I barking up the wrong tree?
Thanks for your help
Probably it is a good idea to refer the Name of the worksheet as a variable and refer it later. Something like this:
Option Explicit
Sub OpenSesame()
Dim ClosedBook As Workbook
Dim nameOfWorksheet As String
Dim pathToOpen As String
With Worksheets(1)
nameOfWorksheet = .Range("A10") 'for example
pathToOpen = .Range("ClosedBookFile")
End With
Set ClosedBook = Workbooks.Open(pathToOpen)
ClosedBook.Worksheets(nameOfWorksheet).Activate
Range("A1").Select
End Sub
Furthermore, it is a good practice to refer the worksheet, whenever you are referring to a range. Thus, With Worksheets(1) refers the first worksheet in your current workbook.
Along #Vityata lines, I'd add you need explict reference of which workbook the worksheet with data belongs to, and avoid implicit reference to the currently active workbook
here's a compressed code with what above
Option Explicit
Sub OpenSesame()
With ThisWorkbook.Worksheets("myWorksheetWithFileInfoName") ' reference worksheet holding info of workbook and worksheet to activate
Workbooks.Open(Filename:=.Range("ClosedBookFile").value).Worksheets(.Range("A2").value).Activate ' open wanted workbook and activate wanted worksheet
'from now on the wanted worksheet in the wanted workbook is the active one
Range("A1").Select ' almost always not needed
End With
End Sub

VBA: How to address the correct workbook when giving a worksheet as an argument to a function?

I have a question regarding the correct address of Workbooks in VBA, which I am fairly new to.
Here is what I have done so far:
I have written a sub that, amongst other things, creates a worksheet with the CodeName "table10".
Then I defined a function to manipulate the contents of said sheet: this function
Text_To_Numbers(worksheet as worksheet)
expects a worksheet argument. I call the function from another sub using the following line:
Call Text_To_Numbers(table10)
Now, here is my issue:
The above works flawlessly when the only open workbook is the one I want to manipulate with my function. However, when I have multiple open workbooks, the function will try to manipulate a different workbook, resulting in an error.
I am quite certain that there must be a way to specify the workbook to be used, but I am unable to find it. That being said, there is another complication: The name of the workbook which I would like to manipulate is machine generated, so it always has a different name. This means that using an explicit reference to the same file name time and again is not an option.
Could anybody help me resolve this?
You need to fully qualify objects in VBA to avoid situations like this where it is ambiguous what the parent is.
In your situation, you want the sheet to be connected to its parent workbook, so make sure you specify that it came from a given workbook!
You cannot directly refer to worksheets in other workbooks by their CodeName, this can only be done to the ThisWorkbook object (the workbook containing the VBA code). See the question Fully reference a worksheet by codename for details on how to get the sheet by its codename from another workbook. I have included the function in the answer and how to use it in this context.
You created the sheet table10 in one of the following:
ActiveWorkbook
ThisWorkbook
WB (some workbook object)
So you can access it using that workbook object without a need for the name!
Using ThisWorkbook.table10 should give same behaviour as just table10, but here are two neater examples for calling the function.
' A neater way to call the function:
Text_To_Numbers worksheet:=ThisWorkbook.table10
' You could also call it simply using
Text_To_Numbers ThisWorkbook.table10
If your sheet is not within ThisWorkbook
' Get sheet (from the workbook object you are using, WB) and pass to your Text_To_Numbers
Text_To_Numbers GetSheetWithCodename("table10", WB)
Function GetSheetWithCodename(ByVal worksheetCodename As String, Optional wb As Workbook) As Worksheet
Dim iSheet As Long
If wb Is Nothing Then Set wb = ThisWorkbook ' mimics the default behaviour
For iSheet = 1 To wb.Worksheets.Count
If wb.Worksheets(iSheet).CodeName = worksheetCodename Then
Set GetSheetWithCodename = wb.Worksheets(iSheet)
Exit Function
End If
Next iSheet
End Function
Try assigning the workbook and sheet to a variable then calling it in this way when you need to do some work in it:
Dim WB As Workbook
Dim WS As Worksheet
'If you want to open the workbook before doing work
Set WB = Workbooks.Open("/Workbook path name goes here”)
Set WS = WB.Worksheets("Table‌​10")
Then you just need to pass a call to the WS variable from within your function to perform operations within the specified sheet.
Edit:
Apologies, didn't realise you were trying to reference the index name in the project editor when I first read your question. The code name can be referenced from an external workbook with the following example which shows how to select the workbook and sheet codename to perform a copy/paste from one workbook to another:
Sub UseCodeNameFromOutsideProject()
Dim WS As Worksheet
With Workbooks("MyWorkbook.xlsb")
Set WS = _
.Worksheets(CStr(.VBProject.VBComponents("Sheet1").Properties(7)))
WS.Range("A1").Copy
Selection.Copy
WS.Range("B1").PasteSpecial
End With
End Sub
Thanks to Enderland for the idea.

VBA: Initialize Combo Box in worksheet

I have an error during initialization and I do not get why this is not working:
Private Sub Workbook_Open()
Dim ws As Worksheet
Set ws = Worksheets(1)
ws.ComboC15.AddItem "Technology"
end sub
It is very weird, the code should be correct. I have checked the combo name and it is "ComboC15".
In fact, this is the sub:
Private Sub ComboC15_Change()
Ps: I also checked the sheet and it is the first sheet where I have the Combo
The Worksheet object in VBA doesn't have a property or method called ComboC15, as this is entirely your own invention. However, the individual worksheet object in your workbook, i.e. the sheet itself as a physical sheet and not as a VBA sheet, knows all about ComboC15 since it's been dropped on it by you. Therefore, you need to access the worksheet object (notice the little w) and not the Worksheet object (notice the big W). If it's confusing to read, imagine how confusing it is for me to try to explain this...
To get access to the worksheet Object, you can do any of the following:
' Assuming "Sheet1" is the code name of the object. You can find this code name
' in the VBA editor. In the "Project Explorer" window, look under Microsoft
' Excel Objects. Your sheets are listed there in the form (for a blank, new
' workbook) "Sheet1 (Sheet1)". The bit *outside* the brackets is the code name.
Sheet1.ComboC15.AddItem "Technology"
' You can even call it directly from the "Worksheet" object by using the sheet
' index.
Worksheets(1).ComboC15.AddItem "Technology"
However, if you want to create a variable with it so you don't have to copy/paste the same thing over and over, declare it as an Object and not as a Worksheet. So do this:
Private Sub Workbook_Open()
Dim ws As Object ' Declare ws as "Object"!
Set ws = Worksheets(1)
ws.ComboC15.AddItem "Technology"
End Sub
The following SO Q&A explains a bit more about the different kind of sheet names:
Excel tab sheet names vs. Visual Basic sheet names
and I hope this article might give you a better insight on how to reference different kinds of objects in VBA.