Excel slowed down after using 'on active cell change' macro - vba

I recently experimented with a macro that runs every time the active cell column changes:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cell As Integer
cell = ActiveCell.Column
Select Case cell
'code
End Select
End Sub
I quickly realized that this slows down Excel by a lot, so I turned the macro off. The problem is that it must have turned something on, because now every time I change the active cell in any Excel file on my computer, it loads a little bit, like if that macro was still running.
I deleted the macro, restarted the computer, but nothing.
If I manually turn off events (Application.EnableEvents = False), this problem goes away, but as soon as I open another Excel file (any file, not just the one I wrote the macro in), it turns back on.
What have I done and how do I turn it off?

The way you describe it, it seems that you have Saved the Worksheet_SelectionChange event to a personal.xlsb file.
Find it, delete the code and enjoy your Friday!
https://support.office.com/en-us/article/Copy-your-macros-to-a-Personal-Macro-Workbook-aa439b90-f836-4381-97f0-6e4c3f5ee566

Related

Worksheet_Change Event not firing

My Excel project functions properly at home (with Excel 2010), but not on two work computers (with Excel 2016) and I suspect the Worksheet_Change event is the problem.
When the user makes changes, the yellow bar (in the screenshot) should turn white again, but it is not. I am getting 2 different responses on 2 work computers.
Two things to point out in the code:
In some places I use vbColor extensions, in others I had to use a numerical code.
One computer is not firing the Worksheet_Change event at all. I would note that the change event is at the top of the code, although that shouldn't have anything to do with it.
I'd appreciate advice and detailed explanations, to help me learn.
Private Sub Worksheet_Change(ByVal Target As Range) 'Check for On-Time and Delays then change the Command Button Colors to show completed.
'Return headers to white after jump to
Range("B3:I3,O3:V3,B28:I28,O28:V28,B53:I53,O53:V53,B78:I78,O78:V78,B103:I103,O103:V103,B128:I128,O128:V128,B153:I153,O153:V153").Interior.Color = vbWhite
'Check for On Time and Delayed Trips
'Trip 1 Scan Ready
If IsEmpty(Range("L3").Value) = False Then
If Range("L3").Value > Range("I3").Value Then 'If actual is greater than Departure
'If Delayed check for a delay code
If IsEmpty(Range("L24").Value) Then 'If Delay code is missing
Range("K24:L25").Interior.Color = 16711935
CommandButton1.BackColor = 16711935
CommandButton1.ForeColor = vbBlack
Else 'If Delay Code is present check for delay time
If IsEmpty(Range("L25").Value) Then
Range("K24:L25").Interior.Color.Index = 16711935
CommandButton1.BackColor = 16711935
CommandButton1.ForeColor = vbBlack
Else
CommandButton1.BackColor = vbRed
CommandButton1.ForeColor = vbWhite
Range("K24:L25").Interior.Color = vbWhite
End If
End If
Else
'Flight was on Time
CommandButton1.BackColor = 32768 '32768 = Green
CommandButton1.ForeColor = vbWhite
Range("K24:L25").Interior.Color = vbWhite
End If
End If
There could be a number of factors causing this problem. One way to diagnose is to troubleshoot like this:
At the beginning of your procedure, right after this line:
Private Sub Worksheet_Change(ByVal Target As Range)
...add a temporary line:
MsgBox "Changed: " & Target.Address
...then go change something in your worksheet (whatever change isn't firing the event as you'd expect).
One of two things will happen:
You'll have a message box pop up, showing the cell reference of whatever was just changed.
This demonstrates that the event is firing properly, so the issue must be in your code that follows.
Or, you won't get a message box pop up. This indicates the event is not firing, which could be caused by a few possibilities:
Are macros completely disabled in the workbook? This is often done automatically on workbooks received from outside sources. Save the workbook to a trusted location on the local computer or network (rather than opening from the email). Do other sections of code run properly? When you close/re-open the file, are you given a warning about Macro Security? Also, try rebooting the computer.
Other security settings could be an issue. Have you ever run VBA on these machines? You can confirm sure code is able to run in Excels' security settings in:
File→Options→Trust Center→Trust Center Settings→Macro Settings
As well as making sure macros are enabled there, you could also check Trusted Locations in the Trust Center, and either save your document in a listed location, or add a new location. Security settings will be "reduced" for documents saved in those locations.
Is EnableEvents being intentionally disabled elsewhere in your code? If you wrote all the code, you should know whether you set EnableEvents = False at some point. Perhaps it was intentional, but it's not being re-enabled.
Remember to remove the line you added temporarily, or that MsgBox will quickly get annoying by popping up every time a change is made. :)
You say "the change event is at the top of the code". A worksheet change event will only fire if you put the code in the sheet module concerned. If you've put the code concerned in a non sheet module (e.g. "Module 1" or similar, listed under the "Modules" branch in the object explorer) then that's the problem.
Also, you really shouldn't hard-code cell references like "L3" in your VBA code, because every hard reference will require amending should you (or a user) later insert rows/columns above/to the left of these references. Instead, assign meaningful named ranges to these cells back in Excel, and use those in your VBA.
Also, when using event handlers like you're doing, you should have something like If not intersect(Target, InputRange) is nothing then... so that the code only runs if something of interest changes.
I had the same problem.
I checked everything.
Everything seemed to be proper (enabled macros, EnableEvents=True, etc).
I closed and opened Excel.
Problem persisted.
There was nothing I could do.
I restarted Windows.
Problem disappeared.
Restart took 7 minutes (with all applications closing & restarting), trying to find the cause would take much more. Maybe I could have tried to find & kill every Excel process in Task Manager.
I don't like giving people the advice "try rebooting", but well, Windows is Windows.
I had a different problem. I had saved my worksheet under a new name and then added the code for the event. To get it to work, I had to close the worksheet and reopen it. It then showed the button to enable macros and the code started to work. Hope this helps someone.
Wade
I solved it simply deactivating "Design Mode" in the "Developer" tab.
It seems if you are in "Design Mode", this event (I don't know about others) won't work.
In 2019 Excel cut copy -> paste would not work the paste options were grayed out. Online sources said update and repair the app. I updated office and the copy/paste options worked.
However the worksheet_change event stopped working. After a lot debugging with no luck, I did a hail mary and commented out the subroutine and recreated it. It WORKED!! I have absolutely no idea why or how. If anyone has thoughts please share.
I had some code in a worksheet change that wasnt firing. I also had some code in Thisworkbook upon opening and saving. Resolved the issue by putting Application.EnableEvents = True at the end of the code for workbook open and workbook save.

Stop Excel from changing active sheet on Sheets.Visible = True command

I have a large workbook with many sheets used for background calculation that I hide when they are not in use. The workbook is locked down (no ribbon, sheet tabs, formula bar, etc) so it cannot be tampered with when it is in use.
In Excel 2010, everything went smoothly and the active sheet was not changed, but now in Excel 2016 the following Sub changes the active sheet to the "CompCalc" sheet which leaves the user with no way to return to the sheet they need to be on to use the workbook.
Sub MakeSheetsVisible(Status As Boolean)
Dim VarSubName As String
VarSubName = "MakeSheetsVisible"
'***********************************************************
ProtectSheets (False)
Sheets("DATA_INPUT").Visible = Status
Sheets("RAW_DATA").Visible = Status
Sheets("MASTERHISTORY").Visible = Status
Sheets("CompCalc").Visible = Status
'Sheets("Event_Enter").Visible = Status
Sheets("Raw_Chart_Data").Visible = Status
End Sub
This Sub is called at the end of a Sub that is called from another Sub which can be triggered 1 of 2 ways, on a button press or ListView double click. The active sheet is only changed in the above routine when the button is used to call the initial Sub and when the routine is ran continuously (not stepped through with F8).
I can work around this issue by checking the original active sheet at the beginning of the routine and setting it back to the original at the end, but I would like to know why this is happening and if there is a way to stop it without a workaround. Any help is appreciated
It's an annoying bug in Excel 2013/2016 and as far as I know, there is no fix. A workaround I use is:
Set CurrentSheet = ActiveSheet
'Instructions here
CurrentSheet.Activate
I only ever use active sheet if it's needed for something specific. (as per MatthewD)
But surely when you've set all your sheets to visible, you can add another line to make the sheet you want to be active?
Sheets("The one you want").Activate
would do the job? (or maybe .select?)

Setting calculation mode to automatic in Excel workbook activate event disables inter-workbook copy-paste

I have a workbook with the following VBA code to ensure the formula calculation mode is set to automatic:
Private Sub Workbook_Activate()
Application.Calculation = xlCalculationAutomatic
End Sub
If I open that workbook (let's call it WB1) and then any other workbook (WB2, opened under the same EXCEL.EXE instance), then I can't copy cells from WB2 to WB1. By "can't" I mean that when I press ctrl-v I hear Windows' "ding" sound and nothing happens.
If I use the following code instead, everything works fine.
' Now in Workbook_Open instead of Activate
Private Sub Workbook_Open()
Application.Calculation = xlCalculationAutomatic
End Sub
Is that behavior expected? Is this documented anywhere? Or is this a bug? Somehow I feel like I can't be the first person to do this.
I've tried with a C# Excel Add-In and using the equivalent Excel Interop code yields the same result.
Ok so I figured this out as I was typing the question but I'll answer anyway if someone else ever wonders...
The issue is that calling Application.Calculation = xlCalculationAutomatic makes the original workbook lose focus (the moving lines around the cells to be copied disappear, as if I had pressed escape).
Since I put my code in Workbook_Activate, it was called every time I went to copy in WB1 and caused my issue.
Moving the code to Workbook_Open is a good enough solution for me, but I like to think that making Excel non-interactive while I'm changing the calculation mode would have worked. I did not test this solution tough.

Saving values upon excel cell deletion

So, I'm back with a more specific answer/problem.
Also, I'm sorry, I picked up excel (hadn't actually used the program) a few weeks back only and minimal usage. So if the code is bad/explanations unclear, comment and i'll do my best to get this together.
I am currently in a situation with two separate (albeit linked) excel files.
Src (Book1)
Dest (Book2)
They each have one worksheet.
The idea is that Src will be modified (including deletion and insertion of rows) and i need these changes to be reflected onto Dest.
I have the insertion so far, scrounged up a little bit of code using Before_DoubleClick.
However i am having a few issues on deletion.
What i have this far is :
Private Sub Worksheet_Change(ByVal Target As Range)
Const destBook As String = "Book2"
Const destSheet As String = "Sheet2"
Dim wb1 As Workbook
Set wb1 = Workbooks(destBook)
' Here is the main problem i have. I need a better way to detect
' deletion of one or more rows. Otherwise the Application.Undo
' re-enters the if and it just loops.
If Target.Address = Target.EntireRow.Address Then
' Here i Undo the deletion to be able to copy the values.
Application.Undo
Target.Copy
' I also haven't found a way to delete again but google can help me on that
' Pasting line
'wb1.Sheets(destSheet).Cells(Target.Row, 1).PasteSpecial Paste:=xlPastValues
End If
End Sub
Ideally, what should happen is, upon deletion of one or more rows, i would like to undo the last action, copy the data, delete the row and finally past the data in another worksheet. However, as of now i am blocked at undoing the last action. It calls my VBA macro again and just starts looping.
Im not sure what you want but you either have to replace formulas with values in the new cells, or if those cells are supposed to have a formula you probably have to do
application.Calculation=xlCalculationManual
make the deletion or change then
application.Calculation=xlCalculationAutomatic
to turn autocalculation back on
Manual is tricky because if code crashed you would want to make sure you didn't leave the sheet in a state that didn't calculate

Save undo stack during macro run

I am wondering if there is a way to save ability to undo actions after macro has been run.
I do not care about results of macro - just need to undo actions that were done by user before macro.
Background:
I have a macro on the worksheet_change event that logs who and when made the change on this worksheet. I do not want it to restrict user's ability to undo his/her actions.
There is no easy way to do this, but it's possible. The approach to this is to create three macros, and use some global variables to save state:
MyMacro
MyStateSavingMacro
MyStateRevertingMacro
E.g. My macro changes Cells in Range A1:A10 of the active sheet. So, whenever the code to run my macro is called, it executes
Sub MyMacro()
Call MyStateSavingMacro()
' Copies contents and formulae in range A1:A10 to a global data object
'... Code for MyMacro goes here
'
'................
Call Application.OnUndo("Undo MyMacro", "MyStateRevertingMacro")
'This puts MyStateRevertingMacro() in the Undo queue
'So pressing ctrl-Z invokes code in that procedure
End Sub
Sub MyStateSavingMacro()
' Code to copy into global data structures anything you might change
End Sub
Sub MyStateRevertingMacro
' Code to copy onto the spreadsheet the original state stored in the global variables
End Sub
So there it is. It's not pretty, but can be done.
Ref: http://msdn.microsoft.com/en-us/library/office/ff194135%28v=office.15%29.aspx
Edit:
To preserve the Undo queue prior to your MyMacro being run, the inelegant solution would be to create a chain of 4-5 MyStateRevertingMacro_1, _2, etc. where you can apply the information from your Worksheet_Change logging system and then chain-up the Application.OnUndo in each of those, so Application.OnUndo for each of those Reverting Macros would refer the previous state reversion code.
You can use the hidden mirror sheet to do this. Of course it will work if your worksheet is simple enough. You must decide which cells are editable and copy them TO mirror sheet, which are not editable and copy them FROM mirror sheet. And your macro should work only in the mirror sheet. That's it.
This one is a bit old now but in case anyone is still trying to get this to work - I just tried setting the undo stack to be able undo the formatting on a column that a macro had reformatted and noticed that by doing that the full undo command worked (before I added this bit the undo was unavailable) - does not matter what the custom undo code contains (in my case I had not even created the routine yet), the application undo works perfectly
Application.OnUndo "Undo Amount Format", "sUndo_Col2"