I have a two list boxes with one button when the user can click the button move all the list item from listbox1 to listbox2. when the listbox1 is becomes empty app is getting restarted IN EXCEL 2016.
My Code is
For i = 1 To ThisWorkbook.Sheets("MultiSheet").ListBoxes(strFromlb).listCount
ThisWorkbook.Sheets("MultiSheet").ListBoxes(strTolb).AddItem ThisWorkbook.Sheets("MultiSheet").ListBoxes(strFromlb).List(1)
ThisWorkbook.Sheets("MultiSheet").ListBoxes(strFromlb).RemoveItem (1)
Next i
Here strFromLb is clearing the values but when it clearing last value my VBA App is excel has been restarted.
Then I have tried code to clear the listbox
ThisWorkbook.Sheets("MultiSheet").ListBoxes(strFromlb).ControlFormat.RemoveAllItems
ThisWorkbook.Sheets("MultiSheet").ListBoxes(strFromlb).Items.Clear
The error is
"Object doesnt supported to property or method"
Then
ThisWorkbook.Sheets("MultiSheet").ListBoxes(strFromlb).Clear
This code I got the 400 error. so kindly help me.
Worksheets("MultiSheet").ListBoxes(strFromlb).ControlFormat.RemoveAllItems
Reference: The Complete Guide to Excel VBA Form Control ListBoxes
There are two type listbox controls for the worksheet Forms control and MsForms ActiveX control. getListBox will return get either one.
You code has a couple of syntax errors in it
Listbox.List returns a 0 based array
You don't use parentheses when using RemoveItem because it is a not a function
Dim lBoxFrom As Object, lBoxTo As Object
Set lBoxFrom = getListBox("MultiSheet", strFromlb)
Set lBoxTo = getListBox("MultiSheet", strTolb)
For i = 0 To lBoxFrom.ListCount - 1
lBoxTo.AddItem lBoxFrom.List(1)
lBoxFrom.RemoveItem 1
Next
or
lBoxTo.List = lBoxFrom.List
lBoxFrom.Clear
Sub Test()
Const WORKSHEET_NAME = "Sheet1"
Const strFromlb = "BoxFrom"
Const strTolb = "BoxTo"
Dim lBoxFrom As Object, lBoxTo As Object
Dim i As Integer
Set lBoxFrom = getListBox(WORKSHEET_NAME, strFromlb)
Set lBoxTo = getListBox(WORKSHEET_NAME, strTolb)
lBoxFrom.AddItem "A"
lBoxFrom.AddItem "B"
lBoxFrom.AddItem "C"
For i = 0 To lBoxFrom.ListCount - 1
lBoxTo.AddItem lBoxFrom.List(0)
lBoxFrom.RemoveItem 0
Next
End Sub
Function getListBox(WorkSheetName As String, ListBoxName As String) As Object
Dim lBox As Object
On Error Resume Next
Set lBox = Worksheets(WorkSheetName).ListBoxes(ListBoxName)
On Error GoTo 0
If lBox Is Nothing Then
On Error Resume Next
Set lBox = Worksheets(WorkSheetName).Shapes(ListBoxName).OLEFormat.Object.Object
On Error GoTo 0
End If
Set getListBox = lBox
End Function
Related
So I have this code to loop through selected items in a listbox and add them to a collection. For some reason it is throwing the compile error "Argument Not Optional" on the commented out line that is trying to add the selected item to the Collection.
However, the line adding "test" works fine.
I know this is an optional argument because it even gives me Intellisense popup to use "Add". So I'm pretty confused.
If optPaste = True Then
'Paste Code
Else
'Read In Selection
Dim tempArray As Variant
Dim i As Integer
Dim colSelected As Collection
Set colSelected = New Collection
colSelected.Add ("test")
For i = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Selected(i) Then
tempArray = Split(Me.ListBox1.List(i), " - ")
' colSelected.Add = tempArray(1)
End If
Next i
MsgBox (colSelected(1))
End If
I am trying to get the name of theListbox that I just selected ("ListBox1"). Caveat: ListBox1 is located within Multipage1 (on the first tab).
Private Sub ListBox1_Click()
Dim m As String
m = Me.ActiveControl.Name
MsgBox (m)
End Sub
Since I have selected the ListBox1, I'm expecting the message box value to be ListBox1. Instead I am receiving Multipage1.
What should I be doing differently?
It helps to consider MultiPage, Pages, and Frames as subforms. If a subform control is active then the parent form will return the subform as the ActiveControl.
Here is the proper way to drill down to the actual ActiveControl.
Function ActiveControlName(Object As Object) As String
Dim Obj As Object
On Error Resume Next
Set Obj = Object.ActiveControl
If Err.Number = 0 Then
ActiveControlName = ActiveControlName(Object.ActiveControl)
Else
Set Obj = Object.SelectedItem
If Err.Number = 0 Then
ActiveControlName = ActiveControlName(Object.SelectedItem)
Else
ActiveControlName = Object.Name
End If
End If
On Error GoTo 0
End Function
Demo
An old post but I landed here with the sames issue. Unfortunately this answer didn't work for my scenario (controls positioned within nested frames on a multipage). But user6432984 gave a great headstart.
The key to the proper solution is that the active control (reported by "ActiveControl") is the top level control that is active on the userform. It may have either:
1) Another nested "ActiveControl",
2) A "SelectedItem"
3) Neither of the above - in which case it really is the "ActiveControl" you want.
So, the technique to drill-down requires that you determine which of 1), 2) or 3) above you have. If you don't have 3) keep throwing whichever of 1) or 2) you do have into the recursive function until you find 3):
Function ActiveControlName(Object As Object) As String
'modified my Malcolm Farrelle
Dim Obj As Object
Set Obj = Nothing
On Error Resume Next
Set Obj = Object.ActiveControl
On Error GoTo 0
If Obj Is Nothing Then
On Error Resume Next
Set Obj = Object.SelectedItem
On Error GoTo 0
End If
If Obj Is Nothing Then
ActiveControlName = Object.Name
Else
ActiveControlName = ActiveControlName(Obj)
End If
End Function
I have a Userform with several pages, one of which is called FXForward1 and if a certain condition is met I want to create a new page in the userform called FXForward2 that has all the same controls as FXForward1. Does anyone know how I can go about doing this? The following is the relevant part of the code I currently have and it's giving me the following error:
Run-Time Error '-2147319767(80028029)':
Could not paste the control. Invalid forward reference, or reference to uncompiled type
Sub UpdateForm()
Dim vbObject As Object
Dim objControl As Control
Dim OptionNumber As Integer
Set vbObject = ThisWorkbook.VBProject.VBComponents("UserForm1")
Set objControl = vbObject.Designer.Controls("MultiPage1")
' Other code here
If OptionNumber > 1 Then
objControl.Pages.Add ("FXForward" & OptionNumber)
objControl.Pages(FXForward1).Controls.Copy
objControl.Pages("FXForward" & OptionNumber).Paste ' This line is where I get the error
End If
UserForm1.Show
End sub
I try to create a macro, placed in Workbook_Open() procedure, which adds items for combo boxes, named CBTask for each sheet in workbook, (which has combo box named CBTask in it).
Unfortunatelly following code generates Compile error: Method or data member not found"
I believe it is because not every sheet has CBTask in it (even on error resume next does not help).
Is there any way to check if sheet contains combo box, so I could do the checking before trying clear it, or adding new items?
Private Sub Workbook_Open()
Dim ws As Worksheet
Dim i As Integer
Dim strTaskName As String
On Error Resume Next
For Each ws In ThisWorkbook.Worksheets
ws.CBTask.Clear
strTaskName = taskName(1)
Do
ws.CBTask.AddItem strTaskName
strTaskName = taskName(i)
i = i + 1
Loop While taskName <> "LastOne"
Next ws
On Error GoTo 0
End Sub
(as you can see, this code also uses additional function "taskName(intSubtaskValue as integer)" to convert integer to string (e.g. taksName(1) = "Task01", taskName(2) = "Task02...)
The Worksheet class doesn't have a member named CBTask which is why that code fails. I suggest you use the OLEObjects property instead:
ws.OLEObjects("CBTask").Object.Clear
To expand on Rory's answer, in addition to fully qualifying your objects, you can check if an ActiveX-control of a given name exists on a worksheet by using this function:
Function obj_exists(obj_name As String, on_worksheet As Worksheet) As Boolean
On Error GoTo errHandler
Debug.Print on_worksheet.OLEObjects(obj_name).Name
obj_exists = True
On Error GoTo 0
Exit Function
errHandler:
obj_exists = False
On Error GoTo 0
End Function
In a dropdown list I have a few items. Can I, when I select an item, get the position of that item in the list as a number?
If you are looking for the index of a Data Validation list, this is what I'd do:
Put the following code in the ThisWorkbook module:
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim ValidationIndex As Long
Dim rngTest As Excel.Range
'assumes the data validation is in a cell named "rngTest"
On Error Resume Next
Set rngTest = Sh.Range("rngTest")
If rngTest Is Nothing Then
Exit Sub
End If
On Error GoTo 0
If Not Intersect(ActiveCell, Sh.Range("rngTest")) Is Nothing Then
ValidationIndex = GetValidationIndex
MsgBox ValidationIndex
End If
End Sub
Put this function in the ThisWorkbook module also, or else in any regular module:
Function GetValidationIndex() As Long
'returns a 1-based index
Dim rngTest As Excel.Range
Dim varValidationString As Variant
Dim ErrNumber As Long
Dim i As Long
With ActiveCell.Validation
If .Type = xlValidateList Then '3
On Error Resume Next
Set rngTest = ActiveCell.Parent.Range(.Formula1)
'I do this goofy thing with ErrNumber to keep my indenting and flow pretty
ErrNumber = Err.Number
On Error GoTo 0
'if the Validation is defined as a range
If ErrNumber = 0 Then
GetValidationIndex = Application.WorksheetFunction.Match(ActiveCell.Value2, rngTest, 0)
Exit Function
'if the validation is defined by comma-separated values
Else
varValidationString = Split(.Formula1, ",")
For i = LBound(varValidationString) To UBound(varValidationString)
If varValidationString(i) = ActiveCell.Value2 Then
GetValidationIndex = i + 1
Exit Function
End If
Next i
End If
End If
End With
End Function
If you are using a list or combo box, ListIndex would seem to be what you are after.
VB Help for ListIndex property: Returns or sets the index number of the currently selected item in a list box or combo box. Read/write Long. Remarks. You cannot use this property with multiselect list boxes.
If nothing is selected, ListIndex's value is -1. If memory serves, it is a zero based index.
ListIndex cannot be set at design time so it is not listed in the properties window.
When entering your code, type the list box name then dot and the editor displays all the available properties. Scroll down the list, note any that look interesting, then look them up.
I think it is not necessary to use a function. You can get it by using only Match function, like in above Doug's answer.
Dim GetValidationIndex as Integer
Dim rngTest as Range
' Get the validation list
With ActiveCell.Validation
Set rngTest = ActiveCell.Parent.Range(.Formula1)
end with
GetValidationIndex = Application.WorksheetFunction.Match(ActiveCell.Value2, rngTest, 0)
The function GetValidationIndex is good.
However, for some regional settings the line varValidationString = Split(.Formula1, ",") is not valid, because the character used to separate the different values is ";"
I suggest use:
varValidationString = Split(.Formula1, Application.International(xlListSeparator))