Actually, I don't understand how this suggestion could work.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.
I haven't.Have you considered always sending the report to PDF and presenting the PDF as the preview.
Disregard bypassing spooler since you only want to know the job was received by the spooler.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.)
Your question and desire contradict each other. Anyway, send print jobs to the spooler. Your Access app can call WinAPI's to get a status from the printer server as to whether the job is queued for printing, currently printing, or cancelled. Once a print job has successfully completed printing, it will no longer appear in the queue.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.)
Indeed it would. It includes the comparatively easy part of fetching print job info from the print queue. I added something similar as a fallback because the print spooler events API function behave somewhat unpredictably in regards to the data the can be retrieved with their events.Would this be of any use?
The tangible information is in the print queue (print spooler). Luckily it's not really the printer itself that needs to be interrogated for that information. It is in the windows print spooler already. This is very fortunate, because there is no need for "advanced printers". Basically every printer that has a Windows driver should be good enough. However, some printer drivers (e.g., "Microsoft Print to PDF") don't support the notifications from the spooler.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.
The screenshot in my last post is proof that you can see queues of remote printers. It shows the remote printer's intranet IP address.OK, I'm impressed. My only question is, given some remote installations, can you see the printer queues from the remote place that is printing (or vice versa, the remote printer queues from the local place that is printing)?
Sorry. That was a foreign language issue. I only noticed now that "is printed" is likely being read as "completed printing" while a literal translation to my language would be "is in the process of being printed".Your question and desire contradict each other.
In theory you are right. The problem is that I need to know *when* to get the status from the print queue. Too frequent polling would waste resources and block the Access UI, while too infrequent polling might miss the report being in the queue.Anyway, send print jobs to the spooler. Your Access app can call WinAPI's to get a status from the printer server as to whether the job is queued for printing, currently printing, or cancelled.
Use a timer to poll the status every 500 ticks (half second).You can set a limit of 10 seconds, (20 polls) using a loop. Play with the polling frequency and total time until you feel it's right.I need to know *when* to get the status from the print queue. Too frequent polling would waste resources and block the Access UI, while too infrequent polling might miss the report being in the queue.
I only noticed now that "is printed" is likely being read as "completed printing" while a literal translation to my language would be "is in the process of being printed".
The answer to the modified question is, start asking immediately after you open the report object. Check for it in the appropriate print queue on a one-second timer loop until you see the job or you reach a time-out point when the report object has been closed for at least 10-15 seconds. Your comments about using CTRL/P to trigger printing from the Preview screen means you might not have a clear-cut event for when it gets sent out for printing. Therefore, you have to have that loop running during the time it COULD be requested by command or keyboard shortcut.The problem is that I need to know *when* to get the status from the print queue.
Function GetRemotePrinterQueueStatus(strPrinterName As String, strRemoteComputer As String) As String
Dim objWMIService As Object
Dim colPrinters As Object
Dim objPrinter As Object
Dim strStatus As String
On Error GoTo ErrorHandler
' Connect to WMI on the remote computer
Set objWMIService = GetObject("winmgmts:\\" & strRemoteComputer & "\root\cimv2")
' Query for the specific printer
Set colPrinters = objWMIService.ExecQuery("SELECT * FROM Win32_Printer WHERE Name = '" & strPrinterName & "'")
If colPrinters.Count > 0 Then
For Each objPrinter In colPrinters
' Get the QueueStatus property
' You can bitwise AND this with specific PrintQueueStatus values
' to check for conditions like PaperProblem, NoToner, Error, etc.
' For simplicity, we'll just return the raw status for now.
strStatus = GetPrinterQueueStatusDescription(objPrinter.QueueStatus)
Exit For ' Assuming unique printer names
Next
Else
strStatus = "Printer not found on remote computer."
End If
GetRemotePrinterQueueStatus = strStatus
ExitFunction:
Set objPrinter = Nothing
Set colPrinters = Nothing
Set objWMIService = Nothing
Exit Function
ErrorHandler:
GetRemotePrinterQueueStatus = "Error: " & Err.Description
Resume ExitFunction
End Function
Private Function GetPrinterQueueStatusDescription(ByVal lQueueStatus As Long) As String
Dim sStatus As String
sStatus = ""
If (lQueueStatus And &H1) = &H1 Then sStatus = sStatus & "Paused, "
If (lQueueStatus And &H2) = &H2 Then sStatus = sStatus & "Error, "
If (lQueueStatus And &H4) = &H4 Then sStatus = sStatus & "Pending Deletion, "
If (lQueueStatus And &H8) = &H8 Then sStatus = sStatus & "Paper Problem, "
If (lQueueStatus And &H10) = &H10 Then sStatus = sStatus & "Offline, "
If (lQueueStatus And &H20) = &H20 Then sStatus = sStatus & "I/O Active, "
If (lQueueStatus And &H40) = &H40 Then sStatus = sStatus & "Busy, "
If (lQueueStatus And &H80) = &H80 Then sStatus = sStatus & "Printing, "
If (lQueueStatus And &H100) = &H100 Then sStatus = sStatus & "Output Bin Full, "
If (lQueueStatus And &H200) = &H200 Then sStatus = sStatus & "Not Available, "
If (lQueueStatus And &H400) = &H400 Then sStatus = sStatus & "Waiting, "
If (lQueueStatus And &H800) = &H800 Then sStatus = sStatus & "Processing, "
If (lQueueStatus And &H1000) = &H1000 Then sStatus = sStatus & "Initializing, "
If (lQueueStatus And &H2000) = &H2000 Then sStatus = sStatus & "Warming Up, "
If (lQueueStatus And &H4000) = &H4000 Then sStatus = sStatus & "Toner Low, "
If (lQueueStatus And &H8000) = &H8000 Then sStatus = sStatus & "No Toner, "
If (lQueueStatus And &H10000) = &H10000 Then sStatus = sStatus & "Page Punt, "
If (lQueueStatus And &H20000) = &H20000 Then sStatus = sStatus & "User Intervention Required, "
If (lQueueStatus And &H40000) = &H40000 Then sStatus = sStatus & "Out of Memory, "
If (lQueueStatus And &H80000) = &H80000 Then sStatus = sStatus & "Door Open, "
If (lQueueStatus And &H100000) = &H100000 Then sStatus = sStatus & "Server Unknown, "
If (lQueueStatus And &H200000) = &H200000 Then sStatus = sStatus & "Power Off, "
If (lQueueStatus And &H400000) = &H400000 Then sStatus = sStatus & "Client Error, "
If (lQueueStatus And &H800000) = &H800000 Then sStatus = sStatus & "Spooling, "
If Len(sStatus) > 0 Then
GetPrinterQueueStatusDescription = Left(sStatus, Len(sStatus) - 2) ' Remove trailing ", "
Else
GetPrinterQueueStatusDescription = "Ready" ' Default if no specific flags are set
End If
End Function
'----------------------------------
'Usage Example:
Sub TestPrinterStatus()
Dim sPrinterStatus As String
' Replace "YourPrinterName" with the actual name of your network printer
' Replace "RemoteComputerNameOrIP" with the name or IP of the computer hosting the printer queue
sPrinterStatus = GetRemotePrinterQueueStatus("YourPrinterName", "RemoteComputerNameOrIP")
MsgBox "Printer Queue Status: " & sPrinterStatus
End Sub