はじめに
draw.ioで作成した図の全ページを一括で画像ファイルに変換する方法をまとめました。
実行環境
- Windows 10 Pro
- バージョン22H2
- drawio-desktop
- v 22.1.2
- Python
- 3.12.0 64bit
実装
ディレクトリ構成
drawioフォルダ内にある.drawio
ファイルからimageフォルダに.svg
を作成します。
出力されるファイル名は{file_name}-{page_name}.svg
になります
./
│ make.py
├─drawio # 入力
│ sample1.drawio
│ sample2.drawio
└─image # 出力
sample1-page-1.svg
sample1-page-2.svg
sample2-page 1.svg
sample2-page 2.svg
コード
from pathlib import Path
import subprocess
import xml.etree.ElementTree as et
DRAWIO_PATH = '"C:\Program Files\draw.io\draw.io.exe"'
ROOT_DIR = Path(__file__).resolve().parent
INPUT_DIR = ROOT_DIR / "drawio"
OUTPUT_DIR = ROOT_DIR / "image"
def generate_image(input_path : Path):
try:
root = et.parse(str(input_path)).getroot()
except et.ParseError:
print(f"Error : Failed to parse XML file {input_path}")
return
# 1ページの場合pagesが存在しないのでデフォルトを1とする。
pages = int(root.get("pages", 1))
for page in range(pages):
page_name = root[page].get("name")
output_file_name = f"{input_path.stem}-{page_name}.svg"
output_path = OUTPUT_DIR / output_file_name
command = f'{DRAWIO_PATH} "{input_path}" -x -f svg -p {page} -o "{output_path}"'
try:
subprocess.run(command, check=True)
except subprocess.CalledProcessError:
print(f'Error : Failed to execute "{command}"')
if __name__ == "__main__":
OUTPUT_DIR.mkdir(exist_ok=True)
for file_path in INPUT_DIR.glob("*.drawio"):
generate_image(file_path)
旧コード
from pathlib import Path
import xml.etree.ElementTree as et
import subprocess
def get_output_path(file_path, page_name, file_type):
stem = '-'.join([str(file_path.stem), page_name])
suffix = '.' + file_type
return file_path.with_name(stem).with_suffix(suffix)
def generate_image(file_path):
DRAWIO = '"C:\Program Files\draw.io\draw.io.exe"'
FILE_TYPE = 'svg'
root = et.parse(file_path).getroot()
for i in range(int(root.get('pages'))):
page_name = root[i].get('name')
# option
f = ' '.join(['-f', FILE_TYPE])
p = ' '.join(['-p', str(i)])
o = ' '.join(['-o', '"' + str(get_output_path(file_path, page_name, FILE_TYPE)) + '"'])
# run
command = ' '.join([DRAWIO, '"' + str(file_path) + '"', '-x', f, p, o])
subprocess.run(command)
if __name__ == '__main__':
root_dir = Path.cwd()
for i in root_dir.glob('image\\*.drawio'):
generate_image(i.relative_to(root_dir))
解説
.drawio
の読み出し
以下のように.drawio
ファイル内にはページ数pages
と各ページの名前name
の情報があります。
これをxml.etree.ElementTree
で読み出してファイル名を生成しています。
<mxfile modified="..." ... pages="3">
<diagram name="page1" id="...">
...
</diagram>
<diagram name="page2" id="...">
...
</diagram>
<diagram name="page3" id="...">
...
</diagram>
</mxfile>
python上ではファイル毎にpages
の数だけ生成処理を行います。
try:
root = et.parse(str(input_path)).getroot()
except et.ParseError:
print(f"Error : Failed to parse XML file {input_path}")
# 1ページの場合pagesが存在しないのでデフォルトを1とする。
pages = int(root.get("pages", 1))
for page in range(pages):
page_name = root[page].get("name")
.drawio
ファイルの各ページの生成方法
drawioをコマンドライン実行する方法はdraw.io をコマンドラインで実行して、画像ファイルをエクスポートするが参考になります。
-p, --page-index <pageIndex>
で指定したページを変換することができます。
-a, --all-pages
はpdf生成のみ対応しているため、画像生成時は使用できないので注意しましょう。
例えば1ページ目を生成する時は以下のようになります。
"C:\Program Files\draw.io\draw.io.exe" "image/sample1.drawio" -x -f svg -p 0 -o "image/sample1-page1.svg"
その他
ファイル名やページ名に空白が含まれる可能性があるため、pathは""
で囲うようにしています。
command = f'{DRAWIO_PATH} "{input_path}" -x -f svg -p {page} -o "{output_path}"'
""
をつけない場合、以下の例ではsample2-page 1.svg
ではなくsample2-page
というファイルが生成されてしまいます。
"C:\Program Files\draw.io\draw.io.exe drawio/sample2.drawio -x -f svg -p 0 -o image/sample2-page 1.svg
参考
drawio-cli
draw.io をコマンドラインで実行して、画像ファイルをエクスポートする
draw.ioの全てのタブを一括で画像出力する
更新履歴
- 2023/12/05
- 機能変更
- 入力と出力のフォルダを分離するように変更
- エラー処理を追加
- バグ修正
- drawioファイル内に1ページしかない場合にエラーになる問題を修正
- その他
- 実行環境を更新
- コード全体を整理
- 機能変更