How do you prevent printing dialog when using Excel PrintOut method - vba

When I use the PrintOut method to print a Worksheet object to a printer, the "Printing" dialog (showing filename, destination printer, pages printed and a Cancel button) is displayed even though I have set DisplayAlerts = False. The code below works in an Excel macro but the same thing happens if I use this code in a VB or VB.Net application (with the reference changes required to use the Excel object).
Public Sub TestPrint()
Dim vSheet As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set vSheet = ActiveSheet
vSheet.PrintOut Preview:=False
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
EDIT: The answer below sheds more light on this (that it may be a Windows dialog and not an Excel dialog) but does not answer my question. Does anyone know how to prevent it from being displayed?
EDIT: Thank you for your extra research, Kevin. It looks very much like this is what I need. Just not sure I want to blindly accept API code like that. Does anyone else have any knowledge about these API calls and that they're doing what the author purports?

If you don't want to show the print dialogue, then simply make a macro test as follows; it won't show any print dialogue and will detect the default printer and immediately print.
sub test()
activesheet.printout preview:= false
end sub
Run this macro and it will print the currently active sheet without displaying the print dialogue.

When you say the "Printing" Dialog, I assume you mean the "Now printing xxx on " dialog rather than standard print dialog (select printer, number of copies, etc). Taking your example above & trying it out, that is the behaviour I saw - "Now printing..." was displayed briefly & then auto-closed.
What you're trying to control may not be tied to Excel, but instead be Windows-level behaviour. If it is controllable, you'd need to a) disable it, b) perform your print, c) re-enable. If your code fails, there is a risk this is not re-enabled for other applications.
EDIT: Try this solution: How do you prevent printing dialog when using Excel PrintOut method. It seems to describe exactly what you are after.

The API calls in the article linked by Kevin Haines hide the Printing dialog like so:
Get the handle of the Printing dialog window.
Send a message to the window to tell it not to redraw
Invalidate the window, which forces a redraw that never happens
Tell Windows to repaint the window, which causes it to disappear.
That's oversimplified to put it mildly.
The API calls are safe, but you will probably want to make sure that screen updating for the Printing dialog is set to True if your application fails.

Related

Worksheet_Change Event not firing

