In der heutigen digitalen Welt sind wir oft mit einer Flut von Dokumenten konfrontiert – sei es für die Arbeit, das Studium oder private Projekte. Aber wie behält man den Überblick über Metadaten, Inhalte und Strukturen dieser Dateien? Hier kommt der Document Folder Analyzer ins Spiel – ein Python-Tool mit einer modernen PyQt6-GUI, das Ordner mit verschiedenen Dokumentformaten analysiert und die Ergebnisse übersichtlich in Excel-Dateien speichert. In diesem Beitrag erkläre ich, wofür du es brauchst, wie du es installierst und wie die Ergebnisse aussehen.

Wofür braucht man den Document Folder Analyzer?

Der Analyzer ist ein vielseitiges Werkzeug für alle, die schnell Informationen aus Dokumenten extrahieren möchten, ohne jede Datei manuell öffnen zu müssen. Hier sind einige Einsatzmöglichkeiten:

  • Dokumentenmanagement: Finde heraus, wann Dateien erstellt oder geändert wurden, wer der Autor ist (bei PDFs) oder wie viele Seiten, Absätze oder Zellen sie enthalten.
  • Archivierung: Erstelle eine Übersicht über einen Ordner mit gemischten Dateitypen – ideal für Projekte oder rechtliche Dokumentationen.
  • Forensische Analyse: Überprüfe Metadaten und Inhalte, um z. B. die Herkunft von PDFs oder Änderungen nachzuvollziehen.
  • Effizienzsteigerung: Automatisiere repetitive Aufgaben wie das Zählen von Bildern in PDFs oder Zeilen in Textdateien.

Das Tool unterstützt vier Formate:

  • PDF: Seiten, Text, Bilder, Anmerkungen, Zeichnungen, Metadaten.
  • Word (.docx): Text, Absätze, Dateisystem-Metadaten.
  • Text (.txt): Text, Zeilenanzahl, Dateisystem-Metadaten.
  • Excel (.xlsx): Tabellenblätter, Zellenanzahl, Dateisystem-Metadaten.

Wie installiert man den Document Folder Analyzer?

Die Installation ist unkompliziert, erfordert aber ein paar Python-Bibliotheken. Folge diesen Schritten:

1. Python installieren

Stelle sicher, dass Python (mindestens Version 3.7) auf deinem System installiert ist. Du kannst es von python.org herunterladen.

2. Bibliotheken installieren

Öffne ein Terminal (oder die Eingabeaufforderung) und führe diesen Befehl aus, um alle benötigten Bibliotheken zu installieren:

bash

pip install PyQt6 PyMuPDF openpyxl python-docx
  • PyQt6: Für die grafische Benutzeroberfläche.
  • PyMuPDF: Zum Lesen von PDFs.
  • openpyxl: Zum Erstellen und Bearbeiten von Excel-Dateien.
  • python-docx: Zum Verarbeiten von Word-Dateien.

3. Code speichern

Kopiere den vollständigen Code (siehe unten) in eine Datei, z. B. document_folder_analyzer.py.

4. Programm starten

Navigiere im Terminal zum Speicherort der Datei und starte das Programm:

bash

python document_folder_analyzer.py

Ein Fenster mit dem Titel „Document Folder Analyzer“ öffnet sich, und du kannst loslegen!


Wie funktioniert das Tool?

  1. Ordner auswählen: Klicke auf „Ordner auswählen“ und wähle einen Ordner mit PDFs, Word-, Text- oder Excel-Dateien.
  2. Analyse starten: Das Tool analysiert jede Datei im Hintergrund und zeigt den Fortschritt mit einem grünen Fortschrittsbalken an.
  3. Statusmeldungen: Während der Analyse siehst du Meldungen wie „Analysiere: dokument.pdf“. Am Ende gibt es eine Zusammenfassung.
  4. Ergebnisse speichern: Für jede analysierte Datei wird eine Excel-Datei mit der Endung _analyse.xlsx erstellt.

Die GUI ist modern und intuitiv: Ein großer Button zum Auswählen, ein Fortschrittsbalken und ein Statusfeld, das in Blau (laufend), Grün (erfolgreich) oder Rot (Fehler) leuchtet.


Wie sehen die Ausgaben und Resultate aus?

Die Ergebnisse variieren je nach Dateityp. Hier ein Überblick:

PDF-Analyse (z. B. dokument_analyse.xlsx)

Eine Tabelle mit einer Zeile pro Seite:

