最終更新日: 2016/03/01
今回の修正点についてはwrdap ver 1.07 の変更点を参照してください。
ruby用ライブラリのwrdap.rbを作ったのは、もちろんワードを自動操縦するためですが、pandocと組み合わせて使うことが大きな目的です。
pandocは高機能な変換ソフトウェアです。markdownで書かれた原稿をワード文書に変換することができます。ただ、細かい調整をすることは難しいので、ワードを自動操縦して調整することを考えました。
pandocによる変換と、ワードの自動操縦による調整を一括して行うのにrubyを用いるというわけです。
wrdap.rbとsetup.rbがカレントディレクトリにある状態で
ruby setup.rb [enter]
上のように入力します。すると、wrdap.rbがrubyのライブラリパスの通ったディレクトリにコピーされます。
wrdap.rbを削除したい時は、付属の unset.rb を実行して下さい。
パッケージにはサンプルスクリプトを同梱してありますが、それらを実行した環境は次のとおり。
ちなみに、Windows8.1|Office2013 の環境でも一通り試しましたが、大丈夫でした。
wrdap.rbをrequireすると、Wrdapというクラスを使えるようになります。このクラスには、文書を開いたり保存したりするためのメソッドがあります。それらについて、サンプルを掲げながら使い方を記します。
なお、rubyのバージョンは ver 1.9 以降を想定しています。
まず「wrd = Wrdap.new」として Wrdap のオブジェクトを生成します。
次に「doc = wrd.doc_open(“test.doc”)」とすれば test.doc というワード文書を開くことができます。変数 doc には、VBAでいうところの ActiveDocument が代入されます。正確にいうと doc は、rubyのオブジェクトなので少しだけ違いますが、同じと思ってもあまり不都合はないと思います。
文書に何か書き込みなどの処理を行ったあとで、「doc.close」として文書を閉じます。
最後に「wrd.quit」としてアプリケーション(つまりワード)を終了させます。
下に、簡単な文章を書き込んで、文書を保存するサンプルを掲げます。
−−−−−−−− test01.rb スクリプトここから
# encoding: Windows-31J
require "wrdap"
filename = "test01.doc"
lines = ["今日は電車に乗って出かけました。",
"明日はバスに乗ってみようと思います。"]
wrd = Wrdap.new # Wordの起動
doc = wrd.doc_open(filename)
slc = doc.Application.Selection
lines.each do |line|
slc.TypeText line # 1行入力
slc.TypeParagraph() # エンターキーを押すことに相当
end
doc.save # ワード文書の保存
doc.close
wrd.quit # ワードの終了
−−−−−−−− スクリプトここまで
上に出てくる doc_open() は、1つの文書を開くためのメソッドですが、複数の文書を開くための opens() というのもあります。
ary = wrd.opens("test01.doc", "test02.doc")
上のように用います。その戻り値は配列で、先のサンプルに出てくる変数docに相当するものが複数記録されています。
opens() は、ブロック付きで呼び出すこともできます。その場合、文書を1つづつ処理していくイメージになります。
wrd.opens("test.doc", "test02.doc") do |doc|
…………
end
もし複数の文書を同時に開いて処理したいのであれば、opens_once() を用います。
wrd.opens_once("test.doc", "test02.doc") do |doc1, doc2|
…………
end
実は、Wrdap.new としてオブジェクトを生成するとき、文書名を指定したり、ブロックを指定したりできます。opens() と同じように記述することができるわけです。
ブロック付きで呼び出した時は、ブロックの処理が終了したところで、自動的に wrd.quit が呼び出され、ワードが終了します。スクリプトを多少簡潔にすることができます。
先のサンプルを書き換えてみると次のようになります。
−−−−−−−− test01_2.rb スクリプトここから
# encoding: Windows-31J
require "wrdap"
filename = "test01_2.doc"
lines = ["今日は電車に乗って出かけました。",
"明日はバスに乗ってみようと思います。"]
Wrdap.new(filename) do |doc|
slc = doc.Application.Selection
lines.each do |line|
slc.TypeText line # 1行入力
slc.TypeParagraph() # エンターキーを押すことに相当
end
doc.save # ワード文書の保存
doc.close
end
−−−−−−−− スクリプトここまで
もう一つ基本的な例を掲げてみます。
ワード文書にテキストファイルを挿入し、中央揃え、右揃え、ページ番号付加の処理を行います。ページ番号は、フッターに中央揃えの形で付加します。
−−−−−−−− test02.rb スクリプトここから
# encoding: Windows-31J
require "wrdap"
data_file = "test02.txt"
File.open(data_file, "w") {|ff| ff.write DATA.read}
filename = "test02.doc"
File.unlink(filename) if test(?e, filename)
Wrdap.new(filename) do |doc|
slc = doc.Application.Selection
slc.InsertFile('FileName'=>Wrd::fullpath(data_file),
'Range'=>"", 'ConfirmConversions'=>false,
'Link'=>false, 'Attachment'=>false)
doc.Paragraphs.each do |para| # 段落を1つづつチェック
str = para.Range.Text.sub(/[\x01-\x1f]+\Z/, "")
case str # 中央揃え・右揃えの処理
when "テキストファイルを読み込んでワード文書作成"
para.Range.ParagraphFormat.Alignment = WdAlignParagraphCenter
when "2014年4月10日(金)"
para.Range.ParagraphFormat.Alignment = WdAlignParagraphRight
end
end
sect = slc.Sections(1) # フッターにページ番号を付加
sect.Footers(WdHeaderFooterPrimary).PageNumbers.Add(
'PageNumberAlignment'=>WdAlignPageNumberCenter,
'FirstPage'=>true)
doc.save # ワード文書の保存
doc.close
end
File.unlink(data_file)
__END__
テキストファイルを読み込んでワード文書作成
2014年4月10日(金)
今日の天気は晴れでした。
電車に乗って出かけました。乗った電車は次のとおり。
・京浜東北線
・山手線
・東西線
明日はバスに乗ってみようと思います。
−−−−−−−− スクリプトここまで
上のスクリプトは、VBAのノウハウをrubyで実現しているものです。VBA関連の詳細は省きます。
本題のpandocとの組合せについて記します。
ワードを起動してキーボードやマウスで操作するのをなるべく避けたい人(つまり処理を自動化したい人)には、それなりに参考にしていただけるのではないかと思います。
まず pandoc をインストールします。
pandocは、MS-Windowsに限らず様々なOSで動作しますが、ここではMS-Windows用のものをインストールします。
上のサイトからWindowsのダウンロードサイトに進み、該当のパッケージを入手します。
「pandoc-1.13.1-windows.msi」のような名前のファイルが該当のパッケージです。
この拡張子 .msi のファイルを実行すれば、簡単にインストールできます。
Windows7以降を使っている場合、pandoc.exeのパス名は次のようになるのではないかと思います。
C:\Users\tarou\AppData\Local\Pandoc\pandoc.exe
「tarou」はユーザー名です。
上のようなパス名でない時は、pandoc.exeの所在ディレクトリを確認しておいて下さい。Windowsのwhereコマンドを使えば確認できます。
なるべくなら、pandoc.exeの所在ディレクトリにpathを通しておくのがいいと思います。
[参考] pandocの日本語解説
pandocの使い方について、次のサイトが参考になります。
rubyスクリプトからpandocを呼び出すためのライブラリに pandoc-ruby というのがあります。これもインストールします。
gem install pandoc-ruby [enter]
上のようにすればインストールできます。
このライブラリを利用する際、pandoc.exeの所在ディレクトリがわかっていて、そこにpathが通っていない場合は、rubyスクリプトの前半の方に次のような1行を置きます。
PandocRuby.bin_path = 'C:/usr/pandoc'
上は、pandoc.exeのフルパス名が「C:/usr/pandoc/pandoc.exe」である場合です。
pandoc-rubyの参考サイトは次のところです。
alphabetum/pandoc-ruby ・ GitHub
wrdap.rbをrequireすると、Wrdというモジュールがロードされます。その中に pandoc_docx() というメソッドがあり、これを用いると、pandocを通して簡単にワード文書を作成できます。
markdownの原稿からワード文書を生成するサンプルを下に掲げます。表と箇条書きを含む原稿です。
−−−−−−−− test03.rb スクリプトここから
# encoding: Windows-31J
require "wrdap"
mkd_str = eval(DATA.read)
docx_file = "test03.docx"
docx_str = Wrd::pandoc_docx(mkd_str)
File.open(docx_file, "wb") {|ff| ff.write docx_str}
__END__
<<EOS
# 都道府県の人口等\n
都道府県を人口の多い順に並べた。上位4県を表形式で記載。\n
|都道府県|人口|面積|人口密度
|:--|--:|--:|--:
|東京都|13216221|2188.67|6038.47
|神奈川県|9072133|2415.86|3755.24
|大阪府|8863324|1901.42|4661.42
|愛知県|7425952|5165.14|1437.71
|全国|127532028|372923.77|341.98\n
上の表の注釈を箇条書きで記す。\n
- 人口は2012年10月1日の推計人口。
- 面積は2012年10月1日の国土交通省国土地理院「全国都道府県市区町村別面積調」\
による(単位:平方km)。
- 人口密度は小数点以下第3位を四捨五入(単位:人/平方km)。\n
------------------------------------------------------------------------\n
EOS
−−−−−−−− スクリプトここまで
markdown記法では段落と段落の間に空白行を置きます。そのため空白行がいっぱい出てきてしまい、スクリプトが間延びした形になります。
それを避けるため、上記では空白行を「\n」と表現する形式にしました。分かりにくくなったかもしれませんが、ご容赦のほど。
[参考] pandoc_html() というメソッド
pandocによってmarkdown→html変換を行うためのメソッド pandoc_html() というのもあります。使い方は pandoc_docx() と同じです。
ブラウザで閲覧できるhtmlを作りたい時は、:s(あるいは :standalone でもよい)というオプションを付けます。これがないと、部分的なhtmlしか作られないのでブラウザで表示することはできません。
例えば次のようにします。
html_str = Wrd::pandoc_html(mkd_str, :s)
pandocがmarkdownの原稿をどのような構造の文書に変換するのかを確かめたいことがあります。そのような場合、ワード文書よりもhtmlの方が確認しやすいと思います。そこで、pandoc_html() も設けました。
pandocは、htmlを基調としているようです。html生成用に様々なオプションが用意されています。例えば、数式を表示できるようにするための :mathml とか :mathjax もその一種です。
そうしたオプションを必要に応じて pandoc_html() の第2引数、第3引数 …… として指定します。どんなオプションがあるかは pandoc の解説を参照して下さい。
ちなみに、markdownの原稿をTeXの原稿に変換するためのメソッド pandoc_tex() というのも設けてあります。
使い方は、上記の pandoc_html() と同じです。
ただ、与えるオプションは、html生成の時と違ってくるので留意して下さい。
wrdap.rbでは、段落の中央揃えや右揃えを行うためのメソッド pa() を設けています。paは省略名で、paragraph_adjust() というのが本来の名前です。
「doc.pa(adjust_str)」のように用います。docは、1つのワード文書を指し示すオブジェクトです。
引数のadjust_strは文字列で、処理したい段落と配置指示の2行を必要な組みだけ書いたものです。各組みの間には空白行を置きます。例えば次のように書きます。
−−−−−−−− adjust_strの例 ここから
業務日誌
center
平成26年7月15日
right
−−−−−−−− adjust_strの例 ここまで
上の例は、「業務日誌」という段落を中央揃えにし、「平成26年7月15日」という段落を右揃えにするものです。
段落の指定は完全一致方式です。段落に書かれている文字が「平成26年7月15日」に一致する時にのみ右揃えが行われます。ここでは数字が全角で書かれていますが、仮に半角で書かれた段落があったとしても、一致しないので処理されません。
また、処理は1回だけ行われます。「業務日誌」という段落が文書中に複数あったとしても、最初にみつかったものだけが処理されます。
2回目の「業務日誌」も処理したい時は、adjust_strの中に、もう1回「業務日誌」とその配置指示を書きます。
それから、実は段落の指定に正規表現を使うことができます。先に「完全一致方式」と書きましたが、正規表現を使うことにより弾力化できます。正規表現は、rubyスクリプトと同じように半角のスラッシュ記号で囲みます。
「/^平成26年7月[0-9]+日$/」とすれば、日にちの数が変更になっても処理されます。
配置指示は、半角アルファベットで書きますが、大文字|小文字はどちらでもかまいません。次のものを書くことができます。
・center 中央揃え
・left 左揃え
・right 右揃え
・justify 両端揃え
・distribute 均等割り付け
・pagebreak 改ページ
・no 処理なし
改ページは、指定された段落の直前に改ページコードを挿入するものです。
今後の景気の動向について
pagebreak
上のようにすると、「今後の景気の動向について」という段落の直前に改ページコードを挿入します。
この pagebreak については、ページ内の残り行数を条件として指定できます。
今後の景気の動向について
pagebreak <=5
上のようにすれば、「今後の景気の動向について」という段落の開始位置がページのどの辺かをチェックして、残り5行以下であれば改ページするけれども、残り6行以上なら改ページしない、ということになります。
例えば、1ページ・30行の文書の場合、該当の段落の開始位置が25行目以降であれば改ページするが、24行目とか23行目であれば改ページしない、ということになります。
「pagebreak」と「<=5」の間には半角スペースを置きます。また、「<=5」などの記述は、半角で書きます。
ある段落を中央揃えにして、更に、その段落の直前に改ページコードを挿入したい時は、1つの段落指定に対して2つの配置指示(center, pagebreak)を書いて下さい。
noの「処理なし」は、中央揃えとか改ページなどの処理を施さない、つまり何も処理を加えないという意味です。
noの代わりに none とか nothing と書いてもかまいません。no の2文字で始まる文字列は、この「処理なし」になります。
下にサンプルのスクリプトを掲げます。簡単な礼状を作る例です。
−−−−−−−− test04.rb スクリプトここから
# encoding: Windows-31J
require "wrdap"
# markdownの原稿
mkd_str = <<EOS1
平成26年7月15日\n
佐々木 太郎 様\n
森田 三郎\n
\n
拝 啓\n
時下ますますご清栄のこととお慶び申し上げます。\n
過日は弊社の○○プロジェクト事業の打ち合わせ会議にご出席いただき\
ありがとうございました。\n
おかげさまで滞り亡く会議を取り行うことができ、また、たいへん\
実りあるご意見を参加者の皆様からいただくことができました。\n
会議で賜ったご意見・ご指摘を踏まえながら、更に事業を進める所存です。\n
今後ともご支援・ご鞭撻のほどよろしくお願い申し上げます。\n
まずはお礼のみにて失礼いたします。\n
敬 具\n
EOS1
# pandocによるmarkdown→docxの変換
docx_file = "test04.docx"
docx_str = Wrd::pandoc_docx(mkd_str)
File.open(docx_file, "wb") {|ff| ff.write docx_str}
# どの段落を中央揃え・右揃えにするかの情報
adjust_str = <<EOS2
/^平成26年7月[0-9]+日$/
center\n
森田 三郎
right\n
敬 具
right\n
EOS2
# ワード文書の調整(中央揃え・右揃えの実行)
adjust_msg = ''
Wrdap.new(docx_file) do |doc|
adjust_msg = doc.pa(adjust_str)
doc.save
end
puts "☆ 段落調整の情報"
print adjust_msg
−−−−−−−− スクリプトここまで
pa() について少し補足します。
pa() に渡す引数は、文字列でなくファイル名でもかまいません。そのファイルが存在するなら、それを読み取って処理します。
pa() の戻り値は文字列で、どの段落が調整されたのか、その情報が記録されています。
それから、1つの段落が行分割されている場合は、markdown記法に従って、行末に半角スペース2つを置くことでそれを表現します。
○○株式会社総務部__
高 橋 次 郎
right
上の「__」は、実際には半角スペース2つを示すものとします。
この場合、1つの段落(行分割された2行)が右揃えになります。
A4サイズの用紙は、横幅が210ミリ、縦の長さが297ミリです。pandocで作成したワード文書は、この大きさになっています。
これを変更したい時は、wrdap.rbで定義されている ps() というメソッドを用いることができます。psは省略名で、本来の名前は page_setup です。
ps() には、引数として文字列を与えます。pa() の時と同じようにファイル名を与えることもできます。
例えば次のような文字列です。
−−−−−−−− setup_strの例 ここから
用紙の横幅 182
用紙の縦の長さ 257
1行の文字数
1ページの行数
上余白 30
下余白 30
左余白 30
右余白 30
ヘッダの高さ 15
フッタの高さ 17.5
ガター 0
段組数 1
段組境界線 false
−−−−−−−− setup_strの例 ここまで
上はB5サイズを指定する例です。
「用紙の横幅」とか「用紙の縦の長さ」といった項目名の後には、半角スペースかタブコードを1つ以上書きます。そして、半角で数値を記します。
「1行の文字数」と「1ページの行数」のところは値がありません。このように指定がないものは、ワードに「お任せ」となります。
この2つは、可能な範囲を超えて指定するとエラーになります。どれくらいまで指定可能かは、ページのサイズ、余白、文字の大きさなどによって違ってきます。特に必要がなければ「お任せ」にしておくのが無難です。
ちなみに、「1行の文字数」は、全角文字が何文字かの値だと思います。pandocで作成した文書(A4サイズ)の場合、35文字になっています。
上に出てくる幅、長さ、高さ、余白の数値は、ミリ単位で指定します。厳密にいうとfloat(実数)で指定しますが、integer(整数)でもかまいません。
VBAではミリ単位でなくポイント単位で指定するのが基本のようですが、ps() ではミリ単位の方にしました。
ガターというのもミリ単位です。これがどのようなものかは、Webなどを参照して下さい。
「段組数」を2にすると、2段組みの文書になります。2段組みにしたとしても、ワード文書を開いた時に、下書き表示になっていると2段組みに見えないと思います。印刷レイアウトモードにすれば、2段組みになって見えます。
「段組境界線」が false だと境界線は入りません。true にすれば境界線が入ります。
ps() に渡す引数 setup_strでは、上に掲げた項目すべてを記述する必要はありません。必要なものだけ記述すればOkです。
下にサンプルスクリプトを掲げます。
−−−−−−−− test05.rb スクリプトここから
# encoding: Windows-31J
require "wrdap"
# markdownの原稿
mkd_str = <<EOS1
平成26年7月15日\n
佐々木 太郎 様\n
森田 三郎\n
\n
拝 啓\n
時下ますますご清栄のこととお慶び申し上げます。\n
過日は弊社の○○プロジェクト事業の打ち合わせ会議にご出席いただき\
ありがとうございました。\n
おかげさまで滞り亡く会議を取り行うことができ、また、たいへん\
実りあるご意見を参加者の皆様からいただくことができました。\n
会議で賜ったご意見・ご指摘を踏まえながら、更に事業を進める所存です。\n
今後ともご支援・ご鞭撻のほどよろしくお願い申し上げます。\n
まずはお礼のみにて失礼いたします。\n
敬 具\n
EOS1
# pandocによるmarkdown→docxの変換
docx_file = "test05.docx"
docx_str = Wrd::pandoc_docx(mkd_str)
File.open(docx_file, "wb") {|ff| ff.write docx_str}
# ページセットアップの情報
setup_str = <<EOS2
用紙の横幅 182
用紙の縦の長さ 257
EOS2
# ワード文書の調整(中央揃え・右揃えの実行)
ps_ary = nil
Wrdap.new(docx_file) do |doc|
doc.ps(setup_str)
ps_ary = doc.psi()
doc.save
end
puts "☆ ページセットアップの情報"
ps_ary[0].each do |key, val|
printf("%s\t%s\n", key, val)
end
−−−−−−−− スクリプトここまで
上のスクリプトに psi() というメソッドが出てきます。これは page_setup_info() の省略名で、ページの大きさなどの情報を取得するためのメソッドです。ps() が設定するためのものなのに対し、こちらは情報を取得します。
その戻り値は Hash です、といいたいところですが、実は Hash から構成される配列が戻り値です。
ワード文書は、たまに複数のセクションから構成されていることがあります。例えば、最初のページが表紙で、2ページ以降が本文だった場合、表紙を第1セクション、2ページ目以降を第2セクションに設定することができます。
そのようにセクションを分けておくと、第1セクションにはページ番号を付けず、第2セクションだけ番号を付けるといったことができます。1行当たりの文字数と1ページ当たりの行数をセクションごとに別々に設定することも可能です。
多くの場合、1つのワード文書には1つのセクションしかないと思いますが、複数のセクションがあるケースを考慮して、psi() の戻り値は配列にしてあります。
「それなら ps() の方はセクションに対応してなくてもいいのか?」と疑問に思われるかもしれません。実は ps() の方もセクションに対応していて、「doc.ps(str, 2, 3)」のように、第2引数以降にセクション番号を指定できます。セクション番号を指定しない時は、すべてのセクションが指定されたものとみなされます。
これまで、中央揃えや右揃え、それから、ページの大きさなどの設定について述べました。この2種類の設定は、VBAの仕組みに即していうと別々に行います。
しかし、実際の文書処理では別々に扱うのが面倒です。中央揃えや右揃え、あるいは、ページの大きさなどに関する情報を1つのファイルに記述しておいて、それに基づいて処理できるようにした方が便利です。
例えば、markdownの原稿を test.md、その文書設定情報を test.inf に記述しておきます。この2つのファイルを基にしてワード文書の作成・設定が簡単に行えるメソッドがあると便利です。
そのようなコンセプトで設けたのが set_info() メソッドです。また、ワード文書の情報を取得するためのメソッドとして get_info() を設けました。set_info() を呼び出すと、その中で get_info() が呼び出されるので実際にはあまり使わないかもしれません。
ともあれサンプルスクリプトを掲げてみます。同梱の test06.md, test06.inf の2つを読み取って、test06.docx を作ります。pandocによりmarkdownの原稿をワード文書に変換した後に、ワードを起動して調整します。用紙サイズをA5横長(縦長ではない)にし、ページ番号を付け、中央揃えなどの処理を施します。
そのほか、標準フォントサイズを 10.5 ポイントにし、表の罫線を細い実線にします。pandocで生成したワード文書は、標準フォントサイズが12ポイント、表の罫線は外枠が点線(内線は細い実線)になっていると思いますが、それらを調整します。
−−−−−−−− test06.rb スクリプトここから
# encoding: Windows-31J
require "wrdap"
# pandocにより、markdown→Word変換
src_file = "test06.md"
filename = "test06.docx"
mkd_str = File.read(src_file)
docx_str = Wrd::pandoc_docx(mkd_str)
File.open(filename, "wb") {|ff| ff.write docx_str}
# ワード文書の調整
info_file = "test06.inf"
adjust_msg = info_msg = get_msg = nil
table_count = 0
wrd = Wrdap.new
wrd.opens(filename) do |doc|
info_msg, adjust_msg, get_msg = doc.set_info(info_file)
table_count = doc.table_border() # 表の罫線を調整
if info_msg or adjust_msg or table_count > 0
doc.save
end
end
if info_msg.to_s != ''
puts "* 設定した項目"
print info_msg
printf("\n")
end
if get_msg.to_s != ''
puts "* 文書情報"
print get_msg
printf("\n")
end
if table_count > 0
printf("* 表の罫線: %d個の表の罫線を細い実線にしました.\n\n",
table_count)
end
if adjust_msg.to_s != ''
print adjust_msg
printf("\n")
end
−−−−−−−− スクリプトここまで
set_info() は、与えられた引数(ファイル名または文字列)に従ってワード文書を調整・設定します。
その戻り値は、3つの要素からなる配列です。3つの要素はいずれも文字列で、1) 調整・設定した事項に関する情報、2) 中央揃えなどの段落指定と配置指示の情報、3) ページセットアップに関する情報です。3番目は get_info() の戻り値です。
戻り値の1番目と2番目は、場合によっては nil かもしれません。調整・設定が行われなかった場合、中央揃えなどの配置指示の調整が行われなかった場合は、該当の要素が文字列ではなく nil になります。
set_info() における段落指定と配置指示の書き方は pa() のところで述べたのと同じです。
それ以外に調整・設定できる事項を掲げておきます。VBAでいうところのページセットアップ以外に、ページ番号と標準フォントに関する記述があります。
(a) set_info() で調整・設定できる事項
set_info() で調整・設定できる事項を列記しておきます。
各々の事項の値は、pandocでワード文書を生成した時の値です。その右側の括弧内は Word2010のデフォルト値。pandocとの違いのあるもののみ記します。
(b) ページ番号
「ページ番号」は、set_info() に引き渡す時に「フッターにあり」あるいは「あり」とすると、フッターに中央揃えの形で付加されます。
それ以外の形でページ番号を付けたい時は「なし」にしておいて、別途、自前でVBAに即したプログラムを記述して下さい。
(c) 標準フォント
「標準日本語フォント」としては、MS 明朝、MS P明朝、MS ゴシック、MS Pゴシックなどを指定できます。
「標準欧文フォント」は、Calibri、Century、Arial、Times New Roman、Tahoma などです。
「標準フォントサイズ」は、ポイントで指定します。ワード文書のデフォルトは 10.5 になるようです。pandocで生成したワード文書は 12.0。
(d) 総ページ数など
上に掲げた情報以外に、get_info() の戻り値には次の情報が含まれています。
これらは設定可能なものではなく、情報として示されるだけです。
「総ページ数」と「最終ページ番号」は、通常は一致すると思いますが、ワード文諸の表紙を第1セクション、本文を第2セクションに設定して、第2の方だけにページ番号をつけている場合は違ってきます。
「最終ページの行数」が1とか2だと、最後のページにほとんど書き込みがないことを意味しますから、あれこれ調整し直して、ページ数を減らすようにするか、最終ページの行数がもっと多くなるように設定し直す、ということになるでしょうか。
なお、この「最終ページの行数」は、画像を考慮して算出されるものではありません。文字の部分だけに着目して算出されるもののようです。
例えば、1ページ36行の文書の最後のところに画像があるとします。この場合に「最終ページの行数」が8行と出たとしても、ページの下の方が28行分だけ大きく空いているというわけではありません。画像があるためページ内に文字を書き込む余裕はほとんどない、ということかもしれません。グラフなどの画像を貼り付けている時は、この点に注意して下さい。
表の罫線を変更したり、表の第1行目の各セルの文字配置を変更するメソッドがあります。それらについて記します。
(a) 表の罫線を調整する table_border()
test06.rb に出てくる table_border() は、表の罫線を細い実線に調整するメソッドです。ワード文書中にある表をすべて同じように処理します。
戻り値は、処理した表の個数です。文書中に表がなければ 0 を返します。
罫線の種類や太さを引数で指定することができます。例えば、内線をなしにして、外枠だけを引く場合は次のとおり。
count = doc.table_border(WdLineStyleNone,
WdLineStyleSingle, WdLineWidth150pt)
上の第1引数は内線の種類(罫線なし)、第2引数が外枠の種類(細線)、第3引数は外枠の太さ(1.5ポイント)を指定するものです。
このメソッドでは内線の太さを指定できません。また、罫線の色を指定することもできません。そうした細かな設定を行いたい時は、自前でVBA風の記述を行って下さい。
罫線の種類は多数ありますが、代表的なもの4つを上げると次のとおり。
罫線の太さを指定するための定数 WdLineWidth150pt の「150」のところは、自由に書けるわけではありません。
025, 050, 075, 100, 150, 225, 300 などです。025が0.25ポイント、300は3.0ポイントです。
table_border() の引数を省略したりnilを指定した時は、内線が 0.5ポイントの細線、外枠は 0.75ポイントの細線になります。
その他、table_border() では、第4引数以降に対象とする表の番号を指定することができます。
doc.table_border(nil, nil, nil, 3, 4)
上は、3番目と4番目の表だけを調整するとの意味になります。表の番号は、必要なだけカンマで区切って列記できます。
第4引数以降がなければ、すべての表を対象にして罫線の調整を行います。
(b) 表の見出しを均等割り付けなどにする table_row(), table_col()
test06.mdには「|都道府県|人口|面積|人口密度」という行が出てきます。これは表の見出しです。
その次の行が「|:--|--:|--:|--:」となっているため、一番左の欄は左詰めですが、それより右の欄は右詰めになります(‘:’の位置に注目)。
しかし、表の本体に出てくる数値の欄は右詰めでいいとしても、見出しは右詰めでなく均等割り付けの方が自然だと思います。
そこで、test06.infではこれら表の見出しを均等割り付けにするための記述を入れてあります。
表の各々の欄は、それぞれ一つの段落(Paragraph)です。都道府県、人口、面積、人口密度がそれぞれ一つの段落です。その各々を distribute に指定すれば均等割り付けにするになります。
実は、wrdapでは table_row() というメソッドを設けてあります。これを使うと、簡単に表の見出しを均等割り付けにすることができます。
都道府県、人口、面積、人口密度の各々について distribute を指定しなくても、下のように書くと、文書中のすべての表の第1行目が均等割り付けになります。
doc.table_row("distribute")
”distribute” のところを “center” にすれば、均等割り付けでなく中央揃えになります。
また、文書中の2番目と3番目の表だけ、第1行目を均等割り付けにしたい時は、次のように書きます。
doc.table_row("distribute", 2, 3)
第2引数以降がなければ、つまり引数が1つだけであれば、すべての表について第1行目の調整を行います。
それから、第1行目でなく、第1列目(最も左の列)だけを均等割り付けなどにしたい時は、table_col() を用います。使い方は table_row() と同じです。
doc.table_col("distribute")
doc.table_col("center", 2, 3)
上のように記述します。
(c) 表を中央揃えにする table_center()
markdownで表を作った場合、その表は、ページの中で左寄せに配置されています。
その表をページの中央に配置したいことがあります。そんな時に table_center() を用います。
doc.table_center()
上のように引数を与えずに呼び出すと、文書中のすべての表を中央揃えにします。
doc.table_center(1, 2)
上のように引数を指定すると、1番目と2番目の表のみ中央揃えにします。
(d) 表の各セルの値を文字列で取得する table_ary()
ワード文書中の表をcsvとして書き出したいような場合、table_ary() を用います。
これは、表の各セルの値を文字列で取得するメソッドです。1つの表が1つの2次元配列になって返ってきます。
ワード文書中には表が複数含まれているかもしれないので、table_ary() の戻り値は、2次元配列を1つ以上含む配列、つまり3次元配列の形になっています。
tbls = doc.table_ary()
count = 0
tbls.each do |tbl|
count += 1
csv_file = sprintf("file%02d.csv", count)
File.open(csv_file, "w") {|ff| ff.print Wrd::ary2str(tbl, ",")}
end
上のようにすると、ワード文書中の表をすべてcsvとして書き出すことができます。
Wrd::ary2str() というのは、rubyの配列をカンマ区切りなどの文字列に変換するメソッドです。wrdap.rbの中で定義されています。
1番目の表だけを対象にしたい時は、table_ary(1) のように引数を指定します。引数は、カンマで区切って複数指定できます。
1つの表だけを対象にした場合も、戻り値は3次元配列です。2次元配列ではありません。
(e) 表の段落番号を取得するための table_para()
表が、ワード文書中において、何段落目から何段落目までを占めるか知りたいことがあります。
表の各々のセルは、基本的に、それぞれ1つの段落(Paragraph)になっています。なので、3×3の表は、少なくとも9つの段落から構成されることになります。
「少なくとも」というのは、実は、最も右側にダミーの空の列が置かれて、3×4列=12個の段落になることがあります。
それはともかく、表の段落番号をチェックしたい時は table_para() を用います。
ary = doc.table_para()
上のように書くと、ワード文書中のすべての表について、その段落番号を取得できます。
戻り値 ary が [[11, 12, 13, 14]] であれば、表の段落番号が11〜14であることが分かります。また、文書中に含まれる表が1つだけであることも分かります。
table_para(2, 3) のように引数を指定すると、2番目の表、3番目の表について段落番号を得ることになります。
ワードとpandocの組み合わせについて、補足的な事柄を記します。また、ワードとエクセルなどのコンビネーションの例も取り上げます。
簡単な数式とグラフを文書に挿入するサンプルを掲げます。
ワードは起動しません。pandocで変換するだけです。
pandocで変換するmarkdownの記法として、数式の挿入方法にはいくつかの種類があるようですが、ここでは数式を ‘$$’ で囲む形にしています。
数式そのものの書き方は、TeXに即したものです(そんなふうに断言していいかどうか、ほんとは自信ありませんが)。例えば、分数の「2分の1」を「\frac{1}{2}」と書きます。
画像は、「![放物線のグラフ](test.png)」のように書きます。今回は、予め作っておいた test07.png(放物線のグラフ)を挿入します。
以下にサンプルを示します。
−−−−−−−− test07.rb スクリプトここから
# encoding: Windows-31J
require "wrdap"
## markdown→docx変換
filename = "test07.docx"
mkd_str = eval(DATA.read)
docx_str = Wrd::pandoc_docx(mkd_str)
File.open(filename, "wb") {|ff| ff.write docx_str}
# markdownの原稿
__END__
<<EOS
# 数式とグラフの表示\n
◇ 分数の計算:
$$ \\frac{1}{2} + \\frac{1}{3} = \\frac{3 + 2}{6} = \\frac{5}{6} $$\n
◇ 相加平均の計算:
$$ μ = \\frac{1}{n}\\sum_{i=1}^{n} x_i = \\frac{x_1 + x_2 + \\cdots + x_n}{n} $$\n
◇ 放物線のグラフ:
![放物線のグラフ](test07.png)
EOS
−−−−−−−− スクリプトここまで
参考まで、スタンドアロンのhtmlを生成するスクリプトも掲げておきます。
MathJax形式ではなく、MathML形式です。pandocがヘッダに小さいJavaScriptを挿入してくれるようです。
MathJax形式で出力するサンプルは、ここには掲げませんが、付属のzip圧縮ファイルに test07_3.rb として同梱しておきます。インターネットエクスプローラ対応にするためのmeta記述をhtmlのヘッダに挿入するので、少し長くなっています。
−−−−−−−− test07_2.rb スクリプトここから
# encoding: Windows-31J
require "wrdap"
## markdown→html変換
filename = "test07_2.htm"
mkd_str = eval(DATA.read)
html_str = Wrd::pandoc_html(mkd_str, :s, :mathml)
File.open(filename, "w") {|ff| ff.write html_str}
# markdownの原稿
[以下、test07.rb と同じなので省略]
−−−−−−−− スクリプトここまで
[参考] 数式の書き方
TeXの記法に即した数式の書き方については、いろいろな解説サイトがありますが、例えば、次のところが参考になります。
ワードでの数式入力の方法については、次のようなpdfの解説ドキュメントがあります。
markdownの原稿を作る場合、そこに盛り込む表のデータがcsvになっていたり、rubyの配列だったりすることがあります。
そこで、rubyの配列をmarkdownの表として書き出すためのメソッドを用意しました。Wrdというモジュールの中で定義しています。
まず、csv(文字列)をrubyの配列に変換するメソッド「Wrd::str2ary(str, “,”)」というのがあります。第2引数はフィールドセパレータ(区切り文字)です。
そして、markdownの表を生成するメソッドとしては次の2つがあります。
○ pipe_table(ary): rubyの配列をパイプテーブル(縦線形式のmarkdownの表)に変換します。別名 matrix2table()。
「|項目1|項目2|項目3|」のような行を何行か列べる形式の表です。
第2行目を「|:---|--:--|---:|」とすれば(コロン記号の位置に着目)、第1列目を左揃え、2列目を中央揃え、3列目を右揃えにすることができます。
○ ascii_table(ary): rubyの配列をアスキー文字罫線の表に変換します。別名 text_table()。
rubyライブラリの terminal-table を利用するので、予めインストールしておく必要があります(gemでインストール可能)。
アスキー文字のプラス、マイナス、縦線の記号を罫線に見立てる形の表で、pandocでは「グリッドテーブル」といいます。この場合、1つのセルの中に箇条書きやコードブロックなどを盛り込むことができます。
それぞれのメソッドの仕様については wrdap_methods を参照して下さい。
これらメソッドを利用する例として test08.rb を掲げます。
ちなみに、pandocでは、基本的にmarkdownの原稿中に出てくる行末の改行を無視します。なので、段落と段落の間には空白行を置かなければなりません。そうしないと、行がつながってしまいます。
ただし、改行コードの直前に半角スペース2個、または、半角の ‘\’ があると、そこで行分割されます。つまり改行されます。
表の1つのセル内に複数行を書き込む時は、行末の半角スペースが意味をなさなくなるので、行末に ‘\’ を置く記法にする必要があります。test08.rb にはその書き方を採用している箇所があります。
以下、サンプルスクリプトです。test08.csvを読み込んで処理します。
−−−−−−−− test08.rb スクリプトここから
# encoding: Windows-31J
require "wrdap"
# ↓ 第1の表のデータを取り込む
csv_str = File.read("test08.csv")
ary = Wrd::str2ary(csv_str, ",") # csv → 配列
ncol = ary[0].size # 表の列数
sepc = ["---"] + ["--:"]*(ncol-1) # 見出しと本体の区切り。2列目以降は右寄せ
tbl1 = Wrd::pipe_table(ary, sepc) # パイプテーブルの生成
# ↓ 第2の表のデータを取り込む
csv_str = <<EOS1
分類,品名
果物類,"- リンゴ5個
- バナナ4本"
野菜類,"- タマネギ4個
- 大根1本"
その他,"肉と魚は\\
店頭価格により\\
適当に判断"
EOS1
csv_str = csv_str.gsub(/\n +/, "\n") # 余計な空白を除去
ary = Wrd::str2ary(csv_str, ",") # csv → 配列
tbl2 = Wrd::ascii_table(ary, '=', 1) # アスキー文字罫線の表を生成
# ↓ markdownの原稿を生成
mkd_str = <<EOS2
# 種類別身体障害者数の推移\n
18歳以上の在宅身体障害者の人数を示す。単位:千人。\n
#{tbl1}
資料:厚生労働省「身体障害児・者実態調査」\n
----------------\n
# 買い物リスト\n
表を表示するためのテストページ.\n
表の1つのセル内に、箇条書き、複数行を書き込む例.\n
#{tbl2}
EOS2
File.open("test08.md", "w") {|ff| ff.print mkd_str}
# ↓ pandocによりワード文書生成
docx_str = Wrd::pandoc_docx(mkd_str)
File.open("test08.docx", "wb") {|ff| ff.print docx_str}
# ↓ ワードを起動して表を調整
Wrdap.new("test08.docx") do |doc|
doc.std_font("MS 明朝", "Century", 10.5) # 標準フォント設定
doc.table_border() # 表の罫線を細い実線にする
doc.table_row("distribute") # 表の1行目を均等割り付けにする
doc.table_col("distribute") # 表の1列目を均等割り付けにする
doc.table_center(1) # 第1表を中央揃えにする
doc.save # 文書を保存
end
−−−−−−−− test08.rb スクリプトここまで
std_font() は、標準フォントを設定するためのメソッドです。和文フォント、欧文フォント、サイズの3つを設定できます。
日本語のワードで用いられている「MS 明朝」, 「Century」, 10.5ポイントに設定しています。
既に触れた set_info() でもこれらを設定できますが、標準フォントだけの設定であれば、この std_font() を利用できます。
ワードとエクセルのデータのやりとりの例として、ワード文書内の表(table)をエクセルに書き出すサンプルを掲げます。クリップボードを経由してデータを送ります。
エクセルの処理については拙作 exlap を利用します。下からダウンロード&インストールして下さい。
下のサンプルは、カレントディレクトリの *.doc, *.docx, *.docm などを対象に処理します。
test.doc の表は test.doc.xls として書き出します。
1つの表をエクセルの1つのワークシートに書き出します。ワード文書中に複数の表があってもかまいません。それぞれを別々のワークシートに書き出します。
−−−−−−−− test09.rb スクリプトここから
# encoding: Windows-31J
require "exlap"
require "wrdap"
wrd = Wrdap.new # Wordの起動
sleep(0.2)
xl = Exlap.new # Excelの起動
xl.CutCopyMode = false # クリップボードのcopy,pasteを無効化(念のため)
Dir.glob("./*.doc\0./*.doc?") do |word_file| # ワード文書を1つづつ処理
excel_file = word_file + ".xls"
if test(?e, excel_file) # excel_fileが既に存在する時は削除
File.unlink(excel_file)
end
wb = xl.book_open(excel_file) # ワークブックを開く
doc = wrd.doc_open(word_file) # ワードファイルを開く
count = 0 # 表の数をカウント
doc.Content.Tables.each do |tbl| # 表を1つづつ確認
count += 1
ss = wb.fes # 空のワークシートを選択
ss.Activate
tbl.Range.Copy # ワードの表をクリップボードにコピー
ss.Range("A1").Select # ワークシートでの書き出しの始点を選択
ss.Paste # クリップボードから貼り付け
xl.CutCopyMode = false # クリップボードのcopy,pasteを無効化
ss.range_autofit # セル幅の自動調整
end
doc.close
if count >= 1 # 表の書き込みを1回以上 行った
wb.ss(1).Activate
wb.save # ワークブックの保存
end
wb.close
end
xl.quit # Excelの終了
wrd.quit # ワードの終了
−−−−−−−− スクリプトここまで
エクセルの制御に関する詳細は省きます。
上は、単純にクリップボードにコピーしたり貼り付けたりしているだけなので、ワード側の罫線やフォントがエクセル側に引き継がれると思います。完全ではないかもしれませんが。
〜 以上 〜
Copyright (C) T. Yoshiizumi, 2013-2014 All rights reserved.