Excel Forum - Porady, Pomoc,  Excel Help, Excel FAQ Strona Główna
 FAQ  RegulaminRegulamin  Szukaj   Użytkownicy   Grupy   Rejestracja   Profil   Twoje wiadomości   Zaloguj 


Poprzedni temat «» Następny temat
ID tematu: 64426 Skopiuj do schowka Wydruk pliku PDF
Autor Wiadomość
marzatela 
Excel Expert



Zaproszone osoby: 295
Pomogła: 422 razy
Posty: 2320
Wysłany: 14-03-2019, 08:40   Wydruk pliku PDF

Jak z poziomu kodu VBA wydrukować plik PDF? Plik nie został utworzony w Excelu, tak naprawdę to rysunek zapisany w PDF.
_________________
marzatela

http://www.szultaset.pl
ID posta: 364193 Skopiuj do schowka
 
 
Marecki 
Excel Expert



Wersja: Win Office 2019
Pomógł: 2117 razy
Posty: 7009
Wysłany: 14-03-2019, 10:25   

marzatela, a takie coś rozwiązanie zadziała u Ciebie ?
http://www.excelforum.pl/viewtopic.php?p=32633
_________________
Hardware - ta część komputera, którą można kopnąć kiedy software przestanie funkcjonować.

Szkolenia z Excela , FB
Office 2019 Professional Plus , Windows 10 x64
Pozdrawiam, były mkkk23 teraz Marecki.
ID posta: 364205 Skopiuj do schowka
 
 
marzatela 
Excel Expert



Zaproszone osoby: 295
Pomogła: 422 razy
Posty: 2320
Wysłany: 14-03-2019, 10:53   

Nie, niestety.
W tej chwili wstawiam ten plik do arkusza jako obiekt i drukuję arkusz. To rozwiązanie mało mi się jednak podoba :(
_________________
marzatela

http://www.szultaset.pl
ID posta: 364206 Skopiuj do schowka
 
 
Marecki 
Excel Expert



Wersja: Win Office 2019
Pomógł: 2117 razy
Posty: 7009
Wysłany: 14-03-2019, 13:41   

No to może takie:
Kod:
Sub test()
    Dim Pdf_File       As String
    Dim Wrd            As Object
    Dim mydoc          As Object

    Set Wrd = CreateObject("Word.Application")
    Pdf_File = "C:\test.PDF"
    Set mydoc = Wrd.Documents.Open(Filename:=Pdf_File, Format:="PDF Files", ConfirmConversions:=False)
    mydoc.ActiveWindow.PrintOut
    mydoc.Close False
    Wrd.Quit

End Sub
_________________
Hardware - ta część komputera, którą można kopnąć kiedy software przestanie funkcjonować.

Szkolenia z Excela , FB
Office 2019 Professional Plus , Windows 10 x64
Pozdrawiam, były mkkk23 teraz Marecki.
ID posta: 364221 Skopiuj do schowka
 
 
marzatela 
Excel Expert



Zaproszone osoby: 295
Pomogła: 422 razy
Posty: 2320
Wysłany: 14-03-2019, 14:08   

Ciekawe rozwiązanie. Drukuje coś, ale coś zupełnie rozsypanego, nic nie przypomina tego, co w pliku.
_________________
marzatela

http://www.szultaset.pl
ID posta: 364223 Skopiuj do schowka
 
 
apollo
ExcelSpec


Pomógł: 1234 razy
Posty: 4296
Wysłany: 14-03-2019, 15:07   

marzatela napisał/a:
Ciekawe rozwiązanie. Drukuje coś, ale coś zupełnie rozsypanego, nic nie przypomina tego, co w pliku.

A masz Word >= 2013?
ID posta: 364226 Skopiuj do schowka
 
 
marzatela 
Excel Expert



Zaproszone osoby: 295
Pomogła: 422 razy
Posty: 2320
Wysłany: 14-03-2019, 15:45   

Nie, 2010.
_________________
marzatela

http://www.szultaset.pl
ID posta: 364231 Skopiuj do schowka
 
 
apollo
ExcelSpec


Pomógł: 1234 razy
Posty: 4296
Wysłany: 14-03-2019, 16:28   

marzatela napisał/a:
Nie, 2010.

No to kup i ciesz się życiem ;-)