Dateiname:SeiteErstellungsdatumÄnderungsdatumText (erste 500 Zeichen)Anzahl der BilderAnzahl der AnmerkungenAnzahl der ZeichnungenAutorTitelBetreffProducerCreatorErstellungsdatum MetadatenÄnderungsdatum Metadaten
dokument.pdf:115. März 2023, 12:3416. März 2023, 09:12„Dies ist ein Test…“210Max MustermannTest PDFTestzweckAdobe AcrobatPyMuPDF15. März 2023, 12:3416. März 2023, 09:12

Word-Analyse (z. B. brief_analyse.xlsx)

Eine einfache Tabelle:

DateinameErstellungsdatumÄnderungsdatumText (erste 500 Zeichen)Anzahl der Absätze
brief.docx10. Januar 2025, 08:1511. Januar 2025, 14:30„Sehr geehrte Damen…“5

Text-Analyse (z. B. notizen_analyse.xlsx)

DateinameErstellungsdatumÄnderungsdatumText (erste 500 Zeichen)Zeilenanzahl
notizen.txt05. Februar 2025, 09:0006. Februar 2025, 10:00„Einkaufsliste: Milch…“12

Excel-Analyse (z. B. tabelle_analyse.xlsx)

DateinameErstellungsdatumÄnderungsdatumAnzahl der TabellenblätterGesamtzahl der Zellen
tabelle.xlsx01. März 2025, 15:2002. März 2025, 11:453150

Zusammenfassung in der GUI

Nach der Analyse eines Ordners mit z. B. drei Dateien könnte die Zusammenfassung so aussehen:

Analyse abgeschlossen!

Erfolgreich analysiert: C:/Dokumente/dokument_analyse.xlsx
Erfolgreich analysiert: C:/Dokumente/brief_analyse.xlsx
Fehler bei notizen.txt: Datei konnte nicht geöffnet werden

Fazit

Der Document Folder Analyzer ist ein praktisches Tool für alle, die schnell und automatisiert Einblicke in ihre Dokumente gewinnen möchten. Egal, ob du PDFs auf Metadaten prüfen, Word-Dokumente auf Absätze analysieren oder Excel-Dateien auf ihre Struktur untersuchen willst – dieses Programm macht es möglich. Mit der einfachen Installation und der übersichtlichen GUI steht deinem Dokumentenmanagement nichts mehr im Weg.


Der vollständige Code

Hier ist der Code, den du einfach kopieren und nutzen kannst:

python

import sys
import fitz  # PyMuPDF
import os
from datetime import datetime
import openpyxl
from openpyxl.styles import Font
from docx import Document  # Für .docx-Dateien
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, 
                             QLabel, QFileDialog, QProgressBar)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtGui import QFont

# Funktion zum Parsen des Datums aus PDF-Metadaten
def parse_pdf_date(pdf_date):
    if not pdf_date or pdf_date == "Nicht verfügbar":
        return "Nicht verfügbar"
    try:
        date_str = pdf_date[2:16]
        date_obj = datetime.strptime(date_str, '%Y%m%d%H%M%S')
        return date_obj.strftime('%d. %B %Y, %H:%M:%S')
    except (ValueError, IndexError):
        return "Nicht verfügbar"

# Funktion zum Extrahieren von Dateimetadaten
def get_file_metadata(file_path):
    created = datetime.fromtimestamp(os.path.getctime(file_path)).strftime('%d. %B %Y, %H:%M:%S')
    modified = datetime.fromtimestamp(os.path.getmtime(file_path)).strftime('%d. %B %Y, %H:%M:%S')
    return created, modified

