Du bist nicht angemeldet. Der Zugriff auf einige Boards wurde daher deaktiviert.

#1 22. Mai 2018 13:59

brandy
Server-Pate
Registriert: 05. Juni 2011
Beiträge: 697
Webseite

CSV auslesen und sortieren

Hallo!

Ich lese eine CSV mit folgenden Feldern aus:
DATUM - UHRZEIT - VERANSTALTUNG - SAAL

Mir fehlt aber die Vorstellung von multidimensionalen Arrays, bzw. wie ich die Daten dahineinbekomme. Im Endeffekt möchte ich die Daten nach Datum sortieren, was ja grundsätzlich mit usort usw. in einem mehrdimensionalen Array kein Problem zu sein scheint.

Auf jedenfall habe dazu zwei Möglichkeiten ausprobiert:

Erste Variante:

[== PHP ==]
$handle = fopen ('resources/veranstaltungen.csv','r');
$eventAll = fread($handle, 10000);
$eventData = explode("\n", $eventAll);
print_r ($eventData);
fclose($handle);

Hier habe ich das Array, das aus der ganz ausgelesen Datei erstellt und nach Zeilenschaltung getrennt wurde!

Zweite Variante:

[== PHP ==]
$handle = fopen ('resources/veranstaltungen.csv','r');
$columns = fgetcsv($handle);

while($data = fgetcsv($handle))
{
  foreach($columns as $key => $col)
  {
    $array[$col][] = $data[$key];
  }
}
print_r ($array);

Hier wurde die CSV zeilenweise ausgelesen und die erste Zeile als Key angelegt.

Für meine Logik würde ich einfach bei der ersten Variante das Array nochmal in Einzelarrays mit explode nach ";" in ein eigenes Array packen. Aber irgendwie stehe ich hier an - vielleicht kann mir wer weiterhelfen!

Vielen Dank!

Offline

#2 22. Mai 2018 16:04

NaN
Moderator
Ort: Halle (Saale)
Registriert: 09. November 2010
Beiträge: 4.138

Re: CSV auslesen und sortieren

Versuch mal dieses Snippet.
Das gibt Dir ein indiziertes Array von Zeilen aus, die ihrerseits wiederum assoziative Arrays sind, bei denen Du jede Spalte über ihren Namen ansprechen kannst. Die Namen der Spalten werden aus der ersten Zeile gebildet. Solange es hier keine riesen CSV Tabellen sind, sollte das ausreichen.

Dann kannst Du Dir eine Funktion schreiben, die nach Spalten sortiert. So z.B.:

<?php

# config
$sort_by    = 'date';                   # column name to sort by
$sort_order = 'ASC';                    # use 'DESC' for descending sort order
$file       = 'path/to/my/file.csv';


# get the csv into array...
$rows = array_map('str_getcsv', file($file));
array_walk($rows, function(&$a) use ($rows) {
    $a = array_combine($rows[0], $a);
});
array_shift($rows); # remove column header


# sort by given column name
uasort($rows, function($row1, $row2) use ($sort_by, $sort_order) {
    return ( strnatcasecmp($row1[$sort_by], $row2[$sort_by]) * ($sort_order == 'DESC' ? -1 : 1) );
});

echo "<pre>" . print_r($rows, true) . "<pre/>";

?>

Offline

#3 23. Mai 2018 08:06

brandy
Server-Pate
Registriert: 05. Juni 2011
Beiträge: 697
Webseite

Re: CSV auslesen und sortieren

Ok, das ist ja schon mal umfangreicher.
Wenn ich das jetzt nicht nur absteigend sortiert haben möchte sondern auch noch mit dem aktuellen Zeitpunkt verglichen haben möchte, damit man laufende Veranstaltungen erkennt, wirds ja noch umfangreicher.

Wie würdest du das dann angehen? Würdest du da überhaupt auf dieser Basis weiterarbeiten?

Vielen Dank!

Beitrag geändert von brandy (23. Mai 2018 08:06)

Offline

#4 23. Mai 2018 09:47

NaN
Moderator
Ort: Halle (Saale)
Registriert: 09. November 2010
Beiträge: 4.138

