To click a button on a UserForm in another workbook - excel

I have searched on the Internet for a few days but I still cannot find the way out. I would be really appreciated if I could get some hints from you guys here. Here is the details of what I am going to do:
I got a read-only Workbook called A, with a button 1 on it. By clicking button 1, a User-form containing a list-box and a button 2 with macro will pop out. The result will be printed on sheet 2 on workbook A.
What I want to do is that, using another workbook B, to call a VBA script to open workbook A and click button 1 for activate the User-form. Then,then select all the rows and run macro by clicking button 2. Finally, copy the value on sheet 2 to the workbook B.
To simplify the problem, I write some code to illustrate the case.
On Workbook A:
Button 1:
Public Sub Button1_Click()
UserForm1.Show
End Sub
Button 2:
Private Sub Button2_Click()
Dim y As Long, z As Long
z = 1
With Me.ListBox1
For y = 0 To .ListCount
On Error GoTo EH
If .Selected(y) = True Then
For i = 1 To ListBox1.ColumnCount
Sheets("Sheet2").Cells(z, i) = .List(y, i - 1)
Next i
z = z + 1
End If
Next y
End With
Unload Me
End
EH:
Unload Me
End Sub
UserForm:
Private Sub UserForm_Initialize()
ListBox1.Clear
With ListBox1
ListBox1.ColumnCount = 3
ListBox1.ColumnWidths = "60;60;60"
.AddItem
.List(0, 0) = 1
.List(0, 1) = 2
.List(0, 2) = 3
.AddItem
.List(1, 0) = 4
.List(1, 1) = 5
.List(1, 2) = 6
End With
End Sub
On Workbook B, I do the following:
Sub selectsheet()
Application.Run Workbooks("WorksbookA").Worksheets("sheet1").Shapes("Button1").OnAction
ListBox1.Selected(1) = True
UserForm1.Button2_click
Worksheets("sheet2").range("A1:B3").copy
Workbooks("WorksbookB").Worksheets("sheet1").range("A1").select
selection.paste
End Sub
The vba seems fine because I could run it. But it sticks at the Application.Run. I am sorry that I am not a good at programming and also explaining this messy stuff. But I would be really appreciated if any of you could give a hand to me. Thanks.

Related

Visual Basic For Applications: Problem with table editing through textbox

