Как программно сгенерировать PDF из любого документа на OSX? - PullRequest
18 голосов
/ 09 ноября 2008

Я работаю над проектом для OSX, где пользователь может выбрать набор документов (из любого приложения), из которого мне нужно сгенерировать PDF. В стандартном диалоговом окне «Печать» в Macintosh есть кнопка PDF, содержащая ряд команд, связанных с PDF, включая «Сохранить как PDF ...». Однако мне нужно создать PDF-файл, не требуя взаимодействия с пользователем. В идеале я хочу, чтобы это работало с любым типом документа.

Вот варианты, которые я изучил до сих пор:

  • Автоматизатор действий. Есть библиотека PDF для Automator, но она предоставляет действия для работы с файлами PDF, а не для их генерации. Существует действие Finder для печати любого файла, но только на реальном принтере.
  • AppleScript. Некоторые приложения имеют возможность генерировать PDF-файлы (например, если вы отправите «сохранить документ в« test.pdf »» на Pages, он сгенерирует PDF-файл (но это работает только для Pages - мне нужна поддержка для любого типа документа) .
  • Пользовательский принтер. Я мог бы создать драйвер виртуального принтера, а затем использовать действие automator, но мне не нравится идея путать пользователя с дополнительным принтером в списке печати. ​​

Я надеюсь, что есть какой-то способ взаимодействия с активным приложением, как если бы пользователь выполнял следующие шаги:

  1. Do Cmd-P (открывает диалоговое окно печати)
  2. Нажмите кнопку «PDF»
  3. Выберите «Сохранить как PDF ...» (второй пункт в меню)
  4. Введите имя файла в диалоговом окне сохранения
  5. Нажмите «Сохранить»

Если это лучший подход (правда?), То реальная проблема заключается в следующем: как отправить события пользовательского интерфейса во внешнее приложение (нажатия клавиш, события мыши, выбор меню)?

Обновление: Просто чтобы прояснить один момент: документы, которые мне нужно преобразовать в PDF, - это документы, созданные другими приложениями . Например, пользователь может выбрать документ Word, электронную таблицу Numbers, чертеж OmniGraffle или веб-страницу. Общим знаменателем является то, что у каждого из этих документов есть связанное приложение, и это приложение знает, как его распечатать (а OSX знает, как отобразить вывод на печать в файл PDF).

Итак, примеры в Cocoa Dev Central не помогают, потому что они о создании PDF из моего приложения .

Ответы [ 5 ]

6 голосов
/ 10 ноября 2008

Я думаю, что вы можете использовать яблочный скрипт, чтобы открыть документ, а затем использовать сценарий пользовательского интерфейса яблочного скрипта , чтобы вызвать меню печати.

Например:

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
3 голосов
/ 28 ноября 2010

Взгляните на программу под названием CUPS-PDF

Это виртуальный принтер для OS X, который выполняет то же, что и метод «Сохранить как PDF», когда печатает на обычном принтере, за исключением того, что каждое пропущенное задание на печать приводит к выводу в формате PDF.

Как только вы установите его, вы можете создать shell или AppleScripts, используя команду lp .

Например, после настройки виртуального принтера вы можете напечатать test.txt и автоматически сохранить его в формате PDF. Чтобы сделать это с помощью AppleScript, вы должны использовать следующий код:

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

Приложение CUPS-PDF сохраняет весь вывод в / Users / Shared / CUPS-PDF. Я не уверен, что вы можете изменить этот путь, но вы можете получить файл в своем скрипте и переместить его.

Хотя есть несколько предостережений.

Во-первых, команда lp не может печатать файлы .doc. Я думаю, что есть и другие сторонние приложения, которые позволят вам сделать это.

Во-вторых, приложение CUPS-PDF показывает на панели «Принтер» в Системных настройках наличие дефиса в своем имени, но CUPS показывает имя очереди как подчеркивание. Итак, в командной строке вам нужно обратиться к имени очереди CUPS, которое является CUPS_PDF с подчеркиванием.

Даже если вам не очень полезно создавать скрипт с помощью команды lp и все же хотите задействовать сценарии графического интерфейса, тогда наличие виртуального принтера должно сэкономить вам некоторые шаги.

1 голос
/ 20 июля 2012

Я создал псевдоним в bash для этого:

convert2pdf() {
  /System/Library/Printers/Libraries/convert -f "$1" -o "$2" -j "application/pdf"
}
1 голос
/ 13 декабря 2010

вы могли бы использовать чашки, как это

    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
0 голосов
/ 25 мая 2010

Я набрал код ниже с помощью Automator (записав действие, а затем перетащив конкретное действие из окна «Watch Me Do», чтобы получить Applescript). Если вы хотите распечатать PDF-файл из приложения, отличного от Safari, вам, возможно, придется выполнить тот же процесс и настроить этот Applescript в диалоговом окне «Печать», поскольку каждая программа может иметь свой графический интерфейс печати. ​​

# 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
...