0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Pandoc】Pandocの `md -> docx` 変換で表の列幅を制御する前処理スクリプトを作った話

0
Posted at

Pandoc で Markdown を Word (.docx) に変換する運用をしているのですが、表の列幅が思った通りにならず、Word 上の見た目が崩れることがありました。

(以下のケースでは、備考列の列幅が小さく、見た目が悪くなっています。)

① Markdown Pipe Table

| 項目 | 値 | 説明 | 備考 |
| -- | --| -- | -- |
| title | 設計書 | 余裕のある列幅を指定したケース。 | ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ |
| owner | 山田太郎 | 文字が短くても列幅はダッシュ数基準となる。 | ああ |
| date | 2026-02-17 | 余白の見え方を確認。 | ああ |

② Pandocによるdocx変換後

image.png

そこで、Markdown のパイプテーブルを Grid Table に自動変換する前処理スクリプトsh/format-grid-table.mjs)を作ってみたところ、かなり安定したので記事にまとめます。

いきなりまとめ

以下リポジトリ内のプログラムをPandocのmd-to-docx変換の前に実行することで変換時の列幅を制御できるようになります。
https://github.com/SKZeeee/conversion-pipe-to-grid.git

【Markdown Pipe Table】

| 項目 | 値 | 説明 | 備考 |
| - | - | -- | -- |
| title | 設計書 | 余裕のある列幅を指定したケース。 | ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ |
| owner | 山田太郎 | 文字が短くても列幅はダッシュ数基準となる。 | ああ |
| date | 2026-02-17 | 余白の見え方を確認。 | ああ |

【前処理なし】

image.png

【前処理あり】

image.png

課題

Pandoc による docx 変換を前提にした Markdown 管理では、通常のパイプテーブルだと列幅の意図を表現しづらいです。

  • 「ID列は狭くてよい」
  • 「説明列は広く取りたい」
  • 「備考列は折り返してよい」

ステップ1. Grid Tableの使用

Pandoc の Grid Table を使うと、列幅を文字数ベースで表現しやすくなります。

例えば以下のような形式です。

+-------------------+-----------------+------------------------------------------------------------+
| 項目              | 値              | 説明                                                       |
+===================+=================+============================================================+
| title             | 設計書          | 標準的な幅指定での変換確認。                               |
+-------------------+-----------------+------------------------------------------------------------+
| owner             | 山田            | 基本的な3列テーブル。                                      |
+-------------------+-----------------+------------------------------------------------------------+
| version           | 1.0             | 初版。                                                     |
+-------------------+-----------------+------------------------------------------------------------+

+---+ の罫線幅とセルの幅で、列幅の意図を Markdown 側に持たせられます。
上記をdocx変換すると、以下のようになります。(Grid Tableの罫線幅の通りに変換されていることが分かると思います。)
image.png

ステップ2. ただし Grid Table を人手で書くのはつらい

Grid Table は便利ですが、日常的に手で書くにはコストが高いです。
※Grid Tableの難解さの詳細は最下部の補足に記載しています。

  • 罫線の長さを毎回そろえる必要がある
  • セル数がずれると壊れる
  • 文章修正のたびに線を引き直す必要がある

つまり最終的な出力には向いているが、入力フォーマットとしてはつらい という状態でした。

ステップ3. パイプテーブルを自動で Grid Table に変換する

そこで、普段は書きやすいパイプテーブルで記述し、Pandoc実行の前処理で Grid Table に変換するスクリプトを作りました。

  • スクリプト: sh/format-grid-table.mjs
  • 入力: Markdown のパイプテーブル
  • 出力: Pandoc 向け Grid Table

変換前(普段書くMarkdown)

区切り行の - の数を「幅のヒント」として使います。-の数に応じてその列の幅を決定されるイメージです。

| ID | 項目 | 説明 |
| - | -- | ---- |
| A-1 | タイトル | これは長めの説明文です。Word上で折り返して表示したい列です。 |
| B-2 | 備考 | この列は可変幅で扱いたいです。 |

変換後(Grid Table)

以下のように自動変換されます(実際に sh/format-grid-table.mjs を実行した結果)。

+-------+--------------------------------+---------------------------------------------------------+
| ID    | 項目                           | 説明                                                    |
+=======+================================+=========================================================+
| A-1   | タイトル                       | これは長めの説明文です。Word上で折り返して表示したい列  |
|       |                                | です。                                                  |
+-------+--------------------------------+---------------------------------------------------------+
| B-2   | 備考                           | この列は可変幅で扱いたいです。                          |
+-------+--------------------------------+---------------------------------------------------------+

ステップ4. - 1個を「固定列」、2個以上を「可変列」にした

最初は「- の数をそのまま列幅比率」にしていましたが、これだと毎回考えるのが面倒でした。実際の文書では次のようなケースが多いです。

  • この列は全行とも1行で見せたい(例: ID, 区分, ステータス)
  • この列は折り返してよい(例: 説明, 備考)