I have been running with this problem for a while, I leave the sample file code, written below, the thing is that when I run it on the computer from where I work at, in the Sub CommandButton1_Click() when it starts to run the 3 lines after the commented line with i=1, each line starts the ListBox1_Click() and resets the textbox values making a mess, how I overcome this?, by using a conditional so it doesn't overwrite anything when working in other functions.
I want to know if anyone had before this problem, and know how to fix it. Running it from my personal computer is not an option, but the if conditional makes the thing, however I don't think is the optimal way to solve the problem.
Private Sub CommandButton1_Click()
Dim Ultima_Fila As Integer
Ultima_Fila = Sheets("Sheet1").Range("E2") + 1
Sheets("Sheet1").Range("A" & Ultima_Fila).EntireRow.Insert
Sheets("Sheet1").Range("A" & Ultima_Fila) = Sheets("Sheet1").Range("E2")
'i=1 'Required i to be 1 in order to avoid the code to jump and read the textbox from the ListBox1_Click
Sheets("Sheet1").Range("B" & Ultima_Fila) = TextBox1.Value
Sheets("Sheet1").Range("C" & Ultima_Fila) = TextBox2.Value
Sheets("Sheet1").Range("D" & Ultima_Fila) = TextBox3.Value
'i=0 Restarts i value
End Sub
Private Sub ListBox1_Click()
'If i = 0 Then 'When the sub is initialized directly from the listbox click it stores the values displayed on the textboxes
TextBox1 = ListBox1.List(ListBox1.ListIndex, 1)
TextBox2 = ListBox1.List(ListBox1.ListIndex, 2)
TextBox3 = ListBox1.List(ListBox1.ListIndex, 3)
'End If 'This conditional jumps the following instruction when it is reached from the CommandButton1_Click
End Sub
Private Sub UserForm_Activate()
With ListBox1
.ColumnCount = 4
.RowSource = "Table1"
.ColumnHeads = True
End With
End Sub
Please don't be disheartened by the changes I made to your code. In essence it remains the same. I just wanted to be sure that what I tell you is 100% correct:-
The ListBox1_Click event is triggered by a change to ListBox1.ListIndex. My code below contains such a change and disables the event it causes in the way you already found. The explanation for the procedure being fired on another computer is that the ListIndex is changed. Perhaps the code being run there is different and perhaps it's a Mac or Google sheets, in short, a non-Microsoft engine interpreting the same code.
However, you may still like my code because it has some features that yours didn't have. Please try it. It should run on both systems.
Option Explicit
Private DisableListBoxEvents As Boolean
Private Sub UserForm_Activate()
' 263
With ListBox1
.ColumnCount = 4
.RowSource = "Table1"
.ColumnHeads = True
End With
End Sub
Private Sub CommandButton1_Click()
' 263
Dim Ultima_Fila As Integer
Dim Tbx As Control
Dim i As Integer
With Worksheets("Sheet1")
Ultima_Fila = .Range("E2").Value + 1
With .ListObjects(1)
' inserts a table row before table row Ultima_Fila
' Omit the number to append a row.
' To convert sheet row to table row enable this line:-
' Ultima_Fila = Ultima_Fila - .Range.Row - 1
With .ListRows.Add(Ultima_Fila).Range
For i = 1 To 3
Set Tbx = Me.Controls("TextBox" & i)
.Cells(i + 1).Value = Tbx.Value
Tbx.Value = ""
Next i
End With
End With
End With
With ListBox1
DisableListBoxEvents = True
.RowSource = "Table1"
.ListIndex = -1
DisableListBoxEvents = False
End With
End Sub
Private Sub ListBox1_Click()
' 263
Dim i As Integer
If DisableListBoxEvents Then Exit Sub
With ListBox1
For i = 1 To 3
Me.Controls("TextBox" & i).Value = .List(.ListIndex, i)
Next i
End With
End Sub

Moving items from Listbox1 to Listbox2 code

So, Listbox1 is populated (from another sub, linked to range of cells in the workbook) and users can select (one at a time) items from that Listbox to be shown in Listbox2, using a Command Button (Add) to move them. I've nearly managed to get it perfect. My problem is that if a user only selects the final entry in Listbox1, all other possible entries in Listbox1 are removed (blanked out/not visible/cannot be selected).
I want only the entry which has been selected from Listbox1 to be removed from Listbox1 as it appears in Listbox2.
Here's the code:
Private Sub Add_Click()
Dim i as Integer
For i = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Selected(i) = True Then
Me.ListBox2.AddItem Me.ListBox1.List(i)
End If
Next i
For i = Me.ListBox1.ListCount - 1 To 0 Step -1
If Me.ListBox1.Selected(i) = True Then
Me.ListBox1.RemoveItem i
End If
Next
End Sub
If there's anything obvious here, I'm really sorry. But these Listboxes have been driving me crazy for about 3 days now.
Thanks in advance
It's a single-select list, so try adding Exit For inside each loop once you've hit the selected item:
Private Sub Add_Click()
Dim i as Long
For i = Me.ListBox1.ListCount - 1 To 0 Step -1
If Me.ListBox1.Selected(i) = True Then
Me.ListBox2.AddItem Me.ListBox1.List(i)
Me.ListBox1.RemoveItem i
Exit For
End If
Next
End Sub

How to display Progress Bar while macro runs?

