CSV-Datei einlesen und dynamisch als sortierbare Tabelle ausgeben

[Bildschirmfoto] CSV-Datei einlesen und dynamisch als sortierbare Tabelle ausgeben

Viele CSV-Dateien, wenn man sich diese mit einem Editor anschaut, sind oft schwer zu lesen. Als Trennzeichen in der CSV-Datei fungiert meist ein Komma, ein Strichpunkt; oder ein Mittelstrich |.

David Brittain;1954-05-03;London;England;5558;david@mail.com;1
Shuichiro Inomata;1995-09-12;Tokio;Japan;6522;shui@mail.com;2
M. Houssouba;2002-03-05;Kapstadt;S.Afrika;9325 3307;mohu@mail.com;3
Margaret Melton;1979-11-15;Sydney;Australien;5822 7754;melton@mail.com;4
Ruslan Belkin;1977-04-09;Moskau;Russland;3636;rbelkin@mail.com;5
Rafael Martinez;1996-01-30;Madrid;Spanien;11985 884;rafmartin@mail.com;6
Moacir de Oliveira;1981-09-10;Porto;Portugal;9865 5681;oliveira@mail.com;7
Sander Roobol;1966-07-25;New York;USA;6325 70029;roobol@mail.com;8
Dan Scott;1975-08-17;Tallinn;Estland;5658 8103;dscott@mail.com;9
Masahiro Takagi;2001-12-06;Hongkong;China;5862 5578;takagi@mail.com;10
Torben Wilson;1989-06-01;Ottawa;Kanada;3652 11228;t-wilson@mail.com;11
Jouni Ahto;1992-02-07;Athen;Griechenland;5214 078;ahto@mail.com;12

Um die Daten besser zu formatieren, können diese in eine HTML-Tabelle eingelesen und ausgegeben werden.

Demo

Wähle eine CSV-Datei aus der Auswahlliste!

Eigenschaften

Die Anleitung wie alles genau funktioniert, finden Sie im folgenden Quelltext.

Quelltext:  csv-datei_einlesen.php AusblendenKopierenLinkZeilen

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
<?php
/*
 * CSV-Datei einlesen und dynamisch als sortierbare Tabelle ausgeben
 * - https://werner-zenk.de/scripte/csv-datei_einlesen_und_dynamisch_als_tabelle_ausgeben.php
 */

$verzeichnis "daten/"// Verzeichnis der Daten
$dateiendung "csv"// Dateiendung
$trenner ";"// Trennzeichen

// Verzeichnisliste ausgeben
if (isset($_GET["liste"])) {

    
// Verzeichnis auslesen
    
foreach (array_slice(scanDir($verzeichnis), 2) as $datei) {
        
$path pathinfo($datei);
        if (
$path["extension"] == $dateiendung) {
            
$arr[] = ['datei' => $datei];
        }
    }

    
// Und im JSON-Format ausgeben
    
echo json_encode($arr);
    exit;
}

