Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Convert a CSV file to a styled .xlsx workbook with type inference.
|
||||
|
||||
Type inference per cell (disable with --no-infer):
|
||||
int, float, bool ("true"/"false", case-insensitive), ISO date
|
||||
(YYYY-MM-DD) and ISO datetime; everything else stays a string.
|
||||
|
||||
Styling applied by default (disable with --plain):
|
||||
bold header row with a light fill, frozen top row, autofilter over the
|
||||
data range, and column widths sized to the longest cell (capped at 60).
|
||||
|
||||
Usage:
|
||||
csv_to_xlsx.py data.csv out.xlsx
|
||||
csv_to_xlsx.py data.csv out.xlsx --sheet-name Import --encoding cp1252
|
||||
csv_to_xlsx.py data.csv out.xlsx --delimiter ';' --no-infer
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import csv
|
||||
import json
|
||||
import sys
|
||||
from datetime import date, datetime
|
||||
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Font, PatternFill
|
||||
from openpyxl.utils import get_column_letter
|
||||
|
||||
MAX_COL_WIDTH = 60
|
||||
COL_PADDING = 2
|
||||
DEFAULT_COL_WIDTH = 8
|
||||
|
||||
|
||||
def infer(text):
|
||||
if text == "":
|
||||
return None
|
||||
low = text.lower()
|
||||
if low in ("true", "false"):
|
||||
return low == "true"
|
||||
for caster in (int, float):
|
||||
try:
|
||||
return caster(text)
|
||||
except ValueError:
|
||||
pass
|
||||
for parser in (date.fromisoformat, datetime.fromisoformat):
|
||||
try:
|
||||
return parser(text)
|
||||
except ValueError:
|
||||
pass
|
||||
return text
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
ap = argparse.ArgumentParser(description="CSV -> styled .xlsx converter.")
|
||||
ap.add_argument("csv_file", help="input CSV path")
|
||||
ap.add_argument("output", help="output .xlsx path")
|
||||
ap.add_argument("--sheet-name", default="Sheet1")
|
||||
ap.add_argument("--encoding", default="utf-8",
|
||||
help="CSV file encoding (default utf-8)")
|
||||
ap.add_argument("--delimiter", default=",")
|
||||
ap.add_argument("--no-infer", action="store_true",
|
||||
help="keep every cell as a string")
|
||||
ap.add_argument("--plain", action="store_true",
|
||||
help="skip header styling / freeze / autofilter")
|
||||
args = ap.parse_args(argv)
|
||||
|
||||
with open(args.csv_file, newline="", encoding=args.encoding) as fh:
|
||||
rows = list(csv.reader(fh, delimiter=args.delimiter))
|
||||
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
ws.title = args.sheet_name
|
||||
for i, row in enumerate(rows):
|
||||
if args.no_infer or i == 0:
|
||||
ws.append(row)
|
||||
else:
|
||||
ws.append([infer(cell) for cell in row])
|
||||
|
||||
if rows and not args.plain:
|
||||
header_font = Font(bold=True)
|
||||
header_fill = PatternFill("solid", fgColor="DDEBF7")
|
||||
for cell in ws[1]:
|
||||
cell.font = header_font
|
||||
cell.fill = header_fill
|
||||
ws.freeze_panes = "A2"
|
||||
ws.auto_filter.ref = ws.dimensions
|
||||
for col_idx in range(1, ws.max_column + 1):
|
||||
longest = max((len(str(r[col_idx - 1])) for r in rows
|
||||
if len(r) >= col_idx), default=DEFAULT_COL_WIDTH)
|
||||
ws.column_dimensions[get_column_letter(col_idx)].width = \
|
||||
min(longest + COL_PADDING, MAX_COL_WIDTH)
|
||||
|
||||
wb.save(args.output)
|
||||
print(json.dumps({"ok": True, "output": args.output,
|
||||
"rows": len(rows)}, ensure_ascii=False))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(main())
|
||||
except Exception as exc: # noqa: BLE001
|
||||
print(json.dumps({"ok": False, "error": str(exc)}), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user