My Excel project functions properly at home (with Excel 2010), but not on two work computers (with Excel 2016) and I suspect the Worksheet_Change event is the problem.
When the user makes changes, the yellow bar (in the screenshot) should turn white again, but it is not. I am getting 2 different responses on 2 work computers.
Two things to point out in the code:
In some places I use vbColor extensions, in others I had to use a numerical code.
One computer is not firing the Worksheet_Change event at all. I would note that the change event is at the top of the code, although that shouldn't have anything to do with it.
I'd appreciate advice and detailed explanations, to help me learn.
Private Sub Worksheet_Change(ByVal Target As Range) 'Check for On-Time and Delays then change the Command Button Colors to show completed.
'Return headers to white after jump to
Range("B3:I3,O3:V3,B28:I28,O28:V28,B53:I53,O53:V53,B78:I78,O78:V78,B103:I103,O103:V103,B128:I128,O128:V128,B153:I153,O153:V153").Interior.Color = vbWhite
'Check for On Time and Delayed Trips
'Trip 1 Scan Ready
If IsEmpty(Range("L3").Value) = False Then
If Range("L3").Value > Range("I3").Value Then 'If actual is greater than Departure
'If Delayed check for a delay code
If IsEmpty(Range("L24").Value) Then 'If Delay code is missing
Range("K24:L25").Interior.Color = 16711935
CommandButton1.BackColor = 16711935
CommandButton1.ForeColor = vbBlack
Else 'If Delay Code is present check for delay time
If IsEmpty(Range("L25").Value) Then
Range("K24:L25").Interior.Color.Index = 16711935
CommandButton1.BackColor = 16711935
CommandButton1.ForeColor = vbBlack
Else
CommandButton1.BackColor = vbRed
CommandButton1.ForeColor = vbWhite
Range("K24:L25").Interior.Color = vbWhite
End If
End If
Else
'Flight was on Time
CommandButton1.BackColor = 32768 '32768 = Green
CommandButton1.ForeColor = vbWhite
Range("K24:L25").Interior.Color = vbWhite
End If
End If
There could be a number of factors causing this problem. One way to diagnose is to troubleshoot like this:
At the beginning of your procedure, right after this line:
Private Sub Worksheet_Change(ByVal Target As Range)
...add a temporary line:
MsgBox "Changed: " & Target.Address
...then go change something in your worksheet (whatever change isn't firing the event as you'd expect).
One of two things will happen:
You'll have a message box pop up, showing the cell reference of whatever was just changed.
This demonstrates that the event is firing properly, so the issue must be in your code that follows.
Or, you won't get a message box pop up. This indicates the event is not firing, which could be caused by a few possibilities:
Are macros completely disabled in the workbook? This is often done automatically on workbooks received from outside sources. Save the workbook to a trusted location on the local computer or network (rather than opening from the email). Do other sections of code run properly? When you close/re-open the file, are you given a warning about Macro Security? Also, try rebooting the computer.
Other security settings could be an issue. Have you ever run VBA on these machines? You can confirm sure code is able to run in Excels' security settings in:
File→Options→Trust Center→Trust Center Settings→Macro Settings
As well as making sure macros are enabled there, you could also check Trusted Locations in the Trust Center, and either save your document in a listed location, or add a new location. Security settings will be "reduced" for documents saved in those locations.
Is EnableEvents being intentionally disabled elsewhere in your code? If you wrote all the code, you should know whether you set EnableEvents = False at some point. Perhaps it was intentional, but it's not being re-enabled.
Remember to remove the line you added temporarily, or that MsgBox will quickly get annoying by popping up every time a change is made. :)
You say "the change event is at the top of the code". A worksheet change event will only fire if you put the code in the sheet module concerned. If you've put the code concerned in a non sheet module (e.g. "Module 1" or similar, listed under the "Modules" branch in the object explorer) then that's the problem.
Also, you really shouldn't hard-code cell references like "L3" in your VBA code, because every hard reference will require amending should you (or a user) later insert rows/columns above/to the left of these references. Instead, assign meaningful named ranges to these cells back in Excel, and use those in your VBA.
Also, when using event handlers like you're doing, you should have something like If not intersect(Target, InputRange) is nothing then... so that the code only runs if something of interest changes.
I had the same problem.
I checked everything.
Everything seemed to be proper (enabled macros, EnableEvents=True, etc).
I closed and opened Excel.
Problem persisted.
There was nothing I could do.
I restarted Windows.
Problem disappeared.
Restart took 7 minutes (with all applications closing & restarting), trying to find the cause would take much more. Maybe I could have tried to find & kill every Excel process in Task Manager.
I don't like giving people the advice "try rebooting", but well, Windows is Windows.
I had a different problem. I had saved my worksheet under a new name and then added the code for the event. To get it to work, I had to close the worksheet and reopen it. It then showed the button to enable macros and the code started to work. Hope this helps someone.
Wade
I solved it simply deactivating "Design Mode" in the "Developer" tab.
It seems if you are in "Design Mode", this event (I don't know about others) won't work.
In 2019 Excel cut copy -> paste would not work the paste options were grayed out. Online sources said update and repair the app. I updated office and the copy/paste options worked.
However the worksheet_change event stopped working. After a lot debugging with no luck, I did a hail mary and commented out the subroutine and recreated it. It WORKED!! I have absolutely no idea why or how. If anyone has thoughts please share.
I had some code in a worksheet change that wasnt firing. I also had some code in Thisworkbook upon opening and saving. Resolved the issue by putting Application.EnableEvents = True at the end of the code for workbook open and workbook save.

Auto clicking on a message box using VBA

I am automating testcases for my company's addin.
In one of the testcases, after saving my workbook on my local machine when I try closing the workbook, I am required to click on 'Yes'- saves edited data in our database, 'No'- discards the edits or 'cancel'- simply closes the message box.
I have tried using sendKeys but that didn't work for me.
Eg: For clicking 'No' through my VBA code, I tried to send tab and enter keys like this:
Application.Wait (Now() + TimeValue("00:00:10"))
Call SendKeys("{TAB}", True)
Call SendKeys("{ENTER}", True)
I have tried with various time values still didn't get any success. I would be glad if someone can help me with this.
Thanks in advance! :)
UPDATE: As of now, I have been doing this:
'Some tasks...
ActiveWorkbook.Save
Call Application.Run("workbook.xlsm!Discard")
Application.DisplayAlerts = False
ActiveWorkbook.Close SaveChanges:=False
Application.DisplayAlerts = True
But is there any way to get the window object reference for the message box? Or anyway to stick to the workflow: edit workbook -> save -> try closing -> opt to discard/commit changes to database?
NOTE: By discarding/committing changes to database, what I mean is a server where the data gets updated. Excel is just an interface for the user. I don't want just the excel to be saved but the operation of calling discard/save changes on server as well...
if you have already saved the workbook, you only need to close the workbook. Please try the below code
Activeworkbook.close false
This will close your workbook and you wont be promted for selecting any options.

Allow user to write in a programmatically created Excel sheet without closing the userform

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

Allow user to make entries on worksheet during run-time

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

VBA Dialogs.Show doesn't display warning message

Have Excel (2010 in my case but I think it will be the same also in other versions) with two workbooks. Save first one with name "1.xlx" (example) via Save As dialog. Save second one with the same name "1.xlx" to different location. Excel will not allow it with following warning message:
"You cannot save this workbook with the same name as another open workbook or add-in. Choose a different name, or close the other workbook or add-in before saving."
So far so good. But my problem is that I need to invoke dialog via VBA. I am using following code:
Sub test()
Application.Dialogs(XlBuiltInDialog.xlDialogSaveAs).Show
End Sub
Now I am trying to save second workbook (with the same name to different location) but when I click to 'Save' button nothing happen, no warning message. If I wouldn't know what is wrong it would be very difficult to tell. I didn't change any setting (there is nothing as DisplayAlerts set to true or so). Any idea how make SaveAs dialog invoked via VBA to display similar warnings?
I'm not sure why that doesn't give you an error, but it doesn't me either. If you use Application.FileDialog, you can get that error.
Sub testts()
With Application.FileDialog(msoFileDialogSaveAs)
.Show
.Execute
End With
End Sub
Or you could use GetSaveAsFileName and check the names of all the open workbooks and generate the error yourself.
Can you try with the below code on starting on your code.
Application.DisplayAlerts = True