add: wenn input folder leer -> hochladen von xlxs Dateien vereinfacht
This commit is contained in:
1 parent
7d63063024
commit
2237779e56
4 files changed
+75
-2
No files matched your search
@@ -9,6 +9,12 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).
|
||||
|
||||
## [1.3.2] – 2026-10-07
|
||||
|
||||
### Hinzugefügt
|
||||
|
||||
- **Input-Dateien hinzufügen**: Bei leerem Input-Ordner können `.xlsx`-Dateien per Drag-and-drop oder Dateiauswahl in den Input-Ordner kopiert werden
|
||||
- **Input-Ordner öffnen**: Ein Button öffnet den Input-Ordner direkt im Explorer
|
||||
- **Input-Ordner neu einlesen**: Dateiliste kann über Button aktualisiert werden
|
||||
|
||||
### Behoben
|
||||
|
||||
- EXE erkennt laufende Entwicklungsinstanz und fragt vor dem Neustart
|
||||
|
||||
@@ -9,6 +9,10 @@ Um das Programm zu starten: Doppelklick auf `Tätigkeitsnachweis-Generator.exe`
|
||||
## Bedienung
|
||||
|
||||
1. **Input-Datei wählen** – Dropdown zeigt alle `.xlsx`-Dateien aus dem `input/`-Ordner
|
||||
- Bei leerem Input-Ordner: „Input-Ordner öffnen“ öffnet den Explorer.
|
||||
- Excel-Dateien können per Drag-and-drop hochgeladen werden. Sie werden in den
|
||||
Input-Ordner kopiert; danach wird die Dateiliste automatisch neu eingelesen.
|
||||
- Nach manuellem Kopieren im Explorer „Input-Ordner neu einlesen“ anklicken.
|
||||
- Nach Auswahl wird die Datei sofort validiert
|
||||
- Angezeigt werden: Anzahl Mitarbeiter, Antragsnummern, Einträge pro Monat
|
||||
2. **Template wählen** – Dropdown zeigt alle `.xlsx`-Dateien aus dem `template/`-Ordner
|
||||
|
||||
+64
-1
@@ -32,6 +32,14 @@ from src.writer import generate_activity_reports
|
||||
from version_check import UPDATE_DIR, get_latest_version
|
||||
|
||||
|
||||
def open_input_folder(directory: Path):
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
if sys.platform == "win32":
|
||||
os.startfile(str(directory))
|
||||
else:
|
||||
subprocess.run(["open" if sys.platform == "darwin" else "xdg-open", str(directory)], check=True)
|
||||
|
||||
|
||||
def set_active_employee(employee_name: str):
|
||||
"""Merkt die zuletzt angeklickte Person für die Monatsliste."""
|
||||
st.session_state.active_month_employee = employee_name
|
||||
@@ -155,9 +163,64 @@ col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
st.subheader("1. Input-Datei")
|
||||
input_files = get_available_input_files(app_config)
|
||||
for message in st.session_state.pop("input_upload_messages", []):
|
||||
st.success(message)
|
||||
for message in st.session_state.pop("input_upload_errors", []):
|
||||
st.error(message)
|
||||
if not input_files:
|
||||
st.warning("Keine .xlsx-Dateien im input/-Ordner gefunden.")
|
||||
with st.container(border=True, key="input_file_panel"):
|
||||
st.markdown("**Excel-Datei hinzufügen**")
|
||||
st.caption("Keine .xlsx-Dateien im Input/-Ordner gefunden.")
|
||||
input_directory = Path(app_config.input_dir)
|
||||
uploaded_files = st.file_uploader(
|
||||
"Excel-Dateien hierher ziehen oder auswählen",
|
||||
type=["xlsx"], accept_multiple_files=True,
|
||||
key=f"input_upload_{st.session_state.get('input_upload_generation', 0)}",
|
||||
label_visibility="collapsed",
|
||||
)
|
||||
if uploaded_files:
|
||||
saved, errors = [], []
|
||||
for uploaded_file in uploaded_files:
|
||||
try:
|
||||
name = uploaded_file.name
|
||||
if (Path(name).name != name or "/" in name or "\\" in name
|
||||
or Path(name).suffix.lower() != ".xlsx" or name.startswith("~")):
|
||||
raise ValueError("Bitte eine .xlsx-Datei mit gültigem Dateinamen auswählen.")
|
||||
input_directory.mkdir(parents=True, exist_ok=True)
|
||||
destination = input_directory / name
|
||||
counter = 1
|
||||
while True:
|
||||
try:
|
||||
with destination.open("xb") as output:
|
||||
output.write(uploaded_file.getbuffer())
|
||||
break
|
||||
except FileExistsError:
|
||||
counter += 1
|
||||
destination = input_directory / f"{Path(name).stem} ({counter}).xlsx"
|
||||
saved.append(f"{destination.name} wurde in den Input-Ordner kopiert.")
|
||||
except (OSError, ValueError) as exc:
|
||||
errors.append(f"{uploaded_file.name} konnte nicht übernommen werden: {exc}")
|
||||
st.session_state.input_upload_messages = saved
|
||||
st.session_state.input_upload_errors = errors
|
||||
st.session_state.input_upload_generation = st.session_state.get("input_upload_generation", 0) + 1
|
||||
st.session_state.last_input_file = None
|
||||
st.rerun()
|
||||
st.caption("Dateien hierher ziehen oder auswählen. Sie werden automatisch im Input-Ordner gespeichert.")
|
||||
folder_action, refresh_action = st.columns(2)
|
||||
with folder_action:
|
||||
if st.button("Ordner öffnen", icon="📁", key="open_input_directory", use_container_width=True):
|
||||
try:
|
||||
open_input_folder(input_directory)
|
||||
except (OSError, subprocess.SubprocessError) as exc:
|
||||
st.error(f"Der Input-Ordner konnte nicht geöffnet werden: {exc}")
|
||||
with refresh_action:
|
||||
if st.button("Neu einlesen", icon="🔄", key="refresh_input_directory", use_container_width=True,
|
||||
help="Dateiliste aktualisieren, nachdem Dateien im Explorer hinzugefügt wurden."):
|
||||
st.rerun()
|
||||
selected_input = None
|
||||
st.session_state.parsed_records = []
|
||||
st.session_state.input_validated = False
|
||||
st.session_state.last_input_file = None
|
||||
else:
|
||||
# Bei nur einer Datei: automatisch selektieren (keine Leerauswahl)
|
||||
if len(input_files) == 1:
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.3.2
|
||||
1.3.3
|
||||
Reference in new issue
Block a user