Hatena::ブログ(Diary)

名もないテクノ手 このページをアンテナに追加 RSSフィード Twitter

EPUB版『InDesign者のための正規表現入門』

InDesignのTips一覧

2010-09-27

[][]「9・25大阪の陣」顛末記

既報の如くであるが、過日第六回大阪DTPの勉強部屋のセッション2において、拙者せうぞーと、たけうちとおる氏が、あかね氏の初心者向けサンプルコードをグーでボコボコにした事件の顛末を記そうと思ふ。この事件は後に「大阪9・25」と呼ばれ、DTP正史にこびりついた一点の軌跡として長く語り継がれるであらう。ライブで目撃された方はまことに重畳という他はない。いま、すべてを語る時がきた。


陽が落ちたなら狼煙をあげよ、密者を入れて伝令を飛ばせ

そもそもの話をしやう。DTPスクリプトに関してディスカッションを供しようと、4人のスクリプト書きが集められた。秋葉氏を司会に戴き、あることないことえへらえへら喋り散らかす態を見ていただこうってな趣向である。

MLが立ち上げられ、ネタだしをしていく白熱した議論の過程で、「初心者の人が書きそうなサンプルコードをでっちあげて、それを添削していく」プランがぶちあげられた。その時、スケープゴートとして名指しされたのがあかね氏である。思い返せばこの時、錯綜した伏線が幾重にも重なり、すでに今日の結果は自明であったかもしれぬ。しかしながら、遠隔地で十分なコミュニケーションなく、どのようなストーリーが起ち現れるのか誰が予想できたらう。

あかね氏より示されたコードを前に、ML上では「サブルーチン化・エラー処理・JavaScript化」のような上っ面を撫でた指摘に始終した。我々はネタが出たことにすつかり安堵していたのである。


さあ、幕が上がったぞ!

あかね氏はスライドを巧みに使って、サンプルコードの全体像、考え方のコツ、そして実際のデモへと順調にオーディエンスの心を鷲づかみにしていった。彼女が示したサンプルコードの全文を、いまもそのブログの中に見ることができる。

大阪DTPの勉強会 - ちくちく日記

あかね氏にとってこのセッションは、聴衆を前にして初めて語る初舞台であった。初陣である。凛々しくそして堂々とした講義であった。天晴である。

あかね氏のコード中の83行目に、白刃の鋭さを見た。こ、こやつできるっ!

save InDes_Doc to Save_Path --ドキュメントを別名で保存

これは一見するとなんでもないように見えるが、長く辛い自己鍛錬のたまものである。レコードのループに入った途端に、すぐに別名保存されているのだ。いつなんどきInDesignがクラッシュしてもよいようになっているのだ。

刃を交えるもの、それが真剣勝負であればこそ手加減は許されない。お愛想を交えてお茶を濁す行為は侍の誇りを侮辱するものだ。心を鬼にせねばならない。


奇襲は夜明けを待ってはならない

先陣を切るはたけうち氏による添削。柔らかい物腰ながら、徹底したサブルーチン化で信長公の鉄砲隊を彷彿とさせる。

大阪DTP勉強会終了しました。 - たけうちとおるのスクリプトノート

たけうち氏が波状サブルーチン攻撃を続ける合間、あかね氏は拙者のディスプレイに用意されたコマンドを見て「目が点」になったそうだ。こんな話聴いてないぞ、と。すまぬ、言ってなかった

拙者はサンプルコードに対して3つの作戦を立てていた。すなわち、「(1)コードデザイン」「(2)サブルーチン化」「(3)JavaScriptで書き直し」である。(1)コードデザイン作戦については、以下のとおり。

(*
● 設計上の添削

1)パス階層が暗黙の内に決まっていて、注意書きが必要。あるいはスクリプトを読まないとそれがわからない。
  →必要なものはダイアログで選ばせて汎用性を高める
2)CSVが複数ある前提になっている。CSVはすでに複数のレコードを含んでいるので、複数ファイルに対応することで、コードを複雑にしている。必要ならばCSVを結合させればよい。
  →CSVをひとつだけ読むようにする
3)同じInDesignファイルを何度も開いている。
  →ファイルをひとつ開いておいて、変更したあとに別名保存する

*)

tell application "Finder"
	activate
	
	set Daishi_File to choose file with prompt "ひな形のInDesignドキュメントを選択してください" --InDesignの台紙ファイルを設定
	set Daishi_File to Daishi_File as Unicode text
	
	set Drop_File to choose file with prompt "CSVファイルを選択してください" as Unicode text ---テスト用テキストファイルを指定
	set Drop_File to Drop_File as Unicode text
	
	set Picture_File_Folder to choose folder with prompt "画像ファイルの入ったフォルダを選択してください"
	set Picture_File_Folder to Picture_File_Folder as Unicode text
	
	set Save_Folder to choose folder with prompt "ドキュメントの保存先を選択してください"
	set Save_Folder to Save_Folder as Unicode text