Tylko Word >= 2013 otworzy PDF

Cytat:

W tej chwili wstawiam ten plik do arkusza jako obiekt i drukuję arkusz. To rozwiązanie mało mi się jednak podoba :(

Czyli nie masz również programu do otwierania i drukowania PDF? np. Acrobat Reader

No to zainstaluj i ciesz się życiem. ;-)
ID posta: 364236 Skopiuj do schowka
 
 
marzatela 
Excel Expert



Zaproszone osoby: 295
Pomogła: 422 razy
Posty: 2320
Wysłany: 14-03-2019, 16:59   

apollo, Acrobat Reader mam. Wyższą wersję Office'a zamierzam kupić (choć nie 2013). W tym przypadku jednak zależy mi na rozwiązaniu, które będzie działało nie tylko u mnie.
W sumie osadzenie tego PDF-a w arkuszu i wydrukowanie arkusza działa, więc chyba zostanę przy tym rozwiązaniu.
_________________
marzatela

http://www.szultaset.pl
ID posta: 364237 Skopiuj do schowka
 
 
ąćęłńóś
Excel Expert


Pomógł: 198 razy
Posty: 937
Wysłany: 14-03-2019, 23:15   

To powinno działać:
http://www.excelforum.pl/...otwierania.html

I jeszcze moje trzy grosze ... z przejrzanych w sieci kodów, mała kompilacja ludzkiej pomysłowości, u mnie działa "na drukarce bez drukarki", tj. na samych sterownikach i podglądzie wydruku:
Kod:
Option Explicit

Const acrd$ = "C:\Program Files\Adobe\Reader 11.0\Reader\AcroRd32.exe" 'Lub inna ścieżka - zależnie od instalacji
Const plikPDF$ = "C:\Temp\JakisDokPDF.pdf"

Sub a_Druk_PDF()
    'Application.ScreenUpdating = False
    Dim strcmd$, czekaj!, objshl As Object
    strcmd = Chr(34) & acrd & Chr(34) & " /s /h /p " & Chr(34) & plikPDF & Chr(34)
    Set objshl = CreateObject("Wscript.Shell")
    objshl.Run strcmd, 0, False
    czekaj = Timer: While Timer - czekaj < 5: DoEvents: Wend
    objshl.AppActivate "Adobe Reader"
    objshl.SendKeys "%{F4}", True
    Set objshl = Nothing
    'Application.ScreenUpdating = True
End Sub

W kodzie musi być jednak spowalniacz inaczej okropnie się to wszystko gryzie ze sobą.
ID posta: 364260 Skopiuj do schowka
 
 
apollo
ExcelSpec


Pomógł: 1234 razy
Posty: 4296
Wysłany: 15-03-2019, 00:45   

ąćęłńóś napisał/a:


I jeszcze moje trzy grosze ... .

Obawiam się, że nie o to chodzi.

Nie bez powodu pytałem o to, czy ma Acrobat Reader. Bo jeśli ma to zamiast ręcznie otworzyć plik z kodem i uruchomić kod można ręcznie otworzyć plik PDF w Acrobat Reader i drukować. A jeśli chce kod to można pisać kod.

Ale marzatela pisała
Cytat:

Acrobat Reader mam. Wyższą wersję Office'a zamierzam kupić (choć nie 2013). W tym przypadku jednak zależy mi na rozwiązaniu, które będzie działało nie tylko u mnie

Czyli chodzi o to, żeby działało nawet u tych, którzy nie mają Acrobat Reader i Word >= 2013. Jeśli ktoś nie ma Acrobat Reader to żaden kod nie pomoże.

