Initial commit: intercompany ledger app
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
class UnsupportedWorkbookError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RawSheet:
|
||||
name: str
|
||||
rows: tuple[tuple[Any, ...], ...]
|
||||
|
||||
|
||||
def read_workbook(path: Path) -> tuple[RawSheet, ...]:
|
||||
suffix = path.suffix.lower()
|
||||
if suffix == ".xlsx":
|
||||
return _read_xlsx(path)
|
||||
if suffix == ".xls":
|
||||
return _read_xls(path)
|
||||
raise UnsupportedWorkbookError(f"Unsupported workbook type: {suffix}")
|
||||
|
||||
|
||||
def _read_xlsx(path: Path) -> tuple[RawSheet, ...]:
|
||||
try:
|
||||
from openpyxl import load_workbook
|
||||
except ImportError as exc:
|
||||
raise UnsupportedWorkbookError(
|
||||
"Reading .xlsx files requires openpyxl. Install requirements.txt."
|
||||
) from exc
|
||||
|
||||
workbook = load_workbook(path, read_only=True, data_only=True)
|
||||
try:
|
||||
return tuple(
|
||||
RawSheet(
|
||||
name=worksheet.title,
|
||||
rows=tuple(tuple(row) for row in worksheet.iter_rows(values_only=True)),
|
||||
)
|
||||
for worksheet in workbook.worksheets
|
||||
)
|
||||
finally:
|
||||
workbook.close()
|
||||
|
||||
|
||||
def _read_xls(path: Path) -> tuple[RawSheet, ...]:
|
||||
try:
|
||||
import xlrd
|
||||
except ImportError as exc:
|
||||
raise UnsupportedWorkbookError(
|
||||
"Reading .xls files requires xlrd. Install requirements.txt."
|
||||
) from exc
|
||||
|
||||
workbook = xlrd.open_workbook(path, on_demand=True)
|
||||
sheets: list[RawSheet] = []
|
||||
try:
|
||||
for sheet_name in workbook.sheet_names():
|
||||
worksheet = workbook.sheet_by_name(sheet_name)
|
||||
rows: list[tuple[Any, ...]] = []
|
||||
for row_index in range(worksheet.nrows):
|
||||
values: list[Any] = []
|
||||
for column_index in range(worksheet.ncols):
|
||||
cell = worksheet.cell(row_index, column_index)
|
||||
value = cell.value
|
||||
if cell.ctype == xlrd.XL_CELL_DATE:
|
||||
value = xlrd.xldate_as_datetime(value, workbook.datemode)
|
||||
values.append(value)
|
||||
rows.append(tuple(values))
|
||||
sheets.append(RawSheet(name=sheet_name, rows=tuple(rows)))
|
||||
finally:
|
||||
workbook.release_resources()
|
||||
return tuple(sheets)
|
||||
Reference in New Issue
Block a user