I'm trying to rename the ThisWorkbook code module of an Excel worksheet using VBA Extensibility.
I accomplish this with the line
ThisWorkbook.VBProject.VBComponents("ThisWorkbook").Name = "wb"
I can see the change in the VB editor and also access the workbook's properties, e.g. Debug.? wb.Name.
However: If I save and close the file and then reopen it, I get strange behavior. If the code module was empty before renaming it, it reverts back to the old empty ThisWorkbook name.
If it was not empty or was populate before the saving, I now have both, an empty ThisWorkbook module (that would fire events if there were any) - and the filled wb module - which does not fire workbook events:
Has anyone seen this behavior - and knows a fix/workaround?
Quick answer: ThisWorkbook.[_CodeName] = "newName"
Detailed answer
When I add references to the Microsoft Visual Basic For Applications Extensibility 5.3 and run your line
ThisWorkbook.VBProject.VBComponents("ThisWorkbook").Name = "wb"
The ThisWorkbook Name property isn't actually being modified
Saving and re-opening the file causes a duplication of the ThisWorkbook object
Which pretty much means now I have two Workbook objects within one workbook and both are named ThisWorkbook
The workaround is to rename the ThisWorkbook to wb using the Properties window or
ThisWorkbook.[_CodeName] = "newName" because ThisWorkbook.CodeName is read-only.
Related
Today I was learning about sheet codenames, and discovered that you can change the name of the workbook object in the same way. workbook object name change
I tried to use this as a reference in my code and it worked:
Dim statusWB As Workbook
Set statusWB = MultiTracker 'codename in place of thisworkbook.
TestVal = statusWB.Worksheets(NewSheetName).Range("A1").Value
I'm getting inconsistent results using ThisWorkbook when I have two workbooks open at the same time, so I'm thinking specifically referencing the workbooks in this way (basically like using codenames for sheets) will fix this problem. Is there any reason I would NOT want to do this? Has anybody else tried it?
Thanks!
I write Excel VBA reports that tap into SQL databases. I'm also in a company that uses dozens of such reports, and any user could have multiple such reports open at once from multiple different sources. Because of this, it is paramount that code does not affect or interfere with any other open workbooks.
My current report unavoidably uses volatile functions, so users that open and then immediately close the file will get prompted with a Save? dialog. Searching online has always pointed to using
Private Sub Workbook_Open()
ActiveWorkbook.Saved = True
End Sub
While effective, I've never been a big fan because of the non-specific nature of "ActiveWorkbook".
Question:
What are the pros/cons/pitfalls of using any of the following options-
ActiveWorkbook.Saved
ThisWorkbook.Saved
Me.Saved
Something_I_haven't_thought_of.Saved
ActiveWorkbook
I would argue that there are no pros to using ActiveWorkbook, as a direct reference to what you're working with should always be preferable, especially in the case stated above where multiple workbooks are involved. Even in the event of opening and working with arbitrary workbooks whose names you don't specifically know (via a FSO or Dir() loop), you can always set a workbook variable equal to the return value of a Workbook.Open function.
ThisWorkbook
Any time you have code working with more than one workbook or even code working with one workbook while multiple workbooks are open, I would recommend ThisWorkbook. It is versatile in that it can be used in object code modules and generic modules to return a consistent reference to the workbook it is placed within. There really aren't any cons to explicitly specifying ThisWorkbook when that's what you mean to reference.
Me
Me and ThisWorkbook are interchangeable when using them inside the ThisWorkbook object code module, but outside of that, Me refers to the object which it is placed within. For instance Me.Name inside a worksheet object code module will get you the name of the worksheet. Doing the same inside the workbook code module will get you the name of the workbook.
For the sake of clarity and re-usability, I would personally recommend ThisWorkbook out of all 3.
Active workbook is the workbook that is in use/activated (hence can change during code execution) and thus less reliable.
This workbook is the workbook on which the code is run. Hence, a good option if that is the workbook you want to refer to.
"Me" refers to where the code is. E.g. if in sheetmodule, it refers to that sheet, if in a userform module it refers to that module, if in thisworkbook module it is the same as 'thisworkbook', etc.
Defining a variable as workbook can refer to any open workbook. Can be redefined as desired in the code and hence very flexible as long as you know the name of the book
Application.DisplayAlerts = False can be used to suppress save/overwrite requests. Which can be very handy if you do not want users to receive a prompt.
Do re-enable as this is a powerful yet 'dangerous' piece of code.
I'm trying to create a custom library of subs and functions saved as .txt files in a network location where various users of the workbook I'm creating can import them based on which userform function they select. The users of the workbook are only going to be using the workbook through the userforms. I don't want to require them to modify their security trust center settings for this import libraries code to work, so I don't want to use the wb.VBproject.References.import command, or make them add-in.
I found this method which works great, but only as long as no other workbooks are open. If another workbook is open, this code ends up inserting a new module in that other workbook instead, and then the userform calls are meaningless.
I don't understand how this is possible, since I'm referencing all of this code within a "With ThisWorkbook" statement. What am I doing wrong?
Sub importLib(libName As String)
Application.DisplayAlerts = False
Path = "C:\Users\(username)\Desktop\excelLibraries\" 'Example only, my path is actually a network location
lib = Path & libName
Dim wb As Workbook
Set wb = ThisWorkbook
With wb
On Error Resume Next
Dim wbModules As Modules
Set wbModules = .Application.Modules 'wb=ThisWorkbook, but doesn't point to this workbook when other workbooks open???
'wb.VBProject.VBComponents.Import lib '---> library saved as .bas, but this requires the user to change their security settings
'wb.VBProject.References.AddFromFile lib '---> library saved as add-in reference, but this requires user to change security settings
'----This method works when no other workbooks are open
For Each a In wbModules 'Clear any previous Library Module
If a.Name = "Library" Then
a.Delete
Exit For
End If
Next
Set m = wbModules.Add 'Create a new Library Module
m.Name = "Library"
m.InsertFile lib 'Insert the code
On Error GoTo 0
End With
Application.DisplayAlerts = True
End Sub
Sub callsub()
importLib "library1.txt"
End Sub
Making the following changes seemed to work for me.
Change Dim wbModules As Modules to Dim wbModules. Otherwise I get a type-mismatch error.
Remove the .Application in Set wbModules = .Application.Modules.
EDIT:
As #Mathieu Guindon has pointed out in a comment, but worth preserving in the question body, Application refers to the Excel application instance, the host. The Modules collection contains all open modules, regardless of the workbook.
Try referencing the following through the VBA editor
Tools > References > Microsoft Visual Basic For Applications Extensibility 5.3
This will allow the code to remove "Library" then reimport the new code.
I've got my macros tucked away in my Personal.xlsb file, and I would like to save a file in the same directory as the workbook I'm applying the macro to.
Currently when I use:
Application.ThisWorkbook.Path
Its getting the location of Personal.xlsb (where the macro stems from) and not the workbook's directory. Can someone please tell me how I can fix this (without adding a module to my workbook)?
The Path property can be used on any Workbook object, not just on the ThisWorkbook one.
So, to obtain the path of the ActiveWorkbook, you can use ActiveWorkbook.Path.
Or if you have, for instance, opened a workbook using something like:
Dim wb As Workbook
Set wb = Workbooks.Open("C:\Temp\Test\File1.xlsx")
then you can use wb.Path which would, of course, return "C:\Temp\Test".
I want to reference different workbooks in my code and I have used this code:
Dim Basicwb As Excel.Workbook
Dim Basic As Excel.Application
Set Basic = New Excel.Application
Set Basicwb = Basic.Workbooks.Open("X:\Job\Masroori\3-042-PMS.xlsx")
but the problem is how can I refrence it if I dont want to open it each time. I used this code (without .Open) but I get this Error! : "Subscript out of range"
Set Basicwb = Basic.Workbooks("X:\Job\Masroori\3-042-PMS.xlsx")
Also, I dont want to activate the workbook each time, Is there any way?
Taken from the msdn site for the Workbooks property:
"Returns a Workbooks collection that represents all the open workbooks. Read-only."
hence the last line of your code gives you an error since the file is not open. AFAIK, you cannot reference objects within a workbook if that workbook is not open. You can access whatever a workbook has without activating it (so without using .Activate), but it has to be open. Maybe this SO question is of help to you:
Open Excel file for reading with VBA without display
If your workbook is open, you can do the following:
Dim wBook as Excel.Workbook, rngTemp as range
Set wBook = workbooks("wbName.xls")
With wBook
' Do stuff, no need to activate. Example:
set rngTemp=.sheets(1).usedRange
End With
I hope this helps?