Re: CSV auslesen und sortieren

Wo kommen denn diese CSV Daten her?
Und wie umfangreich sind die?
Wenn die Anforderungen nicht viel komplexer werden, könnte man in einer Schleife einfach alle Datensätze durchgehen und nur die ausgeben, bei denen das Datum dem aktuellen Datum entspricht. Pseudo-Code: Foreach ... if $dings[datum] >= $jetzt ... usw.

Ansonsten wären XML oder SQL hier vielleicht die besseren Alternativen, weil man da viel differenzierter gezielt Einträge auswählen und filtern kann bzw. geht es viel einfacher und performanter.

Offline

#5 23. Mai 2018 10:02

brandy
Server-Pate
Registriert: 05. Juni 2011
Beiträge: 697
Webseite

Re: CSV auslesen und sortieren

Aha, okay, stimmt...
Ich habe nämlich in der gleichen Anwendung eine AJAX Suchfunktion. Dazu hab ich mir eine Datei angelegt, die eine CSV in ein XML umwandelt.

In diesem Fall wäre das dann wohl gescheiter, das hier auch anzuwenden.

Offline

#6 23. Mai 2018 16:52

NaN
Moderator
Ort: Halle (Saale)
Registriert: 09. November 2010
Beiträge: 4.138

Re: CSV auslesen und sortieren

Man kann die Sortierung/Filterung natürlich auch komplett via Javascript vornehmen. Aber wie gesagt, das kommt darauf an, wie umfangreich die Daten sind. Denn dazu müssten sie immer vollständig geladen werden. D.h. immer vollständig die CSV-Datei auslesen und vollständig z.B. als Tabelle oder JSON im Template ausgeben. Den Rest erledigt das Javascript. Da gibt es einige Tools, zum Sortieren von Tabellen. Allerdings sind die meist auch etwas heavy. Lohnt sich also meist nur für umfangreiche Daten. Ein paar Einträge mit einem Script zu sortieren, das mehr Datenvolumen verbraucht als die eigentlichen Daten, ist aus ökonomischer Sicht schon nicht zu empfehlen.

Keine Ahnung ab wann man wirklich von umfangreich sprechen kann. Müsste man mal testen (benchmarks/pagespeed). Ist zum Teil auch subjektiv. Mehr als 50 Einträge wären mir persönlich zu viel für eine Seite. Wird ja auch irgendwann unübersichtlich. Warum also mehr laden, als man dem Besucher zumuten will? Das sollte man dann auf einzelne Seiten aufteilen.

Wenn es also zu umfangreich werden sollte, wäre meine Idee eigentlich die, dass man die CSV-Datei in eine Datenbank importiert. Dann kann man sich per SQL schonmal alle relevanten Daten in der gewünschten Menge und der korrekten Reihenfolge holen. Spart ne Menge Arbeit. Das ganze dann kombiniert mit Javascript/AJAX wäre optimal. Die meisten Javascripts zum Sortieren von Tabellen bieten auch Paginierung und AJAX-Schnittstellen.

Man könnte z.B. ein PHP-Script schreiben, das eine bestimmte CSV-Datei nur dann ausliest und in die Datenbank importiert, wenn sich die CSV-Datei geändert hat (timestamp/hash). Anderenfalls werden die Einträge einfach aus der Datenbank geladen. Somit bräuchtest Du bei Änderungen nur die aktuelle CSV auf den Server zu laden. Du bräuchtest nicht mal einen Administrationsbereich im Backend und somit auch kein ganzes Modul. Ein Plugin reicht völlig aus.

Offline

#7 24. Mai 2018 09:12

brandy
Server-Pate
Registriert: 05. Juni 2011
Beiträge: 697
Webseite

Re: CSV auslesen und sortieren

Ich mach es momentan noch ohne CMS im Hintergrund.
Bin aber am Überlegen, ob ich nicht eines hinterlege - somit könnte ich den Kunden auch gleich direkt darauf lassen und er kann seine Veranstaltungen direkt verwalten!

Danke für die Infos!

