193 lines
7.0 KiB
Python
193 lines
7.0 KiB
Python
import os
|
|
import json
|
|
import datetime
|
|
import pandas as pd
|
|
import ezodf
|
|
from openpyxl import Workbook
|
|
from openpyxl.utils import get_column_letter
|
|
from openpyxl.styles import Alignment
|
|
import logging
|
|
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
|
|
|
# ---------------- SPOT-Baumstruktur ----------------
|
|
class Node:
|
|
def __init__(self, name, node_type="category", id=None):
|
|
self.name = name
|
|
self.id = id
|
|
self.type = node_type # "category", "subcategory", "word"
|
|
self.children = []
|
|
|
|
def add_child(self, child):
|
|
self.children.append(child)
|
|
|
|
def to_dict(self):
|
|
if self.type == "word":
|
|
return self.name
|
|
return {
|
|
"id": self.id,
|
|
"name": self.name,
|
|
"type": self.type,
|
|
"children": [c.to_dict() for c in self.children]
|
|
}
|
|
|
|
@staticmethod
|
|
def from_dict(d):
|
|
if isinstance(d, str):
|
|
return Node(d, "word")
|
|
node = Node(d["name"], d.get("type", "category"), d.get("id"))
|
|
node.children = [Node.from_dict(c) for c in d.get("children", [])]
|
|
return node
|
|
|
|
# ---------------- Funktionen zum Laden ----------------
|
|
def load_excel_or_ods(input_file, master_sheet="Masterstruktur"):
|
|
ext = os.path.splitext(input_file)[1].lower()
|
|
engine = "openpyxl" if ext in [".xlsx", ".xls"] else "odf"
|
|
xls = pd.ExcelFile(input_file, engine=engine)
|
|
sheet_names = [s for s in xls.sheet_names if s != master_sheet]
|
|
dfs = {s: pd.read_excel(xls, sheet_name=s, engine=engine) for s in sheet_names}
|
|
master_df = pd.read_excel(xls, sheet_name=master_sheet, engine=engine)
|
|
return master_df, dfs
|
|
|
|
# ---------------- Baum aus Sheet erstellen ----------------
|
|
def process_sheet_to_tree(df):
|
|
df = df.fillna("").astype(str)
|
|
tree_nodes = []
|
|
current_cat = None
|
|
current_sub = None
|
|
for idx, row in df.iterrows():
|
|
id_val = row.get("ID", "").strip()
|
|
uk_val = row.get("Unterkategorie", "").strip()
|
|
uuk_val = row.get("Unterunterkategorie", "").strip()
|
|
word_val = row.get("Wort/Vokabel", "").strip()
|
|
|
|
if id_val:
|
|
current_cat = Node(uk_val or word_val, "category", id=id_val)
|
|
tree_nodes.append(current_cat)
|
|
current_sub = None
|
|
elif uuk_val:
|
|
current_sub = Node(uuk_val, "subcategory")
|
|
if current_cat:
|
|
current_cat.add_child(current_sub)
|
|
elif word_val:
|
|
word_node = Node(word_val, "word")
|
|
if current_sub:
|
|
current_sub.add_child(word_node)
|
|
elif current_cat:
|
|
current_cat.add_child(word_node)
|
|
return tree_nodes
|
|
|
|
# ---------------- SPOT laden/speichern ----------------
|
|
def save_spot_json(tree_nodes, file_path):
|
|
with open(file_path, "w", encoding="utf-8") as f:
|
|
json.dump([n.to_dict() for n in tree_nodes], f, indent=2, ensure_ascii=False)
|
|
logging.info(f"SPOT gespeichert: {file_path}")
|
|
|
|
def load_spot_json(file_path):
|
|
with open(file_path, "r", encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
return [Node.from_dict(n) for n in data]
|
|
|
|
# ---------------- Export in Excel ----------------
|
|
def export_spot_to_excel(tree_nodes, output_file):
|
|
wb = Workbook()
|
|
wb.remove(wb.active)
|
|
for node in tree_nodes:
|
|
ws = wb.create_sheet(title=node.name[:31])
|
|
row_idx = 1
|
|
# Kategorie
|
|
ws.cell(row=row_idx, column=1, value=node.id)
|
|
ws.cell(row=row_idx, column=2, value=node.name)
|
|
row_idx += 1
|
|
for sub in node.children:
|
|
if sub.type == "subcategory":
|
|
ws.cell(row=row_idx, column=3, value=sub.name)
|
|
row_idx += 1
|
|
for word in sub.children:
|
|
ws.cell(row=row_idx, column=4, value=word.name)
|
|
row_idx += 1
|
|
elif sub.type == "word":
|
|
ws.cell(row=row_idx, column=4, value=sub.name)
|
|
row_idx += 1
|
|
# Spaltenbreiten anpassen
|
|
for col_idx, col_letter in enumerate(["A","B","C","D"],1):
|
|
ws.column_dimensions[col_letter].width = 20
|
|
for r in range(1,row_idx):
|
|
ws.cell(r,col_idx).alignment = Alignment(horizontal='left')
|
|
wb.save(output_file)
|
|
logging.info(f"Excel exportiert: {output_file}")
|
|
|
|
# ---------------- Export in ODS ----------------
|
|
def export_spot_to_ods(tree_nodes, output_file):
|
|
doc = ezodf.newdoc(doctype="ods", filename=output_file)
|
|
for node in tree_nodes:
|
|
sheet = ezodf.Sheet(node.name[:31], size=(len(node.children)+10,4))
|
|
doc.sheets += sheet
|
|
sheet[0,0].set_value("ID")
|
|
sheet[0,1].set_value("Unterkategorie")
|
|
sheet[0,2].set_value("Unterunterkategorie")
|
|
sheet[0,3].set_value("Wort/Vokabel")
|
|
row_idx = 1
|
|
sheet[row_idx,0].set_value(node.id)
|
|
sheet[row_idx,1].set_value(node.name)
|
|
row_idx +=1
|
|
for sub in node.children:
|
|
if sub.type == "subcategory":
|
|
sheet[row_idx,2].set_value(sub.name)
|
|
row_idx +=1
|
|
for word in sub.children:
|
|
sheet[row_idx,3].set_value(word.name)
|
|
row_idx +=1
|
|
elif sub.type == "word":
|
|
sheet[row_idx,3].set_value(sub.name)
|
|
row_idx +=1
|
|
doc.save()
|
|
logging.info(f"ODS exportiert: {output_file}")
|
|
|
|
# ---------------- CLI-Funktionen zum Editieren ----------------
|
|
def add_category(tree_nodes, cat_id, cat_name):
|
|
tree_nodes.append(Node(cat_name, "category", id=cat_id))
|
|
logging.info(f"Kategorie hinzugefügt: {cat_id} {cat_name}")
|
|
|
|
def add_subcategory(tree_nodes, cat_id, sub_name):
|
|
for cat in tree_nodes:
|
|
if cat.id == cat_id:
|
|
cat.add_child(Node(sub_name, "subcategory"))
|
|
logging.info(f"Unterkategorie hinzugefügt: {sub_name} in {cat_id}")
|
|
return
|
|
|
|
def add_word(tree_nodes, cat_id, sub_name, word_name):
|
|
for cat in tree_nodes:
|
|
if cat.id == cat_id:
|
|
for sub in cat.children:
|
|
if sub.name == sub_name:
|
|
sub.add_child(Node(word_name, "word"))
|
|
logging.info(f"Wort hinzugefügt: {word_name} unter {sub_name}")
|
|
return
|
|
|
|
# ---------------- HAUPTPROGRAMM ----------------
|
|
def main():
|
|
INPUT_FILE = "NV_MASTER.ods" # Beispielpfad
|
|
OUTPUT_SPOT = "nv_spot.json"
|
|
today = datetime.datetime.today().strftime("%y.%m.%d")
|
|
OUTPUT_EXCEL = f"NV_MASTER_SPOT_{today}.xlsx"
|
|
OUTPUT_ODS = f"NV_MASTER_SPOT_{today}.ods"
|
|
|
|
master_df, dfs = load_excel_or_ods(INPUT_FILE)
|
|
spot_tree = []
|
|
for sheet, df in dfs.items():
|
|
spot_tree.extend(process_sheet_to_tree(df))
|
|
save_spot_json(spot_tree, OUTPUT_SPOT)
|
|
|
|
# Beispiel: Editieren
|
|
# add_category(spot_tree, "10.1", "Neue Kategorie")
|
|
# add_subcategory(spot_tree, "10.1", "Neue Unterunterkategorie")
|
|
# add_word(spot_tree, "10.1", "Neue Unterunterkategorie", "Neues Wort")
|
|
|
|
export_spot_to_excel(spot_tree, OUTPUT_EXCEL)
|
|
export_spot_to_ods(spot_tree, OUTPUT_ODS)
|
|
logging.info("SPOT-Workflow abgeschlossen.")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|