end tell




set Open_Txt_File to open for access Drop_File --ファイルにアクセス
set Read_Txt to read Open_Txt_File --ファイルを読み込む
close access Open_Txt_File --ファイルをクローズ

--テキストからリストを作成
set DLMT to AppleScript's text item delimiters --現在のデリミタを保存する
set AppleScript's text item delimiters to {return} --デリミタを改行に
set Documenttext_List to (every text item of Read_Txt) --テキストからリストを作る



--ひな形のInDesignドキュメントを開く
tell application "Adobe InDesign CS4"
	activate
	--台紙ドキュメントで開く
	open file Daishi_File --台紙ファイルを開く
	
	
	repeat with Documenttext in Documenttext_List
		set Documenttext to Documenttext as Unicode text
		
		set AppleScript's text item delimiters to {tab} --デリミタをタブに
		set Item_List to (every text item of Documenttext) --テキストからリストを作る
		--流しこみ項目とラベルのリストを作成
		set Syohin_no to {(item 1 of Item_List), "商品番号"}
		set Syohin_Name to {(item 2 of Item_List), "商品名"}
		set Syohin_Kakaku to {(item 3 of Item_List), "価格"}
		set Syomi_Kigen to {(item 4 of Item_List), "賞味期限"}
		set Syohin_Naiyou to {(item 5 of Item_List), "商品内容"}
		set Syohin_Photo to {(item 1 of Item_List), "画像"}
		
		---項目に対する処理
		--価格に"円"をつける
		if (item 1 of Syohin_Kakaku) is not equal to "" then
			set (item 1 of Syohin_Kakaku) to ((item 1 of Syohin_Kakaku) & "円")
		end if
		--画像ファイルのパスを作成する
		if (item 1 of Syohin_Photo) is not equal to "" then
			tell application "Finder"
				set (item 1 of Syohin_Photo) to (Picture_File_Folder & (item 1 of Syohin_Photo) & ".psd")
			end tell
		end if
		--賞味期限に"賞味期限"を付ける
		if (item 1 of Syomi_Kigen) is not equal to "" then
			set (item 1 of Syomi_Kigen) to ("賞味期限:" & (item 1 of Syohin_Kakaku))
		end if
		
		--マスターページの指定
		set Master_page to 1
		--ドキュメント保存先の指定
		set Save_Path to (Save_Folder & (item 1 of Syohin_no) & ".indd")
		
		
		---InDesignでの処理
		set InDes_Doc to (a reference to active document)
		
		tell InDes_Doc
			save InDes_Doc to Save_Path --ドキュメントを別名で保存
			set applied master of page 1 to master spread Master_page --マスターページを適用する
			override master page items of page 1 destination page page 1 --masterページアイテムを上書きする--編集可能にする
			tell page 1
				
				--テキストフレームと内容のリストに繰り返し処理
				repeat with Flame_Txt in {Syohin_no, Syohin_Name, Syohin_Kakaku, Syomi_Kigen, Syohin_Naiyou}
					set Flame_Txt to Flame_Txt as list
					set Text_contents to item 1 of Flame_Txt as Unicode text
					set Frame_Name to item 2 of Flame_Txt as string
					
					--ラベルのついたテキストフレームを探す
					set Text_Frame_list to (every text frame whose label is equal to Frame_Name)
					set Text_Frame to item 1 of Text_Frame_list
					
					tell Text_Frame
						set contents to Text_contents --テキストフレームにテキストを入れる
					end tell
					
				end repeat
				
				--グラフィックフレームと画像ファイルパスのリストに繰り返し処理
				repeat with Flame_Pict in {Syohin_Photo}
					set Flame_Pict to Flame_Pict as list
					set Frame_Name to item 2 of Flame_Pict as string
					set Pict_path to item 1 of Flame_Pict as Unicode text
					
					--ラベルのついたグラフィックフレームを探す
					set Pict_Frame_list to (every rectangle whose label is equal to Frame_Name)
					set Pict_Frame to item 1 of Pict_Frame_list
					
					tell Pict_Frame
						place Pict_path --グラフィックフレームに画像を入れる
						fit given proportionally --画像を短辺合わせでフレームにおさめる
						fit given center content --画像をセンターに
					end tell
				end repeat
				
				save InDes_Doc --保存
			end tell --page1
		end tell --InDes_Doc
		
		set AppleScript's text item delimiters to {DLMT} --デリミタを元に戻す
	end repeat
	close document 1 --最後のドキュメントを閉じる
