スクスニップ

AppleScriptの断片をここに書く

InDesign 文字の置換 AppleScript

2-3 01 全てのページのテキストフレーム内の文字を置換する(P.111)

組版時間を半減する! InDesign自動処理実例集

組版時間を半減する! InDesign自動処理実例集

部品作製

f:id:mikomaya:20141112101115p:plain

-- 検索ワードを返す
on searchWord()
    tell application "Adobe InDesign CS6"
        find what of find text preferences
    end tell
end searchWord

-- 検索ワードの設定
on setSearchWord(myStr)
    tell application "Adobe InDesign CS6"
        set find what of find text preferences to myStr
    end tell
end setSearchWord

-- 置換ワードを返す
on changeWord()
    tell application "Adobe InDesign CS6"
        change to of change text preferences
    end tell
end changeWord

-- 置換ワードの設定
on setChangeWord(myStr)
    tell application "Adobe InDesign CS6"
        set change to of change text preferences to myStr
    end tell
end setChangeWord

部品が揃ったので、まとめ

tell application "Adobe InDesign CS6"
    -- 検索・置換ワードの初期化?
    set find text preferences to nothing --[accept or nothing]
    set change text preferences to nothing --[accept or nothing]
    -- 検索・置換ワードの設定
    tell me
        setSearchWord("★")
        log searchWord() -- イベント画面に出力
        setChangeWord("OS X")
        log changeWord() -- イベント画面に出力
    end tell
    
    tell active document
        set pMax to number of page
        repeat with myPage from 1 to pMax
            set fMax to number of every text frame of page myPage
            repeat with i from 1 to fMax
                set myObj to text frame i of page myPage
                change text parent story of myObj
            end repeat
        end repeat
    end tell
end tell

実行結果

f:id:mikomaya:20141112101202p:plain

f:id:mikomaya:20141112101210p:plain

InDesign インライングラフィック(確認しながら文字列を置換) AppleScript

2-2 07 テキストフレーム内の特定の文字列を、確認しながら画像に置換する(P.108)

組版時間を半減する! InDesign自動処理実例集

組版時間を半減する! InDesign自動処理実例集

部品作製

f:id:mikomaya:20141111190417p:plain

-- テキストフレーム内の[cFrom]番目の文字から[cTo]番目の文字を選択する
on selectString(tfObj, cFrom, cTo)
    tell application "Adobe InDesign CS6"
        tell tfObj
            select (text from character cFrom to character cTo)
        end tell
    end tell
end selectString

-- テキストフレームの[cFrom]番目の文字から[cTo]番目の文字数部分に前に画像を挿入する
on replaceStr2Image(tfObj, cFrom, cTo, myFile)
    tell application "Adobe InDesign CS6"
        tell tfObj
            place myFile on text from character cFrom to character cTo
        end tell
    end tell
end replaceStr2Image

他のハンドラは以下のURLで実装済http://scsnip.hatenablog.com/entry/2014/11/11/141330

-- 指定されたページのテキストフレームを返す
on getTextFrames(myPage)
-- 文字列内にある特定の文字列の開始位置を返す JavaScriptのindexOf(出現回数の引数を追加)
on textIndexOf(myStr, myPat, myCount)
-- 文字列内にある特定の文字列の全ての開始位置を返す
on textIndexList(myStr, myPat)

部品が揃ったので、まとめ

-- 検索パターンを指定
display dialog "置換対象のタグ(文字)を入れてください" default answer "<<icon_AScript>>"
set myPat to text returned of result

-- 画像ファイルを指定
set myFile to "Macintosh HD:Users:logox:Desktop:asDocIcon.png" as alias

set myList to getTextFrames(1)

set loop to number of myList
repeat with i from 1 to loop
    set myTF to item i of myList
    tell document 1 of application "Adobe InDesign CS6"
        set myStr to (text of myTF as string)
    end tell
    
    set pList to textIndexList(myStr, myPat) -- [AppleScript]が出現する全ての位置
    set pList to reverse of pList -- 後ろの文字から処理
    set loop to number of pList
    repeat with p from 1 to loop
        set insFrom to item p of pList
        set insTo to insFrom + (length of myPat) - 1
        selectString(myTF, insFrom, insTo)
        display dialog "置換しますか?" buttons {"キャンセル", "NG", "OK"}
        if button returned of result is "OK" then
            if insFrom > 0 then replaceStr2Image(myTF, insFrom, insTo, myFile)
        end if
    end repeat
end repeat

実行結果

f:id:mikomaya:20141111190431p:plain

f:id:mikomaya:20141111190432p:plain

f:id:mikomaya:20141111190434p:plain

f:id:mikomaya:20141111190435p:plain

f:id:mikomaya:20141111190437p:plain

f:id:mikomaya:20141111190439p:plain

InDesign インライングラフィック(文字列を置換) AppleScript