Co do podanego kodu to u mnie niewiele działało. Znaczy, że PDF został otwarty w moim NitroPDF ale nic więcej. Nie ma okna Print. Opcja "/p" nic nie daje. Poprawiłem trochę. Zwłaszcza nie objshl.AppActivate "Adobe Reader" bo przecież u każdego jest inaczej, nie koniecznie "Adobe Reader". U mnie 5s to za mało, bo wyskoczyło jakieś okno niby-błąd, które trzeba ręcznie zamknąć. U mnie musiałem wysłać "^p" żeby otworzyć okno Print. I zazwyczaj Ctrl + P to właśnie skrót w Windows do otwierania okna Print.
Kod:

Const acrd = "C:\Program Files\Nitro PDF\Professional\NitroPDF.exe" 'Lub inna ścieżka - zależnie od instalacji
Const plikPDF = "C:\hichic.pdf"

Sub a_Druk_PDF()
Dim a
    Dim strcmd$, czekaj!, objshl As Object
    strcmd = Chr(34) & acrd & Chr(34) & " " & Chr(34) & plikPDF & Chr(34)
    a = Shell(strcmd, vbNormalFocus)
    czekaj = Timer
    Do While Timer - czekaj < 15
        DoEvents
    Loop
    AppActivate a
    Application.SendKeys "^p", True
End Sub
ID posta: 364262 Skopiuj do schowka
 
 
marzatela 
Excel Expert



Zaproszone osoby: 295
Pomogła: 422 razy
Posty: 2320
Wysłany: 15-03-2019, 06:12   

ąćęłńóś, widziałam to rozwiązanie wcześniej, ale zrezygnowałam, nie chcąc na sztywno wpisywać ścieżki do Acrobat Reader. Nie mam pewności gdzie jest zainstalowany na innych komputerach.
_________________
marzatela

http://www.szultaset.pl
ID posta: 364264 Skopiuj do schowka
 
 
apollo
ExcelSpec


Pomógł: 1234 razy
Posty: 4296
Wysłany: 15-03-2019, 10:38   

marzatela napisał/a:
ąćęłńóś, widziałam to rozwiązanie wcześniej, ale zrezygnowałam, nie chcąc na sztywno wpisywać ścieżki do Acrobat Reader. Nie mam pewności gdzie jest zainstalowany na innych komputerach.

Czyli jednak zakładasz, że u każdego jest program do PDF a jedyny problem to niewiadomo, co (różne programy do PDF) i gdzie jest zainstalowane?

Spróbuj poniższy kod. Uruchomi domyślny program do PDF i otworzy okno Print.
Kod:

Option Explicit

Sub drukPDF(ByVal plikPDF As String)
Dim czekaj As Double, strcmd As String, shell As Object
    Set shell = CreateObject("Shell.Application")
    shell.ShellExecute plikPDF, vbNullString, vbNullString, "open", 1
   
    czekaj = Timer
    Do While Timer - czekaj < 10
        DoEvents
    Loop
   
    Application.SendKeys "^p", True
   
    Set shell = Nothing
End Sub

Sub test()
    drukPDF "c:\hichic.pdf"
End Sub
ID posta: 364288 Skopiuj do schowka
 
 
Artik 



Wersja: Win Office 365
Pomógł: 2644 razy
Posty: 8757
Wysłany: 05-04-2019, 12:43   

marzatela napisał/a:
zrezygnowałam, nie chcąc na sztywno wpisywać ścieżki do Acrobat Reader. Nie mam pewności gdzie jest zainstalowany na innych komputerach.
To nie jest wielki problem. Ścieżkę można wyciągnąć w ten sposób:
Kod:
Option Explicit

#If VBA7 Then
    Private Declare PtrSafe Function FindExecutable Lib "shell32.dll" _
                                                    Alias "FindExecutableA" (ByVal lpFile As String, _
                                                                             ByVal lpDirectory As String, _
                                                                             ByVal lpResult As String) As LongPtr
#Else
    Private Declare Function FindExecutable Lib "shell32.dll" _
                                            Alias "FindExecutableA" (ByVal lpFile As String, _
                                                                     ByVal lpDirectory As String, _
                                                                     ByVal sResult As String) As Long