// Tabelle ausgeben
if (isset($_GET["ausgeben"])) {

    
// Tabellenkopf - Spalten-Beschriftungen
    // Je nach Anzahl der Spalten anpassen!
    
$tabellenSpalten = [
        
'Name',
        
'Geb.',
        
'Stadt',
        
'Land',
        
'Tel.',
        
'Mail',
        
'Nr.',
    ];

    
// Tabellenkopf - Spalten-Typen (string/number)
    
$tabellenSpaltenTypen = [
        
'string',
        
'number',
        
'string',
        
'string',
        
'number',
        
'string',
        
'number',
    ];

    
// Tabellenkopf erstellen
    
$caption 'Tabelle: ' str_replace('.' $dateiendung''$_GET["ausgeben"]);
    
$ausgabe '<div id="box">
      <table id="foobar-table">
      <caption> <span id="nachoben" title="Zum Anfang der Tabelle">$caption '</span> | <span id="info"></span> </caption>
      <thead><tr>';

    foreach (
$tabellenSpalten as $i => $spalte) {
        
$ausgabe .= '<th data-type="' $tabellenSpaltenTypen[$i] . '" title="Nach ' $spalte ' sortieren">$spalte '</th>';
    }
    
$ausgabe .= '</tr></thead>';

    
// Tabellenkörper erstellen
    
$ausgabe .= '<tbody>';

    
// Datei auslesen
    
$datensaetze file($verzeichnis $_GET["ausgeben"], FILE_IGNORE_NEW_LINES FILE_SKIP_EMPTY_LINES);
    foreach (
$datensaetze as $nr => $datensatz) {

        
//if ($nr > 0) { // Wenn Spaltenüberschriften in der CSV-Datei vorhanden sind

        // PHP-Variablen - Je nach Anzahl der Spalten anpassen!
        
list($s[1], $s[2], $s[3], $s[4], $s[5], $s[6], $s[7]) = explode($trenner$datensatz);

        
// Tabellenzeilen und Spalten erstellen
        
$ausgabe .= '<tr>';
        for (
$i 1$i <count($tabellenSpalten); $i++) {
            
$checkbox = ($i == 1) ? '<input type="checkbox" id="cb' $nr '">'';
            
$ausgabe .= '<td>$checkbox '<label for="cb' $nr '">htmlspecialchars($s[$i]) . '</label></td>';
        }
        
$ausgabe .= '</tr>';
        
//}
    
}

    
// Tabelle ausgeben
    
exit($ausgabe '</tbody></table></div>');
}
?>
<!DOCTYPE html>
<html lang="de">

