ComboBox inputbox causes reselection of range - vba

Currently I'm working on a userform prompting an inputbox for a range whenever the combobox dropdown button is clicked.
The problem is that whenever the range is selected (selecting a cell and then clicking ok), the userform is unselected (greys out), shows an empty dropdown list and forces me to reselect a range after I click anywhere on the workbook.
Is there any way to prevent a re selection of a range when clicking the dropdown button?
Code Below:
Private Sub ComboBox1_DropButtonClick()
Dim InputCell As Range
Set InputCell = Application.InputBox("Select Lookup Cell", "Obtain Object Range", Type:=8)
ComboBox1.Text = InputCell.Address(0, 0, external:=True)
End Sub

When I've used the RefEdit object in the past, I used the real thing (which I know has it's issues) and just used the Change event.
Perhaps you could just use the Enter event (you just have to ignore it the first time, if's it the first object that gets focus when initialized)
Resources:
Using RefEdit Controls in Excel
Dialogs - Jon Peltier
RefEdits must be placed directly on the UserForm itself. If you put a
RefEdit in a frame or on a multipage, strange things will happen,
including bizarre Excel crashes.
RefEdits must not be used on modeless forms. RefEdits on modeless
forms will result in bizarre Excel crashes.
RefEdit event procedures should be avoided. RefEdit events do not
behave reliably, and they may result in VBA errors which are difficult
to debug.
References to RefEdits must be removed. When a UserForm is added to a
VB project, Excel adds a reference to the Microsoft Forms 2.0 Object
Library. This reference is required for proper operation of the
UserForms in your project. To see what references your project has,
select the project in the Project Explorer, then select References
from the Tools menu.
Alternative to Excel’s Flaky RefEdit Control - Jon Peltier
The new approach uses a TextBox in the dialog instead of the RefEdit.
The TextBox does not interact directly with a range as does the RefEdit. Instead, when this drop button is clicked, the dialog is temporarily hidden, and an InputBox appears to solicit the user’s input.
"It may be tempting to use type 8 to indicate a range object, but there
is an obscure glitch that causes it to fail when the worksheet
contains conditional formatting conditions that use formulas in their
definitions. Fortunately using Type 0 to specify a formula works just
fine."
Cannot use keyboard shortcuts to select ranges in RefEdit control in Excel

From this source: Ozgrid
Though I'll be using custom text boxes, this could also work if anyone wants to use the combo boxes.
Private Sub ComboBox1_DropButtonClick()
Static Abort As Boolean
If Abort Then Exit Sub
Abort = False
Dim InputCell As Range
Set InputCell = Application.InputBox("Select Lookup Cell", "Obtain Object Range", Type:=8)
ComboBox1.Text = InputCell.Address(0, 0, external:=True)
Abort = True
End Sub

Related

How to use Events with Option Button Controls on Userform [duplicate]

This question already has answers here:
Assign code to a button created dynamically
(2 answers)
Closed 4 years ago.
I am trying to add an option button from the range in the Excel worksheet.
For Each Value In OptionList
Set opt = UserForm3.Controls.Add("Forms.OptionButton.1", "radioBtn" & i, True)
opt.Caption = Value
opt.Top = opt.Height * i
opt.GroupName = "Options"
UserForm3.Width = opt.Width
UserForm3.Height = opt.Height * (i + 2)
i = i + 1
Next
I want to create an event handler so that if radiobtn1 is selected while running the code from the user. Alhough I got a lot of answers, those are meant for worksheet user form.
My intention is to work on the VBA user form. Please help me with your thoughts.
There is only one type of userform, however there is [eternal] confusion surrounding the two types of controls available to Excel — exacerbated by the contrasting terminology used by different online sources. (Only the sections about ActiveX controls apply to userforms.) Perhaps I can help shed some light by putting it in words that help me understand. ☺
Overview:
There are two types of controls: Form controls and ActiveX controls:
Both types of controls can be used on worksheets but only ActiveX controls can be used on userforms.
Form controls are part of the Shapes collection (just like Drawing Objects), and thus are referred to like:
ActiveX controls are basically part of the worksheet and are therefore referred to like:
Both types of controls can be created, modified and deleted from either the worksheet, or programmatically with VBA, however, the 2 types of controls have slightly varying syntax when using VBA to refer to them.
Some sites discuss also discuss a Data Form. This is nothing more than a userform made specifically for data entry/manipulation of data, so it would've made more sense to call them (the more familiar sounding) "Data Entry Userform".
Office documentation also occasionally refers to a worksheet as a form. While this is technically correct, don't let this confuse you. Think of the word "form" as being used in a general sense:
Two Types of Controls
Form Controls
ActiveX Controls
The two look, behave, and are controlled similarly, but not identically. (List here.)
For example, let's compare the two types of Combo Boxes. In some programming languages, comparable controls are referred to as a "drop-down menu" or "drop-down list". In Excel, we have a "Form Control Combo Box", and an "ActiveX Control Combo Box":
(Click image to enlarge.)
☆ "Default name" applies to controls created manually. Controls created programmatically do not have (or require) a default name and therefore should have one assigned immediately upon creation.
(Source: my answer)
About ActiveX controls and related security concerns
An ActiveX control is an extension to the VBA Toolbox. You use ActiveX controls just as you would any of the standard built-in controls, such as the CheckBox control. When you add an ActiveX control to an application, it becomes part of the development and run-time environment and provides new functionality for your application.
An ActiveX control is implemented as an in-process server (typically a small object) that can be used in any OLE container. Note that the full functionality of an ActiveX control is available only when used within an OLE container designed to be aware of ActiveX controls.
This container type, called a control container or control object, can operate an ActiveX control by using the control’s properties and methods, and receives notifications from the ActiveX control in the form of events. The following figure demonstrates this interaction:
(Source: this and this)
See also:
Wikipedia: ActiveX
Symantec.com : Discussion of ActiveX Vulnerabilities
How-To Geek : What ActiveX Controls Are and Why They’re Dangerous
Option Buttons (Radio Buttons)
In Excel, the two types of radio buttons are actually called Option Buttons. To further confuse matters:
the default name for the form control is OptionButton1.
the default name for the ActiveX control is Option Button 1.
A good way to distinguish them is by opening the control's Properties list (on the ribbon under the Development tab, or by right-clicking the control and choosing Properties, or hitting F4), because the ActiveX control has many more options that the simpler form control.
Option buttons and checkboxes can be bound together (so only one option at a time can be selected from the group) by placing them in a shared Group Box.
Select the group box control and then hold Ctrl while selecting each of the other controls that you want to group. Right-click the group box control and choose Grouping → Group.
The first two links below are separate sets of instructions for handling each type of option button.
HANDLING CONTROL EVENTS:
Form control events (Click event only)
Form control events are only able to respond to one event: the Click event. (More info here.) Note that this section doesn't apply to userforms since they use only ActiveX controls.
To add a procedure for the Click event:
Right-click the control and choose Assign Macro...
In the 'Assign Macro` Dialog:
Select an existing procedure, and click OK, or,
Create a new procedure in the VBE by clicking New..., or,
Record a new macro by clicking Record..., or,
to Remove the assigned event, delete its name from Macro Name field and click OK.
(Click image to enlarge.)
To rename, edit or delete existing macros, hit Alt+F8 to open the Macro interface:
ActiveX control events
ActiveX controls have a more extensive list of events to which they can be set up to respond.
To assign events to ActiveX controls, right-click the control and choose View Code. In the VBE, you can paste in code, or choose specific events from the drop-down list at the top-right of the VBE window.
(Click image to enlarge.)
Control event handling on a userform:
Events can also be used in controls on userforms. Since only ActiveX controls can be placed a userform, you'll have the "more coding + more functionality" trade-off.
ActiveX controls are added to userforms the same way as they are added to a worksheet. Keep in mind that any events assigned to the userform itself (ie., background) will be "blocked" in any areas covered up by a control, so you may need to assign the same events to the controls as well as the userform.
For example, in order to make this userform respond to MouseMove anywhere on the form, the same event code was applied to the userform, textboxes, option buttons and the frame:
VBA EXAMPLES
Add/Modify/Delete a form control option button using VBA:
Sub formControl_add()
'create form control
Dim ws As Worksheet: Set ws = ActiveSheet
With ws.Shapes.AddFormControl(xlOptionButton, 25, 25, 100, 100)
.Name = "cOptionButton1" 'name control immediately (so we can find it later)
End With
End Sub
Sub formControl_modify()
'modify form control's properties
Dim ws As Worksheet: Set ws = ActiveSheet
ws.Shapes("cOptionButton1").Select
With Selection 'shapes must be Selected before changing
.Characters.Text = "wxyzabcd"
End With
End Sub
Sub formControl_delete()
'delete form control
Dim ws As Worksheet: Set ws = ActiveSheet
ws.Shapes("cOptionButton1").Delete
End Sub
Shapes.AddShape Method (Excel)
Shape Properties (Excel)
Characters Object (Excel)
Add/Modify/Delete an ActiveX command button using VBA:
Sub activexControl_add()
'create ActiveX control
Dim ws As Worksheet: Set ws = ActiveSheet
With ws.OLEObjects.Add("Forms.CommandButton.1")
.Left = 25
.Top = 25
.Width = 75
.Height = 75
.Name = "xCommandButton1" 'name control immediately (so we can find it later)
End With
End Sub
Sub activexControl_modify()
' modify activeX control's properties
Dim ws As Worksheet: Set ws = ActiveSheet
With ws.OLEObjects("xCommandButton1").Object
.Caption = "abcxyz"
.BackColor = vbGreen
End With
End Sub
Sub activexControl_delete()
' delete activeX control
Dim ws As Worksheet: Set ws = ActiveSheet
ws.OLEObjects("xCommandButton1").Delete
End Sub
OLEObjects.Add Method (Excel)
BackColor, ForeColor Properties (ActiveX Controls)
Add/Remove items from a form control combo box:
Sub ComboBox_addRemoveItems_FormControl()
Dim ws As Worksheet: Set ws = ActiveSheet
'add item to form control combo box
ActiveWorkbook.Sheets("Sheet1").Shapes("Drop Down 1").ControlFormat.AddItem "abcd"
'remove all items from from form control combo bo
ActiveWorkbook.Sheets("Sheet1").Shapes("Drop Down 1").ControlFormat.RemoveAllItems
End Sub
Add/Remove items from an ActiveX combo box:
Sub ComboBox_addRemoveItems_ActiveXControl()
Dim ws As Worksheet: Set ws = ActiveSheet
'add items to ActiveX combo box
ActiveWorkbook.Sheets("Sheet1").ComboBox1.AddItem "abcd"
'remove all items from ActiveX combo box
ActiveWorkbook.Sheets("Sheet1").ComboBox1.Clear
End Sub
More Information:
Office.com : Add a checkbox or option button (Form controls)
Office.com : Add a checkbox, option button, or toggle button (ActiveX controls)
Office.com : Overview of forms, Form controls, and ActiveX controls on a worksheet
Office.com : Enable selection through choice controls (check and list boxes)
Office.com : Add, edit, find, and delete rows by using a data form
MSDN : VBA Shape Members
MSDN : Using ActiveX Controls on Sheets (Office)
Exceldemy : How to Use Form Controls in Excel
MSDN : Using Windows Forms Controls on Excel Worksheets (Visual Studio)
Microsoft TechNet : Behaviour of ActiveX controls embedded in Office documents

Running a VBA script from a button after selecting a chart

I’m running Excel 2010 on Windows 7.
I have four charts on a worksheet. What I want to do is select one of the charts and then click a button to open the ‘Format Axis’ dialogue box. I found the following code online to open the dialogue box. If I select a chart and then run the code from the toolbar (Developer tab, Macros, select macro, press ‘Run’), it works well.
Sub formatXAxis1()
ActiveChart.Axes(xlCategory).Select
Application.CommandBars.ExecuteMso "ChartFormatSelection"
End Sub
The trouble I have is when the VBA script is assigned to a button. If I use a shape as the button, I get “Run-time error ‘91’: Object variable or With block variable not set”. I get the same error if I use an ActiveX Command Button. However, with a Form Control button it works as expected. The only problem with this solution is that it is not possible to change the background colour of the button so it looks out of place against the other macro calling buttons on the worksheet.
I'm guessing that in the first two cases (shape and ActiveX buttons), VBA drops or loses the chart selection when I press the button – even though the chart still appears selected on screen. Is there a fix for this, or am I doing something wrong?
For an ActiveX button, in the Properties set the property
TakeFocusOnClick
to False. That will cause Selection to keep on the chart rather than switch to the button and your code should work. The color can also be changed from the properties box, though you probably already know that.
You need to reference the chart by name. So either have 4 buttons (one for each chart), or ask the user to input the name of the chart, then:
Dim co as ChartObject
Dim c as Chart
Dim NameOfChart as String
NameOfChart = Inputbox("Enter name of chart")
Set co = ActiveSheet.ChartObjects(NameOfChart)
Set c = co.chart
c.Axes(xlCategory).Select
Application.CommandBars.ExecuteMso "ChartFormatSelection"

Order of Events for the SheetFollowHyperlink Event

I have a workbook that lists people's names and overall performance for the past few weeks. I was asked to make it so that when their names are clicked, the details for that person would show. The solution I came up with at the time was to point all of the hyperlinks to a sheet that reminded them to turn on their macros.
In the WorkSheet_Activate event, I redirected them to another sheet that populated with the details for the person they had selected. This works fine. If the user doesn't have their macros turned on, they get a friendly reminder, but if they do, they immediately get redirected. There's just one problem. Because the hyperlink takes them somewhere else first, it causes the infamous "screen flicker".
On researching, I found the FollowHyperlink Events (I think the workbook level event would be most suitable for my purposes, though). However, before I get started rebuilding it, I wanted to make sure that this would solve the "screen flicker".
On MSDN, it states that the Event occurs when the user clicks the hyperlink. I can't seem to find anywhere that directly states whether this Event is triggered before or after the user is directed to the other sheet, though. If it gets triggered right after, that wouldn't really help me, but if it gets triggered before, I could put an Application.ScreenUpdates = False in the event, and it would solve my problem.
TL;DR (Get to the point already):
Does the Workbook_SheetFollowHyperlink Event happen before or after the user is directed to where ever the hyperlink is pointed?
To answer your question, the event is triggered after the hyperlink is followed. You can demonstrate this using the code below:
Private Sub Workbook_SheetFollowHyperlink(ByVal Sh As Object, ByVal Target As Hyperlink)
Debug.Print "Workbook level: " & ActiveSheet.Name
End Sub
When the event is triggered, the ActiveSheet is the sheet directed to by the hyperlink.
I'm not sure of a way to solve your problem directly, even the Click() event won't be raised when you click a hyperlink. However, the Worksheet level hyperlink event handler will be called before the Workbook level handler and this may speed the process up enough to not see the flicker.
You can prove this if you leave the Workbook level event as is and add the following code to the Worksheet containing the hyperlinks:
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Debug.Print "Worksheet level: " & ActiveSheet.Name
Sleep 1000
Debug.Print "Leaving worksheet level event"
End Sub
After a few experiments (see below) I concluded that:
Allow the user to use the hyperlink columns when macros are disabled.
When macros are enabled, hide the current hyperlink column and show another column that gives the user a different "hyperlink" that takes them directly to where you want them to go.
The 2nd hyperlink can easily be "simulated" such that it picks up the other columns hyperlink. (See below)
I hope his helps
Interesting, here's a few things I tried
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' This does not fire if the user clicks directly on the hyperlink text
' it only fires if when click on the cell space that is not text
With ActiveCell
If Hyperlinks.Count Then
MsgBox "hi" & .Hyperlinks(1).Range
.Hyperlinks(1).Follow
End If
End With
End Sub
However you could make the text in the cells look like a hyperlink but actually just be blue underlined text. You could then use the Worksheet_SelectionChange to go to a related cell.
The question then become how to store the related cell.
You want to store it so that if row and column are inserted on the destination sheet, the reference will adjust. (eg NOT in comments, or the description of named ranges etc..)
Depending on how much data you have there's a variety of ways you could choose from.
I think I would favour this:
Having a hidden column next to the cell on display that has a hyperlink. The cell on display has a formula that is set to pick up the value from the hidden column (I quite like the sound of this as you have the hyperlink column already - so just modify the above code to get the hyperlink from the column next to the clicked cell using offset perhaps)
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' This does not fire if the user clicks directly on the hyperlink text
With ActiveCell.offset(0,1)
If Hyperlinks.Count Then
.Hyperlinks(1).Follow
End If
End With
End Sub
You could mess around with named ranges, but it will be a pain.
I've just realised that what I tried won't help much as you need the hyperlink to work when macros have not been enabled!
So to get the above to work you could change the columns displayed when the user enables macros. ie the hyperlink column is shown when macros are disabled (and the column to the left of it is not).
When macros are enabled hide the hyperlink column and show the one to the left of it that will cause the SelectionChange event to run.
(You need to beware how other hyperlinks are used as any cell with a hyperlink next to it will respond to the event. You may need to use intersection to check the cell clicked is in a namedrange that contains "all the cells that need to respond to a user clicking them in the manner".
All the above sounds a bit mad, but it would appear the event model does not facilitate stopping the screen flickering.
I hope there is a better way of doing what you want, but for what it's worth, the above might help.
Harvey

How to get selected text in VBA

I have a macro that changes the selected text, and I have it assigned to a button.
It works perfectly when i run it directly from visual basic, but when I click the button, the button gets the focus and my text is no longer selected so the macro change the selected element to (button).
How can I select the text and run the macro by clicking on the button and still have the text selected?
The way to do this is to set the set the TakeFocusOnClick property of the CommandButton to False. Here are is the code I use.
Private Sub CommandButton1_Click()
Dim Sel As Selection
Set Sel = Application.Selection
If Sel.Type <> wdSelectionIP Then
MsgBox Sel.Text
End If
End Sub
Is the button embedded in the document? You may need to put it on a form that loads on top of the Word window or in a menu/toolbar, so that clicking it does not affect the selection in the document itself.
Edit:
I think you can use Application.Selection.Previous to get at what you need. You could use this to restore the selection after the click event, or to act upon that section of the document, or both.
I assume that this is available in previous versions of Word, but have only confirmed its presence in 2007.
You need to change TakeFocusOnClick to "False" in the Button Preferences.

Modeless MsgBox, Error trapping, .Find

I have a subroutine that searches for an occurrence of a string in another workbook. I'm trying to get an error message to pop up if the string can't be found (it's most likely due to spelling mistakes), as vbModeless, and allows to user to click on the cell in the searched sheet with the correct value. Then I'd like to resume the search with the new value.
I'm at the moment stuck on making my simple MsgBox to be modeless.
Can anyone help? So far I have (simplified):
With ...
On Error GoTo UserSelect
celladdress = .Range("a1:bb100").Find("searchstring").Address
And my error label:
UserSelect:
MsgBox("Select the cell with the correct spelling") vbModeless
newstring = ActiveCell.Value
searchstring = newstring
Resume
I think it's the Modeless MsgBox giving me grief.
I don't believe that you can use vbModeless with msgbox. That is for use with the Show method of a user form.
What you probably need to do is create a user form that has a refedit control and a button on it. They can then pick a cell with the refedit control. When the user clicks on the button set a public variable on the form with the cell reference the selected.
Then you you need to use ".Show vbModal" on the user form and read off the cell they selected from the form public variable.
Edit:
Actually, you shouldn't need the public variable as the refedit control should be a public property of the form anyway.
I'm not 100% sure on the requirements here. Given a search string of dgo and a worksheet with cells containing bird, cat and dog. Do you want the user to:
(a) edit the cell containing dog and change it to say dgo instead
This would use the modal form and RefEdit control outlined by andynormancx. Like a MsgBox, the modal form pauses the macro until the form is closed
(b) allow the user to click on the cell containg dog and then re-run the search with dog as the search term
This is more complicated. I think that you would need to look at events here. This is fine if your subroutine is pretty much standalone but if it is part of a larger program then this could require substantial rewriting