18

我正在为 OSX 开发一个项目,用户可以选择一组文档(从任何应用程序),我需要从中生成 PDF。标准 Macintosh 打印对话框有一个 PDF 按钮,其中包含许多与 PDF 相关的命令,包括“另存为 PDF...”。但是,我需要在不需要用户交互的情况下生成 PDF 文件。理想情况下,我希望它适用于任何类型的文档。

以下是我迄今为止探索过的选项:

  • 自动化操作。Automator 有一个 PDF 库,但它提供了处理 PDF 文件的操作,而不是生成它们。有一个 Finder 操作可以打印任何文件,但仅限于真正的打印机。
  • 苹果脚本。某些应用程序能够生成 PDF 文件(例如,如果您将“在“test.pdf”中保存文档”发送到 Pages,它将生成 PDF(但这仅适用于 Pages - 我需要对任何类型的文档的支持) .
  • 自定义打印机。我可以创建一个虚拟打印机驱动程序,然后使用自动操作,但我不喜欢将用户与打印列表中的额外打印机混淆的想法。

我希望有某种方式可以与活动应用程序进行交互,就好像用户正在执行以下步骤一样:

  1. 执行 Cmd-P(打开打印对话框)
  2. 点击“PDF”按钮
  3. 选择“另存为 PDF...”(菜单中的第二项)
  4. 在保存对话框中输入文件名
  5. 点击“保存”

如果这是最好的方法(是吗?),那么真正的问题是:如何将 UI 事件发送到外部应用程序(击键、鼠标事件、菜单选择)?

更新:只是为了澄清一点:我需要转换为 PDF 的文档是由其他应用程序创建的文档。例如,用户可能会选择 Word 文档或 Numbers 电子表格或 OmniGraffle 绘图或网页。共同点是这些文档中的每一个都有一个关联的应用程序,并且该应用程序知道如何打印它(并且 OSX 知道如何将打印输出呈现为 PDF 文件)。

因此,Cocoa Dev Central 的示例没有帮助,因为它们是关于从我的应用程序生成 PDF 的。

4

6 回答 6

6

我认为您可以使用 applescript 打开文档,然后使用 applescript UI 脚本调用打印菜单。

例如 :

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
于 2008-11-10T03:40:18.763 回答
3

看看一个名为CUPS-PDF的程序

它是 OS X 的虚拟打印机,它在通过普通打印机打印时执行“另存为 PDF”方法所做的工作,但通过它的每个打印作业都会产生 pdf 输出。

安装后,您可以使用lp命令创建 shell 或 AppleScripts。

例如,一旦设置了虚拟打印机,您就可以打印 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命令构建脚本并不是很有用,并且仍然希望涉及 GUI 脚本,那么拥有虚拟打印机应该可以为您节省一些步骤。

于 2010-11-28T17:18:45.863 回答
1

你可以用这样的杯子

    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
于 2010-12-13T14:50:42.497 回答
1

为此,我在 bash 中创建了一个别名:

convert2pdf() {
  /System/Library/Printers/Libraries/convert -f "$1" -o "$2" -j "application/pdf"
}
于 2012-07-20T08:48:29.900 回答
0

我在 Automator 的帮助下输入了下面的代码(记录一个动作,然后将特定动作拖出“Watch Me Do”窗口以获取 Applescript)。如果要从 Safari 以外的应用程序打印 PDF,则可能必须运行相同的过程并围绕“打印”对话框调整此 Applescript,因为每个程序可能具有不同的打印 GUI。

# 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
于 2010-05-25T19:35:53.793 回答
0

"/System/Library/Printers/Libraries/./convert" 已在更高版本的 MacOS 中删除。

你现在可以使用sips了。AppleScript 示例:执行 shell 脚本:sips -s format pdf Filename.jpg --out Filename.pdf

于 2022-02-13T01:54:52.840 回答