I created a ProgressBar I want to display with % while my macro runs.
I tried the parameters UserForm1.Show vbModeless and UserForm1.Repaint in my main macro.
Private Sub UserForm_Activate()
Dim reminder As Long
Dim i As Long, j As Long
reminder = 0
For i = 1 To 200
UserForm1.Label2.Width = UserForm1.Label2.Width + 1
If i Mod 2 = 0 Then
reminder = reminder + 1
UserForm1.Caption1 = reminder & " % completed"
End If
For j = 1 To 150
DoEvents
Next j
Next i
Unload UserForm1
End Sub
The UserForm stops on 0% and my main macro runs to the end, then the UserForm with ProgressBar runs from 0 to 100% and closes.
WORKING:
I create two NON MODAL! Forms NAMED "progressbar"
( with 1 Textbox NAMED counter)
and "tester "
(with 3 Buttons NAMED count hide and show)
the code in progressbar:
Dim count As Long
Public Sub progressbar_show()
count = 0
progressbar.Show
End Sub
Public Sub progressbar_update()
If count < 100 Then count = count + 1
progressbar.counter.Text = Str(count)
DoEvents
End Sub
Public Sub progressbar_close()
counter = 0
progressbar.hide
End Sub
The code in tester: (calls routines in form progressbar)
Private Sub count_Click()
Call progressbar.progressbar_update
End Sub
Private Sub hide_Click()
Call progressbar.progressbar_close
End Sub
Private Sub show_Click()
Call progressbar.progressbar_show
End Sub
Works as designed.
on the click button the textbox will be updated on each click.
Please note HOW i call the functions from on form to the other form. The form name has to be included. The name of the controls have also to match. Its a good idea to rename the controls and forms. I made a autocad VBA with has 1700 controls. Its not the fun after some weeks
to imagine what commandbutton_762 actuelly may do ;)
That can not work like this. You need 3 functions
one to show the userform progressbar 0 percent.
then you need a function to update your form
end finaly the function to remove the form
This code is NOT tested see the testing code i posted here also !
Dim counter As Long
Public Sub UserForm_Activate()
counter = 0
UserForm1.Label2.Width =0
UserForm.show
End Sub
Public Sub UserForm_update()
if counter <100 then counter=counter+1
UserForm1.Label2.Width = counter
DoEvents
end sub
Public Sub UserForm_close()
counter = 0
UserForm.hide
End Sub
'somewhere in a module or class
sub calculate
call UserForm_Activate()
for i=0 to 100
call UserForm_update()
'whatever
' Sleep (200) if this very handy OS call is included somewhere
next
call UserForm_close
end sub

Creating a Userform that changes depending on the elements it should contain

Below is part of the code used to create a chart in Excel:
elements = 0
For j = 1 To x - 1
ans = MsgBox(Activity(j), vbYesNo, "Do you wish for this Element to appear in the Gantt Chart?")
If ans = vbYes Then
elements = elements + 1
ActivityNew(elements) = Activity(j)
End If
Next j
The idea is that I have a list of x-1 activities in the array Activity() only some of which need to be displayed on the chart. These are stored in ActivityNew() and the variable elements counts the population of this array.
At the moment I use a VbYesNo message box to loop through all the activities in Activity() and ask the user to decide which should be shown in the chart.
I would like to show all the activities on a Userform each with a tickbox to either include in ActivityNew() or not but I have no idea how to go about that.
Do you know how to manipulate UserForms ?
You can use this code to create an element :
Set TheTickBox = UserForm.Controls.Add("Forms.TickBox.1", Visible = True)
With TheTickBox
.Left 'Beginning of the tickbox compared to the left side of the UserForm
.Width
.Top 'Beginning of the tickbox compared to the top of the UserForm
.Height
.Caption 'Change the displayed text
End With
So you could use something like this :
For j = 0 to x - 1
Set TheTickBox = UserForm.Controls.Add("Forms.TickBox.1", Visible = True)
With TheTickBox
.Left = 10
.Width = The_Width_You_Want
.Top = 10 + j*The_Height_You_Want
.Height = The_Height_You_Want
.Caption = activity(j)
End With
Next j
At the end of your UserForm you could add a Button 'Validate' that goes through all the tickboxes, and checks the value you've given them:
Sub ButtonValidate_Click()
elements = 0
For each Ctrl in UserForm.Controls
If Ctrl.Value = True Then
ActivityNew(elements) = Ctrl.Caption
elements = elements + 1
End If
Next Ctrl
End Sub
Edit :
To create the UserForm, just click on 'Add UserForm' when right clicking on your project (in the VBA editor).
The code lines I have given you at the beginning will have to be written in the UserForm code box (right click on your UserForm -> Code) and the following in the normal code area :
Sub UserForm()
UserForm.Show 'Here I suppose UserForm is the name of your UserForm
End Sub
And in the UserForm code box make sure that your sub has this name :
Sub UserForm_Initialize()
ACTIONS
End Sub
Please refer to the simplified output below:
To have the output:
1. You need to have user form with its property of list box MulitSelect set to 1.
The following are the codes:
In Userform module:
Private Sub ButtonOK_Click()
Dim Msg As String
Dim i As LoadPictureConstants
Msg = ""
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) Then _
Msg = Msg & ListBox1.List(i) & vbCrLf
Next i
MsgBox "You selected: " & vbCrLf & Msg
Unload Me
End Sub
Private Sub UserForm_Initialize()
Dim i As Long
Me.Caption = "Select Activities"
Call BuildActivityArray
For i = 1 To 5
Me.ListBox1.AddItem Activity(i)
Next
End Sub
In standard code module:
Sub ShowForm()
UserForm1.Show
End Sub

