All:
Thank you in advance, you all have been a tremendous resource!!!
I have a couple of spreadsheets where the sheet is protected, but users can still use filters. I'm processing most of the sheets automatically, but what I need to do, is present the user with the sheets that need to be filtered, then have them select a "Finish" type button or toolbar entry, which I already have.
What I need to be able to do, is to bring this sheet up, pause the macro, if possible, while they make their changes (could be up to 5 filters that they select before the sheet is ready.
Then, copy the visible cells only to a specific sheet and then resume the macro.
I don't think that Worksheet change event will do this.
I'm thinking more on the lines of maybe setting a flag on a spare sheet, firing up the next macro and then see if it can find the original macro and pick up where it is flagged?
I thought about a modeless userform that the user could click OK on and then call the next macro, but that does not work.
The calling code is:
UserForm3.Show
CopyToDisplay "AEP"
LastPos = LastPos + 1
Where AEP is the sheet name to copy the filtered rows from.
Userform displays, but clicking ok does nothing and of course, the macro keeps on going.
Any suggestions would be greatly appreciated!
Thanks,
Jeff
Jeff let's try this. Your current code:
UserForm3.Show
CopyToDisplay "AEP"
LastPos = LastPos + 1
When we display a UserForm, the default behavior is vbModal, which essentially freezes the application and the user cannot interact with anything but the UserForm, that is not what you want. What you need is a way to display the form, and then just wait for the user to signal that s/he is finished with the input.
So we need to modify a few things:
The UserForm needs to effectively "pause" while also allowing the user to interact with the worksheet. A vbModal form can't do this (it pauses, without interaction), and really neither can a vbModeless (it continues execution AND allows interaction).
Conundrum? No. we can simulate a pause with the vbModeless form, and preserve the user's ability to interact with the sheet. The best of both worlds!!
We will show the form with the optional vbModeless, this allows the user to interact with the rest of the Application /worksheets/etc. Since a modeless form continues code execution, we need to simulate a pause and we can do this with a Loop. The loop will run indefinitely, and only break once the UserForm is closed, at which point the rest of the code will continue to execute.
UserForm3.Show vbModeless
Do While UserForm3.Visible
DoEvents
Loop
LastPos = LastPos + 1
'You MAY need to reset some variables, if the Filter/Autofilter has affected these/etc.
Design-wise, give your form a single Label control and set its .Caption property (and the form's .Caption property) in some useful/instructive way. You could add a command button but that seems unnecessary, since all the button would do is invoke the Terminate event (which can always be done with the red "X")
For your issue with copying (apparent failure to paste), try changing this:
Sheets("AEP").Select
With ActiveSheet
.UsedRange.SpecialCells(xlCellTypeVisible).Copy _
Destination:=Sheets("Display").range("A" & LastPos)
.AutoFilterMode = False
Application.CutCopyMode = False
End With
To this:
With ActiveSheet
.UsedRange.SpecialCells(xlCellTypeVisible).Copy
Sheets("Display").range("A" & LastPos).PasteSpecial
.AutoFilterMode = False
Application.CutCopyMode = False
End With
Related
I have a requirement for VBA script in Microsoft Word to pause so that the user can select text that will be copied to the clipboard so that it can exported to an Excel file. The user will make a number of selections and finally indicate he/she is done when the contents of the clipboard will be copied to a template Excel file.
I have the code working to copy each selection to the clipboard and then all rows to the Excel file. But I need assistence in figuring out how to pause the code to allow the user to make the selection and then restart the code to copy the selection to the clipboard. I am able to get the userform with toggle switch to switch states and labels when pressed. But have not figured out how to pause the VBA code to allow the user to navigate to the next section of the Word document for the next selection.
The Stakeoverflow question/answer below appears to address this requirement but I have not been able to get it to work. It appears that the code is incomplete.
Pause VBA macro, allow user to make a selection, and restart where it left off
Can someone provide example VBA code that accomplishes this?
Your assistence is much appreciated as I have been beating my head against the wall and it is starting to hurt!
There's no way in VBA to "pause" a macro. Code must run to completion... Unless there's a command for user input.
Input can be requested via the InputBox and MsgBox methods, but those block access to the document because they're modal. A UserForm, however, can be set to display as non-modal, meaning it stays on top, but doesn't block access to the document or the application features. Since you're already working with a UserForm, this can be implemented relatively easily.
In the small example below, the Continue button runs the code to perform an action on the user selection. When Done is clicked the entire code is exited and the form unloaded.
Code behind the user form
Option Explicit
Private Sub cmdContinue_Click()
Debug.Print Selection.Range.Text
End Sub
Private Sub cmdDone_Click()
Me.Hide
End Sub
Private Sub UserForm_Activate()
'Position the form near the top-left of the window
'So that the user can work with the document
Me.Top = Application.ActiveWindow.Top + 50
Me.Left = Application.ActiveWindow.Left + 50
End Sub
Code in a regular module
Option Explicit
Sub DisplayModeless()
Dim frm As frmModelessForInput
Set frm = New frmModelessForInput
frm.Show False 'Display as non-modal
Set frm = Nothing
End Sub
I have a checkbox "Check_Group" in a worksheet "FA 2.0 Pricing Worksheet". I have a subroutine defined in said worksheet that changes some values elsewhere when the user clicks on it:
Private Sub Check_Group_Click()
Active = ActiveSheet.Name
Sheets("FA 2.0 Pricing Worksheet").Activate 'This activate has to happen here because there are some steps in a different routine where this checkbox has to be clicked programmatically
If ActiveSheet.OLEObjects("Check_Group").Object.Value = True Then
Sheets("FA 2.0 Risk Checklist").Range("UI_GROUP_RISK").Value = "No"
Else
Sheets("FA 2.0 Risk Checklist").Range("UI_GROUP_RISK").Value = "Yes"
End If
Sheets(Active).Select
End Sub
This works like a charm, except I've noticed a particularly annoying side-effect - the keyboard seems to lock after you click on it!
I can click into cells and navigate around the sheet with no problem, but when I try to type into (an unprotected) cell it doesn't react to my key presses at all.
I have confirmed with the debugger that EnableEvents and ScreenUpdating are both on.
I can skirt around the issue by clicking to another tab and back - typing works as normal then... in the exact same cells where it failed to type before! I'd still like to find a solution rather than just this cheap workaround though.
This is in Excel 2016.
Why does my subroutine lock the keyboard?
There's no need to activate the sheet for your code to execute.
And, when you're in a sheet code module you can refer to the sheet using Me
Private Sub Check_Group_Click()
Me.Range("UI_GROUP_RISK").Value = IIf(Me.Check_Group.Value, "No", "Yes")
End Sub
I have a Worksheet_Change event where if a cell in column F changes, a message pops up asking if the user wants to change the cell text.
Now, I have VBA code that inserts new rows and, therefore, makes changes in column F, but I don't want the message to pop up or this code to be called at all.
Is there a way to distinguish between a user and Excel itself (VBA) making a change on the worksheet?
Just insert the line
Application.EnableEvents = False
before executing your code and then (at the end) set
Application.EnableEvents = True
again to make sure that Excel reacts to Events on the worksheet again.
For more information read this: https://msdn.microsoft.com/en-us/library/office/ff821508.aspx
I programmatically create a new Excel sheet within my VBA application when the user clicks on a button. I would like to allow the user to write this newly created sheet and keep the userform of creation of new sheets displayed in the same time.
EDIT : Additional precision : I use a succession of userforms, the first one is an authentification form, the second one is a functionnality selection menu and the one I mentionned in my question offers one of those functionnalities. Therefore the correct solution to my problem was to show all these user-forms as non-modals.
Show the userform as non-modal:
Userform1.Show False '//<-- Allows user interaction whilst form is active.
Caveat:
Displaying a form as non-modal will allow code execution to resume after the form is displayed - this could result in unexpected behavior and should be considered at design time. For example:
Sub ModalExample()
UserForm1.Show '// Show modal, code will pause here until form is closed.
MsgBox "Userform has now been closed."
UserForm1.Show False '// Show non-modal, code will continue to execute regardless.
MsgBox "Userform is still open."
End Sub
The accepted answer is wrong. The following line of code is incorrect:
Userform1.Show False
The suggestion to display the userform modelessly is a good one for this question's scenario, but to be correct it should be done like so:
Userform1.Show vbModeless <---This is correct.
It is true that both False and vbModeless evaluate to the value zero. HOWEVER, that's just coincidence.
For example, if you were to try the inverse to display the userform modally, it would not work:
Userform1.Show True <---This does NOT work.
But this does:
Userform1.Show vbModal
Never use Boolean values as an argument to a userform's Show method. Instead use the members of the FormShowConstants enum.
I am pretty sure that if a userform is active then it will not allow you to access the worksheet until it is closed.
Couple of ways around this though. Hide the userform until it is needed again. Set it to a keyboard shortcut or something to show it again. So it would be userform.hide then have another macro or a button in the ribbon to show the userform again by using userform.show
Instead of creating a new sheet. Create a new instance of Excel with a new workbook. That would allow the userform to stay open in one Excel instance and then the user can write to the other workbook in the other instance of Excel
To create a new instance of Excel you would need to use the code
Dim objExcel As Excel.Application
Set objExcel = CreateObject("Excel.Application")
objExcel.Workbooks.Add
objExcel.Visible = True
That will create a new Excel instance and still have the userform in the other instance of Excel
I have a macro that takes roughly five seconds to execute and I'm using the code Application.ScreenUpdating = False so it looks like Word has locked up when it's running.
I use a message box at the end to tell them it's complete, but I'd like to display an image during its execution that tells the user the macro is running (primarily so they don't get worried, but also because it's nicer to look at).
There might be an easier way to go about this, but I decided to create an image, create a very basic user form, and simply set my image as its background. Then, I have that user form pop up as soon as the code starts to run.
The problem I'm having is that unless I close it, the rest of the code won't execute. It just hangs until I do something. Is there a way I can get the user form to be displayed without stopping the rest of the process? If not, is there another approach I can take to display an image while the macro is running?
You can show the userform as non-modal:
Userform1.Show False
'do more stuff (doesn't wait for form to close)
Userform1.Hide
I too have found that if you .show a userform at the beginning of the process, images contained within userform take a while to display and the result is less than smooth.
I have solved it by inserting a 1 second "wait" immediately after the userform.show instruction. In that split second, the image loads and displays successfully and the result is seamless.
Here the code. I have 2 macros: 1 to display and 1 to hide. I call the first macro at the beginning of the process just before freezing the screen and the second at the end of the process just before unfreezing the screen
Userform name is "myuserform"
Sub message_show()
userform.Show False
Application.Wait (Now + TimeValue("0:00:01"))
End Sub
Sub message_hide()
Application.Wait (Now + TimeValue("0:00:02"))
userform.Hide
End Sub