#End If


Sub TestExeFileName()
    Dim sFolder     As String
    Dim sFile       As String

    sFolder = "e:\Zbiory\Książki\"

    If Right(sFolder, 1) <> Application.PathSeparator Then
        sFolder = sFolder & Application.PathSeparator
    End If

    sFile = "Raspberry pi -przewodnik użytkownika Wydanie III E.Upton G.Halfacree" & ".pdf"

    MsgBox ExeFileName(sFolder, sFile)
    MsgBox ExeFileName(sFolder, sFile, False)

End Sub


Function ExeFileName(sFolder As String, sFile As String, Optional blnFullPath As Boolean = True) As String
    #If VBA7 Then
        Dim lRet    As LongPtr
    #Else
        Dim lRet    As Long
    #End If
    Dim sResult     As String
    Dim i           As Long

    Const MAX_PATH = 260

    sResult = Space$(MAX_PATH)

    lRet = FindExecutable(sFile, sFolder, sResult)

    If lRet > 32 Then
        sResult = Split(sResult, Chr$(0))(0)

        If blnFullPath Then
            ExeFileName = sResult
        Else
            i = InStrRev(sResult, Application.PathSeparator)
            If i > 0 Then
                ExeFileName = Mid(sResult, i + 1)
            End If
        End If
    End If

End Function
Powinnaś wywołać funkcję ExeFileName bez ostatniego parametru, wtenczas zwrócona zostanie pełna ścieżka do pliku wykonywalnego.
Tyle, że plikiem wykonywalnym... wcale nie musi być Acrobat Reader. :-)


Ale głównie skupiłem się na tym:
apollo napisał/a:
Kod:
    Do While Timer - czekaj < 10
        DoEvents
    Loop
(apollo to nie do Ciebie, ale akurat byłeś pod ręką :-) ) Wiadomo, 10 s może być za mało, 15 s też może być za mało (a może już zdecydowanie za dużo?). To może 30 s? No tak, ale czekać bez żadnej informacji, że za chwilę pojawi się okno drukowania, więc "drogi użytkowniku nic nie klikaj, za chwilę samo się zrobi" nie jest OK. Tym bardziej, że jeżeli ustawiony czas jest za krótki, to może nam się otworzyć okno drukowania... innej aplikacji niż oczekiwaliśmy.
Zacząłem więc drążyć temat ile trzeba czekać by mieć pewność, że można już wywołać okno drukowania? Okazało się, że nie jest to (chyba) problem trywialny. Musimy poczekać aż otworzy się odpowiednia aplikacja. To nie całe czekanie. Musimy jeszcze poczekać aż załaduje się plik, który chcemy wydrukować. Dopiero po pełnym załadunku możemy wydać dalsze polecenia. Ale jak to wszystko sprawdzić? Na tyle, co przejrzałem wszechświat, wszyscy bąkali, że uuuuu problem, że trzeba by się odwoływać do obiektów danej aplikacji. A kurna olek, jak mam się odwoływać do obiektów aplikacji, jak nie mam zielonego pojęcia, którą ona będzie?! Nastąpiło więc dalsze drill-owanie tematu. Wpadłem na pomysł, by z pomocą API szukać okien. Jeżeli znajdę, to mogę uznać, że plik się załadował. Ostatnie zdanie jest raczej "na czuja", a nie wynikające z wiedzy! Po prostu, przeprowadzone badania dały mi możliwość wysnucia takiego wniosku.
Poniższy kod był testowany dla domyślnego czytnika Adobe Acrobat Reader DC, acz starałem się wziąć pod uwagę, że może być to inna aplikacja. Dlatego ostateczny wynik działania makra może być różny, w zależności od używanego czytnika.
W optymistycznej wersji wykonania ma się otworzyć plik, wywołać okno drukowania i wydruk.
W trochę mniej optymistycznej wersji ma się otworzyć plik i wywołać okno drukowania.
W wersji pesymistycznej ma się tylko otworzyć plik.
Makro nie przewiduje nieobecności żadnego czytnika PDF-ów!

