スクリプトファイルを追加

This commit is contained in:
2026-04-03 18:22:33 +09:00
commit 809d3bc3e4
14 changed files with 1956 additions and 0 deletions

132
makeFomat.py Normal file
View File

@@ -0,0 +1,132 @@
# -*- 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")