IllustratorファイルのPDF書き出しに[別名で保存]を使用すると,作業中の書類はPDFに変わります。元データがai/epsファイルでもPDFです。
もし書き出しオプションで[Illustrator の編集機能を保持]をOFFにしていた場合,書類を閉じた瞬間に編集可能な元データは消え去ります。大変なことですね。
そんな悲劇を避けるため,次の策が推奨されています。
- [複製を保存]を利用する
- [別名で保存]でPDFを書き出したあと書類を閉じるアクションを利用する
ただこれらは,ファイル名の「のコピー」を毎回削除する必要がある,使用しているIllustratorすべてのバージョンにアクションを設定しておかなければいけない,などいった理由でなかなか自分に定着しません。正しいけど面倒臭いことはすぐやらなくなるのが人間というものです。
そこで今回は,開いている書類と同じフォルダ・名前で,プリセット名を指定してPDFを複製書き出しするIllustratorスクリプトを紹介します。
あらましを教えて
Illustratorで開いている書類と同じフォルダ・名前で,PDFを複製書き出しするスクリプトです。ファイル名を特定の形式にすることで,[PDF/X-4:2008 (日本)] [最小ファイルサイズ] など使用するAdobe PDF プリセットの種類を指定できます。もちろんご自身でカスタマイズしたオリジナルプリセットも使用可能です。あらかじめ指定済みのスクリプト(exportPDF=[最小ファイルサイズ].jsxなど)10個セットで公開しています。とプリセット名をテキストとして取得するスクリプト,計11個セットで公開しています。
Keyboard MaestroやSPAi・Sppyなど,スクリプトにショートカットを割り当てたりパネルから実行できるアプリの併用がおすすめです。実行と管理の手間が格段に減るため,新しい習慣を無理なく定着させられます。次の画像はSPAiのパネルです。
便宜上「複製書き出しする」と表記しましたが,実際に実行しているのは[スクリーン用に書き出し]です。Illustratorスクリプトに複製保存機能はないためそうしました。名前はスクリーン用ですが,PDFについては印刷用プリセットを指定すれば印刷用になります。例えば [PDF/X-4:2008 (日本)] で書き出し,Adobe Acrobatでプリフライト[PDF/X-4 への準拠を確認]を実行すると,PDF/X-4に準拠していることがわかります。
どのバージョンに対応してるの?
Illustrator CC 2018(22) かそれ以降のバージョンに対応しています。CC 2018 から搭載された機能に依存するため,それ以前のバージョンでは動きません。
使いかたは?
それではこちらのファイルをダウンロードしてください。
sttk3-exportPDF.zip
難しいことは何もありません。Illustratorで書類を開いた状態で,exportPDF=[最小ファイルサイズ].jsx など使いたいAdobe PDF プリセット用スクリプトを実行するだけです。開いている書類と同じフォルダに,同じ名前でPDFファイルが書き出されます。もちろん拡張子は.pdfです。
書類が1度も保存されていないときや,ファイル名が重複するときには,保存先指定ダイアログが出ます。
バージョン1.2.0からは,リンク切れの画像があるとき処理を続けるか確認します。基本的には「いいえ」を選んで中止し,リンクを手動で修正してください。
どうやって種類を指定するの?
スクリプトのファイル名を exportPDF=[最小ファイルサイズ].jsx のような特定の形式にすることで,使用するAdobe PDF プリセットの種類を指定します。ファイル名[最小ファイルサイズ]部分の編集により,それらの設定を変えられます。
ただ[PDF/X-4:2008 (日本)]のように,ファイル名に使えない文字を含むプリセット名があります。 /(半角スラッシュ)と :(半角コロン)はシステムがパス区切り文字として扱うので,ファイル名には使用禁止なのです。そこで%/(全角パーセント全角スラッシュ)で /(半角スラッシュ),%:(全角パーセント全角コロン)で :(半角コロン)として扱うルールにしました。プリセット名に%(全角パーセント)を使いたい場合は%%(全角パーセント全角パーセント)としてください。
どんな種類が指定できるの?
次のようになっています。
プリセットの種類 | 動作説明 |
---|---|
dialog | ダイアログでAdobe PDF プリセットを選択して実行する |
[Illustrator 初期設定] | [Illustrator 初期設定] を使用する |
[PDF%/X-1a%:2001 (日本)] | [PDF/X-1a:2001 (日本)] を使用する |
[PDF%/X-3%:2002 (日本)] | [PDF/X-3:2002 (日本)] を使用する |
[PDF%/X-4%:2008 (日本)] | [PDF/X-4:2008 (日本)] を使用する |
[プレス品質] | [プレス品質] を使用する |
[最小ファイルサイズ] | [最小ファイルサイズ] を使用する |
[最小ファイルサイズ (PDF 1.6)] | [最小ファイルサイズ (PDF 1.6)] を使用する |
[雑誌広告送稿用] | [雑誌広告送稿用] を使用する |
[高品質印刷] | [高品質印刷] を使用する |
プリセット名 | ユーザー定義プリセット名を直接指定する。この場合は「プリセット名」というプリセットが存在したらそれを使用する。他の種類と違い[](ブラケット)はつけない |
exportPDF=dialog.jsx では,ダイアログでプリセットを選択して実行できます。各項目の左にある数字がショートカットキーです。単体でキーを押して項目を選択し,returnキーまたはOKボタンで確定します。
exportPDF=argv.jsx は,Keyboard Maestroとスクリプトファイルを実行するKeyboard Maestro用アクション(無料)とのセットで使います。argumentsに入力する文字を変えれば使うファイルをこれ1つに絞れるので,スクリプトをアップデートするときなどに管理が楽になります。
getPresetNames.jsx は,実行するとIllustratorが認識しているAdobe PDF プリセットの名前をダイアログで表示します。テキストのコピーにご使用ください。1行分しか見えませんが複数行あります。
これでまた少し仕事が速くなりました。今日もさっさと仕事を切り上げて好きなことをしましょう!
コードはこちら。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
/** * @file Adobe PDF プリセットに基づきPDFを書き出す。 * exportPDF=dialog.jsxのようなファイル名からプリセット名(または動作)を取り出しそれを実行する。 * exportPDF=プリセット名.jsx : プリセット名を直接指定 * exportPDF=dialog.jsx : プリセット名をダイアログで指定 * exportPDF=argv.jsx : プリセット名をargumentsで指定 * @version 1.2.0 * @author sttk3.com * @copyright © 2021 sttk3.com */ //#target 'illustrator' (function(argv) { $.localize = true ; var msgNoPreset = {ja: 'Adobe PDF プリセットの指定が不明でした。', en: 'Adobe PDF Presets were unknown.'} ; if(app.documents.length <= 0) {return ;} var doc = app.documents[0] ; if(appVersion()[0] < 22) { alert({ja: 'このスクリプトは Illustrator CC 2018 以降のみに対応しています。', en: 'This script requires Illustrator CC 2018 or later.'}) ; return ; } // PDF書き出しプリセットの名前一覧を取得する var pdfPresetNames = app.PDFPresetsList ; // スクリプトファイル名から引数を生成する var tempArgv = parseArguments(decodeURIComponent(combineDakuten(new File($.fileName).name)), argv) ; if(tempArgv == null) { alert(msgNoPreset) ; return ; } var command = expandVars(tempArgv.option) ; // リンク切れがある場合,続行するかダイアログで確認する。答えがいいえなら終了する if(existsInvalidLink(doc)) { var msgInvalidLink = { ja: 'この書類には無効なリンク画像があります。それでも処理を続けますか?\n「いいえ」を選びリンクを修正するか「はい」を選んで続行してください。', en: 'This document contains invalid links. Do you accept it?\nSelect "No" to correct the link or "Yes" to continue.' } ; var retval = confirm(msgInvalidLink) ; if(!retval) {return ;} } var targetPreset ; if(command == 'dialog') { // PDF書き出しプリセットリストをダイアログで指定する // 一覧を作る var hotKeys = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' ; var delim = '\t' ; var commandList = [] ; for(var i = 0, len = pdfPresetNames.length ; i < len ; i++) { commandList.push((hotKeys[i] || ' ') + delim + pdfPresetNames[i]) ; } if(commandList.length <= 0) {return ;} // ダイアログ var win = new Window('dialog', 'exportPDF') ; // リスト var body = win.add('group', undefined) ; body.orientation = 'column' ; body.alignChildren = ['fill', 'fill'] ; body.add('statictext', undefined, {ja: 'Adobe PDF プリセットを選択', en: 'Select an Adobe PDF preset'}) ; var list = body.add('listbox', undefined, commandList) ; list.selection = list.items[0] ; list.active = true ; win.addEventListener('keyup', function(e) { var dstIndex = hotKeys.indexOf(e.keyName) ; if(dstIndex >= 0) {list.selection = list.items[dstIndex] ;} }) ; // Cancel | OK var footer = win.add('group', undefined) ; footer.orientation = 'row' ; footer.alignChildren = ['center', 'fill'] ; var cancelButton, okButton ; var os = $.os ; var cancelLabel = 'Cancel' ; var okLabel = 'OK' ; if(/^w/i.test(os)) { okButton = footer.add('button', undefined, okLabel) ; cancelButton = footer.add('button', undefined, cancelLabel) ; } else { cancelButton = footer.add('button', undefined, cancelLabel) ; okButton = footer.add('button', undefined, okLabel) ; } okButton.selected = true ; var doCancel = false ; okButton.onClick = okButton.onSubmit = function(e) {win.close() ;} ; cancelButton.onClick = function(e) { doCancel = true ; win.close() ; } ; // ダイアログを表示する win.show() ; if(doCancel) {return ;} targetPreset = pdfPresetNames[list.selection.index] ; } else { // 引数に指定したPDFプリセットが存在するか調べ,なければ終了する var currentName ; for(var i = 0, len = pdfPresetNames.length ; i < len ; i++) { currentName = pdfPresetNames[i] ; if(currentName == command) { targetPreset = command ; break ; } } if(targetPreset == null) { alert(msgNoPreset) ; return ; } } // 書類の情報を取得する var dstDir = doc.path ; var patternExt = /\.(\w{2,4})$/i ; var docName = doc.name.replace(patternExt, '') ; // 書類の親フォルダが不明なときは,ひとまず初期設定としてデスクトップを指定し,後でダイアログで指定する var needSaveDlg = false ; if(!dstDir.exists) { needSaveDlg = true ; dstDir = Folder.desktop ; } var ext = '.pdf' ; var delim = '/' ; var dstFile = new File(decodeURIComponent(dstDir.fullName) + delim + docName + ext) ; // 書類の親フォルダが不明なとき,またはすでに保存先に同じ名前のファイルがある場合,ダイアログで保存先を指定する var needRename = false ; var newDir, newName ; if((needSaveDlg) || (dstFile.exists)) { var retval = dstFile.saveDlg({ja: '保存先を指定', en: 'Specify the save location'}) ; if(retval == null) {return ;} needRename = true ; dstDir = Folder.temp ; newDir = retval.parent ; newName = decodeURIComponent(retval.name) ; } // 画像フォーマットの設定 var pdfOptions = new ExportForScreensPDFOptions() ; pdfOptions.pdfPreset = targetPreset ; // 書き出し範囲など設定 var whatToExport = new ExportForScreensItemToExport() ; whatToExport.document = true ; whatToExport.artboards = '' ; try { // exportForScreensでサブフォルダを生成しない設定にする var prefAi = app.preferences ; var keyCreateFoldersPreference = 'plugin/SmartExportUI/CreateFoldersPreference' ; var origCreateFoldersPreference = prefAi.getBooleanPreference(keyCreateFoldersPreference) ; prefAi.setBooleanPreference(keyCreateFoldersPreference, false) ; // PDFを書き出す doc.exportForScreens(dstDir, ExportForScreensType.SE_PDF, pdfOptions, whatToExport) ; if(needRename) { // ダイアログで保存先を指定した場合,仮の場所から指定した場所へ移動&リネームする try { var tempFile = new File(decodeURIComponent(dstDir.fullName) + delim + docName + ext) ; tempFile.copy(new File((decodeURIComponent(newDir.fullName) + delim + newName))) ; } finally { try {tempFile.remove() ;} catch(e) {} } } } catch(e) { alert(e) ; } finally { prefAi.setBooleanPreference(keyCreateFoldersPreference, origCreateFoldersPreference) ; } })(arguments) ; /** * スクリプト実行元アプリケーションのバージョンを取得して数値の配列にする。16.0.4の場合[16, 0, 4] * @return {Array of numbers} */ function appVersion() { var tmp = app.version.toString().split('.') ; var res = [] ; for(var i = 0, len = tmp.length ; i < len ; i++) { res.push(Number(tmp[i])) ; } return res ; } /** * exportPDF=[高品質印刷].jsxのような文字列を解析する * @param {String} str 対象の文字列 * @param {Arguments} argv ファイル実行引数 * @return {Object} {mode: String, option: String} */ function parseArguments(str, argv) { var res ; var matchObj = str.match(/^(exportPDF)[\s ]*[==](.+?)(?:\.js(?:x|xbin)?)?$/i) ; if(!matchObj) {return res ;} var mode = matchObj[1] ; // PDFプリセット名。'[高品質印刷]'のような文字が来る var opt = matchObj[2] ; // 単一ファイルで引数を受け取るパターンに対応する if(/^argv$/i.test(opt)) { var tempStr = $.getenv('sttk3_arguments') ; if((tempStr == null) || (tempStr == '')) { if(argv.length <= 0) {return res ;} tempStr = argv[0].toString() ; } res = {mode: mode, option: tempStr} ; } else { res = {mode: mode, option: opt} ; } return res ; } /** * 分割された濁点・半濁点を結合された文字にする。ウムラウトなどは無視する * @param {String} str 対象の文字列。URIエンコードされたもの * @return {String} 変換されたテキスト */ function combineDakuten(str) { // 置換対象の文字とその順番 // ゔがぎぐげござじずぜぞだぢづでどばぱびぴぶぷべぺぼぽヴガギグゲゴザジズゼゾダヂヅデドバパビピブプベペボポ // 分割された文字 var nfd = ['%E3%81%86%E3%82%99', '%E3%81%8B%E3%82%99', '%E3%81%8D%E3%82%99', '%E3%81%8F%E3%82%99', '%E3%81%91%E3%82%99', '%E3%81%93%E3%82%99', '%E3%81%95%E3%82%99', '%E3%81%97%E3%82%99', '%E3%81%99%E3%82%99', '%E3%81%9B%E3%82%99', '%E3%81%9D%E3%82%99', '%E3%81%9F%E3%82%99', '%E3%81%A1%E3%82%99', '%E3%81%A4%E3%82%99', '%E3%81%A6%E3%82%99', '%E3%81%A8%E3%82%99', '%E3%81%AF%E3%82%99', '%E3%81%AF%E3%82%9A', '%E3%81%B2%E3%82%99', '%E3%81%B2%E3%82%9A', '%E3%81%B5%E3%82%99', '%E3%81%B5%E3%82%9A', '%E3%81%B8%E3%82%99', '%E3%81%B8%E3%82%9A', '%E3%81%BB%E3%82%99', '%E3%81%BB%E3%82%9A', '%E3%82%A6%E3%82%99', '%E3%82%AB%E3%82%99', '%E3%82%AD%E3%82%99', '%E3%82%AF%E3%82%99', '%E3%82%B1%E3%82%99', '%E3%82%B3%E3%82%99', '%E3%82%B5%E3%82%99', '%E3%82%B7%E3%82%99', '%E3%82%B9%E3%82%99', '%E3%82%BB%E3%82%99', '%E3%82%BD%E3%82%99', '%E3%82%BF%E3%82%99', '%E3%83%81%E3%82%99', '%E3%83%84%E3%82%99', '%E3%83%86%E3%82%99', '%E3%83%88%E3%82%99', '%E3%83%8F%E3%82%99', '%E3%83%8F%E3%82%9A', '%E3%83%92%E3%82%99', '%E3%83%92%E3%82%9A', '%E3%83%95%E3%82%99', '%E3%83%95%E3%82%9A', '%E3%83%98%E3%82%99', '%E3%83%98%E3%82%9A', '%E3%83%9B%E3%82%99', '%E3%83%9B%E3%82%9A'] ; // 結合された文字 var nfc = ['%E3%82%94', '%E3%81%8C', '%E3%81%8E', '%E3%81%90', '%E3%81%92', '%E3%81%94', '%E3%81%96', '%E3%81%98', '%E3%81%9A', '%E3%81%9C', '%E3%81%9E', '%E3%81%A0', '%E3%81%A2', '%E3%81%A5', '%E3%81%A7', '%E3%81%A9', '%E3%81%B0', '%E3%81%B1', '%E3%81%B3', '%E3%81%B4', '%E3%81%B6', '%E3%81%B7', '%E3%81%B9', '%E3%81%BA', '%E3%81%BC', '%E3%81%BD', '%E3%83%B4', '%E3%82%AC', '%E3%82%AE', '%E3%82%B0', '%E3%82%B2', '%E3%82%B4', '%E3%82%B6', '%E3%82%B8', '%E3%82%BA', '%E3%82%BC', '%E3%82%BE', '%E3%83%80', '%E3%83%82', '%E3%83%85', '%E3%83%87', '%E3%83%89', '%E3%83%90', '%E3%83%91', '%E3%83%93', '%E3%83%94', '%E3%83%96', '%E3%83%97', '%E3%83%99', '%E3%83%9A', '%E3%83%9C', '%E3%83%9D'] ; var currentPattern ; for(var i = 0, len = nfd.length ; i < len ; i++) { currentPattern = new RegExp(nfd[i], 'ig') ; if(currentPattern.test(str)) { str = str.replace(currentPattern, nfc[i]) ; } } return str ; } /** * %記号を使った独自エスケープシーケンスを展開する * @param {String} fmt 対象の文字列 * @return {String} */ function expandVars(fmt) { var res = fmt ; var fmtPattern = /%(.)/gi ; var replaceTable = { '/': '/', ':': ':', '%': '%' } ; res = fmt.replace(fmtPattern, function(m0, m1) { return replaceTable[m1] || m0 ; }) ; return res ; } /** * 書類にリンク切れ画像があるかを返す。ある場合true。 * 画像名は取得方法が複雑なので,このメソッドでは取得を諦める * @param {Array} doc 対象の書類 * @return {Boolean} */ function existsInvalidLink(doc) { var res = false ; var linkItems = doc.placedItems ; for(var i = 0, len = linkItems.length ; i < len ; i++) { try { linkItems[i].file ; } catch(e) { res = true ; break ; } } return res ; } |
このサイトで配布しているスクリプトやその他のファイルを,無断で転載・配布・販売することを禁じます。
それらの使用により生じたあらゆる損害について,私どもは責任を負いません。
スクリプトやファイルのダウンロードを行った時点で,上記の規定に同意したとみなします。
PDFにアウトラインをかけて書き出ししたいです!スクリプト作っていただけないでしょうか?
何となく推奨しないワークフローの気配がしますが,ひとまず話は聞いてみたいです。
Illustrator書類内の文字をアウトライン化した後,PDFで保存したいという意味ですか。それともまずPDFがあって,その中の文字をアウトライン化した後保存するイメージですか?