I know how to assign a macro to a cell and launch when it has changed.
I know how to assign a macro to a 'button' and launch it when clicked.
I know how to assign a macro to a worksheet and launch when any cell has changed.
But now ..... I have a text box in a chart and wish to have a macro launch AFTER the text box has been moved to a new location. Currently, I click on a 'button' after I move the text box and this works well. I would like to eliminate the final step in order to avoid a problem if the user fails to click the button.
If there is no built-in Event associated with a worksheet property or characteristic you wish to monitor, you can always use an Application.OnTime macro to monitor the item.
For example the TopLeftCell.Address of a Shape can be monitored from call to call and action taken if the property changes.
Some some information see OnTime
I think you can found what you want Here.
Related
Macros on my spreadsheet that have been working for years, stopped working via buttons, though they still work from the VBA Developer window.
I use a normal shape (rectangle) as the button and assigned the macro to it (selecting from "ThisWorkbook").
To head off suggested fixes I've seen for other similar posts:
It is still an .xlsm file
Macros are still enabled.
It's running on the same laptop as before (Windows 10, Office 365).
No Windows updates have occurred lately.
I only have this one file open.
I tried rebooting laptop and restarting Excel.
I'm not using an Active-X Control.
I tried it with a Form Control button and a regular Shape button - neither work.
It's not related to the actual VBA code (see below for proof).
I created a new program to show the problem is not the code itself:
Sub button_not_working()
MsgBox "button_not_working"
End Sub
This program works using the green Play button in the VBA screen, but not via an assigned button on a sheet.
Code is in a normal VBA code Module (not "ThisWorkbook" area on VBA screen).
Macro is assigned by right-clicking shape, and the list of available Macros is just those in "This Workbook" on the Assign Macro popup.
When clicking the Shape to run the assigned macro I get this error message.
You can't call code from ThisWorkbook in a button event.
I like to put the button events in the code behind the sheet where the button lives. This way the code move with the sheet wherever that sheet is copied.
Use a form button. Right-click on the form button and select Assign Macro.... Then select the VBA subroutine from the list that pops up. Only procedures visible on this popup will work.
NOTE:
Never use _ in any names in VBA. It's reserved for event handling.
Public Sub ButtonIsWorking()
MsgBox "button is working"
End Sub
Code in sheet:
Assign Macro:
Button press:
Often this issue can occur due to multiple screens or resolution difference issues. If you are using a laptop connected to screens try using the button on the laptop while it's disconnected from your monitors. If this fixes the issue then ensure you have the same resolution and/or scaling between the two setups.
If this change only happened recently and is on a desktop or laptop screen without additional monitors ensure your scaling is set to 100% in case it has recently changed.
Solved - turned out I needed to check the box for "Enable Excel 4.0 Macros".
Apparently, Microsoft has just started disabling this by default in Office 365 starting this month!
So in Excel... File>>Options>>Trust Center>>Trust Center Settings>>Macro settings
Something to try: Make sure your 'caller' shapes have unique names
Note: It's possible to have multiple shapes with the same name and (for whatever reason) that can confuse excel's shape-to-macro-connection.
Additional Info 1:
If you use a 'grouped shapes' object as a control, you should assign the same name to all shapes in the group.
Additional Info 2:
The original OP symptom was simply "Macros ... stopped working via buttons." The OP has since been updated, and shows an error message. The disconnect-due-to-non-unique-naming described here doesn't elicit an error message. Rather the symptoms can be either of: a) the macro isn't run at all or b) the 'caller' object in the called macro is invalid.
Macros on my spreadsheet that have been working for years, stopped working via buttons, though they still work from the VBA Developer window.
I use a normal shape (rectangle) as the button and assigned the macro to it (selecting from "ThisWorkbook").
To head off suggested fixes I've seen for other similar posts:
It is still an .xlsm file
Macros are still enabled.
It's running on the same laptop as before (Windows 10, Office 365).
No Windows updates have occurred lately.
I only have this one file open.
I tried rebooting laptop and restarting Excel.
I'm not using an Active-X Control.
I tried it with a Form Control button and a regular Shape button - neither work.
It's not related to the actual VBA code (see below for proof).
I created a new program to show the problem is not the code itself:
Sub button_not_working()
MsgBox "button_not_working"
End Sub
This program works using the green Play button in the VBA screen, but not via an assigned button on a sheet.
Code is in a normal VBA code Module (not "ThisWorkbook" area on VBA screen).
Macro is assigned by right-clicking shape, and the list of available Macros is just those in "This Workbook" on the Assign Macro popup.
When clicking the Shape to run the assigned macro I get this error message.
You can't call code from ThisWorkbook in a button event.
I like to put the button events in the code behind the sheet where the button lives. This way the code move with the sheet wherever that sheet is copied.
Use a form button. Right-click on the form button and select Assign Macro.... Then select the VBA subroutine from the list that pops up. Only procedures visible on this popup will work.
NOTE:
Never use _ in any names in VBA. It's reserved for event handling.
Public Sub ButtonIsWorking()
MsgBox "button is working"
End Sub
Code in sheet:
Assign Macro:
Button press:
Often this issue can occur due to multiple screens or resolution difference issues. If you are using a laptop connected to screens try using the button on the laptop while it's disconnected from your monitors. If this fixes the issue then ensure you have the same resolution and/or scaling between the two setups.
If this change only happened recently and is on a desktop or laptop screen without additional monitors ensure your scaling is set to 100% in case it has recently changed.
Solved - turned out I needed to check the box for "Enable Excel 4.0 Macros".
Apparently, Microsoft has just started disabling this by default in Office 365 starting this month!
So in Excel... File>>Options>>Trust Center>>Trust Center Settings>>Macro settings
Something to try: Make sure your 'caller' shapes have unique names
Note: It's possible to have multiple shapes with the same name and (for whatever reason) that can confuse excel's shape-to-macro-connection.
Additional Info 1:
If you use a 'grouped shapes' object as a control, you should assign the same name to all shapes in the group.
Additional Info 2:
The original OP symptom was simply "Macros ... stopped working via buttons." The OP has since been updated, and shows an error message. The disconnect-due-to-non-unique-naming described here doesn't elicit an error message. Rather the symptoms can be either of: a) the macro isn't run at all or b) the 'caller' object in the called macro is invalid.
I have written a code to open a workbook and filter data by the number in a particular column. I need to filter "0" first and then edit the data and then filter between "+8" and "-8".
I added a message box to pause the macro but I am not able to edit the opened workbook while the message box is displayed. I tried with "Application.waiting" option.
I need to pause the macro automatically and start it manually.
Sub Filter_data()
Workbooks.open"D:\Reposrts\AAA.csv"
Activesheet.Range("I1:I100").Autofilter field:=1,Criterial:="0"
Activesheet.columns("A:Z").Autofit
MsgBox"Task ok" 'Here I need to pause the macro and allow for edit opened wb and then manually start macro for below line'
Activesheet.Range("I1:I100").Autofilter field:=1,Criterial:=">8", Opersator:=xlAnd, Criterial:="<-8"
End Sub
Split your existing Macro into two parts
The first part contains everything up to have the MsgBox"Task ok" line
The second part contains everything after that point
Create a Modeless (or "Non-Modal") User Form with your label and an "OK" button to call the second part of your split macro
"Modeless" means you can edit the workbook while the User Form is open. MsgBox is "Modal", which is why you can't edit anything. More details available from Microsoft
Replace the MsgBox"Task ok" line in the first part of your split macro with a line that opens your User Form.
Once the first half-macro has finished, and the User Form is waiting for you to click "OK", you will be able to edit workbooks. Once you click "OK", the second part will start.
It is probably best to first consider if the "edits" you need the user to make are possible via VBA, a User Form, or a DialogBox (which include the likes of the "Select Range" DialogBox, or the "Colour Picker" DialogBox)
I would recommend you not to try to edit the Workbook while a macro is running- I don't even think that is possible at all. Furthermore, try not to refer to ranges by activating/selecting ranges.
Activesheet.Range("I1:I100").Autofilter 'Instead of this use the code below
With Workbooks("AAA.csv")
.Sheets("NAME").Range("I1:I100).Autofilter
'More code
End With
Like Chillin mentioned, you could assign hotkeys to your filter macros- split them in two. Other than that, you can use buttons to activate the macros.
To assign a keyboard shortcut to a macro:
Press ALT+F8 to open the macro dialog box. Select the macro, and click on Options. In the window that opens you can assign a keyboard shortcut to the macro you selected.
I've researched this to death and feel like I'm the only person it's ever happened to.
I have some VBA that:
Creates a copy of 3 sheets to a new wb
In the new wb converts to values, deletes objects (shapes and controls) and all but 3 ranges
Opens an existing third file and sets the contents of three ranges in that to match the new wb
Closes the existing file (saved)
Closes the new wb (saved)
Gives a message box saying complete
At the end of all this, something weird happens with the state of the windows. The selected cell does not appear selected. If I try and click a control afterwards, it selects the object (hence users could drag them). It shouldn't and this is the big problem.
I've tried selecting a cell through code, it throws an error. I had limited success by forcing drawing mode off using Call CommandBars("Drawing").Controls("Select Objects").Execute and activating a specific sheet & selecting a cell. However, even then if I even click on a few cells afterwards, the next time I select a control it will select it as an object rather than click the thing.
I have no idea why and can't find anyone who's seen this before.
Any ideas on what I can do?
Thanks,
Basil
I didn't figure it out entirely, but I did find a fix. Hopefully it works for anyone else who finds this problem.
At the end of the code I added this:
ActiveSheet.Shapes.Range("ctrlExportPrices").Select
ActiveSheet.Range("B8").Select
So it forced a control on the sheet to be selected, and then a cell.
The next time I select the control manually, it clicks it rather than selecting the drawing object.
ActiveX combobox objects in Excel do not behave well when their ListFillRange refers to a formula-based Named Range (Defined Name).
I think I have encountered other errors and possibly even Excel crashes thanks to this, but right now all that happens is the combobox_change() event is triggered anytime ANY cell in the workbook is changed.
I am not sure if this is really a bug, or if there is a fix, or a workaround. If it is a bug, how do I report it to the Excel people?
And finally, the real meat of my question is "How do I work around this issue best?" I would like to have some formula-based named ranges, but it seems like this won't be possible.
To reproduce this bug, do the following:
Create a new workbook. On Sheet3, create a small table 3 columns across, and several rows high.
Create a named range with this formula (or an equivalent): =OFFSET(Sheet3!$A$2:$C$36,0,0,COUNTA(Sheet3!$A:$A),COUNTA(Sheet3!$4:$4)) To do this use Input>Name>Define. Name the range something like "demoRange"
Go to Sheet1 and create a combobox, (it must be on a separate sheet). (Use the Control Toolbox menu, not the Forms menu).
Click on the Design Mode button (the blue triangle with pencil), then right click on the combo box and go to Properties.
In the properties window for the combobox, change the ListFillRange property so that it points at the named range you created in step 2 ("demoRange").
You may want to change the ColumnCount property to 3, and the ColumnWidths property to "50,50,50"
Set the linkedCell property to cell "A1" by typing A1 in the linkedCell property.
Close the properties window, and double click on the combobox to define its change() event.
Put a Debug.Assert(false) or Msgbox("demo") line in the subroutine for the new combobox's change event.
Exit design mode
important - Now select an item in the combobox. The event should trigger normally the first time. (The bug will not show if you don't do this step--something must be selected in the combobox)
Edit cells anywhere in the workbook [Edit] or any other open workbook [/edit], on any sheet and any location. Each time you edit any cell, (at least for me), the onchange event for the combo box is run.
Again, is this normal, and what is the best alternative for what I am doing? This combo box gets linked to various cells, and is supposed to be a replacement for the tiny font in the data validation dropdowns excel provides by default.
My advice is to never use ListFillRange and LinkedCell. They are just trouble. Fill your listbox with List and use the Change event to write to the cell. Somewhere, maybe the Workbook_Open event, fill the listbox
Private Sub Workbook_Open()
Sheet2.ListBox1.Clear
Sheet2.ListBox1.List = Sheet1.Range("demoRange").Value
End Sub
Then in the change event in the Sheet2 module, check that something was clicked and write it to the cell
Private Sub ListBox1_Change()
If Me.ListBox1.ListIndex >= 0 Then
Sheet2.Range("A1").Value = Me.ListBox1.Value
End If
End Sub
I have a few options available that I am aware of thus far. The best I can come up with is this:
Avoid directly using formula-based named ranges. Instead, define a subroutine that will check whether the defined range "demoRange" should be changed from what its current value is. Run this subroutine on the workbook_open and sheet3_deactivate events. If needed, prompt the user to ask if it's all right to update the named range. [edit] The macro that updates "demoRange" could probably just copy from a "demoRange_FormulaBased" named range into "demoRange" which would be static. [/edit]
This solution works well because you can keep using the linkedcell property, you don't have to use VBA to populate the comboboxes, and the named range can still be used for whatever other purposes it already had. Avoid using the onchange event to run this new subroutine, since it might end up being triggered thousands of times if a user opens the Find/Replace dialog and chooses "Replace All".