I have a userform which has the following bit of code included:
Private Sub RemoveRecipientCommandButton_Click()
Application.ScreenUpdating = False
Dim intCount As Integer
For intCount = RecipientsListBox.ListCount - 1 To 0 Step -1
If RecipientsListBox.Selected(intCount) Then RecipientsListBox.RemoveItem (intCount)
Next intCount
Application.ScreenUpdating = True
End Sub
This code is run on a listbox which is MultiSelect 1 - fmMultiSelectMulti, and works just fine. The problem comes when I try to allow parameters to be passed to it, so I can use the same sub on more than one ListBox. I've tried:
Private Sub RemoveRecipientCommandButton_Click()
Application.ScreenUpdating = False
RemoveSelected (RecipientsListBox)
Application.ScreenUpdating = True
End Sub
with
Private Sub RemoveSelected(LB As ListBox)
Dim intCount As Integer
For intCount = LB.ListCount - 1 To 0 Step -1
If LB.Selected(intCount) Then LB.RemoveItem (intCount)
Next intCount
End Sub
I've also tried:
Private Sub RemoveSelected(LB As MSForms.ListBox)
and as
Private Sub RemoveSelected(LB As ListObject)
with the rest of the RemoveSelected code being the same. All of these forms of this code throw Error 424 - object required. I'm by no means an Excel pro, so my main concern here is just finding code that works - I want to be able to make this into something I can use on more than one ListBox, if necessary, without having to write the code as new for each ListBox. If someone could even point me in the right direction, I'd appreciate any help I can get. Thanks.
Multiple issues here.
Don't wrap parameters in parentheses calling Subs without Call.
So either Call RemoveSelected(RecipientsListBox) or RemoveSelected RecipientsListBox.
Default modus to hand over parameter is ByRef but that's not possible here. So using ByValis needed.
Correct type is MSForms.ListBox
Code:
Private Sub RemoveRecipientCommandButton_Click()
Application.ScreenUpdating = False
RemoveSelected RecipientsListBox
'Call RemoveSelected(RecipientsListBox)
Application.ScreenUpdating = True
End Sub
Private Sub RemoveSelected(ByVal LB As MSForms.ListBox)
Dim intCount As Integer
For intCount = LB.ListCount - 1 To 0 Step -1
If LB.Selected(intCount) Then LB.RemoveItem intCount
Next intCount
End Sub
Edit:
As #Patrick Lepelletier stated, ByRef is possible in this case. I had the Control object stored in a local variable Set oListboxControl = RecipientsListBox : RemoveSelected oListboxControl what caused the problem with ByRef
So
Private Sub RemoveSelected(LB As MSForms.ListBox)
Dim intCount As Integer
For intCount = LB.ListCount - 1 To 0 Step -1
If LB.Selected(intCount) Then LB.RemoveItem intCount
Next intCount
End Sub
will also work.
Related
I want to add dynamically CommandButtons to my Userform within the For-Loop. How can i get add new CommandButtons in the For-Loop?
Dim CommandButtons(5) As clsCommandButtons
Private Sub UserForm_Initialize()
Dim zaehler As Integer
For zaehler = 0 To 4
Set CommandButtons(zaehler) = New clsCommandButtons
Set CommandButtons(zaehler).cmdCommandButton = Me.Controls(zaehler)
Next
End Sub
And This is my class:
Option Explicit
Public WithEvents cmdCommandButton As CommandButton
Private Sub cmdCommandButton_Click()
Dim sFilepath As String
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
.InitialFileName = ActiveWorkbook.Path & "\"
.Filters.Add "TextFiles", "*.txt", 1
.FilterIndex = 1
If .Show = -1 Then
sFilepath = .SelectedItems(1)
End If
End With
Cells(c_intRowFilterPathStart, c_intClmnFilterPath) = sFilepath
End Sub
I don't know how to handle this Error. How can i fix this?
I assume you get the error because you're accessing a control that doesn't exist. Note that the controls are counted from 0 to Me.Controls.count-1, so probably your issue is solved with
Set CommandButtons(zaehler).cmdCommandButton = Me.Controls(zaehler-1)
But I guess a better solution is to name your buttons and assign them by name:
Set CommandButtons(zaehler).cmdCommandButton = Me.Controls("CommandButton" & zaehler)
Define the CommandButtons collection as a Variant:
Dim CommandButtons(15) As Variant, instead of Dim CommandButtons(15) As clsCommandButtons.
In this Variant, you would put your CommandButtons. This is some minimal code, that would help you get the basics of what I mean:
CustomClass:
Private Sub Class_Initialize()
Debug.Print "I am initialized!"
End Sub
In a module:
Private SomeCollection(4) As Variant
Public Sub TestMe()
Dim cnt As Long
For cnt = 1 To 4
Set SomeCollection(cnt) = New CustomClass
Next cnt
End Sub
From this small running code, you can start debugging further :)
I think your problem is in the Me.Controls(zaehler) part. zaehler starts at 1, but Me.Controls(...) starts at 0.
Set CommandButtons(zaehler).cmdCommandButton = Me.Controls(zaehler - 1)
would probably solve it
Dim a() As clsCommandButton
Private Sub UserForm_Initialize()
Dim c As Control
On Error GoTo eHandle
For Each c In Me.Controls
If TypeName(c) = "CommandButton" Then
ReDim Preserve a(UBound(a) + 1)
Set a(UBound(a)) = New clsCommandButton
Set a(UBound(a)).cmd = c
End If
Next c
Exit Sub
eHandle:
If Err.Number = 9 Then
ReDim a(0)
End If
Resume Next
End Sub
With a class as follows
Public WithEvents cmd As commandbutton
Private Sub cmd_Click()
MsgBox "test"
End Sub
I have a list box not linked to any range.
I want to click on a row and remove it. If I step through the code below, the ListBox1_Click() function ends up being called twice for some reason and the application produces an "Unspecified Error" on the second run
My entire code:
Private Sub ListBox1_Click()
ListBox1.RemoveItem (ListBox1.ListIndex)
End Sub
Private Sub UserForm_Initialize()
For i = 0 To 10
ListBox1.AddItem ("A" & Str(i))
Next i
End Sub
If you make a button about it, then this solution would be quite ok there:
Private Sub CommandButton1_Click()
Dim cnt As Long
For cnt = Me.ListBox1.ListCount - 1 To 0 Step -1
If Me.ListBox1.Selected(cnt) Then
Me.ListBox1.RemoveItem cnt
Exit Sub
End If
Next cnt
End Sub
So I have scoured google and forum after forum (including the Stack) trying to figure this out. All I want to do is have an ActiveX button export the contents of a list box to a range in Excel.
Below is the code I have that adds items from ListBox1 to ListBox2. After all desired items are moved to ListBox2, said ActiveX button (SomeButton_Click) would then export all the items in ListBox2 to "Sheet15" starting at range("a1").
(Please note, this is an ActiveX ListBox that is not on an actual form. It is within a worksheet)
Public Sub BTN_MoveSelectedRight_Click()
Dim iCtr As Long
Dim n As Long, lRow As Long
Dim cStartCell As Range
For iCtr = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Selected(iCtr) = True Then
Me.ListBox2.AddItem Me.ListBox1.List(iCtr)
End If
Next iCtr
For iCtr = Me.ListBox1.ListCount - 1 To 0 Step -1
If Me.ListBox1.Selected(iCtr) = True Then
Me.ListBox1.RemoveItem iCtr
End If
Next iCtr
End Sub
Below would be the button that would perform the export:
Public Sub SomeButton_Click()
'What code can I put here to perform the export to abovementioned range?
End sub
Any help would be extremely appreciated as I have spent hours trying to figure this out (as much as I don't want to actually admit this, it is true)
Thank you!
Here you go:
Public Sub SomeButton_Click()
Dim v
v = Sheet15.ListBox2.List
Sheet15.[a1].Resize(UBound(v)) = v
End Sub
If the listbox is on a different worksheet, you'll need to adjust that.
Edit #1
This is better:
Public Sub SomeButton_Click()
With Sheet15
.[a1].Resize(.ListBox1.ListCount) = .ListBox1.List
End With
End Sub
I wrote the code below to delete control in another VB.NET Form; that workd fine; But the code cannot Detect that the Form has NO Controls; What is wrong with the code please:
Sub DeleteControls() ' WORKING
For i As Integer = Form2.Controls.Count - 1 To 0 Step -1
Dim ctrl = Form2.Controls(i)
ctrl.Dispose()
Next
End Sub
Sub TestForm() ' NOT WORKING
If Form2.Controls Is Nothing Then
MessageBox.Show("Form2 has No Controls")
End If
End Sub
Thanks
First you need to count the controls on form 2."
Dim GetControls As Integer = Form2.Controls.Count"
Then Check if GetControls is smaller then 1 "No controls"
Sub TestForm()
Dim GetControls As Integer = Form2.Controls.Count
If GetControls < 1 Then
MessageBox.Show("Form2 has No Controls")
End If
End Sub
I am trying to Close a User Form from a module, but it's not working.
Here is what I have tried
Sub UpdateSheetButton()
Dim subStr1 As String
Dim subSrrt2() As String
Dim tmp As Integer
Dim pos As Integer
Dim Form As WaitMessage
Set Form = New WaitMessage
With Form
.Message_wait = Module2.Label_PleaseWait
.Show
End With
For Each Cell In ActiveSheet.UsedRange.Cells
subStr1 = RemoveTextBetween(Cell.formula, "'C:\", "\AddIns\XL-EZ Addin.xla'!")
tmp = Len(subStr1) < 1
If tmp >= 0 Then
Cell.formula = subStr1
status = True
End If
Next
Unload Form
MsgBox Module2.Label_ProcessComplete
End Sub
Form Name is WaitMessage.
I have also tried WaitMessage.Hide but it's also not working.
Considering a modeless form, create a subroutine within the userform:
Sub UnloadThisForm ()
unload me
End Sub
and call the sub from outside the userform;
call Userform1.UnloadThisForm
Another possibility could be to put your code to ClassModule and to use Events to callback to WaitMessage user form. Here short example. HTH
Standard module creates the form and the updater object and displays the form which starts processing:
Public Sub Main()
Dim myUpdater As Updater
Dim myRange As Range
Dim myWaitMessage As WaitMessage
Set myRange = ActiveSheet.UsedRange.Cells
Set myUpdater = New Updater
Set myUpdater.SourceRange = myRange
' create and initialize the form
Set myWaitMessage = New WaitMessage
With myWaitMessage
.Caption = "Wait message"
Set .UpdaterObject = myUpdater
' ... etc.
.Show
End With
MsgBox "Module2.Label_ProcessComplete"
End Sub
Class module containes the monitored method and has events which are raised if progress updated or finished. In the event some information is send to the form, here it is the number of processed cells but it can be anything else:
Public Event Updated(updatedCellsCount As Long)
Public Event Finished()
Public CancelProcess As Boolean
Public SourceRange As Range
Public Sub UpdateSheetButton()
Dim subStr1 As String
Dim subSrrt2() As String
Dim tmp As Integer
Dim pos As Integer
Dim changesCount As Long
Dim myCell As Range
Dim Status
' process task and call back to form via event and update it
For Each myCell In SourceRange.Cells
' check CancelProcess variable which is set by the form cancel-process button
If CancelProcess Then _
Exit For
subStr1 = "" ' RemoveTextBetween(Cell.Formula, "'C:\", "\AddIns\XL-EZ Addin.xla'!")
tmp = Len(subStr1) < 1
If tmp >= 0 Then
myCell.Formula = subStr1
Status = True
End If
changesCount = changesCount + 1
RaiseEvent Updated(changesCount)
DoEvents
Next
RaiseEvent Finished
End Sub
User form has instance of updater class declared with 'WithEvent' keyword and handles events of it. Here form updates a label on 'Updated' event and unloads itself on 'Finished' event:
Public WithEvents UpdaterObject As Updater
Private Sub UpdaterObject_Finished()
Unload Me
End Sub
Private Sub UpdaterObject_Updated(updatedCellsCount As Long)
progressLabel.Caption = updatedCellsCount
End Sub
Private Sub UserForm_Activate()
UpdaterObject.UpdateSheetButton
End Sub
Private Sub cancelButton_Click()
UpdaterObject.CancelProcess = True
End Sub
A userform is an object in it's own right, you do not need to declare or set as a variable. Also, when you use the .Show Method it will set the Modal property to True by default, which will pause code execution until the user interacts in some way (i.e. closes the form).
You can get around this by using a boolean declaration after the .Show method to specify if the userform is to be shown modal.
Try this instead:
Sub UpdateSheetButton()
Dim subStr1 As String
Dim subSrrt2() As String
Dim tmp As Integer
Dim pos As Integer
With WaitMessage
.Message_wait = Module2.Label_PleaseWait
.Show False
End With
For Each Cell In ActiveSheet.UsedRange.Cells
subStr1 = RemoveTextBetween(Cell.Formula, "'C:\", "\AddIns\XL-EZ Addin.xla'!")
tmp = Len(subStr1) < 1
If tmp >= 0 Then
Cell.Formula = subStr1
Status = True
End If
Next
Unload WaitMessage
MsgBox Module2.Label_ProcessComplete
End Sub
i guess you can do yourself the screenupdating and enableevents, so here is :
(next time add more description to what you are trying to do, and no just post code...)
Option Explicit 'might help to avoid future miss declaring of variables...
Sub UpdateSheetButton()
Dim subStr1 As String
'Dim subSrrt2() As String 'not used in shown code !
'Dim tmp As Integer
Dim pos As Long
Dim Cell as Range 'you forgot to declare this
Dim Form As object
Set Form = New WaitMessage
load Form
With Form
.Message_wait = Module2.Label_PleaseWait
.Show false 'if you ommit false, the code won't continue from this point unless the Form is closed !
End With
For Each Cell In ActiveSheet.UsedRange.Cells
subStr1 = RemoveTextBetween(Cell.formula, "'C:\", "\AddIns\XL-EZ Addin.xla'!")
'tmp = Len(subStr1) < 1 'might replace with a boolean (true/false, instead 0/-1)
'If tmp >= 0 Then 'you don't use tmp later, so i guess its just using variables without need
if substr1<>"" then 'why use a cannon to put a nail in a wall?, go to the point
Cell.formula = subStr1
pos = pos+1 'you declared pos but didn't use it !?
Form.SomeTextbox.caption = pos 'or other counter
'can also use the .width property of a button or picture... to make a progression bar.
status = True 'Status is not declared , and not used elsewhere , so what ?!
End If
Next
Unload Form
set Form = Nothing
MsgBox Module2.Label_ProcessComplete
End Sub