end tell --app "InDesign"
display dialog "終了しました" as Unicode text

(2)サブルーチンについては、2つのサブルーチンを例示した。

--ファイル・フォルダ選択サブルーチン

to choose_F(my_prompt, my_kind)
	tell application "Finder"
		activate
		if my_kind is "Folder" then
			set tmp to choose folder with prompt my_prompt
		else
			set tmp to choose file with prompt my_prompt of type {my_kind}
		end if
		return tmp as Unicode text
	end tell
end choose_F

set test to choose_F("フォルダを選ぶんだ!", "Folder")
set test to choose_F("InDesign CS4ファイルを選んでね♡", "IDd6")
(*
【文字列を任意の文字列を区切りにリストの分割する--ノーマル版】
2000.08.30	市川せうぞー	

使い方は...
set ans to my as_split(デリミタ文字列,  対象文字列)

という具合に引数を渡すことで、対象文字列をデリミタ文字列で分解したリストを返します。
*)

set str to "市川せうぞー"& tab &"男"& tab & "1964年生まれ"--タブ区切りテキスト
set ans to my as_split(tab, str)

----------------------------------------

to as_split(thedelimit, theText)
	set oldDelim to AppleScript's text item delimiters
	set AppleScript's text item delimiters to thedelimit
	set tmpList to every text item of theText
	set AppleScript's text item delimiters to oldDelim
	return tmpList
end as_split

この2つを組み込んだのがこちらのコードだ。

(*
● サブルーチン

1)ファイル・フォルダを選択させたあとにunicodeテキストにしている箇所が重複している
  →DRY原則。
2)text item delimitersの遷移がわかりづらい。
  →サブルーチン化して見通しをよく

※ サブルーチン化の利点
・同じ処理を何度も書かなくて済む
・短くなってコードの見通しがよくなって、バグが減る
・部品としてテストできる
・細かい処理を任せて、コードの流れに集中できる
・使い回しができる
・いいことづくめ

*)
--ファイル・フォルダ選択
set Daishi_File to my choose_F("ひな形のInDesignドキュメントを選択してください", "IDd6") --InDesignの台紙ファイルを設定
set Drop_File to my choose_F("CSVファイルを選択してください", "TEXT") --CSVテキストファイルを指定
set Picture_File_Folder to my choose_F("画像ファイルの入ったフォルダを選択してください", "Folder")
set Save_Folder to my choose_F("ドキュメントの保存先を選択してください", "Folder")

--ファイルの読み込み
set Open_Txt_File to open for access Drop_File --ファイルにアクセス
set Read_Txt to read Open_Txt_File --ファイルを読み込む
close access Open_Txt_File --ファイルをクローズ

--テキストからリストを作成
set Documenttext_List to my as_split(return, Read_Txt)

