|
|
|
"""some helper functions"""
|
|
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
from typing import TypeVar
|
|
|
|
|
|
|
|
import openpyxl
|
|
|
|
|
|
|
|
ExcelItem = TypeVar("ExcelItem")
|
|
|
|
|
|
|
|
DEFAULT_RECIPIENTS = ["frey@imtek.de"]
|
|
|
|
|
|
|
|
|
|
|
|
def excel_value_as_number(value: ExcelItem) -> float | int:
|
|
|
|
if value is None:
|
|
|
|
return 0
|
|
|
|
if isinstance(value, str):
|
|
|
|
try:
|
|
|
|
return float(value)
|
|
|
|
except ValueError:
|
|
|
|
return 0
|
|
|
|
return value
|
|
|
|
|
|
|
|
|
|
|
|
def get_sheet_of_file(excel_file: str, sheet: str | None = None) -> ExcelItem:
|
|
|
|
"""returns a sheet from an excel FileCache
|
|
|
|
|
|
|
|
if name is set to None, the function returns the first sheet
|
|
|
|
"""
|
|
|
|
workbook = openpyxl.open(excel_file)
|
|
|
|
if sheet is None:
|
|
|
|
all_sheets = workbook.sheetnames
|
|
|
|
sheet = all_sheets[0]
|
|
|
|
return workbook[sheet]
|
|
|
|
|
|
|
|
|
|
|
|
def is_empty_excel_value(value: ExcelItem) -> bool:
|
|
|
|
"""is the cell value considered empty"""
|
|
|
|
if value is None:
|
|
|
|
return True
|
|
|
|
return isinstance(value, str) and value.strip() == ""
|
|
|
|
|
|
|
|
|
|
|
|
def strip_excel_value(value: ExcelItem) -> str | ExcelItem:
|
|
|
|
"""remove whitespace from an excel value if it is a string"""
|
|
|
|
if isinstance(value, str):
|
|
|
|
return value.strip()
|
|
|
|
return value
|
|
|
|
|
|
|
|
|
|
|
|
def is_budget_file_name(path_or_name: str | Path) -> bool:
|
|
|
|
"""checks if a filename has the format "budget[...]-<year>.xlsx"""
|
|
|
|
path = Path(path_or_name)
|
|
|
|
if path.suffix.lower() != ".xlsx":
|
|
|
|
return False
|
|
|
|
if not path.name.lower().startswith("budget"):
|
|
|
|
return False
|
|
|
|
try:
|
|
|
|
return int(path.stem[-5:]) <= -2019 # noqa: PLR2004
|
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def list_budget_files(folder: str | Path) -> list[Path]:
|
|
|
|
"""lists all files with the name "budget[...]-<year>.xlsx"""
|
|
|
|
files = (i for i in Path(folder).iterdir() if i.is_file())
|
|
|
|
visible = (i for i in files if not i.name.startswith("."))
|
|
|
|
return [i for i in visible if is_budget_file_name(i)]
|
|
|
|
|
|
|
|
|
|
|
|
def find_budget_file(folder: str | Path, year: str | int) -> Path | None:
|
|
|
|
"""searches for a file with the name "budget[...]-<year>.xlsx"""
|
|
|
|
for path in list_budget_files(folder):
|
|
|
|
if path.stem.endswith(f"-{year}"):
|
|
|
|
return path
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def find_recipients(
|
|
|
|
folder: str | Path, filename: str = "recipients.txt"
|
|
|
|
) -> list[str]:
|
|
|
|
"""finds the recipients of the budget list"""
|
|
|
|
file_path = folder / filename
|
|
|
|
if file_path.is_file():
|
|
|
|
with file_path.open() as filehandle:
|
|
|
|
stripped = (line.strip() for line in filehandle)
|
|
|
|
return [line for line in stripped if line]
|
|
|
|
return DEFAULT_RECIPIENTS
|