Files
scripts/owi pdfs nach ods/process-owi2.pl

183 lines
6.4 KiB
Perl
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use open qw(:std :utf8);
use Excel::Writer::XLSX;
my $input = 'pdfs.txt';
my $csv_out = 'anzeigen.csv';
my $xlsx_out = 'anzeigen.xlsx';
my $sep = ';';
# Hilfsfunktion: trim
sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s // '' }
# --- Bestehende CSV einlesen (falls vorhanden) ---
my %entries;
if (-e $csv_out) {
open(my $old, '<:encoding(UTF-8)', $csv_out) or die "Kann $csv_out nicht lesen: $!";
my $hdr = <$old>; # Kopfzeile überspringen
while (<$old>) {
chomp;
next unless length($_);
my @cols = split /$sep/, $_;
# trim alle Felder
@cols = map { trim($_) } @cols;
my ($datum, $start, $ende, $tatort, $kennz, $marke, $file) = @cols;
$entries{$file} = {
Datum => $datum // '',
'Tatzeit(Anfang)' => $start // '',
'Tatzeit(Ende)' => $ende // '',
Tatort => $tatort // '',
Kennzeichen => $kennz // '',
Marke => $marke // '',
Datei => $file // ''
};
}
close $old;
print "📂 Bestehende CSV geladen: " . scalar(keys %entries) . " Einträge\n";
}
# --- Neue Daten aus pdfs.txt einlesen ---
open(my $in, '<:encoding(UTF-8)', $input) or die "Kann $input nicht öffnen: $!";
while (<$in>) {
chomp;
next unless /:/;
my ($file, $content) = split(/:/, $_, 2);
$file = trim($file);
$content = trim($content);
# initialisieren falls neu
$entries{$file} //= {
Datum => '',
'Tatzeit(Anfang)' => '',
'Tatzeit(Ende)' => '',
Tatort => '',
Kennzeichen => '',
Marke => '',
Datei => $file
};
# Kennzeichen
if ($content =~ /Fahrzeug Kennzeichen\s+(.+)/i) {
$entries{$file}->{Kennzeichen} = trim($1);
next;
}
# Marke
if ($content =~ /Marke des Fahrzeuges\s+(.+)/i) {
$entries{$file}->{Marke} = trim($1);
next;
}
# Tatort
if ($content =~ /Tatort\s+(.+)/i) {
$entries{$file}->{Tatort} = trim($1);
next;
}
# Datum in der Form DD.MM.YYYY auf derselben Zeile
if ($content =~ /Tattag\s*\(Datum\)\s*([0-3]?\d\.[01]?\d\.\d{4})/) {
my $d = $1;
if ($d =~ /(\d{2})\.(\d{2})\.(\d{4})/) {
$entries{$file}->{Datum} = sprintf("%04d-%02d-%02d", $3, $2, $1);
}
# es könnten zusätzlich Zeiten auf dieser Zeile sein -> weiter prüfen unten
}
# Falls die Zeile "Tattag (Datum) (Tatzeit Bis)" ohne Datum, wir lassen Datum unverändert (nicht überschreiben)
# Zeiten: überall nach HH:MM suchen (erkennt auch "17:30- 17:49", "11:35 - 11:40 Uhr", "21:13" etc.)
if ($content =~ /Tatzeit|Tatzeit|Tatzeit.*|Tattag.*Tatzeit/i or $content =~ /(\d{1,2}:\d{2})/) {
my @times = ($content =~ /(\d{1,2}:\d{2})/g);
# Falls Zeiten gefunden wurden, setzen (überschreiben)
if (@times) {
$entries{$file}->{'Tatzeit(Anfang)'} = $times[0];
$entries{$file}->{'Tatzeit(Ende)'} = $times[1] // ''; # falls keine Endzeit, leer lassen
}
}
# Manchmal steht das Datum ohne Label (seltener), versuchen wir ein generelles Datumsmuster in content
if (!$entries{$file}->{Datum} && $content =~ /(\d{2}\.\d{2}\.\d{4})/) {
my $d = $1;
if ($d =~ /(\d{2})\.(\d{2})\.(\d{4})/) {
$entries{$file}->{Datum} = sprintf("%04d-%02d-%02d", $3, $2, $1);
}
}
}
close $in;
# --- Sortieren: neueste zuerst; falls Datum leer, ans Ende ---
my @sorted = sort {
my $da = $entries{$a}->{Datum} // '';
my $db = $entries{$b}->{Datum} // '';
# leere Datum nach unten
return $da cmp $db if $da eq '' || $db eq '';
($db cmp $da) || ( ($entries{$b}->{'Tatzeit(Anfang)'} // '') cmp ($entries{$a}->{'Tatzeit(Anfang)'} // '') )
} keys %entries;
# --- CSV schreiben (gewünschte Reihenfolge) ---
open(my $csv, '>:encoding(UTF-8)', $csv_out) or die "Kann $csv_out nicht schreiben: $!";
print $csv "Datum${sep}Tatzeit(Anfang)${sep}Tatzeit(Ende)${sep}Tatort${sep}Kennzeichen${sep}Marke${sep}Datei\n";
for my $e (@sorted) {
my $row = join($sep, map { $entries{$e}->{$_} // '' } qw(Datum Tatzeit(Anfang) Tatzeit(Ende) Tatort Kennzeichen Marke Datei));
print $csv "$row\n";
}
close $csv;
print "✅ CSV-Datei '$csv_out' erstellt.\n";
# --- XLSX erzeugen ---
my $workbook = Excel::Writer::XLSX->new( $xlsx_out );
my $worksheet = $workbook->add_worksheet();
# Formatierungen
my $bold_format = $workbook->add_format( bold => 1, bg_color => '#D9D9D9' );
my $date_format = $workbook->add_format( num_format => 'yyyy-mm-dd' );
my $time_format = $workbook->add_format( num_format => 'hh:mm' );
# Kopfzeile
my @header = qw(Datum Tatzeit(Anfang) Tatzeit(Ende) Tatort Kennzeichen Marke Datei);
$worksheet->write_row( 'A1', \@header, $bold_format );
# Datenzeilen
my $row_index = 1;
for my $e (@sorted) {
my @row_data = (
$entries{$e}->{Datum} // '',
$entries{$e}->{'Tatzeit(Anfang)'} // '',
$entries{$e}->{'Tatzeit(Ende)'} // '',
$entries{$e}->{Tatort} // '',
$entries{$e}->{Kennzeichen} // '',
$entries{$e}->{Marke} // '',
$entries{$e}->{Datei} // '',
);
for my $col (0..$#row_data) {
my $value = $row_data[$col];
# Datum als echtes Excel-Datum (ISO + T)
if ($col == 0 && $value =~ /^(\d{4})-(\d{2})-(\d{2})$/) {
my $iso = sprintf("%04d-%02d-%02dT00:00:00", $1, $2, $3);
$worksheet->write_date_time($row_index, $col, $iso, $date_format);
}
# Zeit als echte Excel-Zeit (Bruchteil eines Tages)
elsif (($col == 1 || $col == 2) && $value =~ /^(\d{1,2}):(\d{2})$/) {
my ($h,$m) = ($1,$2);
my $time_fraction = ($h*3600 + $m*60)/86400;
$worksheet->write_number($row_index, $col, $time_fraction, $time_format);
}
else {
# Text (leer als leere Zelle)
$worksheet->write_string($row_index, $col, $value // '');
}
}
$row_index++;
}
# Optional: Autofit (nur grobe Breiten setzen)
$worksheet->set_column(0, 0, 12); # Datum
$worksheet->set_column(1, 2, 10); # Zeiten
$worksheet->set_column(3, 3, 30); # Tatort
$worksheet->set_column(4, 5, 15); # Kennzeichen, Marke
$worksheet->set_column(6, 6, 60); # Datei
$workbook->close;
print "📊 XLSX-Datei '$xlsx_out' erstellt alle Daten sichtbar und formatiert.\n";