import streamlit as st
import os
import pandas as pd
from datetime import datetime
from io import BytesIO
from PIL import Image
from reportlab.lib.pagesizes import landscape, A4
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Image as ReportLabImage
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Spacer, Paragraph
# Streamlit app
st.title("Eingaben")
# Funktion zum Erstellen des Ordners und der CSV-Datei
def create_project(project_name):
if not os.path.exists(project_name):
os.makedirs(project_name)
csv_path = os.path.join(project_name, f"{project_name}.csv")
if not os.path.exists(csv_path):
columns = ["Nummer", "Kategorie", "Gewerk", "Foto", "Beschrieb", "Datum", "Bemerkung"]
df = pd.DataFrame(columns=columns)
df.to_csv(csv_path, index=False)
return csv_path
# Funktion zum Ermitteln der nächsten fortlaufenden Nummer
def get_next_number(csv_path):
if os.path.exists(csv_path):
df = pd.read_csv(csv_path)
if not df.empty:
return df['Nummer'].max() + 1
return 1
# Funktion zum Speichern des Fotos
def save_photo(photo, project_name, number, category, date):
if photo is not None:
img = Image.open(photo)
photo_name = f"{number}_{category}_{date.strftime('%Y%m%d')}.jpg"
image_path = os.path.join(project_name, photo_name)
img.save(image_path)
return image_path
return None
# Funktion zum Erstellen des PDF-Berichts mit ReportLab
def create_pdf_report(csv_path, project_name, export_date):
# Speicherort und Dateiname
pdf_output_path = os.path.join(project_name, f"{project_name}_Bericht_{export_date.strftime('%Y%m%d')}.pdf")
# Querformat PDF erstellen
document = SimpleDocTemplate(pdf_output_path, pagesize=landscape(A4), rightMargin=36, leftMargin=36, topMargin=36, bottomMargin=36)
elements = []
# Titel des Berichts
title = f"Übersicht der Mängel und Themen: {project_name} - {export_date.strftime('%Y-%m-%d')}"
elements.append(Spacer(1, 24))
elements.append(Paragraph(title, style=getSampleStyleSheet()['Title'])) # Titel hinzufügen
elements.append(Spacer(1, 12))
# CSV-Datei laden
df = pd.read_csv(csv_path)
if not df.empty:
# Erstellen der Kopfzeile für die Tabelle
data = [["Nummer", "Kategorie", "Gewerk", "Foto", "Datum", "Beschrieb", "Bemerkung"]]
for index, row in df.iterrows():
img_path = row['Foto']
if img_path and os.path.exists(img_path):
# Bildgröße anpassen und sicherstellen, dass es innerhalb der Zelle bleibt
img = ReportLabImage(img_path, width=80, height=80) # Bildgröße auf 70x70 setzen
data.append([
str(row['Nummer']),
row['Kategorie'],
row['Gewerk'],
img,
row['Datum'],
row['Beschrieb'],
row['Bemerkung']
])
else:
data.append([
str(row['Nummer']),
row['Kategorie'],
row['Gewerk'],
"", # Falls kein Bild vorhanden ist
row['Datum'],
row['Beschrieb'],
row['Bemerkung']
])
for i in range(0, len(data[0])): # Für die Spalten "Beschrieb" und "Bemerkung"
for j in range(1, len(data)):
if isinstance(data[j][i], str): # Nur für Texte in den Zellen
data[j][i] = Paragraph(data[j][i], style=getSampleStyleSheet()['Normal'])
# Tabelle erstellen mit angepassten Zellenbreiten und Zeilenhöhen
table = Table(data, colWidths=[50, 80, 80, 100, 70, 200, 200], rowHeights=90) # Erste Spalte breiter
# Style anpassen
table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.lightgrey), # Hintergrundfarbe der Kopfzeile (hellgrau)
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke), # Textfarbe der Kopfzeile (weiß)
('ALIGN', (0, 0), (-1, -1), 'LEFT'), # Text zentrieren
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), # Schriftart der Kopfzeile fett
('SIZE', (0, 0), (-1, -1), 10), # Schriftgröße für alle Zellen
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'), # Vertikale Ausrichtung der Zellen
('GRID', (0, 0), (-1, -1), 1, colors.black), # Gitterlinien für die gesamte Tabelle
('LINEBEFORE', (0, 0), (0, -1), 1, colors.black), # Linie links von der Tabelle
('LINEAFTER', (-1, 0), (-1, -1), 1, colors.black), # Linie rechts von der Tabelle
]))
elements.append(table)
elements.append(Spacer(1, 24)) # Abstand nach der Tabelle
else:
# Wenn keine Daten vorhanden sind
elements.append(Paragraph("Keine Daten vorhanden", style=getSampleStyleSheet()['Normal']))
# PDF speichern
document.build(elements)
return pdf_output_path
# Funktion zum Erstellen des Excel-Exports mit eingebetteten Bildern
def create_excel_export(csv_path, project_name, export_date):
df = pd.read_csv(csv_path)
# Speicherort und Dateiname für den Excel-Export
excel_output_path = os.path.join(project_name, f"{project_name}_Bericht_{export_date.strftime('%Y%m%d')}.xlsx")
# Excel-Datei im Excel Writer erstellen
with pd.ExcelWriter(excel_output_path, engine="xlsxwriter") as writer:
df.to_excel(writer, sheet_name="Übersicht", index=False)
workbook = writer.book
worksheet = workbook.get_worksheet_by_name('Übersicht')
# Gehe durch jede Zeile und füge die Bilder in die Excel-Datei ein
for idx, row in df.iterrows():
img_path = row['Foto']
if img_path and os.path.exists(img_path):
# Zellenhöhe und -breite entsprechend dem Bild anpassen
worksheet.set_row(idx + 1, 80) # Zeilenhöhe anpassen
worksheet.set_column('D:D', 20) # Spaltenbreite anpassen
# Bild in die Excel-Zelle einfügen (fixiert)
worksheet.insert_image(idx + 1, 3, img_path, {'x_scale': 0.2, 'y_scale': 0.2, 'object_position': 2})
return excel_output_path
# Seitenleiste für das neue Projekt
st.sidebar.title("Projektverwaltung")
# Eingabefeld für den neuen Projektnamen
project_name = st.sidebar.text_input("Projektname eingeben:")
# Button zum Erstellen des Projekts
create_project_button = st.sidebar.button("Projekt erstellen")
if create_project_button:
if project_name:
# Erstellen der CSV-Datei, falls noch nicht existiert
csv_path = create_project(project_name)
st.sidebar.success(f"Projekt '{project_name}' wurde erfolgreich erstellt.")
else:
st.sidebar.error("Bitte einen Projektnamen eingeben.")
# Auswahl eines bestehenden Projekts
project_folders = [folder for folder in os.listdir() if os.path.isdir(folder)] # Verzeichnisse im aktuellen Ordner
selected_project = st.sidebar.selectbox("Oder bestehendes Projekt auswählen", project_folders)
# Wenn ein bestehendes Projekt ausgewählt wurde
if selected_project:
project_name = selected_project
csv_path = os.path.join(project_name, f"{project_name}.csv")
# Datum für den PDF-Export
export_date = st.sidebar.date_input("Exportdatum", value=datetime.today().date())
# Button zum PDF-Bericht exportieren
if st.sidebar.button("PDF Bericht exportieren"):
pdf_path = create_pdf_report(csv_path, project_name, export_date)
st.sidebar.success(f"PDF-Bericht erfolgreich erstellt: {pdf_path}")
st.download_button("Download PDF", data=open(pdf_path, "rb"), file_name=os.path.basename(pdf_path),
mime="application/pdf")
# Button zum Excel-Export
if st.sidebar.button("Excel Bericht exportieren"):
excel_path = create_excel_export(csv_path, project_name, export_date)
st.sidebar.success(f"Excel-Bericht erfolgreich erstellt: {excel_path}")
# Nummer für den neuen Mangel automatisch festlegen
number = get_next_number(csv_path)
# Eingabefelder für Mängel
st.header(f"Sie befinden sich im Projekt: {project_name}")
# Dropdown für Kategorie anstelle von Textinput
category = st.selectbox("Kategorie", ["Mangel", "Aufgabe", "Sicherheit", "Sonstiges"])
gewerk = st.text_input("Gewerk:")
photo = st.camera_input("Foto aufnehmen:")
description = st.text_area("Beschrieb:")
date = st.date_input("Datum", value=datetime.today().date())
remarks = st.text_area("Bemerkung:")
# Speichern-Button für Mängel
if st.button("Mangel speichern"):
if gewerk and description and date:
photo_path = save_photo(photo, project_name, number, category, date)
# Neue Mangelzeile in die CSV-Datei einfügen
new_row = {
"Nummer": number,
"Kategorie": category,
"Gewerk": gewerk,
"Foto": photo_path,
"Beschrieb": description,
"Datum": date.strftime("%Y-%m-%d"),
"Bemerkung": remarks
}
df = pd.read_csv(csv_path)
df = df.append(new_row, ignore_index=True)
df.to_csv(csv_path, index=False)
st.success(f"Mangel {number} erfolgreich gespeichert.")
else:
st.error("Bitte alle Pflichtfelder ausfüllen.")