2-2 06 テキストフレーム内の特定の文字列を、画像に置換する(P.107)

組版時間を半減する! InDesign自動処理実例集

組版時間を半減する! InDesign自動処理実例集

書籍では、ダイアログを開いて挿入する画像を指定しているが、 当ブログでは、画像ファイルのパスを設定しておく。

部品作製

f:id:mikomaya:20141111172232p:plain

-- テキストフレームの[cFrom]番目の文字から[cTo]番目の文字数部分に前に画像を挿入する
on replaceStr2Image(tfObj, cFrom, cTo, myFile)
    tell application "Adobe InDesign CS6"
        tell tfObj
            set contents of characters cFrom thru cTo to ""
            place myFile on insertion point cFrom
        end tell
    end tell
end replaceStr2Image

書籍のスクリプトで文字範囲を取得する部分

… insertionPoints.itemByRange(cFrom,cTo)

AppleScriptでどう書けばいいのか分からなかったので、

  • 検索パターンにヒットした部分の文字列を消去
  • 画像を挿入

という手順で実装した。

-- 追記 -- 2104.11.11 以下のように書けることがわかった。

place myFile on text from character cFrom to character cTo

他のハンドラは以下のURLで実装済http://scsnip.hatenablog.com/entry/2014/11/11/141330

  • on getTextFrames(myPage)
  • on textIndexOf(myStr, myPat, myCount)
  • on textIndexList(myStr, myPat)

部品が揃ったので、まとめ

-- 検索パターン
set myPat to "<<icon_AScript>>"

-- 画像ファイルのパス
set myFile to "Macintosh HD:Users:yourUserName:Desktop:asDocIcon.png" as alias
set myList to getTextFrames(1)

set loop to number of myList
repeat with i from 1 to loop
    set myTF to item i of myList
    tell document 1 of application "Adobe InDesign CS6"
        set myStr to (text of myTF as string)
    end tell
    
    set pList to textIndexList(myStr, myPat) -- [AppleScript]が出現する全ての位置
    set pList to reverse of pList -- 後ろの文字から処理
    set loop to number of pList
    repeat with p from 1 to loop
        set insFrom to item p of pList
        set insTo to insFrom + (length of myPat) - 1
        if insFrom > 0 then replaceStr2Image(myTF, insFrom, insTo, myFile)
    end repeat
end repeat

実行結果

f:id:mikomaya:20141111172325p:plain

InDesign インライングラフィック AppleScript

2-2 05 テキストフレーム内の特定の文字列の前に画像を挿入する(P.106)

組版時間を半減する! InDesign自動処理実例集

組版時間を半減する! InDesign自動処理実例集

書籍では、ダイアログを開いて挿入する画像を指定しているが、 当ブログでは、画像ファイルのパスを設定しておく。

部品作製

f:id:mikomaya:20141111140930p:plain

-- 指定されたページのテキストフレームを返す
on getTextFrames(myPage)
    tell document 1 of application "Adobe InDesign CS6"
        every text frame of page myPage
    end tell
end getTextFrames

-- テキストフレームの[cIdx]番目の文字の前に画像を挿入する
on insertImage(tfObj, cIdx, myFile)
    tell application "Adobe InDesign CS6"
        place myFile on insertion point cIdx of tfObj
    end tell
end insertImage

-- JavaScript の indexOf メソッドを
-- AppleScript で実装する
-- 文字列内にある特定の文字列の開始位置を返す(出現回数の引数を追加)
on textIndexOf(myStr, myPat, myCount)
    set m to 0
    set myPat to every character of myPat
    set sLen to length of myStr
    set pLen to length of myPat
    
    if sLen < pLen then return m
    set loop to sLen - pLen + 1
    repeat with i from 1 to loop
        set iStr to characters i thru (i + pLen - 1) of myStr
        if iStr is myPat then
            set m to m + 1
            if m = myCount then
                return i
            end if
        end if
    end repeat
end textIndexOf

部品が揃ったので、まとめ

-- 検索パターン
set myPat to "AppleScript"

-- 画像ファイルのパス
set myFile to "Macintosh HD:Users:yourUserName:Desktop:asDocIcon.png" as alias
set myList to getTextFrames(1)

set loop to number of myList
repeat with i from 1 to loop
    set myTF to item i of myList
    tell document 1 of application "Adobe InDesign CS6"
        set myStr to (text of myTF as string)
    end tell
    
    set insPos to textIndexOf(myStr, myPat, 1) -- 最初に[AppleScript]が出現する位置
    if insPos > 0 then insertImage(myTF, insPos, myFile)
end repeat

実行結果

f:id:mikomaya:20141111141026p:plain

改造してみよう

下のテキストフレームには「AppleScript」が複数出現するので、それに対処してみる。

部品を追加

