Spaces:
Runtime error
Runtime error
| """ | |
| xlsxβtoolkit β Read, write, and convert Excel spreadsheets. | |
| ================================================================ | |
| Provides four functions for working with .xlsx files without needing | |
| to write throwβaway scripts for every spreadsheet task. | |
| """ | |
| import io | |
| import json | |
| import sys | |
| from pathlib import Path | |
| try: | |
| from toolstore.toolset import tool | |
| except ImportError: | |
| def tool(fn): | |
| return fn # noβop when toolstore package not installed | |
| # ββ xlsx_read ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def xlsx_read(*, filepath: str, sheet: str = "", | |
| max_rows: int = 0) -> dict: | |
| """Read an Excel sheet and return rows as a JSON array. | |
| Args: | |
| filepath: Absolute or relative path to the .xlsx file. | |
| sheet: Sheet name (default: first sheet). | |
| max_rows: Limit rows read (0 = all). | |
| Returns: | |
| dict with keys: | |
| sheet β name of the sheet that was read | |
| columns β list of column headers | |
| rows β list of dicts, one per data row | |
| count β number of data rows returned | |
| """ | |
| try: | |
| from openpyxl import load_workbook | |
| except ImportError: | |
| return {"error": "openpyxl not installed β run: pip install openpyxl"} | |
| p = Path(filepath).expanduser().resolve() | |
| if not p.exists(): | |
| return {"error": f"File not found: {p}"} | |
| try: | |
| wb = load_workbook(p, read_only=True, data_only=True) | |
| except Exception as exc: | |
| return {"error": f"Cannot open workbook: {exc}"} | |
| ws = wb[sheet] if sheet else wb.active | |
| if ws is None: | |
| return {"error": f"Sheet '{sheet or '(default)'}' not found"} | |
| rows_iter = ws.iter_rows(values_only=True) | |
| try: | |
| headers = [str(h) if h is not None else f"col_{i}" | |
| for i, h in enumerate(next(rows_iter))] | |
| except StopIteration: | |
| return {"sheet": ws.title, "columns": [], "rows": [], "count": 0} | |
| rows = [] | |
| for row in rows_iter: | |
| row_dict = {headers[i]: (None if v is None else v) | |
| for i, v in enumerate(row) if i < len(headers)} | |
| for h in headers[len(row):]: | |
| row_dict[h] = None | |
| rows.append(row_dict) | |
| if max_rows and len(rows) >= max_rows: | |
| break | |
| wb.close() | |
| return {"sheet": ws.title, "columns": headers, "rows": rows, "count": len(rows)} | |
| # ββ xlsx_sheets ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def xlsx_sheets(*, filepath: str) -> dict: | |
| """List all sheet names in an Excel file with row/column counts. | |
| Args: | |
| filepath: Path to the .xlsx file. | |
| Returns: | |
| dict with keys: | |
| filename β base name of the file | |
| sheets β list of {name, rows, cols} | |
| """ | |
| try: | |
| from openpyxl import load_workbook | |
| except ImportError: | |
| return {"error": "openpyxl not installed β run: pip install openpyxl"} | |
| p = Path(filepath).expanduser().resolve() | |
| if not p.exists(): | |
| return {"error": f"File not found: {p}"} | |
| try: | |
| wb = load_workbook(p, read_only=True, data_only=True) | |
| except Exception as exc: | |
| return {"error": f"Cannot open workbook: {exc}"} | |
| sheets = [] | |
| for name in wb.sheetnames: | |
| ws = wb[name] | |
| sheets.append({"name": name, "rows": ws.max_row or 0, "cols": ws.max_column or 0}) | |
| wb.close() | |
| return {"filename": p.name, "sheets": sheets} | |
| # ββ xlsx_to_csv ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def xlsx_to_csv(*, filepath: str, sheet: str = "", | |
| delimiter: str = ",") -> dict: | |
| """Convert an Excel sheet to CSV text. | |
| Args: | |
| filepath: Path to the .xlsx file. | |
| sheet: Sheet name (default: first sheet). | |
| delimiter: Field delimiter (default comma). | |
| Returns: | |
| dict with key "csv" containing the full CSV string. | |
| """ | |
| result = xlsx_read(filepath=filepath, sheet=sheet) | |
| if "error" in result: | |
| return result | |
| columns = result["columns"] | |
| lines = [delimiter.join(f'"{c}"' if delimiter in str(c) else str(c) | |
| for c in columns)] | |
| for row in result["rows"]: | |
| lines.append(delimiter.join( | |
| f'"{v}"' if v is not None and delimiter in str(v) else (str(v) if v is not None else "") | |
| for v in (row.get(c, "") for c in columns) | |
| )) | |
| return {"csv": "\n".join(lines), "sheet": result["sheet"], | |
| "rows": result["count"], "columns": columns} | |
| # ββ xlsx_create ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def xlsx_create(*, filepath: str, sheet: str = "Sheet1", | |
| columns: list, rows: list) -> dict: | |
| """Create a new .xlsx file from provided data. | |
| Args: | |
| filepath: Where to write the new .xlsx file. | |
| sheet: Sheet name. | |
| columns: List of column header strings. | |
| rows: List of dicts, each keyed by column name. | |
| Returns: | |
| dict with "written" (absolute path) or "error". | |
| """ | |
| try: | |
| from openpyxl import Workbook | |
| from openpyxl.styles import Font, PatternFill, Alignment | |
| except ImportError: | |
| return {"error": "openpyxl not installed β run: pip install openpyxl"} | |
| p = Path(filepath).expanduser().resolve() | |
| p.parent.mkdir(parents=True, exist_ok=True) | |
| wb = Workbook() | |
| ws = wb.active | |
| ws.title = sheet | |
| hdr_font = Font(bold=True, color="FFFFFF", size=11) | |
| hdr_fill = PatternFill(start_color="4F46E5", end_color="4F46E5", fill_type="solid") | |
| hdr_align = Alignment(horizontal="center", vertical="center") | |
| for col_idx, col_name in enumerate(columns, 1): | |
| cell = ws.cell(row=1, column=col_idx, value=col_name) | |
| cell.font = hdr_font | |
| cell.fill = hdr_fill | |
| cell.alignment = hdr_align | |
| for r, row_data in enumerate(rows, 2): | |
| for c, col_name in enumerate(columns, 1): | |
| value = row_data.get(col_name) if isinstance(row_data, dict) else row_data[c-1] if isinstance(row_data, list) else None | |
| ws.cell(row=r, column=c, value=value) | |
| for col in ws.columns: | |
| max_len = max((len(str(cell.value or "")) for cell in col), default=8) | |
| ws.column_dimensions[col[0].column_letter].width = min(max_len + 2, 60) | |
| wb.save(p) | |
| return {"written": str(p), "sheet": sheet, | |
| "columns": len(columns), "rows": len(rows)} | |