I have a workbook (we'll call it "AAA") that is based on a template and refers to code modules in a second workbook. The second workbook (we'll call it "CodeStorage") is a repository for code modules so that any saved versions of the template will be able to access modified/updates code without a change to the saved workbook.
My problem arises when I have multiple windows open in "AAA" and try to get the activesheet when a module is running in "CodeStorage". In code, I create an object ("oWorkbook") that is a reference to the workbook "AAA" When "AAA" has focus, oWorkbook.Activesheet returns the sheet for the active window. When "CodeStorage" is running a module and thus has focus, oWorkbook.Activesheet returns the sheet that is selected in window #1 regardless of what window (#2, 3, etc) was active when the code module in "CodeStorage" was called.
Has anyone run into this and have you found a work around?
ActiveSheet is confusing the way you are using it.
You need to explicitly activate a sheet for it to be considered the ActiveSheet. Running code in another workbook does not activate it.
Selecting cells in a worksheet will activate it. Or specifically calling Activate.
You could do something like:
oWorkbook.Activate
oWorkbook.Activesheet
Alternatively, and preferably, you could do something like the following:
oWorkbook.Worksheets("Sheet1")
oWorkbook.Worksheets(1)
Both these are better. If your user selects a different workbook during runtime execution or you select something in a different sheet, ActiveSheet will return something different.
It's better to fully qualify you workbook paths when using multiple workbooks. This will save you a ton of headache in the future for dealing with "what is activated?" or "what is selected?" This answer is worth reading, too.
To rephrase my question, I was looking for a way to reference the last active worksheet in a workbook that had multiple windows open. If window 1 was selected, I wanted the sheet from window 1, same for window 2, 3, or ???. I also needed the reference when a code module in a different workbook was running and the code module had a variable that was an object reference to the calling workbook.
The solution is Workbook.Windows.Item(1).ActiveSheetView.Sheet. When called from the running code module, even in a different workbook, it returns the same as workbook.activesheet when that is called from the workbook itself. My tests show that Workbook.Windows.Item(1) is the last active window when a workbook loses focus.
Thank you enderland. You got me pointed in the right direction.
I want to create an excel template that will includes formulas for dating the columns. However, since those formulas will be based on TODAY(), I need to convert them to static strings (so the dates don't change everytime someone opens it). Is there a way to add a macro that will run automatically when someone creates a new spreadsheet based on the template? (Similarly to Auto_Open(), only on Create, rather than Open). If so, I could just create a macro that will replace the formulas with their results upon document creation. Can this be done?
[Note: I'm not married to this solution; it just seemed like the simplest way to protect my spreadsheet. If someone can suggest an alternative approach, I'd be obliged.]
I have a couple thoughts...
If you run a copy/paste values macro every time it really won't matter, right?
You could check if the file exists yet (has been saved), and if not
then this must be the template opened as a new workbook, maybe?
Code:
Private Sub Workbook_Open()
If Dir(ActiveWorkbook.Name) = "" Then
'run the macro?
MsgBox "I'm gonna run this macro"
End If
End Sub
You could have a cell on one of the sheets, that will never be used,
or is hidden, that will store whether or not to run the macro, and
change that when the file is opened or when the macro is ran. Then
have a macro run on open that checks that cell. (Or custom/document property)
You could populate the cells that have the today() formula only on
open and if they are already populated then don't run the macro?
I realized that there is no need for a Workbook_Create() function, as that behavior can be emulated by simply deleting the macro after it has run once (which happens when it is first created). Deleting macros is done automatically when the file is saved with a .xlsx extension. In addition, you need to prevent the macro from running when you open the template itself (while editing the it). You can hold the SHIFT key when opening it to prevent auto-run macros, but since that method isn't foolproof, I added this code at the top:
Private Sub Workbook_Open()
'If we're opening the template, don't run the macro
If Application.ActiveWorkbook.FileFormat = xlOpenXMLTemplateMacroEnabled Then
Exit Sub
End If
...
'add code here to SaveAs .xlsx, thus removing the macros, so it won't run every time.
End Sub
(Note: I didn't show my SaveAs code as it is rather messy: I wanted to suppress the default warning about losing macros, but wanted to also protect the user from inadvertantly overwriting previous file. If anyone is interested, I could post it)
I am making my first VBA program and trying to run the following function. The function checks a specific named range for the first row which does not have a value greater than it's leading value, but less than 1.
Public Function findPurchase()
Dim CRT As Range
Set CRT = Range("CostRateTable")
Dim existsBetter As Boolean
existsBetter = True
Dim r As Integer
r = 2
Dim c As Integer
c = 4
While existsBetter
Dim Found As Boolean
FoundBetter = False
While Not FoundBetter And c <= CRT.Columns.Count
If CRT(r, c) > CRT(r, 2) And CRT(r, c) < 1 Then
FoundBetter = True
Else
c = c + 1
End If
Wend
existsBetter = FoundBetter
If existsBetter Then
r = r + 1
End If
Wend
findPurchase = CRT(r, 3)
'MsgBox(findPurchase)
End Function
I know the function does what it is supposed to because I have both manually checked the table of values, removed the comment ' from the MsgBox, and used the debug tools to step in and out of each of the functions steps as it went through the table. However, when I reference the function in Excel with =findPurchase() I'm given a #NAME? error. The function even shows up in the function auto-complete box when I begin to type its name. When I write other functions, both with and without parameters, I can reference them just fine, for example:
Function addtwo()
addtwo = 1 + 2
End Function
What am I doing wrong with my function which causes it not to work?
You are getting that error because you have a module with the same name as the function.
Change that name to say find_Purchase and everything will be fine :) See the image below...
I had the same issue myself. It turned out that I "Saved As..." another file and macros were not enabled for that file. No banner on the top appeared, but a #NAME? error was generated.
I reopened the file, enabled macros, and the problem was resolved.
Make sure you have placed the function in a Standard Module. The error message means Excel can't find the function.
When Excel opens an unkown workbook containing VBA-Code, it usually asks for macros to be enabled by the user (depending on the application settings).
If the user then enables the macros, all event-driven procedures will be started, such as auto_open or others.
Custom VBA Functions however require for a full recalculation of the workbook. Otherwise the functions return-value still is #NAME, as the calculation is only done directly after opening the workbook.
In order to work directly at the first time opening, one has to add the following line to the workbook_open event
'
' Workbook open event
Private Sub Workbook_Open()
Application.CalculateFullRebuild
End Sub
Check "Trust access to the VBA project object model" in Macro settings from Macros security
One reason for this problem is security restrictions.. I had this problem and I activate "Enable all macros" from security center, and the problem solved
I had a similar persistent problem with one of my functions when everything else seemed fine.
Open the worksheet & go to the Developer Tab. Open VBA, and back on the Developer ribbon select "View Code". See if it opens any similar Code (apart from your Module) specific to that worksheet (eg. Sheet2 (Code). I found that I had duplicated the code on the worksheet in addition to the Module. Delete the "worksheet" code. (You may need to save the workbook & re-open at this stage). When I deleted the worksheet code, the module function then worked.
In addition to checking some of the above mentioned items, you might need to specify the filename where the custom function is actually defined, e.g. cell content
=XLstart.xlsm!myCustomFunc(Arg1,Arg2)
where myCustomFunc is defined in the startup file XLstart.xlsm.
Following the Excel help for "Correct a #NAME? error":
In the formula bar, select the [suspect] function name.
In the Name Box (to the left of the formula bar), click the arrow and then select a [user-defined] function from the list that Excel suggests.
This will add the filename per the above format.
MS 2010, Windows 10.
Here's why I got that error. This answer is not provided so far.
If you have two or more workbooks (spreadsheets) open, then you may have your module under the other workbook - not the only you want to do the calculation on. This may seem impossible but ... as soon as you open the Developer/VBA code editor Excel wants to show you the structure (objects, modules, etc) of every open workbook. It's not what I expect as a developer, but there it is. So like me, you may have pressed 'Add module' and dropped the code in another workbook and worksheet.
If this is your issue, nothing mention above will work. Move your VBA module and code to the correct spreadsheet visible through this VBA code editor.
True,
I had the same (in Excel 2010) and when I migrated to Excel 2016 , the function prototype was shown, but when I completed the function, the #NAME error was shown with a pop-up... so the code was never triggered.
It turned out I had a Macro of the same name as a Sub or UDF function !
I renamed the Macro, and then it worked
Cheers
Another cause I found for the #NAME? error is that the macro workbook with the custom function has a range name the same as the function name. I changed the function name and solved the problem.
This solution applies to users with an Excel installed in another language than "United States English":
I had a similar problem when making a copy of the active workbook to duplicate it and immediately opened the copy afterwards:
Non-working code:
ThisWorkbook.SaveCopyAs NewFileName
Set wb = Workbooks.Open(FileName:=NewFileName)
This always showed me several cells with Error 2029 / "#NAME?". If I opened the Workbook "the official way" via the File-Menu it worked as expected.
I solved the issue by adding the parameter "local:=true" to the open statement:
Working code:
ThisWorkbook.SaveCopyAs NewFileName
Set wb = Workbooks.Open(FileName:=NewFileName, Local:=True)
as VBA expected english function names in my German workbook. With this parameter VBA is told directly to use the local names.
I hope that helps someone not to loose several hours, as I did...
Short answer - if the function was working before, RESTART YOUR COMPUTER.
Long answer - I had this same thing happen to me. The problem is that the function I had created had been working for months. Then one day it just started showing a #NAME error instead of working like it was before. I had tried closing all other excel workbooks and even closing excel all-together and re-opening the sheet. Nothing seemed to work. Then for kicks, I edited the code to where I knew VBA would complain that there is a compile error. Surprisingly, it didn't complain. OK... I saved and closed excel anyways and then restarted my computer.
Once rebooted, I re-opened the excel workbook. Then VBA finally gave me a compile error. So I changed my function back to the original code I had before and now the sheet is running the function like it is supposed to. No more #NAME error.
Not sure all of those steps are necessary, but simply restarting the computer seems to have fixed my issue.
I am attempting to make a custom hotkey that will go to the previous sheet viewed.
As far as I understand, this would involve making a Class Module as a Worksheet object that will capture Sheet Change, Sheet Activate, and Sheet Deactivate Events. Once the event has been captured, I would set the previous active worksheet to an object variable. Then I would make a custom macro that would go to the previously set worksheet object once a hotkey is pressed. Is this the right path?
And if it is the right path, where would I save the Macro code so that it's usable by all future workbooks? I have a PERSONAL.xlsb file created and ready to edit. Would I make the class module in PERSONAL.xlsb? How would I initialize the object in PERSONAL.xlsb when I create a new workbook?
Answers to these questions would be greatly appreciated, thank you!
Generally on the right line, but:
you only need the Deactivate event to capture the last sheet
to code this for all workbooks, you would use an Application level event handler. See cPearson site
you may want to handle WorkbookDeactivate as well
I would create a class event handler (as described in the link) including a property for the last sheet, and a Module level Sub to get the LastSheet from the class, and activate it
Update:
If I defined range as input_range from A2:P29. Then If Enter in row 30, then it works. However, the Input_range is not automatically extended and I would like to shift the whole row down not only last row in the range. How could I achieve these two things?
Previous question
Starting with the help of Siddharth Rout, I am able to make this work on new Excel file. However, no matter what I tried on this file
Sample Excel File - it just does not work. I guess there is some kind of structure to prevent from automating adding row. If so, how can I am able to make the code work?
When you're detecting the Worksheet_Change() event, you need to have your code in the worksheet object, not in a module.
Here's how to do it:
Alt-F11 to open the VBA editor
Copy the Worksheet_Change() sub from Module1
Double-click on Sheet6(itemmaster)
Paste the code in there
Make sure you see Worksheet and Change in the two drop-downs at the top of the editor.
Note: you should always have Option Explicit turned on to require variable declaration. Read this answer to see how to do it: https://stackoverflow.com/a/10653204/138938