Excel 2010 VBA ActiveX Resizing - excel

Hi I am using excel 2010 with activex controls. I know activex controls can cause corruption and random resizing of the controls. This problem starts when I change screens.
I need to be able to add elements to a form control through a button being clicked and I also need to access elements in the form through VBA.
My question is how do you add an element into a form control listbox and how do you access it and how do you delete it.
My code uses all active x components but I want to switch them up. I am not sure how to set a name on a form control listbox to even access it in VBA.
Any help would be awesome!
PS. I am using windows 7, excel 2010

This method creates a listbox runtime. You just need to leave space on UserForm1 for it.
Dim lb As msforms.ListBox
Set lb = UserForm1.Controls.Add("forms.listbox.1", "MyListBox1")
This is also a good demostration on how to refer to an (ActiveX) object. A workaround to avoid accidental/unexpected resizing you can intentionally run the following snippet regularly from within the code:
If lb.width <> 100 Then ' or you can check other properties, too
lb.Top = 120
lb.Left = 40
lb.Width = 100
End If
This can be applied to other ActiveX objects, too, e.g.:
If UserForm1.Width <> 200 Then
UserForm1.Width = 200
...
You just need to find a good place in your code where this snippet is run often, and also definitely in UserForm_Initialize. You can also set other properties like caption or tabstop, etc. this way.
For adding and removing items you need to use indices like this:
lb.AddItem "First item", 1
lb.AddItem "Second item", 2
lb.AddItem "Third item", 3
lb.RemoveItem 2

Related

Setting linkedcell of multi-option field