<head>
    <meta charset="UTF-8">
    <title> CSV-Datei einlesen und dynamisch als sortierbare Tabelle ausgeben</title>

    <style>
        body, input, button, select {
            font-family: Arial, Tahoma, Sans-Serif;
            font-size: 0.93rem;
        }

        div#box {
            max-height: calc(100vh - 4.5em);
            max-width: -moz-fit-content;
            max-width: fit-content;
            min-height: 150px;
            overflow-y: scroll;
            overflow-x: hidden;
            resize: vertical;
            border: solid 0.5px #A4A4A4;
        }

        /* Tabelle */
        table#foobar-table {
            font-family: Arial, Tahoma, Sans-Serif;
            font-size: 0.90rem;
            border-spacing: 3px;
        }

        /* Tabellenüberschrift */
        table#foobar-table>caption {
            background-color: #F5F5F5;
            caption-side: top;
            height: 15px;
            inset-block-start: 0px;
            padding: 5px;
            position: sticky;
        }

        table#foobar-table>caption span#nachoben {
            cursor: pointer;
            font-weight: bold;
            transition: color 0.3s;
            &:hover {
                color: rgb(12, 147, 244);
            }
        }

        /* Tabellenkopf fixieren */
        table#foobar-table>thead {
            position: sticky;
            inset-block-start: 25px;
        }

        /* Spalten anpassen */
        table#foobar-table>thead>tr>th,
        table#foobar-table>tbody>tr>td {
            color: #000000;
            padding: 5px;
            transition: background-color 0.3s;
            outline: Solid 1px #A4A4A4;
        }

        table#foobar-table>thead>tr>th {
            font-weight: 550;
        }

        /* Tabellenkopf spaltenweise einfärben */
        table#foobar-table thead>tr th:nth-child(even) {
            background-color: rgba(174, 213, 243, 0.8);
            cursor: pointer;
            transition: background-color 0.3s;
        }

        table#foobar-table thead>tr th:nth-child(odd) {
            background-color: rgba(154, 193, 223, 0.8);
            cursor: pointer;
            transition: background-color 0.3s;
        }

        /* Tabellenkörper zeilenweise einfärben */
        table#foobar-table tbody>tr:nth-child(even) {
            background-color: rgba(191, 219, 239, 0.8);
            transition: background-color 0.3s;
        }

        table#foobar-table tbody>tr:nth-child(odd) {
            background-color: rgba(255, 255, 255, 0.8);
            transition: background-color 0.3s;
        }

        table#foobar-table tbody>tr>td:nth-child(even) {
            background-color: rgba(219, 236, 248, 0.4);
            transition: background-color 0.3s;
        }

        /* Tabellenzeilen bei Mouseover ändern */
        table#foobar-table tbody>tr:hover {
            background-color: rgba(162, 208, 243, 0.8);
        }

        /* Tabellenspalten bei Mouseover ändern */
        table#foobar-table thead>tr>th:hover {
            background-color: rgba(130, 193, 242, 0.8);
        }

        table#foobar-table tbody>tr>td:hover {
            background-color: rgba(135, 199, 247, 0.8);
        }
        
        /* Checkbox zum markieren (checked) */
        table#foobar-table input[type="checkbox"]:checked + label {
            color: rgb(12, 147, 244);
        }
        table#foobar-table input[type="checkbox"] {
            display: none;
        }

        /* Pfeil nach oben */
        .upArrow::after {
            content: "\2191";
            color: #FFFFFF;
            text-shadow: 1px 1px 0px #000000;
            position: absolute;
        }

        /* Pfeil nach unten */
        .dnArrow::after {
            content: "\2193";
            color: #FFFFFF;
            text-shadow: 1px 1px 0px #000000;
            position: absolute;
        }
    </style>


    <script>
        // Beim laden der Seite diese Funktion aufrufen
        window.addEventListener('DOMContentLoaded', function() {

            // Die URL zu dieser Datei (document.URL) zusammen mit dem Query (?liste) übergeben
            fetch(`${document.URL}?liste`, {

                // Übertragungsmethode: GET
                method: "GET",
            }).then(antwort => {

                // Die Antwort vom Server als Text auswerten:
                return antwort.text();
            }).then(antwort => {

                // Die erhaltenen Daten in einzelne Objekte zerlegen (JSON)
                var obj = JSON.parse(antwort);

                // Neue Elemente in die Auswahlliste einfügen
                for (var counter = 0; counter < obj.length; counter++) {
                    document.querySelector('select[name="selection"]').options[counter] = new Option(obj[counter].datei, obj[counter].datei);
                }

                // Dem HTML-Button (button[name="anzeigen"]) den Event: "click" zuweisen,
                // dieser ruft dann die Funktion: ladeTabelle() auf.
                document.querySelector('button[name="anzeigen"]').addEventListener('click', ladeTabelle);
                document.querySelector('#selection').addEventListener('change', ladeTabelle);
            });
        });

        const ladeTabelle = () => {

            // Den Wert des ausgewählten Elements in der Auswahlliste auslesen
            var sel = document.querySelector('select[name="selection"]').value;

            // Den Wert (sel) mit der Anfrage über GET senden
            fetch(`${document.URL}?ausgeben=${sel}`, {

                // Übertragungsmethode: GET
                method: "GET",
            }).then(antwort => {

                // Die Antwort vom Server als Text auswerten:
                return antwort.text();
            }).then(antwort => {

                // Antwort vom Server im HTML-Element eintragen:
                document.getElementById("ausgabe").innerHTML = antwort;

                // Starte Funktionen
                starteFunktionen();
            });
        }

        const starteFunktionen = () => {

            // Anzahl der Einträge
            let myTable = document.getElementById("foobar-table");
            let myOutput = document.getElementById('info');
            let ofilter = myTable.querySelectorAll("tbody tr").length;
            myOutput.textContent = `${ofilter} Einträge`;

            // Tabelle nach oben scrollen
            document.querySelector("#nachoben").addEventListener("click", () => {
                document.getElementById("box").scroll({top:0,behavior:'smooth'});
            });

            // HTML-Tabelle sortieren
            const table = document.getElementById("foobar-table");
            const headers = table.querySelectorAll("th");
            const tableBody = table.querySelector("tbody");
            const rows = tableBody.querySelectorAll("tr");
            const directions = Array.from(headers).map(function(header) {
                return "";
            });

            // Spalten je nach HTML-Attribut sortieren
            const transform = function(index, content) {
                const type = headers[index].getAttribute("data-type");
                switch (type) {
                    case "number":
                        return parseFloat(content);
                    case "string":
                    default:
                        return content;
                }
            };

            const sortColumn = function(index, headers) {

                // CSS-Klassen entfernen
                const cls = ["upArrow", "dnArrow"];
                headers.forEach((header) => {
                    document.getElementById(header.id).classList.remove(...cls);
                });

                // Richtung aufsteigend (asc) oder absteigend (desc)
                const direction = directions[index] || "asc";
                const multiplier = (direction === "asc") ? 1 : -1;

                // CSS-Klasse hinzufügen
                const cssSort = (direction === "asc") ? cls[0] : cls[1];
                document.getElementById(index).classList.add(cssSort);

                const newRows = Array.from(rows);
                newRows.sort((rowA, rowB) => {
                    const cellA = encodeURIComponent(rowA.querySelectorAll("td")[index].textContent.toLowerCase());
                    const cellB = encodeURIComponent(rowB.querySelectorAll("td")[index].textContent.toLowerCase());

                    const a = transform(index, cellA);
                    const b = transform(index, cellB);

                    switch (true) {
                        case a > b:
                            return 1 * multiplier;
                        case a < b:
                            return -1 * multiplier;
                        case a === b:
                            return 0;
                    }
                });

                [].forEach.call(rows, function(row) {
                    tableBody.removeChild(row);
                });

                directions[index] = direction === "asc" ? "desc" : "asc";
                newRows.forEach(function(newRow) {
                    tableBody.appendChild(newRow);
                });
            };

            [].forEach.call(headers, function(header, index) {
                header.setAttribute("id", index);
                header.addEventListener("click", () => {
                    sortColumn(index, headers);
                });
            });

            // HTML-Tabelle filtern
            document.querySelectorAll('.filter-table').forEach(function(input) {
                var table = document.querySelector(input.dataset.for);
                var rows = table.querySelectorAll('tbody tr');
                input.addEventListener('input', function(event) {
                    rows.forEach(function(tr) {
                        tr.hidden = !tr.textContent.toLowerCase().includes(input.value.toLowerCase());
                    });
                    let filter = ofilter - myTable.querySelectorAll("tr[hidden]").length;
                    myOutput.textContent = (filter < ofilter) ? `${filter} von ${ofilter} Einträgen` : `${ofilter} Einträge`;
                });
            })

            // Tabelle als CSV-Datei exportieren
            const exportBtn = document.getElementById('export');

            const toCsv = function(table) {
                const rows = table.querySelectorAll('tr');

                return [].slice.call(rows)
                    .map(function(row) {
                        const cells = row.querySelectorAll('th,td');
                        return [].slice.call(cells)
                            .map(function(cell) {
                                return cell.textContent;
                            })
                            .join(';'); // Trennzeichen
                    })
                    .join('\n');
            };

            const download = function(text, fileName) {
                const link = document.createElement('a');
                link.setAttribute('href', `data:text/csv;charset=utf-8,${encodeURIComponent(text)}`);
                link.setAttribute('download', fileName);

                link.style.display = 'none';
                document.body.appendChild(link);

                link.click();
                document.body.removeChild(link);
            };

            exportBtn.addEventListener('click', () => {
                const csv = toCsv(table);
                let fileName = document.querySelector('select[name="selection"]').value;
                download(csv, fileName);
            });
        }
    </script>


</head>

<body>

    <p>
        <label>Auswahl:
            <select name="selection" id="selection">
            </select>
        </label>&emsp;
        <button type="button" name="anzeigen">Anzeigen</button> &emsp;
    </p>
    <p>
        <label for="filter">Filter:</label>
        <input type="search" class="filter-table" id="filter" data-for="#foobar-table" spellcheck="false"> &emsp;
        <button type="button" id="export" title="Tabelle als CSV-Datei exportieren">Exportieren</button>
    </p>

    <div id="ausgabe">Wähle eine CSV-Datei aus der Auswahlliste!</div>

</body>

</html>

Siehe auch: CSV-Datei auslesen, HTML-Tabelle filtern, HTML-Tabelle sortieren, HTML-Tabelle Spaltenbreite anpassen, Tabellenkalender und HTML-Tabelle als CSV-Datei exportieren