Come generare a livello di codice un PDF da qualsiasi documento su OSX?
-
07-07-2019 - |
Domanda
Sto lavorando a un progetto per OSX in cui l'utente può scegliere una raccolta di documenti (da qualsiasi applicazione) da cui ho bisogno per generare PDF. La finestra di dialogo Stampa standard di Macintosh ha un pulsante PDF che ha una serie di comandi relativi a PDF tra cui " Salva come PDF ... " ;. Tuttavia, devo generare il file PDF senza richiedere interazioni dell'utente. Idealmente, voglio che funzioni con qualsiasi tipo di documento.
Ecco le opzioni che ho esplorato finora:
- Azioni dell'automatore. C'è una libreria PDF per Automator ma fornisce azioni per lavorare con i file PDF, non per generarli. C'è un'azione Finder per stampare qualsiasi file ma solo su una vera stampante.
- AppleScript. Alcune applicazioni hanno la capacità di generare file PDF (ad esempio, se invii 'salva documento in " test.pdf "' a Pages genererà un PDF (ma questo funziona solo per Pages - Ho bisogno di supporto per qualsiasi tipo di documento ).
- Stampante personalizzata. Potrei creare un driver di stampante virtuale e quindi utilizzare l'azione dell'automatore, ma non mi piace l'idea di confondere l'utente con una stampante aggiuntiva nell'elenco di stampa.
La mia speranza è che ci sia un modo per interagire con l'applicazione attiva come se l'utente stesse eseguendo i seguenti passaggi:
- Esegui Cmd-P (apre la finestra di dialogo di stampa)
- Fai clic su " PDF " pulsante
- Seleziona " Salva come PDF ... " (seconda voce del menu)
- Digitare il nome file nella finestra di dialogo Salva
- Fai clic su " Salva "
Se questo è l'approccio migliore (vero?), allora il vero problema è: come posso inviare eventi dell'interfaccia utente a un'applicazione esterna (sequenze di tasti, eventi del mouse, selezioni di menu)?
Aggiornamento: Giusto per chiarire un punto: i documenti che devo convertire in PDF sono documenti creati da altre applicazioni . Ad esempio, l'utente può scegliere un documento Word o un foglio di calcolo Numbers o un disegno OmniGraffle o una pagina Web. Il comune denominatore è che a ciascuno di questi documenti è associata un'applicazione e quell'applicazione sa come stamparla (e OSX sa come rendere l'output di stampa in un file PDF).
Quindi, gli esempi di Cocoa Dev Central non aiutano perché riguardano la generazione di un PDF dalla mia applicazione .
Soluzione
Penso che potresti usare applecript per aprire un documento e quindi usare script UI applecript per richiamare il menu di stampa.
Ad esempio:
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
Altri suggerimenti
Dai un'occhiata a un programma chiamato CUPS-PDF
È una stampante virtuale per OS X che fa ciò che " Salva come PDF " il metodo funziona quando si stampa attraverso la normale stampante, tranne per il fatto che ogni processo di stampa che lo attraversa genera un output pdf.
Una volta installato, è possibile creare shell o AppleScripts utilizzando il comando lp .
Ad esempio, una volta impostata la stampante virtuale è possibile stampare test.txt e salvarlo automaticamente come pdf. Per fare ciò usando un AppleScript, dovresti usare il seguente codice:
do shell script "lp -d CUPS_PDF test.txt"
L'app CUPS-PDF salva tutto l'output in / Users / Shared / CUPS-PDF. Non sono sicuro se puoi cambiare quel percorso ma potresti recuperare il file nel tuo script e spostarlo.
Tuttavia, ci sono alcuni avvertimenti.
Innanzitutto, il comando lp non può stampare file .doc. Penso che ci siano altre app di terze parti che ti permetteranno di farlo.
In secondo luogo, l'app CUPS-PDF mostra nel riquadro Stampante delle Preferenze di Sistema come se avesse il trattino nel suo nome ma CUPS mostra il nome della coda come un carattere di sottolineatura. Quindi, sulla riga di comando è necessario fare riferimento al nome della coda CUPS che è CUPS_PDF con un carattere di sottolineatura.
Anche se non trovi molto utile creare uno script tramite il comando lp e vuoi comunque coinvolgere lo scripting della GUI, quindi avere una stampante virtuale dovrebbe farti risparmiare alcuni passaggi.
potresti usare tazze come questa
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
Ho creato un alias in bash per questo:
convert2pdf() {
/System/Library/Printers/Libraries/convert -f "$1" -o "$2" -j "application/pdf"
}
Ho digitato il codice seguente con l'assistenza di Automator (registrando un'azione, quindi trascinando l'azione specifica fuori dalla finestra "Guardami fare" per ottenere l'Applescript). Se desideri stampare un PDF da un'applicazione diversa da Safari, potresti dover eseguire lo stesso processo e modificare questo Applescript attorno alla finestra di dialogo Stampa, poiché ogni programma potrebbe avere una GUI di stampa diversa.
# 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