そこでルールを次のようにしました。

  • - が1個の列: 固定列
  • 固定列は「その列の内容が1行で収まる最小幅 + 安全マージン」で確保
  • - が2個以上の列: 可変列
  • 可変列は - の数の比率で余った幅を配分

これで、表を書く側は次のように考えるだけで済みます。

  • | - | を付けた列は「潰したくない」
  • | ---- | を付けた列は「広めに欲しい」

例えば以下のように制御することができます。

①変換処理前Pipe Table形式

| 項目 | 値 | 説明 |
| - | -- | --- |
| title | 設計書 | 列幅を超える長い説明文がセル内改行されることを確認するためのテキスト。 |
| owner | 山田 | 二列目も幅を超える場合に改行されるか確認。 |
| status | draft | 変換ポリシー確認用。 |

②GridTable変換処理後

+----------+----------------------------------+----------------------------------------------------+
| 項目     | 値                               | 説明                                               |
+==========+==================================+====================================================+
| title    | 設計書                           | 列幅を超える長い説明文がセル内改行されることを確認 |
|          |                                  | するためのテキスト。                               |
+----------+----------------------------------+----------------------------------------------------+
| owner    | 山田                             | 二列目も幅を超える場合に改行されるか確認。         |
+----------+----------------------------------+----------------------------------------------------+
| status   | draft                            | 変換ポリシー確認用。                               |
+----------+----------------------------------+----------------------------------------------------+

このように、| - |の列はその列の項目を一行で表示できる最小幅に変換し、残った領域を-2個以上の列で按分します。-2個以上の列については中の文字列に合わせて自動で改行処理が行われます。

③docx出力時

image.png

上記がPandoc変換実行後のdocxファイルですが、見ての通り変換後のGrid Tableの列幅で表示されています。

結果

この前処理を挟むことで、ドキュメント作成者の負担を増やさずに、Word 変換後の見た目を意識した表管理がしやすくなりました。

  • 入力は書きやすいパイプテーブルのまま
  • 出力は Pandoc に優しい Grid Table
  • 列幅の意図を - の数で軽く指定できる

同じように「Markdown 管理はしたいが、最終成果物は Word」という運用の方には、かなり相性が良いと思います。

補足

Grid Table が「人間に優しくない」具体例

例1: セルの文字を少し伸ばしただけで罫線が破綻する

まず、普通の Grid Table はこんな感じです。

+------+------------------+
| ID   | 説明             |
+======+==================+
| A-1  | 短い説明         |
+------+------------------+

ここで、「説明」をちょっとだけ詳しくしたくなって、こう書き換えます。

+------+------------------+
| ID   | 説明             |
+======+==================+
| A-1  | 少し長めの説明文 |
+------+------------------+

すると何が起きるかというと、セルの中身は伸びたのに、罫線の幅はそのままなので、
見た目が崩れたり、Pandoc によっては警告が出たりします。

正しく直すには、こうやって罫線と空白を全部調整し直す必要があります。

+------+----------------------+
| ID   | 説明                 |
+======+======================+
| A-1  | 少し長めの説明文     |
+------+----------------------+

「文章を少し直しただけなのに、表全体の罫線調整が必要」になるのが、まず一つ目のつらさです。

例2: 列を1つ追加しただけで全行に手が入る

次に、列を1つ増やしたくなったケース。

元の表がこれ。

+------+------------------+
| ID   | 説明             |
+======+==================+
| A-1  | 短い説明         |
+------+------------------+
| B-2  | 別の説明         |
+------+------------------+

ここに「備考」列を追加したいとします。
素直にやると、こうなります。

+------+------------------+--------+
| ID   | 説明             | 備考   |
+======+==================+========+
| A-1  | 短い説明         |        |
+------+------------------+--------+
| B-2  | 別の説明         |        |
+------+------------------+--------+

…が、実際には 各列の幅バランスを見直したくなって、結局こうなりがちです。

+------+----------------------+------------+
| ID   | 説明                 | 備考       |
+======+======================+============+
| A-1  | 短い説明             |            |
+------+----------------------+------------+
| B-2  | 別の説明             |            |
+------+----------------------+------------+

つまり、罫線・空白・+, |, = の位置全部の行をまとめて直す羽目になるというやつです。
列を1本足しただけで、差分が地味に地獄になります。

例3: セル内改行を入れると、さらに管理コストが跳ね上がる

説明が長くなって、セル内で折り返したくなった場合。

+------+----------------------+
| ID   | 説明                 |
+======+======================+
| A-1  | これは少し長めの説   |
|      | 明文です。           |
+------+----------------------+

ここで、
① 2行目のインデントを揃える
② 罫線幅とズレないように空白を調整する

といった作業が追加で発生します。

さらに文章を直すと、また全行の空白と罫線を微調整することになります。
もはや「表の中身を書く」より「罫線の整形をする」時間の方が長くなりがちです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?