「明智光秀放浪記」
白泉社 (2019-12-26)
売り上げランキング: 2,093
マンガ「信長の忍び」のスピンオフで、明智光秀がだいたい信長に仕えるまでの物語。「軍師 黒田官兵衛伝」ではすでに本能寺の変が描かれ、「信長の忍び」では謀反に向かう底流として家族や家臣が路頭に迷うことへの光秀の恐怖が描かれている。そうした源流として本書は、家族思いで家臣思いの面を中心にしたストーリーとなっている。
しかし、本書と直接関係ないけど、光秀の前半生は謎が多く、しかも本能寺の変は諸説が百出しているので、大河ドラマ「麒麟がくる」は大変だろうなあ。どう描いても「(私の中の)本当と違う!」と言う人がいそう。
「大江戸ミッション・インポッシブル 顔役を消せ」「大江戸ミッション・インポッシブル 幽霊船を奪え」
講談社 (2019-11-14)
売り上げランキング: 123,506
講談社 (2019-12-13)
売り上げランキング: 134,007
山田正紀氏はメジャーデビュー作「神狩り」の頃から、「謎の提示がうまい」「登場するキャラがみな立ってる」「その2つをもとにどんどんストーリーが転がっていく」「ただし風呂敷は畳まない」という特徴があると思う。このへんは好き嫌いの分かれるところで、私は好きだけど。
エンターテイメント時代劇小説の本作(2冊で完結)もそんな感じで、江戸の闇を統べる川衆と陸衆の争いを中心に、個性的な登場人物が登場するのが特徴だ。「顔役を消せ」のほうは題名どおりミッションもの展開になるんだけど、「幽霊船を奪え」のほうはまあ幽霊船があまり重要じゃないなあとか。
必殺シリーズとか「サイコ」とか過去の有名作品のオマージュがいろいろ。“かま”の笑い方と飄々として謎めいたキャラは、ちょっと「まほろ」の行天っぽい。だいぶ剣呑だけど。
台割のExcelファイルをRubyで自動生成する方法の入口
このエントリーは「書き手と編み手の Advent Calendar 2019」の12月4日分の記事です。
紙の書籍を編集や制作した経験のある人にとって、台割はおなじみのものです。なお、ここでは台割とは何かについては省略します。
自分の見てきたIT系出版の世界では、台割をExcelで作ることが多いようです。台割では、最初のほうの章のページ数が変わったりすると、それ以降をずらす必要があって大変です。そのため、Excelのマクロなどを使って自動化する人もけっこういるのではないかと思います。
ここでは、Ruby言語のコードを使って台割のExcelファイル(.xlsxファイル)を生成するのを目標に、その方法の入口を解説します。あくまで入口であって、台割が完成するところまでは説明しません。
つまりは、「ただツールやライブラリの使い方を紹介するだけ」のエントリーってやつです。
注意
- 対象は広義の平綴じ(無線綴じなどを含む、中綴じでない書籍)用の台割です
- Ruby言語の解説は割愛します
- Ruby処理系やライブラリのインストール方法にまつわることについても割愛します
ステップ0:axlsxをインストールする
Rubyで.xlsxファイルを生成するには、axlsxというライブラリを使うと便利です。
gemやbundleなどで「axlx」をインストールします。ただし、執筆時点では、axlsxのリリース版だと最近のRubyでは警告が出るので、「3.0.0.pre」版を指定してインストールします。
$ gem install axlsx -v 3.0.0.pre
axslxはnokogiriというライブラリに依存しているので、それまでにインストールされていなければいっしょにインストールされます。
なお、axlsxからフォークしたaxlsx-altというライブラリもあるようですが、私は未評価です。
ステップ1:空の.xlsxファイルを出力する
とりあえず、何もせずに空の.xlsxファイルを出力してみます。以下のような内容のsample.rbファイルを作ります。
require 'axlsx'
Axlsx::Package.new do |pkg|
pkg.serialize('out.xlsx')
end
Axlsx::Package#serializeがファイル出力です。
これを実行すると、out.xlsxというファイル名の、何も書かれていない.xlsxファイルが作られます。
$ ruby sample.rb
ステップ2:1行書き込む
out.xlsxを出力するプログラムに、表に1行を追加するコードを追加します。
require 'axlsx'
Axlsx::Package.new do |pkg|
wb = pkg.workbook
wb.add_worksheet(name: 'シート1') do |sheet|
sheet.add_row(['折', '通', nil])
end
pkg.serialize('out.xlsx')
end
Axlsx::Package#workbookでExcelのブックを取得し、そのブックのadd_worksheetでExcelの(ワーク)シートを作成します。そして、そのシートのadd_rowで“折”と“通”と空の3つのセルがある行を追加します。
生成されたExcelファイルは、こんな感じです。
ステップ3:列幅を指定する
このままでは、どの列も同じデフォルトの幅なので、列幅を変更します。各列の幅は、シートのcolumn_widthsで指定します。
sheet.column_widths(4, 4, 20)
column_widthを呼び出すのは、add_rowより後のほうがいいようです。追加後のコードは以下のとおりです。
require 'axlsx'
Axlsx::Package.new do |pkg|
wb = pkg.workbook
wb.add_worksheet(name: 'シート1') do |sheet|
sheet.add_row(['折', '通', nil])
sheet.column_widths(4, 4, 20)
end
pkg.serialize('out.xlsx')
end
生成されたExcelファイルは、こんな感じです。
ステップ4:セルのスタイルを指定する
ここまでで書き込んでいる1行は、表のタイトル行にします。そのため、文字は太字で、セルは罫線で囲んだものにします。
まず、ブックに対してスタイルを定義します。ここでは、表の通常行でも使うように、罫線の形式を指定するHashを変数bordersで参照できるようにしておきます。
styles = wb.styles
borders = { style: :thin, color: '000000' }
title_style = styles.add_style(b: true, border: borders)
add_rowを記述を変更して、定義したスタイルの指定を追加します。
sheet.add_row(['折', '通', nil], style: title_style)
これらを反映したコードは以下のとおりです。
require 'axlsx'
Axlsx::Package.new do |pkg|
wb = pkg.workbook
styles = wb.styles
borders = { style: :thin, color: '000000' }
title_style = styles.add_style(b: true, border: borders)
wb.add_worksheet(name: 'シート1') do |sheet|
sheet.add_row(['折', '通', nil], style: title_style)
sheet.column_widths(4, 4, 20)
end
pkg.serialize('out.xlsx')
end
生成されたExcelファイルは、こんな感じです。
ステップ5:通常行を追加する
タイトル行だけでなく通常行も追加しましょう。
まず通常行のスタイル定義を追加します。
body_style = styles.add_style(alignment: { vertical: :top }, border: borders)
タイトル行の定義から太字指定を抜いて、垂直位置の指定を追加したものです。
通常行もadd_rowで追加します。実用性はありませんが、ここでは内容は決めうちで。
sheet.add_row([1, 1, '本扉'], style: body_style)
sheet.add_row([1, 2, '商標'], style: body_style)
sheet.add_row([1, 3, '前書き'], style: body_style)
sheet.add_row([1, 4, nil], style: body_style)
sheet.add_row([1, 5, nil], style: body_style)
sheet.add_row([1, 6, '目次'], style: body_style)
sheet.add_row([1, 7, nil], style: body_style)
sheet.add_row([1, 8, nil], style: body_style)
sheet.add_row([1, 9, nil], style: body_style)
sheet.add_row([1, 10, nil], style: body_style)
sheet.add_row([1, 11, '1章'], style: body_style)
sheet.add_row([1, 12, nil], style: body_style)
sheet.add_row([1, 13, nil], style: body_style)
sheet.add_row([1, 14, nil], style: body_style)
sheet.add_row([1, 15, nil], style: body_style)
sheet.add_row([1, 16, nil], style: body_style)
これらを追加したコードは以下のとおりです。
require 'axlsx'
Axlsx::Package.new do |pkg|
wb = pkg.workbook
styles = wb.styles
borders = { style: :thin, color: '000000' }
title_style = styles.add_style(b: true, border: borders)
body_style = styles.add_style(alignment: { vertical: :top }, border: borders)
wb.add_worksheet(name: 'シート1') do |sheet|
sheet.add_row(['折', '通', nil], style: title_style)
sheet.add_row([1, 1, '本扉'], style: body_style)
sheet.add_row([1, 2, '商標'], style: body_style)
sheet.add_row([1, 3, '前書き'], style: body_style)
sheet.add_row([1, 4, nil], style: body_style)
sheet.add_row([1, 5, nil], style: body_style)
sheet.add_row([1, 6, '目次'], style: body_style)
sheet.add_row([1, 7, nil], style: body_style)
sheet.add_row([1, 8, nil], style: body_style)
sheet.add_row([1, 9, nil], style: body_style)
sheet.add_row([1, 10, nil], style: body_style)
sheet.add_row([1, 11, '1章'], style: body_style)
sheet.add_row([1, 12, nil], style: body_style)
sheet.add_row([1, 13, nil], style: body_style)
sheet.add_row([1, 14, nil], style: body_style)
sheet.add_row([1, 15, nil], style: body_style)
sheet.add_row([1, 16, nil], style: body_style)
sheet.column_widths(4, 4, 20)
end
pkg.serialize('out.xlsx')
end
生成されたExcelファイルは、こんな感じです。
ステップ6:セルを連結する
折(台)を示すセルは折(台)ごとに共通です。そのため、セルを連結してみます。
シートのmerge_cellsを呼び出します。
sheet.merge_cells('A2:A17')
これらを追加したコードは以下のとおりです。
require 'axlsx'
Axlsx::Package.new do |pkg|
wb = pkg.workbook
styles = wb.styles
borders = { style: :thin, color: '000000' }
title_style = styles.add_style(b: true, border: borders)
body_style = styles.add_style(alignment: { vertical: :top }, border: borders)
wb.add_worksheet(name: 'シート1') do |sheet|
sheet.add_row(['折', '通', nil], style: title_style)
sheet.add_row([1, 1, '本扉'], style: body_style)
sheet.add_row([1, 2, '商標'], style: body_style)
sheet.add_row([1, 3, '前書き'], style: body_style)
sheet.add_row([1, 4, nil], style: body_style)
sheet.add_row([1, 5, nil], style: body_style)
sheet.add_row([1, 6, '目次'], style: body_style)
sheet.add_row([1, 7, nil], style: body_style)
sheet.add_row([1, 8, nil], style: body_style)
sheet.add_row([1, 9, nil], style: body_style)
sheet.add_row([1, 10, nil], style: body_style)
sheet.add_row([1, 11, '1章'], style: body_style)
sheet.add_row([1, 12, nil], style: body_style)
sheet.add_row([1, 13, nil], style: body_style)
sheet.add_row([1, 14, nil], style: body_style)
sheet.add_row([1, 15, nil], style: body_style)
sheet.add_row([1, 16, nil], style: body_style)
sheet.column_widths(4, 4, 20)
sheet.merge_cells('A2:A17')
end
pkg.serialize('out.xlsx')
end
生成されたExcelファイルは、こんな感じです。
その先
このエントリーでは、1折(台)ぶんだけ決めうちで台割を作りました。これだけでは実用性はありませんが、作り方によっていろいろ楽ができるようになります。
たとえば、章とそのページ数を記述したデータを用意して、そこから台割を生成するという応用が考えられます。また、章ごとのPDFファイルからページ数をカウントして台割を生成するという応用も考えられるでしょう。
さらには、文字サイズや表のレイアウト、修飾スタイル、表本体以外の記載事項など、いろいろ工夫できる要素もあります。
このエントリーがそのような自動化のヒントになれば幸いです。