Offline

#8 24. Mai 2018 10:33

brandy
Server-Pate
Registriert: 05. Juni 2011
Beiträge: 697
Webseite

Re: CSV auslesen und sortieren

Eine andere Idee wäre, das Ganze komplett über CMSMS aufzubauen und einfach ein Skript zu erstellen, dass die Daten richtig in die Datenbank schreibt. CMSMS kriegt dann nicht mal was mit, dass sich was ändert.

Und für mich wäre die Ausgabe um einiges einfacher...

Offline

#9 28. Mai 2018 08:16

brandy
Server-Pate
Registriert: 05. Juni 2011
Beiträge: 697
Webseite

Re: CSV auslesen und sortieren

Wie würde ein automatisierter Import der CSV in die Datenbank von CMSMS aussehen?
Quasi, dass sich selbstständig aus der CSV verschiedene Newseinträge erstellen.
Diese dann über das CMS zu Sortieren wäre kein Stress...

Beitrag geändert von brandy (28. Mai 2018 08:18)

Offline

#10 28. Mai 2018 13:49

brandy
Server-Pate
Registriert: 05. Juni 2011
Beiträge: 697
Webseite

Re: CSV auslesen und sortieren

Ich hab jetzt mal ein assoziatives Array erstellt - das ist meine Ausabe:

[== PHP ==]
Array ( 
[0] => Array ( [Datum; Uhrzeit; Veranstaltung; Saal] => 20.03.;10:00;Büroeröffnung;425 )
[1] => Array ( [Datum; Uhrzeit; Veranstaltung; Saal] => 08.06.;09:00;Maibaum-Aufstellen;1 )
[2] => Array ( [Datum; Uhrzeit; Veranstaltung; Saal] => 02.05.;08:00;Freibier;624 )
[3] => Array ( [Datum; Uhrzeit; Veranstaltung; Saal] => 03.04.;10:00;Frühstück?;624 )
[4] => Array ( [Datum; Uhrzeit; Veranstaltung; Saal] => 12.05.;12:00;Biertrinken;624 )
) 

Kann ich hier schon mal zumindest nach Datum sortieren?

Beitrag geändert von brandy (28. Mai 2018 13:50)

Offline

#11 28. Mai 2018 16:38

NaN
Moderator
Ort: Halle (Saale)
Registriert: 09. November 2010
Beiträge: 4.138

Re: CSV auslesen und sortieren

Nein. Weil alle Daten in einem einzigen Element des Zeilen-Arrays stehen.
Eigentlich sollte das am Ende so aussehen:

Array ( 
    [0] => Array ( 
        [Datum]         => 20.03.
        [Uhrzeit]       => 10:00
        [Veranstaltung] => Büroeröffnung
        [Saal]          => 425 
    )
    [1] => Array ( 
        [Datum]         => 08.06.
        [Uhrzeit]       => 09:00
        [Veranstaltung] => Maibaum aufstellen
        [Saal]          => 1
    )
    ...
)

Scheinbar hat Deine CSV-Datei das "falsche" Trennzeichen. Sollte eigentlich ein Komma sein. Ich muss an dieser Stelle nocheinmal fragen: Woher kommen diese Daten? Schreibt ihr die von Hand? Wohl kaum. Also welches Programm wird dazu verwendet? Kann man da evtl. einstellen, dass ein anderes Trennzeichen verwendet wird? Wenn nicht, dann muss mein Code da im obigen Beitrag nochmal überarbeitet werden:

<?php

# config (adapt to your needs)
$sort_by    = 'date';                   # column name to sort by
$sort_order = 'ASC';                    # use 'DESC' for descending sort order
$file       = 'path/to/my/file.csv';
$delimiter  = ',';
$enclosure  = '"';
$escapeChar = "\\";


# get the csv into array...
$rows = array_map(
    function($row) use ($delimiter, $enclosure, $escapeChar) {
        return str_getcsv($row, $delimiter, $enclosure, $escapeChar);
    },
    file($file)
);

array_walk($rows, function(&$a) use ($rows) {
    $a = array_combine($rows[0], $a);
});

