Solved Report Sent to Printer? (1 Viewer)

sonic8

AWF VIP
Local time
Today, 18:12
Joined
Oct 27, 2015
Messages
1,412
I want to know when a certain report is sent to a printer (as opposed to being displayed as preview). I.e., I want to be able to distinguish preview and printing in any of the reports Print events.

This must also work if the report is displayed in preview before being sent to the printer and also when the report is displayed in preview as a dialog.

I’ve spent several hours researching this matter. I’ve “found” more ways that do not work than I can list here.

Please note:
1.) It is not feasible in this scenario to intercept each and every command to print a report. (I doubt this is reliably feasible in any scenario, but definitely not here.)
2.) Please do not insult me by posting unverified AI garbage as suggestion.
 
If you have enabled printer logging, you can view after-the-fact that a file was sent to a networked printer via the print queue manager. That fact would be in a system event log. However, the question of print verification has come up before and I don't recall that we had a foolproof answer.

For example, the log might show that printing was started, but once the job is sent to a networked printer, it is no longer active on your PC. You have no way of knowing if the printer actually finished the job unless that printer allows interactions with its contributor print-job sources. If someone cancels the job, you have little to no way of seeing that. If your printer is hard-wired to the computer (rare these days with the advent of networked autonomous printers), you MIGHT be able to find a program to monitor activity of that device.

Part of the problem is that by default, any printer's queue is managed by a system task (Print Queue Manager, probably running under a SVCHOST job) and you are not allowed to interact with an independent task unless you set up interaction conditions... such as logging. I would be curious to find if there is a foolproof way to find out what you asked. I will not say "impossible" but I will say "I'm skeptical."

I think the problem is less that the data doesn't exist and more that you can't get to the data that DOES exist.
 
Part of the problem is that by default, any printer's queue is managed by a system task (Print Queue Manager, probably running under a SVCHOST job) and you are not allowed to interact with an independent task unless you set up interaction conditions... such as logging. I would be curious to find if there is a foolproof way to find out what you asked. I will not say "impossible" but I will say "I'm skeptical."
@The_Doc_Man, this is a very good idea and one I consider for further investigation.
I think, some of the stated reasons for your skepticism are not that big of a deal. There is a set of Windows API functions for interacting with printer spoolers. However, the apparently most suitable functions for monitoring the printer spooler depend on Windows event signalling (e.g. WaitForSingleObject), which work by blocking a thread until an event of interest occurs. This is difficult to implement in a single threaded environment such as VBA.

I probably will investigate the above mentioned API in more depth but I still hope for a simpler solution which I overlooked so far.
 
A simpler solution would be to ask the user "Did it print OK y/n", but I presume you have already ruled that out.

Did you also rule out offering 2 buttons, one for preview and one for print? You would still have to deal with Ctrl+P after preview, but that would be the only keystroke to catch. EDIT: perhaps better: if there are new Detail_Print events after the initial set, that indicates print after preview.

I tried a variety of events and properties, but nothing so far. I will ask a friend and reports guru if he has any ideas.
 
which work by blocking a thread until an event of interest occurs. This is difficult to implement in a single threaded environment such as VBA.

True enough. Single-threaded VBA makes parallel action difficult to track. But more conditions than just "events of interest" are involved, I think.

You are correct that an API can talk to a spooler task running on the same machine. However, the next question is whether your printer is networked autonomously (smart printer) or networked as a dumb device on another machine? If so, you would lose potentially contact with any print job to a remote printer unless that remote printer allows status queries.

The problem boils down to the fact that we have progressed to "set it and forget it" devices to make our offices simpler and more efficient. So much so that if you ask a printer, "Did you print job 123XYZ?" it might reply "I forgot."
 
@BlueSpruce - the question is, if the NET USE LPTn targets a busy printer, does the print job automatically get spooled anyway, thus falling out of your span of control? A LOT of Windows commands that can't be executed instantly can sometimes get queued up. This auto-queue-print-job option has been part of PCs since MS-DOS was a thing.
 
A simpler solution would be to ask the user "Did it print OK y/n", but I presume you have already ruled that out.
The question I'm trying to get answered is not whether it printed OK, but whether the user sent it to the printer in the first place. Only if I knew that the user tried to print I could ask how it turned out. - But this is not my concern in this context.

Did you also rule out offering 2 buttons, one for preview and one for print? You would still have to deal with Ctrl+P after preview, but that would be the only keystroke to catch.
There currently are exactly these two buttons. Still, users are able to print the report without pressing the print-button.
This report is supposed to be used as sort of a component in multiple applications. Not all of these applications are maintained by me.
So, essentially, it is not just [CTRL]+[P], but it might also be a Print command in the context menu, in the Ribbon, in the QAT, or in an unknown number of other places in those applications. Therefore the report itself should know when it is printed.

EDIT: perhaps better: if there are new Detail_Print events after the initial set, that indicates print after preview.
This does not work, at least not reliably. :-(
If you open a report, browse to its last page, then browse back to the first page, the detail_print events for the first page may be triggered again without ever leaving preview. - This doesn't happen always. The number of pages in the report seems to be one, but not the only, relevant factor. I see it happen consistently if a report has 21+ pages, but sometimes also with fewer pages.
 
> This does not work, at least not reliably. :-(
I thought about it later, and feared what you experienced. Is the ReportHeader_Print event any better?
Of course reports don't need to have a ReportHeader section, but you could add a hidden one.

BTW, I heard back from my report friend, and he is not aware of a solid way to do this using Access report events.
 
So, essentially, it is not just [CTRL]+[P], but it might also be a Print command in the context menu, in the Ribbon, in the QAT, or in an unknown number of other places in those applications. Therefore the report itself should know when it is printed.

I have thought about this for a while now and I'm not even sure how I would do this from a mainframe. I can't even imagine how to do it from a VAX/OpenVMS setup, and I hold sys admin certificates in that machine and have had formal training in the O/S internals from DEC when they were still in business.

Generating a report creates an image in memory of what the report should look like, and THAT is what gets printed. It is also what gets displayed on-screen in Report and Print Preview modes. However, that object is a passive image. That image is now just another temp file that, unless you told Access or the printer command interface to retain the file after printing, will independently cease to exist - and on its own sweet time depending on whether it got spooled or sent directly. In response to your statement, the actual report does NOT know when it is printed.

The way to do anything useful in Access is to trap an event and have a little bit of code tell you what you wanted to know. The thing that has usable events is the report's document object that you open with Print, Print Preview, or Report views. THOSE views, while they are still under control of Access, have events. Another problem in this case is that a print image that is sent to a print device loses its connection back to Access and when that happens, there ARE no Access events that you can see. Windows could still see it, and thus APIs could reveal whether a local printer might have a print log entry. After that, though, if it is a remote printer, once it gets sent to the remote host, the original printing host has no further feedback events either.

The ONLY device that can answer the question is the destination printer itself. If and only if you have a printer that can - and knows to - answer your question, you can network-query the targeted printer to determine whether the report got sent. Otherwise... no reliable way to do it because there is no back-pointing data path. Unlike e-mail, there is no such thing as a standard "printer delivery notice."

This remains one man's opinion, but it is an opinion based on the mechanisms involved.
 
What I said, more or less.

Ask Windows, look at the print queue, look at Event Viewer, or use API code.
User notification of completed jobs is if and only if the printer driver supports that feature, but advanced printers might have it.

Whatever you do, it ain't gonna be easy. But if you think you can do it, I'm sure a lot of folks would be interested in the result.
 
@The_Doc_Man , I also attentively read your previous longer post and mostly agree. I just reply to this short one because it covers the core items.

Ask Windows, look at the print queue, look at Event Viewer, or use API code.
It's not "or use API code", but one must use API code to do any of the former.

User notification of completed jobs is if and only if the printer driver supports that feature, but advanced printers might have it.
I'm not interested in the completion of the print job, I just want to know whether printing was initiated (i.e., a print job started).

In theory, every printer (driver) for Windows should support providing the relevant information. Windows displays the document and owner name in the print queue window. That information would be sufficient for me.
In practice, your "if the printer driver supports that feature" seems to be closer to the truth than I would like.

Whatever you do, it ain't gonna be easy.
I can confirm this. :-/
The print spooler API looked complex and difficult at first glance. After a couple of hours "investigating" it with code, it turns out to be a much more stubborn beast than anticipated.
 
I don't know the environment you're looking for a solution for, but I have an idea that I'd like to at least mention.

As far as I understand, your software solution is about being able to say with certainty that your software has printed and that the job has reached the printer. Whether paper actually comes out is irrelevant.

Perhaps this could be expanded upon in your (customer?) environment and divided into two steps:

Step 1:
- You don't print to the target printer, but rather to PDF files in a network folder, for example.
- Now you can check the existence of the PDF file and your task is done as soon as it exists.

Step 2:
- A service checks the network folder for PDF files and prints them out.
- Ideally, you have nothing to do with this step; it's handled by the customer's IT department.

But the question is whether this is enough for you and whether it can be implemented for the target environment.
 
@AHeyne , thank you for the suggestion. This would indeed be a possible solution to the problem as I presented it here. However, ...

Step 2:
- A service checks [...]
This, unfortunately, is the deal breaker here. The application is used at several distributed locations. Installing and maintaining an external service would add too much complexity to the process and is beyond the capabilities and capacity of the personnel and possibly also the infrastructure at most of the sites.
 
Surely you know it, but just in case:
https://nolongerset.com/detect-report-mode/
Thanks, I know that. It doesn't work with either of these two requirements:
This must also work if the report is displayed in preview before being sent to the printer and also when the report is displayed in preview as a dialog.
I've found a solution that also reliably works with a report displayed as dialog, but the "open preview, then print"-scenario is the tough nut I still try to crack.
 
It's not "or use API code", but one must use API code to do any of the former.

I accept the correction. When dealing with distributed sites, NONE of that stuff is built-in to Access. You always have to use something external - like an API or 3rd-party package - to get your answer.
 
Have you considered always sending the report to PDF and presenting the PDF as the preview. Any attempts to reprint the report would reopen the saved PDF or creating a revision PDF to preview.
 
Maybe it's possible to track completion if the spooler is bypassed and the print job is sent directly using the printer's IP address. IIRC, a batch script with a //NET USE LPTn: command was used to accomplish that.
Actually, I don't understand how this suggestion could work.
How would I sent an Access Report to a printer directly?
Maybe the printer could be configured to bypass the print queue with the "Print directly to printer" option as shown in your screenshot. But this would mean to reconfigure all potentially used printers to use this option, which might have side effects for all the other documents printed there.

And, even if the basic setup could be achieved, the core questions remains: How would I be able to detect when the report is printed?
(I don't want to track completion of the print job, just knowing if the report was sent to the printer is relevant to me.)
 
Have you considered always sending the report to PDF and presenting the PDF as the preview.
I haven't.
Your suggestion would probably solve the problem, but at what cost?
Printing to PDF and displaying the PDF as preview will be much, much slower than just opening the report in preview, even if I use a webbrowser control to display the PDF instead of an external PDF viewer.
Users will be very confused: Why is this report preview looking and working so differently from all the other report previews in the application? - To make the confusion worse: Almost all reports are exclusively printed to PDF, except the one this thread is about, which is printed on paper.
 
This is always going to come back to this question: "What - and where - is the measurable property?" If you cannot get feedback from the printer such as notification for advanced printers, there is no way to answer this question.
 

Users who are viewing this thread

Back
Top Bottom