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
Related
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 downloaded this macro to apply names to worksheets (worth noting that this page is also referenced in Microsoft's help pages somewhere). But when I try to run the macro, it's like it doesn't exist. If I select Macros from the Developer tab, it's not there (and yes, I've checked "all open workbooks"). If I open the VB editor window and open the module, I can see the code, but selecting Run or Debug
F8 does nothing at all. No error, no highlighted code. All works as expected for all my other macros.
This is Excel2010 on Windows7Enterprise.
Any ideas?
You do not run this macro. It goes into the Worksheet_Change event which is the specific Worksheet object module (ie. Sheet1 object module, Sheet2 object module, etc).
It is an event that fires automatically when you modify a cell in worksheet.
There instructions how to run this are actually on that web so it's worth reading them! :)
This is where the code should be placed
You can read more about the Worksheet_Change() event here
Just in case you still wander how to run this
place the code in the Sheet1 object module code area
go back to your spreadsheet Sheet1
type in a name in cell A1, and your sheet1 name will immediately change to whatever you've typed as long as it doesn't cause macro to exit at some point. The restrictions are mentioned here
I have an old workbook (made by someone years ago) with a few worksheets in it. When I open this workbook, Excel complains with messages like 'Cannot find ActivateWorksheet', 'Cannot find DeActivateWorksheet'.
There are no event handlers in the code. I want to avoid getting these messages from Excel but could not find how to reset them. I checked the OnSheetActivate, OnSheetDeactivate etc properties to see if some macro is assigned but found them to be empty.
Is there any other place where I can check and remove these handlers?
It might be related to AddIns - do you have all the necessary AddIns installed?
There's one more place to look: NamedRanges. I found that the worksheet has Names defined with values such as "=ActivateWorksheet", "=DeActivateWorksheet" but these macros were nowhere. When a worksheet is activated, the Names on that sheet is refreshed (or recalculated) and i my case the macro were being called.
I need a way to programatically launch the macro-recorder in Excel, and supply the name for the new macro that will get created.
This can be from VSTO or VBA, or using the Office interop assemblies.
Any ideas how this can be accomplished?
In VBA:
Dim ctrlStart As CommandBarControl, ctrlStop As CommandBarControl
Set ctrlStart = Application.CommandBars.FindControl(ID:=184)
Set ctrlStop = Application.CommandBars.FindControl(ID:=2186)
ctrlStart.Execute
'name part would go here, but first you have to deal with a modal dialog
ctrlStop.Execute
It looks like the Execute method on the RecordMacro control opens a modal dialog. There is no way to feed a parameter to this, or to do anything like SendKeys. The only way I see to do it is to write a sub that will rename the macro after the fact. It will be a little complicated to determine what the name of the new macro is, and you will still have a dialog box to deal with.
Where can I find a list of events in Excel? I want to write macros in VBA based on them. I already know of Worksheet_BeforeDoubleClick, but I more or less just discovered that randomly/remembered it was used in Access.
Does anyone have a complete list or know where I can find one of the different events in Excel?
Here is the excel object model overview which you can use to navigate to the members of each model.
http://msdn.microsoft.com/en-us/library/wss56bz7(VS.80).aspx
You would use this to get to:
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.application_members.aspx
Scroll down for events.
These are some good links to learn about Excel's events:
Beginning VBA: Events
Event Macros, Worksheet Events and
Workbook Events
Events in Excel VBA
Another way to find them is open the VBE (Alt+F11), click on the object's class module (such as ThisWorkbook or Sheet1), and use the drop down boxes at the top of the code panel. If, for instance, you select ThisWorkbook from left drop down, the right drop down will contain all of the events available to you.
For objects that aren't Workbook or Worksheet (Application, QueryTable, etc), create a custom class module in your project (Insert - Class Module) and type (for example)
Public WithEvents qt As QueryTable
Now 'qt' will appear in the left drop down and all of the events for a QueryTable will appear in the right one. You'll notice that the Intellisense only shows a limited number of objects when you include WithEvents. These are the only objects that have exposed events. So you can't type
Public WithEvents rng As Range
because the Range object doesn't expose any events. A little more cumbersome than James' answer, but a nice way to browse the events when you know the object and to get a list of objects with exposed events.