array_shift($rows); # remove column header


# sort by given column name
uasort($rows, function($row1, $row2) use ($sort_by, $sort_order) {
    return ( strnatcasecmp($row1[$sort_by], $row2[$sort_by]) * ($sort_order == 'DESC' ? -1 : 1) );
});

echo "<pre>" . print_r($rows, true) . "<pre/>";

?>

Offline

#12 30. Mai 2018 08:49

brandy
Server-Pate
Registriert: 05. Juni 2011
Beiträge: 697
Webseite

Re: CSV auslesen und sortieren

Die CSV kommt aus Excel.
Möchte ich auch so lassen, damit der Kunde damit umgehen kann!
Eventuell kann ich ihm ein Libreoffice einreden, da kann man das Trennzeichen besser einstellen.

Ich erhalte nun die Ausgabe, wie du meintest - das haut gut hin, danke!
Aber sortiert wird noch nicht - müssen die Werte in Anführungszeichen stehen?

Offline

#13 30. Mai 2018 11:28

NaN
Moderator
Ort: Halle (Saale)
Registriert: 09. November 2010
Beiträge: 4.138

Re: CSV auslesen und sortieren

Die CSV kommt aus Excel.

Ah. Okay. Dachte ich mir.
Soll aber nicht das Problem sein.
Man kann ja PHP sagen, welches Trennzeichen verwendet werden soll.

D.h. Du hättest freie Hand beim Aufbau der Tabelle? Ich frage nur, um auf Deine andere Frage in Bezug auf "automatischer Import als News" zu antworten. Denn dann wäre das "mapping" von CSV auf News-Einträge einfacher, wenn bei Deiner Excel-Tabelle die Spalten bereits so heißen, wie in der Datenbank beim News-Modul. (muss man einfach weniger programmieren bzw. müsste man beim Programmieren nicht wissen, wie die CSV-Datei aufgebaut ist; und bei einem Update, bei dem sich der Aufbau der Datenbank ändert, würde es evtl. ausreichen, nur die CSV-Datei anzupassen)

Aber sortiert wird noch nicht - müssen die Werte in Anführungszeichen stehen?

Verstehe ich nicht.
Poste mal den Abschnitt was Du im Abschnitt "#config ..." im PHP Script eingetragen hast.
Du musst auf Groß- und Kleinschreibung achten.

Offline

#14 30. Mai 2018 11:51

brandy
Server-Pate
Registriert: 05. Juni 2011
Beiträge: 697
Webseite

Re: CSV auslesen und sortieren

Das ist meine CSV:

Datum;Uhrzeit;Veranstaltung;Saal
20.03.2018;10:00;Büroeröffnung;425
08.06.2018;09:00;Maibaum-Aufstellen;1
02.05.2018;08:00;Frühstück;624
03.04.2018;10:00;Freibier;624
12.05.2018;12:00;Biertrinken;624

Man muss dazusagen, dass der Kunde selbst eine CSV erstellen solle und einstellen kann.

Hier der config-Teil deines Codes:

# config (adapt to your needs)
$sort_by    = 'Datum';                   # column name to sort by
$sort_order = 'ASC';                    # use 'DESC' for descending sort order
$file       = 'resources/veranstaltungen.csv';
$delimiter  = ';';
$enclosure  = '"';
$escapeChar = "\\";

Offline

#15 30. Mai 2018 15:22

NaN
Moderator
Ort: Halle (Saale)
Registriert: 09. November 2010
Beiträge: 4.138

Re: CSV auslesen und sortieren

Doch, es wird schon sortiert.
Allerdings nicht so, wie man es bei einem Datum erwarten würde.
Liegt am Datumsformat.
Wäre das Format umgekehrt (Jahr Monat Tag Uhrzeit), dann würde es funktionieren.
Denn das Script weiß weder, dass es sich um ein Datum handelt, noch, wie dieses Datum formatiert ist. Der sortiert stumpf vom ersten Zeichen an. (Stell Dir die Zahlen mal als Buchstaben vor, dann wirds klarer)

