Private Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" (ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String) As Long
Public Sub PrintPDF(FileName As Variant)
On Error GoTo ErrHandler
Dim Error282Count As Integer ' Количество ошибок "Can't open DDE channel"
Dim AcroDDEFailed As Boolean ' Кстанавливается в true если не удалось установить DDE соединение
Dim strCmd As String ' DDE команда
Dim lStatus As Long ' Ответ команды ShellExecute
Const Max282Errors = 6 ' Количество попыток установить DDE соединение, перед тем как будет решено
' что Acrobat Reader не удалось запустить.
' Возможно, что число потребуется изменить для конкретного компьютера
Dim strAcroPath As String ' Path to acrobat, determined by FindExecutable
Dim bCloseAcrobat As Boolean ' If we open acrobat, we will close it when we are done
'' If acrobat is already running (and hidden), shelling it will cause it to be shown.
'' We do not want that. So try a DDE connect, which will fail if acrobat is not running
'' I have looked at other API means of testing this, but it may be running as a process (no window)
'' and there does not seem to be many graceful ways of testing for this.
Error282Count = Max282Errors '' we only need to try once to see if it is already running.
AcroDDEFailed = False '' ErrHandler will set to true if Acro is not running
Dim lngChanel As Long
'создаем DDE канал
lngChanel = DDEInitiate("acroview", "control")
If AcroDDEFailed = True Then
'' Use the FindExecutable API function to grab the path to our PDF handler.
'' This should be Acrobat Reader or Acrobat, but it might be something else.
'' When we try to DDE link to it, non-acrobat will error out. This is ok.
strAcroPath = String(128, 32)
lStatus = FindExecutable(FileName, vbNullString, strAcroPath)
If lStatus <= 32 Then
MsgBox "Acrobat could not be found on this computer. Printing cancelled", vbCritical, "Problem"
Exit Sub
End If
'' Launch the PDF handler
lStatus = Shell(strAcroPath, vbHide)
If (lStatus >= 0) And (lStatus <= 32) Then
MsgBox "An error occured launching Acrobat. Printing cancelled", vbCritical, "Problem"
Exit Sub
End If
bCloseAcrobat = True '' We will try to close Acrobat when we are done
End If
PauseFor 2 '' Lets take a break here to let Acrobat finish loading
Error282Count = 0 '' This time, we will allow all acceptable tries, as
AcroDDEFailed = False '' Acrobat is running, but may be busy loading its modules
'создаем DDE канал
lngChanel = DDEInitiate("acroview", "control")
If AcroDDEFailed = True Then
MsgBox "An error occured connecting to Acrobat. Printing cancelled", vbCritical, "Problem"
Exit Sub
End If
strCmd = "[FilePrintSilent(" & Chr(34) & FileName & Chr(34) & ")]"
DDEExecute lngChanel, strCmd
If bCloseAcrobat = True Then
' нашел в инете что 6.0 6.1, вылетают с ошибкой при DDE команде [AppExit()]
' проверял на 5.0.5 работает нормально
If InStr(strAcroPath, "6.0") = 0 Then
strCmd = "[AppExit()]"
DDEExecute lngChanel, strCmd
End If
End If
'Закрываем все DDE
DDETerminateAll
Exit Sub
ErrHandler:
If Err.Number = 282 Then 'Невозможно открыть DDE канал
' Эта ошибка может возникать когда Acrobat загружился не польностью
' делаем Max282Errors попыток перез тем как вернуть AcroDDEFailed = True
Error282Count = Error282Count + 1
If Error282Count <= Max282Errors Then
PauseFor 3
Resume
Else
AcroDDEFailed = True
Resume Next
End If
End If
MsgBox "Error in PrintPDF sub Error# " & Err.Number & " " & Err.Description & "."
End Sub
Private Sub PauseFor(iSeconds As Integer)
'Пауза iSecond секунд
Dim sngTimer As Single
sngTimer = Timer
While Timer - sngTimer < iSeconds
DoEvents
Wend
End Sub
|