Files
script_dev/makeFomat.py

133 lines
4.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
import json
import re
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter
PAT_H = re.compile(r'^\{\{([A-Za-z0-9_\.]+)\[\]\}\}$') # {{key[]}}
PAT_V = re.compile(r'^\{\{([A-Za-z0-9_\.]+)\[\]\[\]\}\}$') # {{key[][]}}
PAT_S = re.compile(r'^\{\{([A-Za-z0-9_\.]+)\}\}$') # {{key}}
def excel_col_width_to_px(width_char):
if width_char is None:
width_char = 8.43
return int(round(width_char * 7))
def excel_row_height_to_px(height_pt):
if height_pt is None:
height_pt = 15.0
return int(round(height_pt * 96 / 72))
def export_schema_from_excel(xlsx_path: str, sheet_name: str | None, out_json: str = "schema.json"):
wb = load_workbook(xlsx_path, data_only=True)
ws = wb[sheet_name] if sheet_name else wb.active
# 使用範囲
dim = ws.calculate_dimension()
from openpyxl.worksheet.dimensions import SheetDimension
dims = SheetDimension(dim)
min_col, min_row, max_col, max_row = dims.min_col, dims.min_row, dims.max_col, dims.max_row
cols_px = []
for c in range(min_col, max_col+1):
width_char = ws.column_dimensions[get_column_letter(c)].width
cols_px.append(excel_col_width_to_px(width_char))
rows_px = []
for r in range(min_row, max_row+1):
height_pt = ws.row_dimensions[r].height
rows_px.append(excel_row_height_to_px(height_pt))
# 結合セル
covered = set()
merged_top = {}
for mr in ws.merged_cells.ranges:
r0, r1 = mr.min_row, mr.max_row
c0, c1 = mr.min_col, mr.max_col
merged_top[(r0, c0)] = {"rowspan": r1 - r0 + 1, "colspan": c1 - c0 + 1}
for rr in range(r0, r1+1):
for cc in range(c0, c1+1):
if not (rr == r0 and cc == c0):
covered.add((rr, cc))
cells = []
for r in range(min_row, max_row+1):
for c in range(min_col, max_col+1):
if (r, c) in covered:
continue
cell = ws.cell(row=r, column=c)
raw = cell.value
s = str(raw) if raw is not None else ""
entry = {
"r": r - min_row + 1,
"c": c - min_col + 1,
"rowspan": 1,
"colspan": 1,
"style": {},
"type": "text", # 既定はラベル/テキスト
}
if (r, c) in merged_top:
entry["rowspan"] = merged_top[(r, c)]["rowspan"]
entry["colspan"] = merged_top[(r, c)]["colspan"]
# スタイル(簡易)
if cell.font and cell.font.bold:
entry["style"]["bold"] = True
hal = cell.alignment.horizontal
if hal:
entry["style"]["align_h"] = hal
val = cell.alignment.vertical
if val:
entry["style"]["align_v"] = val
if cell.alignment.wrap_text:
entry["style"]["wrap"] = True
# マーカー判定
m = PAT_H.match(s)
if m:
entry["type"] = "repeat_h"
entry["repeat"] = {"key": m.group(1)}
cells.append(entry)
continue
m = PAT_V.match(s)
if m:
entry["type"] = "repeat_v"
entry["repeat"] = {"key": m.group(1)}
cells.append(entry)
continue
m = PAT_S.match(s)
if m:
entry["type"] = "value"
entry["key"] = m.group(1)
entry["label"] = None
else:
entry["label"] = s # ラベル扱い
cells.append(entry)
schema = {
"page": {"size": "A4", "margin_mm": 12},
"cols": cols_px,
"rows": rows_px,
"cells": cells,
# リピータの既定動作(必要に応じて上書き可能)
"repeat_defaults": {
"gap_px": 0, # 項目間の隙間(横/縦)
"border": None, # 項目間の区切り線
"item_wrap": True, # 項目内の折り返し
"max_cols": None # 横方向の最大列数Noneなら均等に1行で詰める
}
}
with open(out_json, "w", encoding="utf-8") as f:
json.dump(schema, f, ensure_ascii=False, indent=2)
print(f"書き出し: {out_json}")
if __name__ == "__main__":
export_schema_from_excel("form.xlsx", sheet_name="A4_帳票", out_json="schema.json")