Du könntest das lösen, indem Du eine Excel-Tabelle anlegst, die Dein Kunde dann aber vor dem Upload noch als CSV Exportieren muss. (Also nicht direkt in der CSV-Datei arbeiten)
Bei dieser Excel-Tabelle kannst Du der Spalte "Datum" ein bestimmtes Format geben. (JJJJ MM.TT. hh:mm) Dann kann das PHP Script besser sortieren.

Soll der Webseitenbesucher die Einträge selber sortieren können? Oder geht's nur um eine sinnvolle Auflistung auf der Seite?

Wenn der Webseitenbesucher nicht selber sortieren soll, und Du ohnehine mit einer .xlsx Datei und CSV-Export arbeiten würdest, dann lass die Daten doch vor dem Export von Excel selber sortieren. D.h. eine normale Excel-Tabelle mit Sortierfunktion anlegen und vor jedem Upload die Daten sortieren und als CSV exportieren. (Tabellenbereich markieren und im Menü "Als Tabelle formatieren", dabei die Checkbox "Tabelle hat Überschriften" aktivieren. Dann wird die erste Zeile als Überschrift erkannt. Dann kann man die Tabelle nach Spalten sortieren und anschließend als CSV speichern - nicht wundern, da kommen dann zwei Meldungen, dass einige Features nicht im CSV-Format gespeichert werden können.)

Ich wüsste jetzt auf die Schnelle sonst nicht, wie man dem PHP-Script auch noch den jeweiligen Datentyp bzw. dessen Schema, nach dem sortiert werden soll, beibringen könnte. Insbesondere beim Datum ist es unmöglich, das automatisch zu ermitteln.

Möglicherweise gibt es auch noch Tools, die native Excel-Daten lesen können, aber ich denke für Deinen Anwendungsfall wäre das zu heavy.

Offline

#16 30. Mai 2018 15:33

brandy
Server-Pate
Registriert: 05. Juni 2011
Beiträge: 697
Webseite

Re: CSV auslesen und sortieren

Ah cool, danke!
An das hab ich jetzt nicht gedacht. Funktioniert.

Wie kann ich den Typ von Array mittels foreach jetzt ausgeben?

Offline

#17 30. Mai 2018 15:42

NaN
Moderator
Ort: Halle (Saale)
Registriert: 09. November 2010
Beiträge: 4.138

Re: CSV auslesen und sortieren

Na so:

<table>
    <thead>
        <tr>
            <th>Datum</th>
            <th>Uhrzeit</th>
            <th>Veranstaltung</th>
            <th>Saal</th>
        </tr>
    </thead>
    <tbody>

<?php

foreach($rows as $row) {

?>

        <tr>
            <td><?php echo $row['Datum']; ?></td>
            <td><?php echo $row['Uhrzeit']; ?></td>
            <td><?php echo $row['Veranstaltung']; ?></td>
            <td><?php echo $row['Saal']; ?></td>
        </tr>

<? php

}

?>

    </tbody>
</table>

Offline

#18 04. Juni 2018 08:11

brandy
Server-Pate
Registriert: 05. Juni 2011
Beiträge: 697
Webseite

Re: CSV auslesen und sortieren

Super, dass gefällt mir so schon sehr!

Kann ich bei der Ausgabe des Datums aus einem Array auch gleich das Format mitübergeben?

Offline

#19 04. Juni 2018 15:28

NaN
Moderator
Ort: Halle (Saale)
Registriert: 09. November 2010
Beiträge: 4.138

Re: CSV auslesen und sortieren

Dazu muss man PHP sagen, welches Format das Datum ursprünglich hat.
Wenn das Datum in der CSV-Datei folgendes Format hat:

Jahr Monat(zahl) Tag(zahl) -> 2018-06-04

Und man möchte daraus folgendes machen:

Tag(zahl) Monat(name) Jahr -> 04. Jun 2018

Dann geht das so:

$original_format = "Y-m-d";
$new_format      = "d. M Y";
$date            = DateTime::createFromFormat($original_format, $row['Datum']));
echo $date->format($new_format);

Mehr dazu in der PHP Doku.

Offline