Jak programowo wygenerować plik PDF z dowolnego dokumentu na OSX?

Pracuję nad projektem dla OSX, w którym użytkownik może wybrać zbiór dokumentów (z dowolnej aplikacji), z których będę musiał wygenerować pliki PDF. Standardowe okno drukowania Macintosh ma przycisk PDF, który ma wiele poleceń związanych z PDF, w tym " Zapisz jako PDF...". Muszę jednak wygenerować plik PDF bez konieczności interakcji z użytkownikami. Idealnie chcę, aby to działało z każdym rodzajem dokumentu.

Oto opcje, które do tej pory zbadałem:

  • działania Automatora. Istnieje Biblioteka PDF dla Automatora, ale zapewnia akcje do pracy z plikami PDF, a nie ich generowania. Istnieje operacja Finder do wydrukowania dowolnego pliku, ale tylko na prawdziwej drukarce.
  • AppleScript. Niektóre aplikacje mają możliwość generowania plików PDF (na przykład, jeśli wyślesz "save doc in" test.pdf "' do stron wygeneruje PDF (ale to działa tylko dla stron-potrzebuję wsparcia dla każdego typu dokumentu).
  • Drukarka Niestandardowa. Mógłbym stworzyć wirtualny sterownik drukarki, a następnie użyj działania Automatora, ale nie podoba mi się pomysł mylenia użytkownika z dodatkową drukarką na liście wydruków.

Mam nadzieję, że jest jakiś sposób na interakcję z aktywną aplikacją, tak jakby użytkownik wykonywał następujące czynności:

  1. Do Cmd-P (otwiera okno dialogowe drukowania)
  2. Kliknij przycisk " PDF "
  3. Wybierz "Zapisz jako PDF..."(druga pozycja w menu)
  4. Wpisz nazwę pliku w oknie Zapisz
  5. Kliknij "Zapisz"

If that ' s the best podejście (tak?) wtedy prawdziwym problemem jest: jak wysłać zdarzenia interfejsu użytkownika do zewnętrznej aplikacji (naciśnięcia klawiszy, zdarzenia myszy, wybory menu) ?

Aktualizacja: Aby wyjaśnić jeden punkt: dokumenty, które muszę przekonwertować do formatu PDF, to dokumenty, które są tworzone przez inne aplikacje. Na przykład użytkownik może wybrać dokument programu Word, arkusz kalkulacyjny Numbers, rysunek OmniGraffle lub stronę internetową. Wspólnym mianownikiem jest to, że każdy z tych dokumentów ma związane aplikacja i Ta aplikacja wie, jak ją wydrukować (a OSX wie, jak renderować wydruk do pliku PDF).

Więc próbki w Cocoa Dev Central nie pomagają, ponieważ chodzi o generowanie pliku PDF z mojej aplikacji.

Author: Denis Hennessy, 2008-11-09

5 answers

Myślę, że możesz użyć applescript do otwarcia dokumentu, a następnie użyć applescript UI scripting do wywołania menu drukowania.

Na przykład:

tell application "System Events"
        tell window of process "Safari"
            set foremost to true
            keystroke "p" using {command down}
            delay 3
            click menu button "PDF" of sheet 2
            click menu item "Save as PDF…" of menu 1 of menu button "PDF" of sheet 2
            keystroke "my_test.file"
            keystroke return
            delay 10
        end tell

    end tell
 6
Author: Timour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-17 14:48:27

Spójrz na program o nazwie CUPS-PDF

Jest to wirtualna drukarka dla systemu OS X, która robi to, co robi metoda "Zapisz jako PDF" podczas drukowania za pomocą zwykłej drukarki, z wyjątkiem każdego zadania drukowania przechodzącego przez to powoduje wyjście pdf.

Po zainstalowaniu można utworzyć skrypty powłoki lub AppleScript używając lp.

Na przykład po skonfigurowaniu wirtualnej drukarki można wydrukować test.txt i mieć go automatycznie zapisać jako pdf. Aby to zrobić używając Applescriptu można użyć następującego kodu:

do shell script "lp -d CUPS_PDF test.txt"

Aplikacja cups-PDF zapisuje wszystkie dane wyjściowe do /Users/Shared / cups-PDF. Nie jestem pewien, czy można zmienić tę ścieżkę, ale można pobrać plik w skrypcie i przenieść go.

Jest jednak kilka zastrzeżeń.

Po pierwsze, polecenie lp nie może drukować .pliki doc. Myślę, że istnieją inne aplikacje firm trzecich, które pozwolą ci to zrobić.

Po drugie, aplikacja CUPS-PDF wyświetla się w okienku Drukarki Preferencji systemowych jako posiadające myślnik w nazwie, ale CUPS pokazuje nazwę kolejki jako podkreślenie. W wierszu poleceń musisz odwołać się do nazwy kolejki CUPS_PDF z podkreśleniem.

Nawet jeśli nie jest to bardzo przydatne, aby zbudować skrypt za pomocą lp nadal chcesz korzystać ze skryptów GUI, a posiadanie wirtualnej drukarki powinno zaoszczędzić kilka kroków.

 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-28 17:58:20

Możesz użyć takich kubków

    on open afile
        set filename to name of (info for afile)
        tell application "Finder"
            set filepath to (container of (afile as alias)) as alias
        end tell
        set filepath to quoted form of POSIX path of filepath
        set tid to AppleScript's text item delimiters
        set AppleScript's text item delimiters to "."
        set filename to text item 1 of filename
        set AppleScript's text item delimiters to tid
        set afile to quoted form of POSIX path of afile
        do shell script "cupsfilter " & afile & " > " & filepath & filename & ".pdf"
    end open
 1
Author: mcgrailm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-13 16:11:56

Utworzyłem alias w bash do tego:

convert2pdf() {
  /System/Library/Printers/Libraries/convert -f "$1" -o "$2" -j "application/pdf"
}
 1
Author: PH.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-20 08:48:29

Wpisałem poniższy kod przy pomocy Automatora (nagrywając akcję, a następnie przeciągając konkretną akcję z okna "Watch Me Do", aby uzyskać Applescript). Jeśli chcesz wydrukować plik PDF z aplikacji innej niż Safari, może być konieczne uruchomienie tego samego procesu i dostosowanie tego Applescriptu wokół okna dialogowego drukowania, ponieważ każdy program może mieć inny interfejs graficzny drukowania.

# Convert the current Safari window to a PDF
# by Sebastain Gallese

# props to the following for helping me get frontmost window
# http://stackoverflow.com/questions/480866/get-the-title-of-the-current-active-window-            document-in-mac-os-x

global window_name

# This script works with Safari, you might have
# to tweak it to work with other applications 
set myApplication to "Safari"

# You can name the PDF whatever you want
# Just make sure to delete it or move it or rename it
# Before running the script again
set myPDFName to "mynewpdfile"

tell application myApplication
    activate
    if the (count of windows) is not 0 then
        set window_name to name of front window
    end if
end tell

set timeoutSeconds to 2.0
set uiScript to "keystroke \"p\" using command down"
my doWithTimeout(uiScript, timeoutSeconds)
set uiScript to "click menu button \"PDF\" of sheet 1 of window \"" & window_name & "\" of application process \"" & myApplication & "\""
my doWithTimeout(uiScript, timeoutSeconds)
set uiScript to "click menu item 2 of menu 1 of menu button \"PDF\" of sheet 1 of window \"" & window_name & "\" of application process \"" & myApplication & "\""
my doWithTimeout(uiScript, timeoutSeconds)
set uiScript to "keystroke \"" & myPDFName & "\""
my doWithTimeout(uiScript, timeoutSeconds)
set uiScript to "keystroke return"
my doWithTimeout(uiScript, timeoutSeconds)

on doWithTimeout(uiScript, timeoutSeconds)
    set endDate to (current date) + timeoutSeconds
    repeat
        try
            run script "tell application \"System Events\"
" & uiScript & "
end tell"
            exit repeat
        on error errorMessage
            if ((current date) > endDate) then
                error "Can not " & uiScript
            end if
        end try
    end repeat
end doWithTimeout
 0
Author: Sebastian Gallese,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-23 11:52:48