# Analyse-Funktionen für verschiedene Dateitypen
def analyze_pdf(file_path):
    filename = os.path.basename(file_path)
    pdf = fitz.open(file_path)
    metadata = pdf.metadata
    meta_fields = {"author": "Nicht verfügbar", "title": "Nicht verfügbar", "subject": "Nicht verfügbar",
                   "producer": "Nicht verfügbar", "creator": "Nicht verfügbar",
                   "creationDate": "Nicht verfügbar", "modDate": "Nicht verfügbar"}
    meta_fields.update({k: v or "Nicht verfügbar" for k, v in metadata.items()})

    workbook = openpyxl.Workbook()
    sheet = workbook.active
    sheet.title = "PDF Analyse"
    headers = ["Dateiname:Seite", "Erstellungsdatum", "Änderungsdatum", "Text (erste 500 Zeichen)",
               "Anzahl der Bilder", "Anzahl der Anmerkungen", "Anzahl der Zeichnungen", "Autor",
               "Titel", "Betreff", "Producer", "Creator", "Erstellungsdatum Metadaten", "Änderungsdatum Metadaten"]
    for col, header in enumerate(headers, 1):
        sheet.cell(row=1, column=col, value=header).font = Font(bold=True)

    for page_num in range(pdf.page_count):
        page = pdf.load_page(page_num)
        text = page.get_text("text")[:500]
        created = parse_pdf_date(meta_fields["creationDate"])
        modified = parse_pdf_date(meta_fields["modDate"])
        images = len(page.get_images(full=True))
        annotations = len(list(page.annots() or []))
        drawings = len(page.get_drawings() or [])

        row = page_num + 2
        sheet.cell(row=row, column=1, value=f"{filename}:{page_num + 1}")
        sheet.cell(row=row, column=2, value=created)
        sheet.cell(row=row, column=3, value=modified)
        sheet.cell(row=row, column=4, value=text)
        sheet.cell(row=row, column=5, value=images)
        sheet.cell(row=row, column=6, value=annotations)
        sheet.cell(row=row, column=7, value=drawings)
        sheet.cell(row=row, column=8, value=meta_fields["author"])
        sheet.cell(row=row, column=9, value=meta_fields["title"])
        sheet.cell(row=row, column=10, value=meta_fields["subject"])
        sheet.cell(row=row, column=11, value=meta_fields["producer"])
        sheet.cell(row=row, column=12, value=meta_fields["creator"])
        sheet.cell(row=row, column=13, value=created)
        sheet.cell(row=row, column=14, value=modified)

    output_file = file_path.replace(".pdf", "_analyse.xlsx")
    workbook.save(output_file)
    pdf.close()
    return output_file

def analyze_docx(file_path):
    filename = os.path.basename(file_path)
    doc = Document(file_path)
    created, modified = get_file_metadata(file_path)

    workbook = openpyxl.Workbook()
    sheet = workbook.active
    sheet.title = "DOCX Analyse"
    headers = ["Dateiname", "Erstellungsdatum", "Änderungsdatum", "Text (erste 500 Zeichen)", "Anzahl der Absätze"]
    for col, header in enumerate(headers, 1):
        sheet.cell(row=1, column=col, value=header).font = Font(bold=True)

    text = " ".join([para.text for para in doc.paragraphs if para.text])[:500]
    sheet.cell(row=2, column=1, value=filename)
    sheet.cell(row=2, column=2, value=created)
    sheet.cell(row=2, column=3, value=modified)
    sheet.cell(row=2, column=4, value=text)
    sheet.cell(row=2, column=5, value=len(doc.paragraphs))

    output_file = file_path.replace(".docx", "_analyse.xlsx")
    workbook.save(output_file)
    return output_file

def analyze_txt(file_path):
    filename = os.path.basename(file_path)
    created, modified = get_file_metadata(file_path)

    workbook = openpyxl.Workbook()
    sheet = workbook.active
    sheet.title = "TXT Analyse"
    headers = ["Dateiname", "Erstellungsdatum", "Änderungsdatum", "Text (erste 500 Zeichen)", "Zeilenanzahl"]
    for col, header in enumerate(headers, 1):
        sheet.cell(row=1, column=col, value=header).font = Font(bold=True)

    with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
        text = f.read()[:500]
        lines = len(f.readlines())

    sheet.cell(row=2, column=1, value=filename)
    sheet.cell(row=2, column=2, value=created)
    sheet.cell(row=2, column=3, value=modified)
    sheet.cell(row=2, column=4, value=text)
    sheet.cell(row=2, column=5, value=lines)

    output_file = file_path.replace(".txt", "_analyse.xlsx")
    workbook.save(output_file)
    return output_file

def analyze_xlsx(file_path):
    filename = os.path.basename(file_path)
    created, modified = get_file_metadata(file_path)
    workbook = openpyxl.load_workbook(file_path)

    analysis_workbook = openpyxl.Workbook()
    sheet = analysis_workbook.active
    sheet.title = "XLSX Analyse"
    headers = ["Dateiname", "Erstellungsdatum", "Änderungsdatum", "Anzahl der Tabellenblätter", "Gesamtzahl der Zellen"]
    for col, header in enumerate(headers, 1):
        sheet.cell(row=1, column=col, value=header).font = Font(bold=True)

    total_cells = sum(sheet.max_row * sheet.max_column for sheet in workbook.worksheets)
    sheet.cell(row=2, column=1, value=filename)
    sheet.cell(row=2, column=2, value=created)
    sheet.cell(row=2, column=3, value=modified)
    sheet.cell(row=2, column=4, value=len(workbook.worksheets))
    sheet.cell(row=2, column=5, value=total_cells)

    output_file = file_path.replace(".xlsx", "_analyse.xlsx")
    analysis_workbook.save(output_file)
    return output_file

