DBsExcel_con_UDT/DB_to_Excel.py

173 lines
6.5 KiB
Python
Raw Normal View History

import re
import json
import pandas as pd
from ExportData import *
from ExpandDB import *
def clean_line(line):
"""Clean line from BOM and extra spaces or quotes."""
# Remove UTF-8 BOM if exists and strip trailing/leading whitespace
line = line.replace("\ufeff", "").strip()
# Standardize TYPE and DATA_BLOCK definitions to ensure they're properly captured
line = re.sub(r'\s*TYPE\s+"?', 'TYPE "', line)
line = re.sub(r'\s*DATA_BLOCK\s+"?', 'DATA_BLOCK "', line)
return line
def extract_name(line):
"""Extract the name from TYPE or DATA_BLOCK definition line."""
# Attempt to find a quoted name first
match = re.search(r'(TYPE|DATA_BLOCK)\s+"([^"]+)"', line)
if match:
return match.group(2).strip() # The name is within quotes
# If no quoted name, find an unquoted name
match = re.search(r"(TYPE|DATA_BLOCK)\s+(\S+)", line)
if match:
return match.group(2).strip() # The name is without quotes
def parse_udts(lines):
udt_json = {}
udt_name = None
nested_structs = []
current_struct = None
is_within_struct = False
for line in lines:
line = clean_line(line)
if "TYPE" in line and "END_TYPE" not in line:
udt_name = extract_name(line)
udt_json[udt_name] = {}
current_struct = udt_json[udt_name]
print(f"Created UDT: {udt_name}")
elif "END_TYPE" in line:
print(f"Completed UDT: {udt_name}")
udt_name = None
nested_structs = []
current_struct = None
is_within_struct = False
elif "STRUCT" in line and "END_STRUCT" not in line and udt_name is not None:
struct_name = (
"Struct" if "STRUCT" == line.strip() else line.split(":")[0].strip()
)
new_struct = {}
current_struct[struct_name] = new_struct
nested_structs.append(current_struct)
current_struct = new_struct
is_within_struct = True
print(f"Created STRUCT: {struct_name}")
elif "END_STRUCT" in line and udt_name is not None:
current_struct = nested_structs.pop() if nested_structs else None
is_within_struct = bool(nested_structs)
print(f"Closed STRUCT in UDT '{udt_name}'")
elif udt_name and ":" in line and is_within_struct:
parts = line.split(":")
field_name = parts[0].strip()
field_details = parts[1].strip().split("//")
field_type = (
field_details[0].replace(";", "").strip()
) # Removing ';' from field type
field_comment = parts[1].split("//")[1].strip() if "//" in parts[1] else ""
if "Struct" in field_type:
new_struct = {}
current_struct[field_name] = new_struct
nested_structs.append(current_struct)
current_struct = new_struct
print(f"Opened inline STRUCT at field '{field_name}'")
else:
current_struct[field_name] = {
"type": field_type,
"comment": field_comment,
}
print(
f"Added field '{field_name}' to STRUCT: Type={field_type}, Comment={field_comment}"
)
return udt_json
def parse_dbs(lines, udts):
db_json = {}
db_name = None
nested_structs = []
current_struct = None
is_within_struct = False
for line in lines:
line = clean_line(line)
if "DATA_BLOCK" in line and "END_DATA_BLOCK" not in line:
db_name = extract_name(line)
db_json[db_name] = {}
current_struct = db_json[db_name]
print(f"Created DATA_BLOCK: {db_name}")
elif "END_DATA_BLOCK" in line:
print(f"Completed DATA_BLOCK: {db_name}")
db_name = None
nested_structs = []
current_struct = None
is_within_struct = False
elif "STRUCT" in line and "END_STRUCT" not in line and db_name is not None:
struct_name = (
"Struct" if "STRUCT" == line.strip() else line.split(":")[0].strip()
)
new_struct = {}
current_struct[struct_name] = new_struct
nested_structs.append(current_struct)
current_struct = new_struct
is_within_struct = True
print(f"Created STRUCT in DB '{db_name}': {struct_name}")
elif "END_STRUCT" in line and db_name is not None:
current_struct = nested_structs.pop() if nested_structs else None
is_within_struct = bool(nested_structs)
print(f"Closed STRUCT in DB '{db_name}'")
elif db_name and ":" in line and is_within_struct:
parts = line.split(":")
field_name = parts[0].strip()
field_details = parts[1].strip().split("//")
field_type = (
field_details[0].replace(";", "").strip()
) # Removing ';' from field type
field_comment = parts[1].split("//")[1].strip() if "//" in parts[1] else ""
if "Struct" in field_type:
new_struct = {}
current_struct[field_name] = new_struct
nested_structs.append(current_struct)
current_struct = new_struct
print(f"Opened inline STRUCT at field '{field_name}' in DB '{db_name}'")
else:
current_struct[field_name] = {
"type": field_type,
"comment": field_comment,
}
print(
f"Added field '{field_name}' to STRUCT in DB '{db_name}': Type={field_type}, Comment={field_comment}"
)
return db_json
if __name__ == "__main__":
file_path = "DB SIPA Supervision.db"
with open(file_path, "r", encoding="utf-8-sig") as file:
lines = file.readlines()
udt_json = parse_udts(lines)
db_json = parse_dbs(lines, udt_json)
expand_dbs(udt_json, db_json) # Expand DBs with UDT definitions
for db_name, db_content in db_json.items():
calculate_offsets(
db_content
) # Calculate offsets including special handling for Bool and String
# Display the expanded DBs as a table
df = display_as_table(db_json)
save_dataframe_to_file(df) # Save the DataFrame to a CSV file
save_dataframe_to_excel(df) # Optionally, save the DataFrame to an Excel file
# Save JSON data to an XML file
save_json_to_xml(db_json)