VBA Excel combobox not displaying the value after selecting option

Private Sub ComboBox1_DropButtonClick()
If ComboBox1.ListCount > 0 Then
ActiveSheet.ComboBox1.Clear
End If
For N = 1 To ActiveWorkbook.Sheets.Count - 1
ComboBox1.AddItem ActiveWorkbook.Sheets(N).Name
Next N
End Sub
I'm new to VBA so please bear with me. I may not be doing this the best way to begin with.
The code is taking the names of each sheet in my workbook (with the exception of the last sheet) and adding them to a combobox list. At first, each time I clicked the drop down, all sheet names were being added again making the list continue to grow with every click. My remedy was to clear the combobox first on each click and repopulate.
However, with the clear option being used, the value is not being displayed when making my selection. It displays fine when not using the clear option. Everything else still works, but I need it to show the selected value so users aren't confused.
Is there a better way to accomplish what I need?
EDIT: If it matters, this is not in a user form, it's just a active x combobox located directly on a worksheet.
this is a very strange behavior - but the DopButtonClick event is triggered again when you select the item in the list. Therefore, the value that was just assigned get cleared upon the .Clear in the second run.
This code fixes it:
Private Sub ComboBox1_DropButtonClick()
Dim strValue As String
Dim n As Integer
strValue = ComboBox1.Value
If ComboBox1.ListCount > 0 Then
ActiveSheet.ComboBox1.Clear
End If
For n = 1 To ActiveWorkbook.Sheets.Count - 1
ComboBox1.AddItem ActiveWorkbook.Sheets(n).Name
Next n
ComboBox1.Value = strValue
End Sub
Something like below would work. However, I'd question why you'd want to repopulate the combobox everytime someone clicks on it. Why not do it when the workbook opens or the worksheet is activated?
Private Sub ComboBox1_DropButtonClick(ComboBox1 As ComboBox)
Dim strSelected As String
If ComboBox1.ListIndex > -1 Then
strSelected = ComboBox1.List(ComboBox1.ListIndex)
End If
If ComboBox1.ListCount > 0 Then
ActiveSheet.ComboBox1.Clear
End If
For N = 1 To ActiveWorkbook.Sheets.Count - 1
ComboBox1.AddItem ActiveWorkbook.Sheets(N).Name
If strSelected = ActiveWorkbook.Sheets(N).Name Then
ComboBox1.ListIndex = N - 1
End If
Next N
End Sub
Very nice solution Peter.
In my case I have a list of items that can change between two combobox runs. If the selected combobox item is not anymore in the combo list, at the next run, the line:
ComboBox1.Value = strValue
throws an error .
I've found that declaring a public index:
Public nr As Integer
and making a count inside the combobox code in order to run .clear only once per button action makes this working independently of the list update:
Private Sub ComboBox1_DropButtonClick()
Dim n As Integer
If nr = 0 Then
ActiveSheet.ComboBox1.Clear
nr = 1
Else
nr = 0
End If
For n = 1 To ActiveWorkbook.Sheets.count - 1
ComboBox1.AddItem ActiveWorkbook.Sheets(n).Name
Next n
End Sub

Resources