I'm aware that I can use Worksheet_SelectionChange but this doesn't do exactly what I want.
For example when I move the active cell with the arrow keys it will still run the code.
How do I only make it run the code when actually physically clicking on the cell?
You can detect left clicks as well. I answered a similar question here
Insert the following code inside the specific worksheet module (for example "Sheet1"):
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If (GetAsyncKeyState(vbKeyLButton)) Then 'left mouse button
'do something here
End If
End Sub
additionally, you have to insert the following part on the top of a normal module (like the standard "Module1"):
Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
That's it. The part "do something here" can be filled by your needs.
However, this has some flaws: If you do something that finishes with a click (e.g. a MsgBox), the next selection change with arrow keys will also fire the event and re-execute your stuff. To bypass this, you can add an extra "empty"
If (GetAsyncKeyState(vbKeyLButton)) Then 'left mouse button
'blank
End If
in the end of the selectionChange Sub. As I said, there are flaws, so this won't disable all unwanted behaviour by Excel. Another one is clicking somewhere else in Excel (e.g. choosing another ribbon) and changing the selection of cells per arrow keys afterwards. Haven't found a solution to that one unfortunately.
The left mouse click cannot be trapped with VBA for the Excel application. There are some methods to check globally if the left mouse button is pressed down but it does not seem simple and reliable from what I gather. See:
http://www.experts-exchange.com/Software/Office_Productivity/Office_Suites/MS_Office/Excel/Q_28343702.html which is unresolved (basically the same question you have)
SelectionChange cannot only work for the mouse: http://excel.tips.net/T003070_Mouse_Click_Event_in_VBA.html
After lots of searching nothing on the web is conculsive about this. This may not be the answer you're looking for but I don't think you'll find what you want.
Related
I have a long running application written in VBA. Because it runs for a long time I call a sub from the main loop every iteration to check if the user has pressed the escape key. The sub is listed below. The code works great except that it is always listening, even when the VBA application does not have the focus. What's the best way to approach this? Is there an alternative to GetAsyncKeyState which only listens when the correct application is in focus, or are there system calls I can use to check that the correct window is in focus.
Private Sub checkForUserEscKeyAbort()
'Listen for escape key and exit gracefully if user aborts.
Dim abortResult As VbMsgBoxResult
If GetAsyncKeyState(vbKeyEscape) Then
abortResult = MsgBox("Escape key pressed, do you want to abort?", vbYesNo)
If abortResult = vbYes Then Call teardownSLICER
End If
End Sub
The problem is the way GetAsyncKeyState operates. It does more than just check it the key is currently down, it also checks if the key was pressed since the last time GetAsyncKeyState was called. Thus, your problem of "always listening".
You could use GetKeyState, but frankly, I'm not a fan of that option either. Your code must be well crafted to avoid a polling window that is so small that you literally have to hold the key down to ensure it isn't missed.
A viable alternative is key masking where you use a combination of keys such as Shift-Escape. There is a decent introduction to this (and many other subjects) on Chip Pearson's site. However, this is still not my preferred method.
My preference has already mentioned in the comments. Your application may best be improved with a user form. It also gives you the ability to get information in front of the user. Perhaps they wouldn't try quitting the application if a progress bar on the user form indicated 95% completion. Maybe you can add a pause button that free's some resources for a prescient need and then resumes when the user is ready. That little extra functionality on its own is enough to win me over but there is an even better reason for using a User Form - it does exactly what you asked!
User forms, and many user form controls, have Keydown, Keyup, and Keypress events that only trigger when the form (or control) have focus. This is precisely what you wanted.
I've gone through a number of tutorials and instructional videos trying to achieve my intended result of simply allowing a checkbox in my form to hide content when selected, or re-show it when being de-selected, but nothing seems to be working.
Currently, I've created a bookmark for the content I want hidden, and try to call his this in VBA with the following statement - which a number of resources indicated as the solution:
Private Sub CheckBox1_Click()
ActiveDocument.Bookmarks("bookmark").Range.Font.Hidden = CheckBox1.Value
End Sub
But despite doing this, selecting the checkbox has no affect on the content.
Is there something additional I'm missing (I'm using Microsoft Word 2013).
Your code worked fine when I tested it, but I ran into a few issues since I've never messed with userforms/checkboxs in Word VBA and I suspect you may have the same.
For instance, the first thing I did was create Insert --> Module. This is incorrect. What you want to do is Insert --> Userform then drag a checkbox over from the ToolBox
https://smallbusiness.chron.com/use-check-boxes-word-54673.html
Then double click the checkbox to bring up the "module" it would run, notice there is no module in the side pane! Edit the module, then go back to the userform and press F5. You should be presented with a checkbox that will hide/unhide your text.
Here is my module:
Public Sub CheckBox1_Click()
ActiveDocument.Bookmarks("bookmark").Range.Font.Hidden = CheckBox1.Value
End Sub
Here is an image:
Note: I didn't test how to insert the checkbox into the word doc, I'll leave you some of the learning!
Update:
This sub will make the CheckBox appear when run, but I'm not sure the logic you would use to call it, perhaps an event like opening of document?
Sub Loadform()
Load UserForm1
UserForm1.Show
End Sub
This could be called via a keyboard shortcut or event, but this will cause a "pop-up window". If you want an inform checkbox you may need to look into using this Legacy Form/Checkbox. I was following the URL from above but I think it's dated.
Update:
You could also add this easily to a toolbar, but that isn't likely what you want. I found the best way is to use a "field code" see --> https://word.tips.net/T001571_Assigning_a_Macro_to_a_Button_in_Your_Text.html
I was able to get this to work by pressing CTRL + F9 then typing { MacroButton Loadform ClickMe} then clicking this text. This may be the best bet as using an image seems not to be a great idea.. (https://answers.microsoft.com/en-us/msoffice/forum/all/using-graphic-with-macrobutton/a9c1ef3b-cf1f-48ba-92a8-c44bffcdc131) & (http://www.addbalance.com/usersguide/parts/macrobutton_fields.htm#Different_behavior)
Gif Example:
I am looking for a simple macro I could activate with a form control button that would clear all of the form control option buttons on my sheet.
I have lists of options for industrial part specifications, of which only one may be selected per section. However, once one is selected, the form control option button stays filled in. I previously circumvented this by using checkboxes, where if you click the box again it will remove the check mark. However once I learned that I was to create the form in such a way that only one option could be selected per section, (for ease of use in case a less computer minded person were to use it) it became clear that option buttons were the right way to go.
So I need a simple macro that I can activate with a button that will clear these option buttons all to blank, as if none were selected. I have looked and tried some strings of code, but none have worked so far. Perhaps I am missing something obvious or looking for the wrong thing, but I dont think I am.
I have checked the following pages and tried their code:
http://www.mrexcel.com/forum/excel-questions/689865-how-clear-all-checkboxes-option-buttons-list-boxes-form-3.html
Re-setting all option buttons at once
http://www.excel-easy.com/vba/examples/option-buttons.html
I feel like this should be simple. A VBA macro code that will reset the FORM CONTROL Option Buttons to blank (which I believe is the false state?). No need to worry about having specific ranges to clear; one button to reset the sheet will do perfectly.
Thanks in advance for any help.
Cycle through the Shapes collection:
Sub Reset()
For Each vCtrl In ActiveSheet.Shapes
vCtrl.DrawingObject.Value = False
Next
End Sub
I just want to connect two arbitrary controls, so that if one is clicked, the other should act as though it's clicked - is this even remotely possible? it seems like it SHOULD be so easy, but the internet seems dry, unless I just don't know how to ask the question properly... I see a way to "click" a button control, but what if the target is not a button? - I don't know the name of any function that might be triggered by this control's click event, so I can't call it directly. I would guess there is some way of using Windows APIs, but I can't find anything that's nice, simple VB
Example
I click a Label control on the form. I want to handle that click event, run one line of code, then simulate a click event on an associated RadioButton control
Is this possible? How?
If you must, call (System.Windows.Forms.Controls.)Control.InvokeOnClick
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokeonclick%28v=vs.71%29.aspx
or even RadioButton.PerformClick
http://msdn.microsoft.com/en-us/library/system.windows.forms.radiobutton.performclick.aspx
A better way would be to create a common Subroutine that would be called on click of either controls. This way clicking on controls will execute their own code which can differ, and some common code as well.
This is how you accomplish executing the same code regardless of which control event was fired.
Private Sub ClickMe()
'code to execute
End Sub
Private Sub label1_Click(...) ...
ClickMe()
End Sub
Private Sub rb_checked(...) ...
ClickMe()
End Sub
Needing some help attaching an Excel/VBA button on an Excel sheet. I need it to stay in the same position on the screen regardless of how I scroll or zoom. Preferably, I need this on the bottom left or right of the screen.
I have tried adding a button. Then, I right clicked on the button. Clicked on Format Controls -> Properties -> selected Don't Move or Size With Cells. Am I missing something that's making this not work?
Thanks!
I know this post is old, but here's to anyone it could be useful. The VisibleRange property of ActiveWindow can solve this problem. Use something like this:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
With ActiveSheet.OLEObjects("MY_BUTTON'S_NAME")
.Top = ActiveWindow.VisibleRange.Top + ActiveWindow.VisibleRange.Height - 5
.Left = ActiveWindow.VisibleRange.Left + ActiveWindow.VisibleRange.Width - .Width - 5
End With
End Sub
Here is the idea that I put across the comment earlier today :) Typically we can get a Floating User Form by setting the Modal property of the form to be 0 which is indeed a Modeless state.
Basic Points to consider:
Look & Feel of the form to make it look like a Button (Not show title bar/Not Resizable/
Hidden Close Button etc)
Setting the position of the Button
Which Event should trigger the form-button (WorkBook Open)
What would you do with Form Initialize Event
Whcih Events should keep it stick to the same position alive
Further Points to consider:
You might only want to keep this button vissible for the workbook you are working, and if you open another instance of a workbook, do you still want to keep the button
If you minimize the Excel Window instance, how do you plan to manage the state of the button and keep it visible
Post about keep displaying a form even the workbook is minimized.
One other great reference I happend to see, (little bit technical) but worth the shot - at least to get to know the certain properties/methods that you could make use: Extending VBA User Form Control.
The article include the following info, and please note the last line as well :)
They give you access to capabilities that are not available from VBA or from the objects (UserForms, Workbooks, etc.,) that make up a VBA Project. When you call an API, you are bypassing VBA and calling directly upon Windows. This means that you do not get the safety mechanisms such as type checking that VBA normally provides. If you pass an invalid value to an API or (a very common mistake) use a ByRef parameter instead of a ByVal parameter, you will most likely completely and immediately crash Excel and you will lose all your unsaved work. I recommend that until you are confident that your API calls are solid you save your work before calling an API function.
Add new Row on the beginning of your WorkSheet and set your button on it, then:
Freeze Top Row
Right click → properties → placement → change to 3.