-- 文字列内にある特定の文字列の全ての開始位置を返す
on textIndexList(myStr, myPat)
    set res to {}
    set m to 0
    set myPat to every character of myPat
    set sLen to length of myStr
    set pLen to length of myPat
    
    if sLen < pLen then return res
    set loop to sLen - pLen + 1
    repeat with i from 1 to loop
        set iStr to characters i thru (i + pLen - 1) of myStr
        if iStr is myPat then
            set end of res to i
        end if
    end repeat
    res
end textIndexList

改造版

-- 検索パターン
set myPat to "AppleScript"

-- 画像ファイルのパス
set myFile to "Macintosh HD:Users:yourUserName:Desktop:asDocIcon.png" as alias
set myList to getTextFrames(1)

set loop to number of myList
repeat with i from 1 to loop
    set myTF to item i of myList
    tell document 1 of application "Adobe InDesign CS6"
        set myStr to (text of myTF as string)
    end tell
    
    set pList to textIndexList(myStr, myPat) -- [AppleScript]が出現する全ての位置
    set pList to reverse of pList -- 後ろの文字から処理
    set loop to number of pList
    repeat with p from 1 to loop
        set insPos to item p of pList
        if insPos > 0 then insertImage(myTF, insPos, myFile)
    end repeat
end repeat

改造版:実行結果

f:id:mikomaya:20141111141110p:plain

InDesign テキストフレームの長体処理 AppleScript

2-2 04 選択されたテキストフレームがオーバーフローしているとき長体をかける(P105)

組版時間を半減する! InDesign自動処理実例集

組版時間を半減する! InDesign自動処理実例集

書籍では、テキストフレームを選択した状態でスクリプトを実行しているが、当ブログではスクリプトで対象オブジェクトを取得する方式に書き替えることにする(オブジェクトを選択する必要のない場合)。

また、書籍の解説部分(当ブログでは部品作製)はスクリプトが1行で書かれているが、なるべくハンドラ化するよう試みる。

部品作製

f:id:mikomaya:20141111111825p:plain

-- 指定されたページのテキストフレームを返す
on getTextFrames(myPage)
    tell document 1 of application "Adobe InDesign CS6"
        every text frame of page myPage
    end tell
end getTextFrames

-- テキストフレームがオーバーフローしているか?
on isOverFlow(tfObj)
    tell application "Adobe InDesign CS6"
        overflows of tfObj
    end tell
end isOverFlow

-- テキストフレームの[tIdx]番目のテキストの長体率を取得する
on horizontalScale(tfObj, tIdx)
    tell application "Adobe InDesign CS6"
        horizontal scale of text tIdx of tfObj
    end tell
end horizontalScale

-- テキストフレームの[tIdx]番目のテキストの長体率を変更する
on setHorizontalScale(tfObj, tIdx, myScale)
    tell application "Adobe InDesign CS6"
        set horizontal scale of text tIdx of tfObj to myScale
    end tell
end setHorizontalScale

部品が揃ったので、まとめ

set limitScale to 65 -- 最小長体率
set myList to getTextFrames(1)
set loop to number of myList
repeat with i from 1 to loop
    set myTF to item i of myList
    if isOverFlow(myTF) is true then
        set myScale to horizontalScale(myTF, 1)
        repeat
            set myScale to myScale - 1
            if myScale < limitScale then exit repeat
            setHorizontalScale(myTF, 1, myScale)
            if isOverFlow(myTF) is false then exit repeat
        end repeat
    end if
end repeat

実行結果

f:id:mikomaya:20141111111842p:plain

  • テキストフレーム 1(以下 TF1)と TF2 の長体率が変更された。
  • TF2 は長体率が最小長体率(上記スクリプトでは65%)に達したので処理が中断している。
  • TF1 のオーバーフローは解消されたが、行頭と行末の長体率が異なっている。

処理中の画面を観察すると、どうやらTF外にある文字の長体率が変更されないようだ。

長体率を変更する対象を text から paragraph に変更すると、上手く動くようだ。

部品を追加

-- テキストフレームの指定された段落(paragraph)の長体率を変更する
-- pidx が 0 なら全ての段落が対象
on setParagraphScaleH(tfObj, pidx, myScale)
    tell application "Adobe InDesign CS6"
        if pidx > 0 then
            set horizontal scale of paragraph pidx of tfObj to myScale
        else
            set horizontal scale of every paragraph of tfObj to myScale
        end if
    end tell
end setParagraphScaleH

改良版

set limitScale to 65 -- 最小長体率
set myList to getTextFrames(1)
set loop to number of myList
repeat with i from 1 to loop
    set myTF to item i of myList
    if isOverFlow(myTF) is true then
        set myScale to horizontalScale(myTF, 1)
        repeat
            set myScale to myScale - 1
            if myScale < limitScale then exit repeat
            setParagraphScaleH(myTF, 0, myScale)
            if isOverFlow(myTF) is false then exit repeat
        end repeat
    end if
end repeat

改良版:実行結果

f:id:mikomaya:20141111111855p:plain