# Worker-Thread für die Ordner-Analyse
class FolderAnalyzer(QThread):
    status_update = pyqtSignal(str, str)  # Text, Farbe
    progress_update = pyqtSignal(int)     # Fortschritt in Prozent

    def __init__(self, folder_path):
        super().__init__()
        self.folder_path = folder_path

    def run(self):
        supported_extensions = {'.pdf', '.docx', '.txt', '.xlsx'}
        files = [f for f in os.listdir(self.folder_path) if os.path.splitext(f.lower())[1] in supported_extensions]
        if not files:
            self.status_update.emit("Keine unterstützten Dateien im Ordner gefunden.", "red")
            return

        total_files = len(files)
        processed_files = 0
        results = []

        for file in files:
            file_path = os.path.join(self.folder_path, file)
            self.status_update.emit(f"Analysiere: {file}", "blue")
            try:
                if file.lower().endswith('.pdf'):
                    output_file = analyze_pdf(file_path)
                elif file.lower().endswith('.docx'):
                    output_file = analyze_docx(file_path)
                elif file.lower().endswith('.txt'):
                    output_file = analyze_txt(file_path)
                elif file.lower().endswith('.xlsx'):
                    output_file = analyze_xlsx(file_path)
                results.append(f"Erfolgreich analysiert: {output_file}")
            except Exception as e:
                results.append(f"Fehler bei {file}: {str(e)}")
            processed_files += 1
            self.progress_update.emit(int((processed_files / total_files) * 100))

        summary = "\n".join(results)
        self.status_update.emit(f"Analyse abgeschlossen!\n\n{summary}", "green")

# Hauptfenster der GUI
class DocumentFolderAnalyzerApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Document Folder Analyzer")
        self.setGeometry(100, 100, 600, 400)
        self.setFixedSize(600, 400)

        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        layout = QVBoxLayout(main_widget)
        layout.setAlignment(Qt.AlignmentFlag.AlignCenter)

        title_label = QLabel("Document Folder Analyzer")
        title_label.setFont(QFont("Arial", 18, QFont.Weight.Bold))
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        layout.addWidget(title_label)

        self.status_label = QLabel("Bitte wähle einen Ordner mit Dokumenten aus.")
        self.status_label.setFont(QFont("Arial", 10))
        self.status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.status_label.setWordWrap(True)
        layout.addWidget(self.status_label)

        self.progress_bar = QProgressBar()
        self.progress_bar.setMaximum(100)
        self.progress_bar.setValue(0)
        self.progress_bar.setTextVisible(True)
        self.progress_bar.setStyleSheet("""
            QProgressBar { border: 1px solid grey; border-radius: 5px; text-align: center; }
            QProgressBar::chunk { background-color: #4CAF50; border-radius: 3px; }
        """)
        layout.addWidget(self.progress_bar)

        self.select_button = QPushButton("Ordner auswählen")
        self.select_button.setFont(QFont("Arial", 12))
        self.select_button.setStyleSheet("""
            QPushButton { background-color: #4CAF50; color: white; padding: 8px; border-radius: 5px; }
            QPushButton:hover { background-color: #45a049; }
            QPushButton:disabled { background-color: #cccccc; }
        """)
        self.select_button.clicked.connect(self.select_folder)
        layout.addWidget(self.select_button)

        exit_button = QPushButton("Beenden")
        exit_button.setFont(QFont("Arial", 12))
        exit_button.setStyleSheet("""
            QPushButton { background-color: #f44336; color: white; padding: 8px; border-radius: 5px; }
            QPushButton:hover { background-color: #da190b; }
        """)
        exit_button.clicked.connect(self.close)
        layout.addWidget(exit_button)

    def select_folder(self):
        folder_path = QFileDialog.getExistingDirectory(self, "Ordner mit Dokumenten auswählen")
        if folder_path:
            self.status_label.setText("Analyse wird durchgeführt...")
            self.status_label.setStyleSheet("color: blue;")
            self.select_button.setEnabled(False)
            self.progress_bar.setValue(0)

            self.worker = FolderAnalyzer(folder_path)
            self.worker.status_update.connect(self.update_status)
            self.worker.progress_update.connect(self.update_progress)
            self.worker.finished.connect(self.enable_button)
            self.worker.start()

    def update_status(self, message, color):
        self.status_label.setText(message)
        self.status_label.setStyleSheet(f"color: {color};")

    def update_progress(self, value):
        self.progress_bar.setValue(value)

    def enable_button(self):
        self.select_button.setEnabled(True)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = DocumentFolderAnalyzerApp()
    window.show()
    sys.exit(app.exec())

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert