Report Sent to Printer? (4 Viewers)

sonic8

AWF VIP
Local time
Today, 16:46
Joined
Oct 27, 2015
Messages
1,376
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.
 
@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?
No, it doesn't get spooled. The print job fails and you get a printer busy message which you would have to trap in your error handler.
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.
Same with Unix, VAX/VMS, and other platforms. I have an Access app that prints directly to a parallel Okidata dot matrix printer using PRINT#1 statements in my VBA code and selecting the net printer's IP address.
 
IMG_0300.jpeg
 
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.
 
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.
GoogleAI said:
Microsoft Access
, or any Windows application, relies on the Windows Print Spooler and associated Print APIs to track the status and eventual completion of a network print job.

The Mechanism
  1. Job Submission: When an Access report or form is printed, the application sends the print job data to the Windows Print Spooler service on the client computer (or a print server).
  2. Spooling and Transfer: The spooler manages the job, sending it to the physical printer. It tracks the job's progress using a job ID.
  3. Status Updates: The printer communicates its status (e.g., "printing," "paused," "error," "completed") back to the Windows Print Spooler via bidirectional communication protocols.
  4. Application Notification:
    • Programmatic Access: Developers can use Windows Print APIs to programmatically monitor the print queue and receive notifications or events when a job's status changes to "Completed" or "Error". This involves registering for print events or actively polling the print queue status using functions like IPrinterQueueView::SetViewRange.
    • User Notification: Windows can display a pop-up message in the system tray to notify the user when a print job finishes. This feature is typically enabled in the printer's properties under the "Advanced" tab by enabling "Notify for Completed Jobs".
    • Print Queue Window: The user can open the print queue window to visually see the job's status. Once the job is completed successfully, it usually disappears from the active queue (unless the "Keep printed documents" option is enabled in the printer settings).

How Access Specifically Knows
Microsoft Access itself is a high-level application that generally doesn't implement low-level print monitoring APIs directly. Instead, it relies on the underlying operating system's (Windows) mechanisms:
  • Default Behavior: By default, Access simply hands the job off to the Windows spooler and assumes it will be handled. The application typically doesn't wait for explicit "completed" confirmation to proceed with other tasks.
  • VBA Automation (Advanced): A developer using VBA within Access could potentially write code that uses Windows API calls (P/Invoke) to monitor the print queue for a specific job ID. This custom code would need to:
    • Obtain the job ID upon submission.
    • Poll or register a callback function with the Windows spooler to check the job's status periodically.
    • Act based on the final status ("completed", "failed", etc.).
In summary, Access relies on the Windows operating system to manage the printing process and report the status. While basic application use doesn't provide explicit job completion feedback, the status is accessible through the Windows print queue, Event Viewer logs, or custom code using Windows APIs.
 
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.
 

Users who are viewing this thread

Back
Top Bottom