Как программно создать PDF-файл из любого документа в OSX?

StackOverflow https://stackoverflow.com/questions/276362

Вопрос

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

Вот варианты, которые я исследовал на данный момент:

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

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

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

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

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

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

Это было полезно?

Решение

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

Например :

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

Другие советы

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

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

После его установки вы сможете создавать оболочки или AppleScripts, используя команду лп команда.

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

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

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

Однако есть несколько предостережений.

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

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

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

ты можешь использовать вот такие чашки

    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

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

convert2pdf() {
  /System/Library/Printers/Libraries/convert -f "$1" -o "$2" -j "application/pdf"
}

Я набрал приведенный ниже код с помощью Automator (записал действие, а затем перетащил конкретное действие из окна «Смотри, как я делаю», чтобы получить 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top