I have an Excel sheet with quite a few groups of option buttons (inserted from form controls and grouped using group boces). What is the easiest way to set the linked cell of each group using VBA code? I tried
ActiveSheet.Shapes.Range("test").Select
.LinkedCell = Range("A1")
but it had no effect. "test" is the name I set for one of the option buttons in the corresponding group.
(The reason for trying to set the LinkedCell via VBA is that these links are sometimes lost for reasons I don't yet understand. If anyone can point out a possible scenario how this could possibly happen in the first place, I would be very grateful.)
Using a named range will only point to one or more cells on a worksheet. It does not refer to a form control. You're likely using a Form Control Option Button somewhere on your worksheet. The code to set the LinkedCell property is
Dim optButton As Shape
Set optButton = Sheet2.Shapes("Option Button 2")
optButton.ControlFormat.LinkedCell = "H4"

Filter populated listbox and keep multiple selections

Context
I have developed a maintenance schedule for a production department in our company. As an extra addition we want to register which spare parts they use and how many. There are four machines in this department. Each machine has its own maintenance schedule made in Excel.
Description application
I have made a external central list which I open by Set myData = Workbooks.Open("Hyperlink"). This list contains all the spare parts for the machines. I have made this list external because the operators of the machine also need to be able to add extra parts.
I then populate a listbox with all the spare parts from the external list. When the listbox is populated I close down the external list, so that someone else can open the list. The image below shows what the userform looks like. The listbox is now filled with dummy products because I am still testing it.
The operators of the machine need to be able to select multiple spare parts.
Problem
I want the operators to be able to filter the listbox and at the same time select multiple spare parts. This is where it gets tricky.
I know how to filter a listbox, but my way resets the listbox each time which consequently makes it impossible to select multiple product. I have looked at some other topic on stack overflow, but they have the same problem.
Question
Is there a way I can filter the listbox, select an item, filter again, select another item, filter again, select again another item etc. etc. ?
*Filter the populated listbox without having the source sheet open
Thank you in advance.
This topic needs the list to remain open and resets the listbox eache time
This topic deletes all the items from the listbox
With help of #JvdV I solved part of the problem. His solution makes sure that I can select some products and save that selection. This enabled me to add some code for a textbox that filters the listbox. This code filters the populated listbox by deleting all the contents that dont equal the textbox.
When the textbox is emptied to "" the listbox is reset and populated again. See the whole code below;
Private Sub FilterProdNr_Change()
For i = UsedPart.ListCount - 1 To 0 Step -1
If InStr(1, UsedPart.List(i), FilterProdNr) = 0 Then UsedPart.RemoveItem (i)
Next i
If FilterProdNr = "" Then
UsedPart.Clear
Dim myData As Workbook
Dim cProd As Range
Dim ws As Worksheet
Set myData = Workbooks.Open("Hyperlink")
Set ws = Worksheets("OnderhoudPartsCentraal")
For Each cProd In ws.Range("Product_nummer")
With Me.UsedPart
.AddItem cProd.Value & " <> " & cProd.Offset(0, 1).Value
End With
Next cProd
myData.Close
End If
End Sub

Rowsource not working via VBA

I can't get the RowSource property of a list box to update via VBA. From another thread, I found the syntax, so I think this is correct. But, despite not failing, it doesn't do anything to the RowSource property (it remains blank). Below:
frmAddIngredient is the user form.
lbxIngredient is a listbox control in that form.
UniqueIngredients is one of the sheets in the workbook.
NumberOfItems is 1 (in this case).
It doesn't give an error, but it doesn't change anything, either. The form itself is not active at this time. This code is supposed to set up the form for later showing.
frmAddIngredient.lbxIngredient.RowSource = Sheets("UniqueIngredients").Range("A1:A" & CStr(NumberOfItems)).Address
The most recent code is
frmAddIngredient.lbxIngredient.RowSource = "=UniqueIngredients!A1:A1"
but, it still doesn't change anything in the actual form.
Also, can I add a new post, or do I have to continue editing this one and adding stuff?
What you want (as discussed in the comments on your question) is not possible. Setting something by code does not change it's property in the properties window and is only so until your project resets.
Consider a Userform with 2 buttons, with their original name and caption and then in a module paste these 2 subs.
Sub demo1()
UserForm1.CommandButton1.Caption = "Demo 1"
UserForm1.Show
End Sub
Sub demo2()
UserForm1.CommandButton2.Caption = "Demo 2"
UserForm1.Show
End Sub
When you run the first Sub demo1 Button 1's caption has changed but Button 2's caption has not.
Close the Userfom and now run demo2, you'll see that Button 1's caption is back to it's original hard set (properties window) name and that now Button 2 has a different name.

Access VBA - Trigger combobox change event

I have been playing around with form designs and now I have constructed a form, which is almost complete, just one problem left. Let me explain first:
Form is bound to a "Join Table", which has only 2 fields - ID from "Table1" and ID from "Table2". Based on those two fields I have added fields from "Table1" & "Table2", on same form. Then I have added 2 option buttons, 1 Combobox and 2 Subforms.
This allows me to watch records from two different tables that are joined, from each point of view - "Table1" or "Table2" view. I am selecting this views with Option buttons, which changes Combobox rowsource, so you can navigate to records from Combobox.
Here is code :
Private Sub OptButton0_Click()
If Me.OptButtonO.Value = True Then
Me.OptButton1.Value = False
Me.Cmbox.RowSource = "SELECT [Table1].[Field1], [Table1].[Field2], [Table1].[Field3] FROM Table1 ORDER BY [Field1];"
Me.Cmbox.SetFocus
Me.Cmbox = Me.Cmbox.ItemData(0)
End If
End Sub
Private Sub Cmbox_AfterUpdate()
If Me.OptButton0.Value = True Then
If IsNull(Me!Cmbox) Then Exit Sub
With Me.RecordsetClone
.FindFirst "[Field1] = " & Me!Cmbox
If Not .NoMatch Then
If Me.Dirty Then Me.Dirty = False
Me.MySubform.Width = 8280
Me.MySubform.SourceObject = "MySubform"
Me.Bookmark = .Bookmark
Else
Me.MySubform.Width = 8000
Me.MySubform.SourceObject = ""
End If
End With
Me.Cmbox.SetFocus
DoCmd.Requery
End If
End Sub
This posted code is only for one Option button, second one is same, just opposite. Now what is problem ?
Problem is that when I navigate through record via Combobox, click second Option button for another view AND THEN RETURN to same view, my subform results stays same as they were when I clicked another Option button, although Combobox listIndex is 0. If I select combobox Listindex from Combobox, code works again.
SO BASICALLY - I NEED CODE THAT WILL TRIGGER COMBOBOX CHANGE WHEN OPTION BUTTONS ARE CLICKED. It works when you're clicking in Combobox, but not when clicking in Option button.
I know It's complicated to understand, please take a look at code, and ask anything. Any help appreciated.
Another option: I had a similar issue: with an unbound combobox. In the '*_Change' event in a combobox, if I pick a value from the dropdown, the value is there; but if I delete the existing value, the prior value still shows up.
...
If Me.series_filter > "" Then
lstrMetric = lstrMetric & "and X.series_name = '" & Me.series_filter & "' "
End If
...
Me.Filter = Mid(lstrMetric, 5)
...
I have a dropdown for a filter on the form: picking a value is meant to set (or clear) the filter. It worked when I picked a value, but would not clear if I delete it.
I added a line to the start of the code to commit updates:
Me.dirty = false
The code now recognizes the null value when the combobox is cleared. This works in my case - of course it would be a problem if you didn't want any updated fields written to the database.
call the the combobox afterupdate event in the option button click event:
private sub optbutton0_click()
...
cmbox_afterupdate()
end sub
PS: Rather than having events for option buttons directly, you should put them in a frame, (even if you then have to make the frame transparent to stop it from appearing) and use the afterupdate or click events of the frame, whereby you can get the selected option button by option value:
private sub frame0_click()
select case frame0
case 0 'option button 0 is selected
...
case 1
...
end select
end sub
In Access, controls can be funny. I mean, when you change the option, you see it change, it changes on the screen... but the control doesn't always change its .value right away... meaning it doesn't Update. For a simpler illustration of this principle, create a textbox, type some stuff into it, and look at the textbox.value in the immediate window. Then, with the cursor still in the textbox, backspace some of it. Check the value again. Do that a few more times. Start including textbox.text in your tests. There are multiple ways around this, but it is most important to understand when controls actually update, so you can understand better when and which work arounds to use.
Now, in this situation, you typed 'click' every time when you referenced selecting an option. I think I will hold you to that. Personally, I use Tab and the arrow keys sometimes, which would be a slightly more complicated answer, but one you will be better equipped to solve yourself, after understanding the textbox example above. But, if you change AfterUpdate above to Click, you should be good.
That said, there are events besides mouse clicks that can activate the Click event. Usually not a problem, but since you are changing the look of your form, specifically the width, you may want to be aware that the subform width may flash back and forth sometimes while using your tool. Not often, probably won't be too much of an annoyance, but I might rethink why I needed to change width at all, or if there might be better triggers for it.

Excel 2007 - Capture OWC11 Spreadsheet Control's Right-Click Context Menu Selection

I know this is probably simple, but I have spent 2 hours Googling for the answer and I can't find it. I am using the Office Web Components 2003 (v11) Spreadsheet Control on an Excel 2007 userform. I am using the BeforeContextMenu event to create a custom context (right-click) menu. I'm using the code sample from the Spreadsheet Control's help file to create the menu. The code is:
Sub Spreadsheet1_BeforeContextMenu(x, y, Menu, Cancel)
Dim cmContextMenu(4)
Dim cmClearSubMenu(2)
cmClearSubMenu(0) = Array("&All", "ClearAll")
cmClearSubMenu(1) = Array("&Formats", "ClearFormats")
cmClearSubMenu(2) = Array("&Values", "ClearValues")
cmContextMenu(0) = Array("Cu&t", "owc2")
cmContextMenu(1) = Array("&Copy", "owc3")
cmContextMenu(2) = Array("&Paste", "owc4")
cmContextMenu(3) = Empty
cmContextMenu(4) = Array("Clea&r", cmClearSubMenu)
Menu.Value = cmContextMenu
End Sub
The custom menu appears perfectly when the spreadsheet is right-clicked. What I can't figure out is how to capture the menu item that I select. Can someone please point me to VBA code that will enable me to capture and use the selection?
Thanks In Advance -
After more Googling I found the answer to this problem in the Help for the OCW11 Spreadsheet Control. The BeforeContextMenu event lists the code shown in my original post. I could see that the menu items were defined with statements like:
cmContextMenu(0) = Array("Cu&t", "owc2")
The "Cu&t" is the menu item label, and the "owc2" is the constant (I assume) that is supposed to execute the Cut command (commands are known as "OCCommands" in OWC11). The problem is that the "owc2" constant wasn't firing the Cut command. I checked the "Programming Information" section of the Help, underneath "Enumerations," in the entry titled "OCCommandID" for the OCCommand ID constants. That's exactly where they are located. I looked up the Cut constant, which is 1001, and replaced the "owc2" with 1001, and the Cut command worked perfectly! I did the same thing for the "&Copy" and "&Paste" commands, with 1002 and 1003, respectively, and they worked as well.
My problem may be that I didn't set up the proper references to the OWC constants. Or it could be that the constants changed and weren't updated correctly in the Help documentation. Whichever may be the culprit, the above method fixed the problem.

Resources