--ひな形のInDesignドキュメントを開く
tell application "Adobe InDesign CS4"
	activate
	open file Daishi_File --台紙ファイルを開く
		
	repeat with Documenttext in Documenttext_List
		set Documenttext to Documenttext as Unicode text
		set Item_List to my as_split(tab, Documenttext)--テキストからリストを作る
		--流しこみ項目とラベルのリストを作成
		set Syohin_no to {(item 1 of Item_List), "商品番号"}
		set Syohin_Name to {(item 2 of Item_List), "商品名"}
		set Syohin_Kakaku to {(item 3 of Item_List), "価格"}
		set Syomi_Kigen to {(item 4 of Item_List), "賞味期限"}
		set Syohin_Naiyou to {(item 5 of Item_List), "商品内容"}
		set Syohin_Photo to {(item 1 of Item_List), "画像"}
		
		---項目に対する処理
		--価格に"円"をつける
		if (item 1 of Syohin_Kakaku) is not equal to "" then
			set (item 1 of Syohin_Kakaku) to ((item 1 of Syohin_Kakaku) & "円")
		end if
		--画像ファイルのパスを作成する
		if (item 1 of Syohin_Photo) is not equal to "" then
			tell application "Finder"
				set (item 1 of Syohin_Photo) to (Picture_File_Folder & (item 1 of Syohin_Photo) & ".psd")
			end tell
		end if
		--賞味期限に"賞味期限"を付ける
		if (item 1 of Syomi_Kigen) is not equal to "" then
			set (item 1 of Syomi_Kigen) to ("賞味期限:" & (item 1 of Syohin_Kakaku))
		end if
		
		--マスターページの指定
		set Master_page to 1
		--ドキュメント保存先の指定
		set Save_Path to (Save_Folder & (item 1 of Syohin_no) & ".indd")
		
		
		---InDesignでの処理
		set InDes_Doc to (a reference to active document)
		
		tell InDes_Doc
			save InDes_Doc to Save_Path --ドキュメントを別名で保存
			set applied master of page 1 to master spread Master_page --マスターページを適用する
			override master page items of page 1 destination page page 1 --masterページアイテムを上書きする--編集可能にする
			tell page 1
				
				--テキストフレームと内容のリストに繰り返し処理
				repeat with Flame_Txt in {Syohin_no, Syohin_Name, Syohin_Kakaku, Syomi_Kigen, Syohin_Naiyou}
					set Flame_Txt to Flame_Txt as list
					set Text_contents to item 1 of Flame_Txt as Unicode text
					set Frame_Name to item 2 of Flame_Txt as string
					
					--ラベルのついたテキストフレームを探す
					set Text_Frame_list to (every text frame whose label is equal to Frame_Name)
					set Text_Frame to item 1 of Text_Frame_list
					
					tell Text_Frame
						set contents to Text_contents --テキストフレームにテキストを入れる
					end tell
					
				end repeat
				
				--グラフィックフレームと画像ファイルパスのリストに繰り返し処理
				repeat with Flame_Pict in {Syohin_Photo}
					set Flame_Pict to Flame_Pict as list
					set Frame_Name to item 2 of Flame_Pict as string
					set Pict_path to item 1 of Flame_Pict as Unicode text
					
					--ラベルのついたグラフィックフレームを探す
					set Pict_Frame_list to (every rectangle whose label is equal to Frame_Name)
					set Pict_Frame to item 1 of Pict_Frame_list
					
					tell Pict_Frame
						place Pict_path --グラフィックフレームに画像を入れる
						fit given proportionally --画像を短辺合わせでフレームにおさめる
						fit given center content --画像をセンターに
					end tell
				end repeat
				
				save InDes_Doc --保存
			end tell --page1
		end tell --InDes_Doc
		
	end repeat
	close document 1 --最後のドキュメントを閉じる
end tell --app "InDesign"
display dialog "終了しました" as Unicode text





--ここからサブルーチン================================================================
--ファイル・フォルダ選択サブルーチン

to choose_F(my_prompt, my_kind)
	tell application "Finder"
		activate
		if my_kind is "Folder" then
			set tmp to choose folder with prompt my_prompt
		else
			set tmp to choose file with prompt my_prompt of type {my_kind}
		end if
		return tmp as Unicode text
	end tell
end choose_F


--文字列を任意の文字列を区切りにリストの分割する
to as_split(thedelimit, theText)
	set oldDelim to AppleScript's text item delimiters
	set AppleScript's text item delimiters to thedelimit
	set tmpList to every text item of theText
	set AppleScript's text item delimiters to oldDelim
	return tmpList
end as_split

そして最後は、JavaScriptへの書き換えであった。サンプルコードはスクリプトラベルに依存している。しかし、InDesign CS5ではスクリプトラベルがAdobe軍部によって補給を断たれているのだ。愚かな! 拙者は迷わずTSVをXMLに書き換えた。むう、パンがなければケーキを食べるのみ!

TSVからInDesignのXML流し込み - 名もないテクノ手


地平線の向こうには血よりも紅い夕焼けがある

戰は終わった。「戦いが終わったらノーサイド」だと菅首相も言っている。流された血に報いるなどとは云わぬ、がしかし何より市井の民が喜んでくれたのだ。本當の勝者は彼の地の労働者諸君である。我等は道化で了ひ。

さあ、とぼとぼと帰ろう。今日も夕日が笑ってら。( - 完 -)


参考史書

Togetter - 「第6回大阪DTPの勉強部屋」

たけうちとおるたけうちとおる 2010/09/29 12:15 あかねさんには絶対勝てないと思い知らされた晩夏。鶴翼の陣では簡単に一転突破されてしまう。

seuzoseuzo 2010/09/29 15:38 ぼくなんか、人として負けています^^

akane_nekoakane_neko 2010/09/29 18:36 おふたりで私をボコボコにしたくせに、なにをおっしゃる(笑)

seuzoseuzo 2010/09/29 19:58 シャープ兄弟と呼んでください。<反則負け

チャチャチャチャ 2010/09/30 09:35 ここまで「スケープゴード」のツッコミ無し

seuzoseuzo 2010/09/30 10:28 あ、ほんとだ。ありがとうございます。
あとでこっそり直しておきます。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/seuzo/20100927/1285570458