Kod:
Option Explicit

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
                                      (ByVal hWnd1 As Long, _
                                      ByVal hWnd2 As Long, _
                                      ByVal lpsz1 As String, _
                                      ByVal lpsz2 As String) As Long

Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
                                       (ByVal hWnd As Long, _
                                       ByVal lpString As String, _
                                       ByVal cch As Long) As Long

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)



Sub TestPrintPDF()
  Dim strFilePath As String
 
 
  strFilePath = "E:\Ścieżka\do\pliku\Sample File.pdf"
 
  Call PrintPDFFile(strFilePath)
End Sub


Sub PrintPDFFile(strPDFPath As String)
    'strPDFPath   - oczekiwana jest pełna ścieżka do pliku

    Dim ReturnStr   As String    'zmienna potrzebna, choć tu nie wykorzystywana
    Dim hWnd        As Long    'uchwyt okna rodzica
    Dim hWnd1       As Long    'uchwyt okna dziecka
    Dim strName     As String   'nazwa pliku z rozszerzeniem
    Dim strShrtName    As String    'nazwa pliku bez rozszerzenia
    Dim strPatrn    As String    'wzorzec do poszukiwania okna
    Dim dtEndTime   As Date    'bezpiecznik czasowy
    Dim blnChild    As Boolean    'flaga czy znaleziono okno dziecka
    Dim blnPrint     As Boolean    'flaga czy znaleziono okno Drukuj
    Dim i           As Long

    i = InStrRev(strPDFPath, Application.PathSeparator)
    strName = Mid(strPDFPath, i + 1)

    i = InStrRev(strName, ".")
    strShrtName = Left(strName, i - 1)

    'do wyszukiwania okna stosuję nazwę pliku bez rozszerzenia
    'bo zakładam, że nie zawsze rozszerzenie musi się pojawiać
    strPatrn = LCase("*" & strShrtName & "*")


    'otwórz domyślny czytnik PDF-ów
    ThisWorkbook.FollowHyperlink strPDFPath, NewWindow:=True

    'maksymalnie przez 5s poszukuj okna rodzica, które w pasku tytułowym będzie
    'zawierać nazwę otwieranego pliku
    dtEndTime = Now() + TimeValue("00:00:05")
    Do Until Now() > dtEndTime
        hWnd = WndwHandle(0&, ReturnStr, strPatrn)
        'Debug.Print hWnd & " | " & ReturnStr
        Sleep 200
        DoEvents
        If hWnd <> 0 Then
            Exit Do
        End If
    Loop

    'jl. okna rodzica nie znaleziono, to może oznaczać, że załadowanie czytnika
    'trwało dłużej niż założony czas (5s) lub w pasku tytułowym czynika
    'nie ma nazwy pliku (bo np. taka jest specyfika czytnika)

    If hWnd <> 0 Then
        'jl. znaleziono  okno rodzica
        'ReturnStr = vbNullString

        'maksymalnie przez 5 s poszukuj okna dziecka.
        '(Z obserwacji by wynikało, że uzyskanie uchwytu do okna dziecka
        'może być wskaźnikiem zakończenia ładowania się otwieranego pliku.)
        dtEndTime = Now() + TimeValue("00:00:05")
        Do Until Now() > dtEndTime
            hWnd1 = WndwHandle(0&, ReturnStr, strPatrn, hWnd)
            'Debug.Print hWnd1 & " | " & ReturnStr
            Sleep 200
            DoEvents
            If hWnd1 <> 0 Then
                blnChild = True
                Exit Do
            End If
        Loop
    End If

    If Not blnChild Then
        'jl. nie znaleziono okna dziecka, poczekaj jeszcze 5 s (tak na wszelki wypadek),
        'wywołaj okno drukowania i na tym zakończ procedurę.

        'Użytkownik sam musi podjąć decyzję o drukowaniu, bo nie jest wykluczonym,
        'że otworzyło się okno drukowania innej aplikacji niż zakładano (np. Excel).
        'Sytuacja może być spowodowana dłuższym niż zakładano (5s) ładowaniem pliku
        'lub czytnik PDF-ów nie posiada okna dziecka.
        Sleep 5000
        'wywołaj okno drukowania
        Application.SendKeys "^p", True
    Else
        'jl. znalezione okno dziecka, mamy (chyba) pewność, że okno jest już załadowane,
        'więc możemy drukować

        'wywołaj okno drukowania
        Application.SendKeys "^p", True

        'ReturnStr = vbNullString
        strPatrn = LCase("*Drukuj*") '<~~UWAGA: Polska wersja językowa
       
        'poszukiwanie okna Drukuj
        dtEndTime = Now() + TimeValue("00:00:05")
        Do Until Now() > dtEndTime
            hWnd1 = WndwHandle(hWnd1, ReturnStr, strPatrn)
            'Debug.Print hWnd1 & " | " & ReturnStr
            DoEvents
            If hWnd1 <> 0 Then
                blnPrint = True
                Exit Do
            End If
        Loop

        If blnPrint Then
            'jl. znaleziono okno drukowania, naciśnij domyślny przycisk
            '(wydaj polecenie wydruku)
            Application.SendKeys "{ENTER}"
           
            'zamknięcie aplikacji (czytnika) może być wykonane dopiero po wyrenderowaniu
            'obrazu do druku. Wcześniejsze zamknięcie spowoduje błąd.
            'W przypadku Adobe Reader-a, po wydaniu polecenia wydruku pojawia się okno
            'o nazwie klasy #32770, które może być trudne do zidentyfikowania,
            'gdyż nie jest to unikalna nazwa związana z aplikacją czytnika (np. MsgBox też jest z klasy #32770)
            'Sleep 10000
            'zamknij czytnik PDF-ów
            'Application.SendKeys "%({F4})", True
        End If
    End If

    'Debug.Print String(30, "=")
