I'm having trouble to loop an userform and get data from it.
My code is already properly working whenever I use it for a single use (out of the loop).
The objective is to send data obtained using the ComboBox values (which is done in the Userform code) in a sheet and this has to be done X times (X being defined by the user at the start of the code) but whenever I enter the loop, my userform is only displayed once.
I did see that some people used the vbModeless option but since I didn't notice any change, I thought of it being a hint but didn't find anything close to it that solved my problem.
Sub nouveau_controle()
Dim nbre_controle As Integer
nbre_controle = InputBox("Entrez le nombre de contrôles à effectuer")
For j = 1 To nbre_controle Step 1
Formulaire_nouveau_controle.Show vbModeless
Next j
End Sub
Thank you for any help you can give me.
If you open a form vbModeless, it means 2 things:
(1) you can continue to work with excel while the form is open
(2) your code will immediately continue to run after the Show
As the code continues to run, your code hits the Show-command without stop. When the user closes it, it is not reopened as the code is already executed completely
The opposite is to open the form modal (this is the default). Execution stops at the Show command and waits until the form is closed. In that case, you should see you form multiple times. Examples for typical modal forms are InputBox or MsgBox
Related
I'm trying to create a system within a VBA textbox that modifies the input.
Textboxes along with other options are in frames that can be opened and closed. Done to keep the form readable for other people.
I know it can be done by editing the string solely in code (and have done that to keep working on the project) but I want people to see the edits the code makes.
These updates are inconsistent. I have two textboxes that edit themselves with identical lines of code and they are both set to update themselves once the textbox has been exited. One only updates if something within the frame that it is in gets clicked on again and the other doesn't update at all whether clicking within its frame or outside.
Ideally the moment a textbox gets edited and something else gets clicked on the textbox updates.
Update
Only updates itself if something else like another checkbox in the frame is clicked or selected and it will also then work when clicking outside of the frame. Does anyone know why?
Code for both
Private Sub Pathbox_Change()
End Sub
Private Sub Pathbox_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Dim sDir As String
sDir = S5Int.Pathbox.Text
If Right(sDir, 1) <> "\" Then
S5Int.Pathbox.Text = sDir & "\"
End If
End Sub
The same code for both except the name of the procedure. Frames are also same except for their names. In the form they look something like this:
Form with textboxes
Settings of the elements are also identical
Found a solution last week;
I have just put the trigger of updating on the form itself whenever the form itself is clicked it runs through checks to see what needs to be updated and updates; Its a bit crude but it works quite well. This solution wont work if something else other than the form is clicked but that didnt work either for Textbox1_Exit(etc). Since it only updates the form when the form is in the forefront.
It is Also a bit wasteful of cycles as it runs every single time anything on the form is clicked too but as long as the checks are efficient it should be good enough.
I will keep working on a better solution however when I have time, maybe see if I can get exiting from the frame working like FaneDuru said but something else on the form seems to be blocking that solution for now.
Context
I'm using the Listbox_DblClick event of on an Excel Userform (within a .xlam AddIn) to do a bunch of thing (which mainly update the Userform, but alost does some external logging...). Those actions can take up to a few seconds.
Problem
Excel winbdows are let almost frozen if the user move the mouse cursor outside the Listbox during the ListBox_DblClick event.
Consequences
I cannot click anywhere on the UserForm or ActiveSheet or the VBA window. Even the close button of Excel is unresponding. But nothing seems to be running (the last line of the event has already ran, nothing visible on the CPU...)
To be able to interact with Excel again, I need to either :
move temporarly the mouse cursor back over the ListBox
or change temporarly the current Windows application (like by doing Alt+Tab twice).
Excel is then globally fine. There isn't any other consequence and everything runs OK after this freeze.
What I already checked
It's not related to an EnableEvents or ScreenUpdating issue. Those are correctly managed by the macro. Even adding two lines to set them to True at the end of the event don't resolve the issue.
It's not that the macro is still running. Adding Debug.Print "Finished" at the end of the event show that "Finished" prints normally, while Excel is kept frozen.
Since I don't want the user to launch a new event while the current event is still running, I prevent that by locking/delocking the many ListBox (including the one realted to the event) using ListBox.Locked at the beginning/end of the event. But commenting these lines doesn't resolve the issue.
Minimal Reproductible Exampe
Add an Array on a UserForm
Add the following code
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
For n = 1 To 3000
Me.Caption = n
Next n
Me.ListBox1.List = Array("Apple")
End Sub
Private Sub UserForm_Initialize()
Me.ListBox1.List = Array("Apple", "Banana")
End Sub
Double click on "Banana" and moove the mouse cursor
Note
In this post form 2012 (Editing listbox items in Dblclick event freezes Excel unless mouse moves over listbox), the user seems to encounter a similar issue.
I'm creating a system that allows an individual to select module choices for their degree.
The users have to navigate between multiple forms (e.g. semester 1 & 2, user info, confirmation pages etc.). I want the users to be able to return to a previous form to make changes after progressing (i.e. return to semester 1 choices after moving onto semester 2 choices) and be able to still edit all the data they inputted into the first form.
I have tried using the hide and show methods but I keep getting an error (Run Time error '400' - Form already displayed, cannot show modally)
'on the AM1 form
AM2.Show
AM1.Hide
'(first form I want to close)
'on the AM2 form
Unload me
AM1.Show
'(I want to return to the first form and close the second)
I want to be hide the first form (AM1) and keep all the info available to be re-edited when successfully returning to it.
Try hiding AM1 first before showing AM2 and that should fix your issue.
Private Sub CommandButton1_Click()
UserForm1.Hide
UserForm2.Show
End Sub
Also I think using the multipage control is probably better than using multiple userforms.
Hi I the following code in Excel VBA,
Sub A ()
Workbooks.open ("A.xls")
ActiveWorkbook.Worksheets("1").Select
ActiveSheet.CommandButton1.value = true
End Sub
I'm opening another workbook (the code inside is protected so I can't modify the workbook "B") and clicking a run button on the worksheet, and it returns a MsgBox with OK button.
I want to know how I can use VBA to close this MsgBox or clicking "OK" ...I tried to use,
`application.DisplayAlert = false`
before opening the workbook "B" but this does not work..
Thanks for your help!
There might be an approach using SendKeys -- but SendKeys is notoriously temperamental. Here is a more reliable approach:
1) If you don't already have it organized like this, have the click-event handler of the button a 1-line sub that looks like:
Private Sub CommandButton1_Click()
Process
End Sub
Where Process is the sub which actually does the heavy lifting. In general, I think it a good idea to have event handlers mostly functioning as dispatchers to subs.
2) Change the code for Process (or whatever you choose to name it) in the following way:
a) Modify the first line to look like
Sub Process(Optional Verbose As Boolean = True)
b) Where Process has something like
MsgBox "Processed!"
replace it by
If Verbose Then MsgBox "Processed!"
3) In the code you gave above, replace the line
ActiveSheet.CommandButton1.value = true
by the line
Application.Run "A.xls!Process", False
This approach will bypass the button entirely and run the code which the button normally triggers, but run it in silent mode.
On Edit: To use SendKeys you could do the following. Put the line
Application.SendKeys "~"
before the line
ActiveSheet.CommandButton1.value = True
~ is the character shortcut for Enter. SendKeys doesn't itself send the keystroke, instead it puts something on the Windows Message Queue. VBA doesn't have any direct control about exactly when this message will be processed. In this case the lack of control is a benefit. The VBA interpreter moves onto the next line, which triggers the MsgBox. By the time the SendKeys message is processed the default Okay button on the message box has the focus hence receives the enter key. This can even happen before the box is painted, making it seem that the MsgBox was never there -- but that is better to think of it as being destroyed before you have time to see it.
The reason why it is necessary to have the SendKeys line before the line which clicks the button is that once the message box appears it will cause the VBA interpreter to wait until it is closed -- hence the calling code will suspend its execution until after the message box is closed, hence the SendKeys wouldn't be processed until it is no longer needed.
I don't really trust SendKeys. I suspect that sometimes when you run the code what will happen is that A1 in the newly activated sheet will receive the enter key (shifting the selection from A1 to A2) before the message box appears. I'm not sure if this can happen, but if it does a workaround might be to move the SendKeys to a VBScript program. Launch this program (with window minimized and not waiting for return) before the button is clicked. The VBScript program can have say an 0.5 second pause before it uses SendKeys. The script will be running in a different thread so it won't be blocked by the message box.
My macro is going to compare a sheet with another sheet. This second sheet needs the user to paste data in there. (Note: The data being copied is not in Excel).
One way is to run the macro, and end it by prompting the user to paste the data in, then run "Macro2". However, I'd like to keep it all in one macro, so have found a way to wait for user input before continuing. This seems to work for me, so my main question is:
How stable is doing it this way?
...macro stuff above here
MsgBox ("[Please copy the data into the new sheet, after clicking 'OK']")
Do While WorksheetFunction.CountA(newWS.Cells(1, 7)) < 1
DoEvents
Loop
...then after the user pastes info, continue on, using the data that's been pasted.
The idea is that DoEvents just runs and runs while my sheet is blank. Right after the user pastes the data into the newWS, the macro continues on (since it will see data in column 7)...
Is this an okay method, or is it a bad idea to use like that? I've never really used DoEvents, so don't know if it's doing something in the background that could cause issues.
Edit: The data is in Lotus Notes, which I can export to Excel. However, that takes a few more steps (and I'd rather not create some new temporary excel files), so copy/pasting is my preferred method. This question is half practical, and half theoretical. Sorry for any confusion!
Probably not the best idea. Instead, allow them to select the data and perform the copy, all through VBA:
MsgBox ("[Please select data to copy into the new sheet, then press 'OK']")
newWs.Cells(1,1).PasteSpecial '### Modify to your specific location to paste the data
'Here you can add logic to validate that they have pasted enough data,
' and use control statement to prompt them to paste more data, etc.,
' if necessary, or exit sub early
'For example:
If WorksheetFunction.CountA(newWS.Cells(1, 7)) < 1 Then
MsgBox "Try again!"
Exit Sub
End If
Alternatively, you can use a DataObject:
Dim dataObj As New MSForms.DataObject
dataObj.GetFromClipboard
newWs.Cells(1,7).Value = dataObj.GetText
You could restructure the code so that it lives inside of a userform with ShowModal set to false (in the properties). Code prior to when you want the user to gather data can be put in the useform's initialize event. Then the userfrom shows (with a simple label caption and an okay button). Since it is modeless the user can copy data from an external program and paste it in. Then the rest of the code runs after the user hits okay. The form itself can be hidden during this phase. As proof of concept I created the following form:
with the following code:
Private Sub CommandButton1_Click()
Me.Hide
MsgBox Range("A1").Value
Unload Me
End Sub
Private Sub UserForm_Initialize()
'macro code can go here
'it runs before the form shows
'e.g.
MsgBox "Initializing"
End Sub
I launch the form on a blank sheet. First a message box appears before the code (confirming that code can run while the form is being initialized but before it is visible) then the form shows:
I go to an open instance of Notepad which contain a sentence and, while the form is still open -- paste it into A1:
Finally I press okay and the userform then hides itself but continues to run code (which now has access to the copied data):
Remember to unload the form at the end.