End Sub


Function WndwHandle(hParent As Long, strRet As String, strPattern As String, Optional hWnd1 As Variant) As Long
    Dim hWnd As Long, lngRet As Long, y As Integer
    Dim strText     As String

    hWnd = FindWindowEx(hParent, 0&, vbNullString, vbNullString)

    Do While hWnd <> 0
        strText = String$(100, Chr$(0))
        lngRet = GetWindowText(hWnd, strText, 100)

        If LCase(strText) Like strPattern Then
            If Not IsMissing(hWnd1) Then
                If hWnd <> hWnd1 Then
                    WndwHandle = hWnd
                    strRet = Left$(strText, lngRet)
                    Exit Do
                End If
            Else
                WndwHandle = hWnd
                strRet = Left$(strText, lngRet)
                Exit Do
            End If
        End If
        DoEvents

        hWnd = FindWindowEx(hParent, hWnd, vbNullString, vbNullString)
    Loop
End Function
W kodzie należałoby zamienić SendKeys-y na API, by nie namieszać na klawiaturze (często wyłączanie się NumLock-a).

Chętnie poznam opinie tych, którzy używają innych czytników niż Acrobat Reader DC.

Artik
_________________
Persistence is a virtue in the world of programming.
ID posta: 365518 Skopiuj do schowka
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Możesz ściągać załączniki na tym forum
Dodaj temat do Ulubionych
Wersja do druku

Skocz do:  

Powered by phpBB modified by Przemo © 2003 phpBB Group
Theme xandgreen created by spleen& Programosy modified v0.3 by warna
Opieka techniczna www.marketingNET.pl

Archiwum

Strona używa plików cookies.

Kliknij tutaj, żeby dowiedzieć się jaki jest cel używania cookies oraz jak zmienić ustawienia cookie w przeglądarce.
Korzystając ze strony użytkownik wyraża zgodę na używanie plików cookies, zgodnie z bieżącymi ustawieniami przeglądarki.
Sprawdź, w jaki sposób przetwarzamy dane osobowe