# React CSV Importer: Spalten zuordnen, Zeilen korrigieren

> Bau einen React CSV Importer in vier Schritten: CSV oder Excel hochladen, Spalten zuordnen, fehlerhafte Zeilen direkt korrigieren, mit Fortschritt importieren.

- Autor: [Serban Rusu](https://wingo-ui.com/blog/authors/serban), Founder of Wingo UI
- Veröffentlicht: 16. Okt. 2026
- Kategorie: [Komponenten-Guides](https://wingo-ui.com/de/blog/category/components)
- Lesezeit: 7 Min.
- Kanonische URL: https://wingo-ui.com/de/blog/react-csv-importer
- Englische Fassung: https://wingo-ui.com/blog/react-csv-importer

## Kurz gesagt

Ein React CSV Importer, mit dem auch Leute ohne Technikwissen ans Ziel kommen, hat vier Schritte: eine CSV- oder Excel-Datei hochladen, ihre Spalten deinen Feldern zuordnen, die Zeilen korrigieren oder überspringen, die an der Validierung scheitern, und dann den Import mit Fortschrittsbalken, Abbrechen-Button und einem Bericht über alles Fehlgeschlagene ausführen. Die Zuordnung sollte Spalten über Namen und Aliase vorab zuweisen, und im Prüfschritt sollte man eine falsche Zelle direkt korrigieren können, statt die Datei zu bearbeiten und von vorn anzufangen. Der CSV Import von Wingo UI erledigt alle vier Schritte mit einem fields-Array und einer onImport-Funktion, und dein Server prüft trotzdem jede Zeile noch einmal.

Die Anfrage klingt einfach: Ein Kunde hat 3.000 Kontakte in einer Tabelle und will sie in deiner App haben. Ein schlichtes File Input und ein Parser bringen dich bis zur Hälfte. Beim Rest geben die Leute auf: Ihre Spalten heißen „E-mail“ statt „Email“, in Zeile 412 steht eine Telefonnummer mit zwei Ziffern, und die Fehlermeldung sagt „Import failed“, ohne Zeilennummer. Ein guter React CSV Importer führt auch Leute ohne Technikwissen durch vier Schritte (hochladen, Spalten zuordnen, Zeilen korrigieren, ausführen) und schickt sie nie zurück in Excel, um es noch einmal zu versuchen. Dieses Tutorial baut einen mit der Komponente [CSV Import](https://wingo-ui.com/components/csv-import) von Wingo UI, der Bibliothek, die wir bauen. Wir sind also nicht neutral; externe Fakten sind mit ihren Quellen verlinkt.

## Was muss ein React CSV Importer können?

Vier Schritte, und jeder beseitigt einen Grund, dem Support zu schreiben:

1. **Hochladen.** Nimm CSV-, TSV- und Excel-Dateien per Drag and Drop, Klick oder Einfügen an und zeig, was gelesen wurde: Zeilen, Spalten, Trennzeichen, Kodierung, Tabellenblatt.
2. **Spalten zuordnen.** Verbinde jedes deiner Felder mit einer Spalte der Datei, vorab über den Namen zugeordnet; über ein Select lässt sich jedes Paar ändern.
3. **Prüfen.** Prüf jede Zeile gegen die Feldtypen, zeig die fehlerhaften Zellen und lass die Leute sie direkt korrigieren oder die Zeile überspringen.
4. **Importieren.** Schick die gültigen Zeilen mit Fortschrittsbalken und Abbrechen-Button und melde danach, was angelegt, aktualisiert, übersprungen und fehlgeschlagen ist. Die fehlgeschlagenen Zeilen gibt es als Datei zum Herunterladen.

Der schnelle Weg zum CSV Import in React ist ein File Input, ein Parser und ein `console.log` der Zeilen. Das deckt Schritt eins ab. Das Open-Source-Paket [react-csv-importer](https://github.com/beamworks/react-csv-importer) (MIT, auf Basis von Papa Parse) geht weiter: Upload, eine Vorschau der Rohdaten und Spaltenzuordnung per Drag and Drop. Zur Validierung der Zeilen steht in der README aber nichts, und das Repository ist seit dem 5. Januar 2024 archiviert (geprüft im Oktober 2026). Schritt drei ist der, der das Support-Ticket erspart, deshalb bekommt er unten den meisten Platz.

## Wie installiere und rendere ich den Import-Wizard?

Installier ihn mit einem CLI-Befehl und render dann `CsvImport` mit zwei Props: den Feldern, die du importierst, und einer Funktion, die die Zeilen speichert.

```bash
npx wingo-ui@latest add csv-import
```

Der Befehl holt auch alles, woraus der Wizard gebaut ist: die Dropzone von [File Upload](https://wingo-ui.com/components/file-upload), die Helfer aus [Spreadsheet](https://wingo-ui.com/components/spreadsheet), die die Datei lesen, die Schritte aus [Form Wizard](https://wingo-ui.com/components/form-wizard) und die Tabelle. `onImport` muss ein Promise auf ein `ImportResult` (`{ created, updated, skipped, failed? }`) zurückgeben. Für den Endpoint unten nehmen wir also an, dass er genau diese Form zurückgibt.

```tsx
"use client";

import { CsvImport, type ImportField } from "@/components/ui/csv-import";

const FIELDS: ImportField[] = [
  { id: "name", label: "Vollständiger Name", required: true, aliases: ["Name", "Contact"] },
  { id: "email", label: "E-Mail", type: "email", required: true, aliases: ["E-mail", "Email address"] },
  { id: "phone", label: "Telefon", type: "phone", aliases: ["Mobile", "Tel"] },
];

export function ImportContacts() {
  return (
    <CsvImport
      fields={FIELDS}
      locale="en-US"
      defaultCountry="US"
      onImport={async (rows, { strategy, signal }) => {
        const response = await fetch("/api/contacts/import", {
          method: "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify({ strategy, rows }),
          signal,
        });
        return response.json();
      }}
    />
  );
}
```

Probier unten den ganzen Ablauf aus. Die Beispieldatei ist ein Kundenexport, in dem ein paar Probleme versteckt sind.

> Live-Demo (CSV Import): Drück „Use the sample file“, prüf die zugeordneten Spalten, geh dann weiter zum Prüfschritt und klick auf eine rot unterstrichene Zelle, um sie vor dem Import zu korrigieren. Probier sie unter [CSV Import](https://wingo-ui.com/components/csv-import) aus und installier sie mit `npx wingo-ui@latest add csv-import`.

## Wie beschreibe ich die Felder?

Das `fields`-Array steuert jeden Schritt: die Zeilen der Zuordnung, die Vorlage zum Herunterladen, die Validatoren und die Form der Zeilen, die du bekommst. Jedes `ImportField` hat eine `id`, ein `label` und optionale Regeln:

- `type`: `text`, `number`, `currency`, `date`, `email`, `phone`, `boolean`, `select`, dazu `cui`, `iban` und `cnp` für rumänische Steuernummern, Bankkonten und Personennummern.
- `required`: Die Zuordnung sperrt „Continue“, bis das Feld eine Spalte hat, und leere Zellen werden zu Fehlern.
- `aliases`: andere Überschriften, die dasselbe Feld meinen. In echten Exporten steht „E-mail“, „Mobile“ oder „Company name“.
- `options` für Selects, mit `keywords` für die Schreibweisen, die Leute wirklich tippen.
- `validate(value, row)` für deine eigene Regel nach der Typprüfung; gibt eine Meldung oder `null` zurück.
- `transform(value)` für den Wert, der an `onImport` geht.
- `example` für die Vorlage.

```tsx
// fields.ts
import type { ImportField } from "@/components/ui/csv-import";

export const FIELDS: ImportField[] = [
  { id: "name", label: "Vollständiger Name", required: true, aliases: ["Name", "Contact"], example: "Emma Carter" },
  {
    id: "email",
    label: "E-Mail",
    type: "email",
    required: true,
    aliases: ["E-mail", "Email address"],
    transform: (value) => String(value).toLowerCase(),
    example: "emma.carter@example.com",
  },
  { id: "phone", label: "Telefon", type: "phone", aliases: ["Mobile", "Tel"], example: "+1 212 555 0147" },
  { id: "company", label: "Firma", aliases: ["Organization", "Account"], example: "Northwind Studio" },
  {
    id: "plan",
    label: "Tarif",
    type: "select",
    options: [
      { value: "free", label: "Free" },
      { value: "team", label: "Team", keywords: ["teams"] },
      { value: "business", label: "Business", keywords: ["biz"] },
    ],
    example: "Team",
  },
  {
    id: "mrr",
    label: "Monatlicher Umsatz",
    type: "currency",
    aliases: ["MRR"],
    validate: (value) => (typeof value === "number" && value < 0 ? "Der Umsatz darf nicht negativ sein" : null),
    example: "49.00",
  },
  { id: "signedUp", label: "Registriert am", type: "date", aliases: ["Created", "Signup date"], example: "09/18/2026" },
];
```

`onImport` bekommt dann typisierte Werte: Zahlen für Beträge, ISO-Daten, Telefonnummern im Format E.164 und die Werte der Optionen statt dessen, was in der Tabelle stand.

## Wie liest der Upload-Schritt CSV- und Excel-Dateien?

Der Upload-Schritt ist ein React CSV Upload in zwei Teilen. Die Dropzone von File Upload kümmert sich um die Eingabe: Drag and Drop, Klick, Enter oder Leertaste, Einfügen und auf dem Handy die native Dateiauswahl. Die Prop `accept` steht standardmäßig auf `.csv,.tsv,.txt,.xlsx` und `maxFileSize` auf 20 MB.

Das Lesen der Datei übernimmt `readSpreadsheet` aus den Spreadsheet-Helfern. Es erkennt, ob Komma, Semikolon, Tab oder Pipe das Trennzeichen ist. Das ist wichtig, weil Excel mit vielen europäischen Ländereinstellungen CSV mit Semikolon speichert. Es liest UTF-16, wenn die Datei mit einer UTF-16-Byte-Order-Mark beginnt, dekodiert den Rest als UTF-8 und fällt auf Windows-1250 zurück, wenn die Bytes kein gültiges UTF-8 sind. Das ist die mitteleuropäische Codepage, so bleiben in einem rumänischen, polnischen oder tschechischen Export aus einem älteren Excel alle Buchstaben erhalten. Eine westeuropäische Datei, die als Windows-1252 gespeichert ist, kommt größtenteils richtig an (é, ü und ç liegen auf denselben Bytes), macht aber aus à ein ŕ, aus è ein č und aus ñ ein ń. Bitte diese Kunden also um „CSV UTF-8“ oder .xlsx. Für Excel-Arbeitsmappen wird das Paket `read-excel-file` erst geladen, wenn jemand eine auswählt. Seiten, die nie eine .xlsx sehen, laden es also nie herunter. Alte binäre .xls-Dateien werden mit der Bitte um .csv oder .xlsx abgelehnt.

> Live-Demo (Spreadsheet): Wähl irgendeine CSV- oder .xlsx-Datei, die du hast: Die Demo zeigt das erkannte Trennzeichen und die Kodierung, wie jede Spalte einem Feld zugeordnet wurde und mit welchem Score, und die ersten Zeilen. Probier sie unter [Spreadsheet](https://wingo-ui.com/components/spreadsheet) aus und installier sie mit `npx wingo-ui@latest add spreadsheet`.

Zwei Details beim Upload sorgen für weniger kaputte Dateien. Ein Link **Download a template** erzeugt eine CSV mit deinen Feld-Labels und ihren `example`-Werten (`templateFileName` gibt ihr den Namen). Und der Schalter „The first row is a header“ hilft bei Exporten, die direkt mit Daten anfangen.

## Wie sollte eine UI zum Zuordnen der CSV-Spalten funktionieren?

Eine gute UI, mit der man CSV-Spalten zuordnen kann, fragt so wenig wie möglich. Jedes Feld bekommt eine Zeile: sein Label und sein Typ, ein Select mit den Spalten der Datei und ein Beispielwert aus der gewählten Spalte. Wenn sich der Wizard öffnet, zeigt jedes Feld schon auf die Spalte, deren Überschrift zu seinem Label, seiner `id` oder einem Alias passt, ohne Rücksicht auf Groß- und Kleinschreibung, Akzente und Satzzeichen. So passt „company_name“ zu „Company name“. Exakte Namen bekommen den Score 1, Teiltreffer weniger, und ein Paar entsteht erst ab einem Score von 0,5. Die Paare mit den besten Scores werden zuerst gebildet, zwei ähnliche Überschriften streiten sich also nie um ein Feld. Zugeordnete Paare tragen das Badge „Matched“.

Die Regeln, die verhindern, dass etwas schiefgeht:

- Jede Spalte wird nur einmal verwendet. Wählst du eine Spalte, die schon ein anderes Feld nutzt, wandert sie hinüber, damit dieselben Daten nicht zweimal importiert werden.
- „Continue“ bleibt deaktiviert, bis jedes Pflichtfeld eine Spalte hat, und die Meldung nennt die fehlenden.
- Jedes Feld hat die Option „Don't import“, zusätzliche Spalten stören also nicht.
- Dateien ohne Kopfzeile lassen sich trotzdem zuordnen: Spalten mit E-Mail, Telefon, Datum und rumänischen IDs werden an ihren Werten erkannt.

Auf dem Handy öffnet sich das Spalten-Select als Bottom Sheet, denn ein Dropdown, das an einem Feld hängt, verdeckt den Daumen, der es geöffnet hat.

## Wie korrigieren Nutzer fehlerhafte Zeilen, ohne den Import zu verlassen?

Prüf jede Zeile, bevor sich der Prüfschritt öffnet, markier jede fehlerhafte Zelle mit dem Grund und lass sie direkt in der Tabelle korrigieren, wo sie sofort neu geprüft wird. Die Zeilen werden schon geprüft, während die Person noch zuordnet (große Dateien in Häppchen von 500 Zeilen, immer dann, wenn der Browser gerade nichts zu tun hat, damit 10.000 Zeilen die Seite nicht einfrieren). Der Prüfschritt ist also fertig, sobald er sich öffnet:

- Ein Filter für All, With errors und Valid.
- Fehlerhafte Zellen bekommen eine rote Wellenlinie und einen Tooltip mit dem Grund („Not an email address“, „Duplicate of row 12“).
- Ein Klick auf eine fehlerhafte Zelle bearbeitet sie direkt. Enter speichert, Escape bricht ab, und die Zeile wird sofort neu geprüft. Nur Zellen mit Fehlern liegen in der Tab-Reihenfolge, wer die Tastatur nutzt, springt also mit Tab von einer zur nächsten.
- Ein Button mit Verbotssymbol überspringt eine einzelne Zeile, und „Skip rows with errors“ lässt alle übrigen fehlerhaften Zeilen weg und schreibt sie in den Bericht.

Setz `allowSkipInvalid={false}`, wenn jede Zeile von Hand korrigiert oder übersprungen werden muss, bevor „Import“ aktiv wird.

Duplikate brauchen einen Schlüssel. Gib `uniqueField="email"` und die E-Mails, die schon in deiner Datenbank stehen, als `existingKeys` mit. Wiederholungen innerhalb der Datei werden zu Fehlern, Zeilen, die es schon gibt, bekommen ein Badge „Exists“, und ein Select fragt, ob sie übersprungen, aktualisiert oder noch einmal angelegt werden. Dein `onImport` bekommt diese Wahl als `context.strategy`. Bei einer großen Tabelle holst du nur die Schlüssel, nicht die Datensätze.

> Live-Demo (CSV Import): Überspringen ist hier abgeschaltet: Klick auf eine rote Zelle, korrigier sie und drück Enter, oder überspring ihre Zeile, bis der Button „Import“ aktiv wird. Probier sie unter [CSV Import](https://wingo-ui.com/components/csv-import) aus und installier sie mit `npx wingo-ui@latest add csv-import`.

## Wie schicke ich die Zeilen mit Fortschrittsbalken und Abbrechen-Button?

`onImport` bekommt die gültigen, nicht übersprungenen Zeilen und einen Kontext mit vier Dingen: `strategy`, `onProgress(done)` für den Fortschrittsbalken, ein `signal`, das der Abbrechen-Button abbricht, und `rows`, die Zeilen aus dem Prüfschritt in derselben Reihenfolge, deren `index` die Zeilennummer ist, wie die Tabelle sie zeigt. Schick die Zeilen in Batches, damit sich der Balken bewegt und Abbrechen zwischen zwei Requests greift:

```tsx
// import-contacts.ts
import type { ImportContext, ImportResult } from "@/components/ui/csv-import";

const BATCH = 200;

export async function importContacts(records: Record<string, unknown>[], context: ImportContext): Promise<ImportResult> {
  const result: ImportResult = { created: 0, updated: 0, skipped: 0, failed: [] };
  for (let start = 0; start < records.length; start += BATCH) {
    const batch = records.slice(start, start + BATCH);
    const response = await fetch("/api/contacts/import", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ strategy: context.strategy, rows: batch }),
      signal: context.signal,
    });
    if (!response.ok) throw new Error("Der Server hat den Import abgelehnt. Versuch es in einer Minute noch einmal.");
    const saved: { created: number; updated: number; skipped: number; failed: { position: number; error: string }[] } =
      await response.json();
    result.created += saved.created;
    result.updated += saved.updated;
    result.skipped += saved.skipped;
    for (const { position, error } of saved.failed) {
      result.failed?.push({ index: context.rows[start + position].index, error });
    }
    context.onProgress(start + batch.length);
  }
  return result;
}
```

Wirft die Funktion einen Fehler, zeigt der Wizard dessen Meldung mit einem Button „Try again“. Abbrechen bricht `context.signal` ab, der offene `fetch`-Aufruf schlägt fehl, und der Lauf endet mit „Import cancelled after N rows“, wobei N der letzte Wert ist, den du an `onProgress` gegeben hast. Der Wizard bricht das Signal auch beim Unmount ab. Wer wegnavigiert, lässt also keine Requests weiterlaufen. Die Zusammenfassung zeigt dann Kacheln für angelegte, aktualisierte, übersprungene und fehlgeschlagene Zeilen, listet die Zeilen, die es nicht geschafft haben, mit ihrem Grund auf und bietet **Download failed rows** an: eine CSV mit einer Spalte „Error“, die die Person korrigieren und erneut importieren kann.

## Warum muss der Server die Zeilen noch einmal prüfen?

Jeder kann beliebiges JSON an `/api/contacts/import` posten. Die Prüfungen im Browser sind also für die Person da, die Prüfungen auf dem Server für deine Daten. Die Komponente exportiert `validateImportRows`, eine reine Funktion, die die Prüfungen des Wizards auf rohe Zeilen anwendet. `csv-import.tsx` beginnt aber mit `"use client"`, also pack die Regeln für den Server in ein eigenes Modul:

```ts
// app/api/contacts/import/route.ts
import { saveContact } from "@/lib/contacts"; // deine Datenschicht: gibt "created" | "updated" | "skipped" zurück

const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

export async function POST(request: Request) {
  const { strategy, rows } = (await request.json()) as {
    strategy: "skip" | "update" | "create";
    rows: Record<string, unknown>[];
  };
  if (!Array.isArray(rows) || rows.length > 200) return Response.json({ error: "Schick höchstens 200 Zeilen" }, { status: 400 });

  const result = { created: 0, updated: 0, skipped: 0, failed: [] as { position: number; error: string }[] };
  for (const [position, row] of rows.entries()) {
    if (typeof row?.name !== "string" || !row.name.trim()) {
      result.failed.push({ position, error: "Der Name fehlt" });
      continue;
    }
    if (typeof row.email !== "string" || !EMAIL.test(row.email)) {
      result.failed.push({ position, error: "Keine gültige E-Mail-Adresse" });
      continue;
    }
    result[await saveContact(row, strategy)]++;
  }
  return Response.json(result);
}
```

Auch die andere Richtung braucht Sorgfalt. Der Bericht der fehlgeschlagenen Zeilen und die Vorlage sind CSV-Dateien, die Leute in Excel öffnen, und eine Zelle, die mit `=` beginnt, kann als Formel ausgeführt werden. [Die OWASP-Seite zu CSV Injection](https://community.owasp.org/attacks/CSV_Injection) nennt als eine Abwehr, solchen Zellen ein einfaches Anführungszeichen voranzustellen, und warnt, dass Excel es nach Speichern und erneutem Öffnen verlieren kann (geprüft im Oktober 2026). `toCsv` aus den Spreadsheet-Helfern macht das standardmäßig für Zellen, die mit `=`, `+`, `-`, `@`, Tab oder Wagenrücklauf beginnen, und der Importer entfernt dieses Anführungszeichen wieder, wenn eine Zelle wie `'=SUM(A1)` in einer Datei zurückkommt.

## Was ändert sich auf dem Handy?

Unter 768px füllt der Wizard seinen Container mit einem Sticky Header und Footer und 48px hohen Buttons (`fullScreenOnMobile`, standardmäßig an, gib dem Container also eine Höhe). Der Stepper wird zu einer kompakten Fortschrittszeile, die Zeilen im Prüfschritt werden zu Karten, und ein Tipp auf einen Wert öffnet ein Sheet mit dem Feld, seinem Fehler und einem einzigen Button zum Speichern. Wer den Import aus einer E-Mail auf dem Handy öffnet, kann ihn also trotzdem abschließen. Mehr zu diesem Muster steht im Beitrag über [responsive Tabellen, die zu Karten werden](https://wingo-ui.com/de/blog/responsive-table-mobile-cards).

## Mit welchen Dateien sollte ich einen CSV Importer testen?

Teste mit den Dateien, die Kunden wirklich schicken werden, denn der saubere Export, den du selbst gemacht hast, besteht jede Prüfung. Leg dir einen kleinen Ordner damit an und schick jede Datei vor dem Launch durch alle vier Schritte:

- Eine CSV mit Semikolon und Dezimalkomma, aus einem Excel mit europäischer Ländereinstellung.
- Eine Datei mit akzentuierten Namen, gespeichert als Windows-1250, eine als Windows-1252 (achte auf à, è und ñ) und eine mit einer UTF-8-Byte-Order-Mark.
- Einen Export ohne Kopfzeile.
- Zellen in Anführungszeichen, die Kommas, verdoppelte Anführungszeichen und Zeilenumbrüche enthalten.
- Eine Arbeitsmappe mit mehreren Tabellenblättern und eine alte .xls-Datei, die mit einer klaren Meldung abgelehnt werden sollte.
- Eine Datei über dem Zeilenlimit. `maxRows` steht standardmäßig auf 10.000; der Rest wird abgeschnitten, und eine Warnung sagt das.
- Denselben Kunden zweimal und einen Kunden, den du schon hast.

Wenn jede dieser Dateien entweder sauber importiert wird oder mit einer Meldung endet, die sagt, was zu ändern ist, wird das Support-Ticket aus dem ersten Absatz nie geschrieben.

## Soll ich den Import selbst bauen oder einen gehosteten Importer nutzen?

Nimm einen gehosteten Importer, wenn du das Ganze lieber im Dashboard eines Anbieters konfigurierst, als den Code selbst zu verantworten. [CSVbox](https://csvbox.io) ist ein Beispiel: Ein JS-Snippet fügt ein Import-Modal hinzu, Dateien werden auf seiner Infrastruktur in einer Region deiner Wahl verarbeitet, und sein Private Mode parst, ordnet zu und validiert im Browser der Person und schickt die Zeilen an deinen eigenen Endpoint (geprüft im Oktober 2026). Nimm eine Komponente, wenn du den Importer in deinem Repository haben willst, typisiert gegen deine eigenen Felder, zusammen mit dem Rest der App reviewt und versioniert und im selben Look. CSV Import ist eine Pro-Komponente ([Preise](https://wingo-ui.com/de/pricing)); jeder Text ist eine `labels`-Prop, und `tone`, `size` und `stepper` ändern das Aussehen, ohne dass du neu stylen musst.

## Wie sieht der fertige Import-Assistent für CSV und Excel aus?

Es ist eine einzige Client-Komponente, die die Felder, das `onImport` mit Batches und die Duplikatprüfung zusammenbringt. Excel-Arbeitsmappen laufen durch dieselben vier Schritte wie CSV-Dateien, dieselbe Seite funktioniert also auch als Excel-Import-Assistent:

```tsx
"use client";

import { CsvImport } from "@/components/ui/csv-import";
import { FIELDS } from "./fields";
import { importContacts } from "./import-contacts";

export function ImportContactsPage({ existingEmails }: { existingEmails: string[] }) {
  return (
    <div className="h-[100dvh] md:h-auto">
      <CsvImport
        fields={FIELDS}
        onImport={importContacts}
        uniqueField="email"
        existingKeys={existingEmails}
        defaultDuplicateStrategy="update"
        locale="en-US"
        defaultCountry="US"
        currency="USD"
        dateFormat="MM/DD/YYYY"
        templateFileName="contacts-template"
      />
    </div>
  );
}
```

Für die Schritte selbst außerhalb eines Imports lies das [Tutorial zum React Multi Step Form](https://wingo-ui.com/de/blog/react-multi-step-form), und für die Dropzone allein die [Anleitung zum React File Upload](https://wingo-ui.com/de/blog/react-file-upload). Der [Guide zu React-Formularkomponenten](https://wingo-ui.com/de/blog/react-form-components-guide) behandelt den Aufbau der Felder, den all diese Komponenten teilen, und weitere Anleitungen zu Komponenten findest du in der [Kategorie Komponenten](https://wingo-ui.com/de/blog/category/components).

## Nächster Schritt

Installier den Wizard mit `npx wingo-ui@latest add csv-import`, stell `fields` auf die Tabelle ein, die du am häufigsten importierst, und schick deinen chaotischsten echten Export hindurch, bevor ein Kunde es tut.

## Komponenten in diesem Artikel

- [CSV Import](https://wingo-ui.com/components/csv-import) (Pro): A React CSV import wizard for CSV and Excel files in four steps: upload, column mapping, row review with inline fixes, and a run report. Installation: `npx wingo-ui@latest add csv-import`
- [Spreadsheet](https://wingo-ui.com/components/spreadsheet) (Pro): Read CSV and Excel files in the browser, match their columns to your fields, and write CSV that Excel opens with diacritics intact. Installation: `npx wingo-ui@latest add spreadsheet`
- [File Upload](https://wingo-ui.com/components/file-upload) (Pro): A React file upload with drag and drop, paste and camera capture: validation, previews, per-file progress, and list, grid or avatar layouts. Installation: `npx wingo-ui@latest add file-upload`

## Häufige Fragen

### Wie importiere ich eine CSV-Datei in React?

Lies die Datei im Browser mit der File API, parse sie mit einem Parser nach RFC 4180, der Anführungszeichen und Zeilenumbrüche in Zellen versteht, ordne dann die Spalten deinen Feldern zu und validiere jede Zeile, bevor du sie abschickst. Eine Wizard-Komponente wie der CSV Import von Wingo UI fasst diese Schritte zusammen, du beschreibst also nur die Felder und schreibst die Funktion, die die Zeilen speichert.

### Kann ein React CSV Importer Excel-Dateien lesen?

Ja, wenn er .xlsx im Browser parst. Der CSV Import von Wingo UI liest .xlsx über read-excel-file, das erst geladen wird, wenn jemand eine Arbeitsmappe auswählt, und lässt das Tabellenblatt wählen. Alte binäre .xls-Dateien lehnt er mit der Bitte um .csv oder .xlsx ab.

### Wie sollte die Spaltenzuordnung bei einem CSV-Import funktionieren?

Weise jedem Feld vorab die Spalte zu, deren Überschrift zu seinem Namen oder einem seiner Aliase passt, ohne Rücksicht auf Groß- und Kleinschreibung, Akzente und Satzzeichen, und lass jedes Paar über ein Select ändern. Sperr den nächsten Schritt, bis jedes Pflichtfeld eine Spalte hat, und nenn die Felder, die noch fehlen.

### Sollte ich CSV-Zeilen im Client oder auf dem Server validieren?

Beides. Prüfungen im Client geben im Prüfschritt sofort Feedback, so korrigieren die Leute Fehler, bevor sie absenden. Der Server muss noch einmal prüfen, denn jeder kann deinen Import-Endpoint mit beliebigem JSON aufrufen.

### Wie gehe ich bei einem CSV-Import mit doppelten Zeilen um?

Wähl ein Feld als Schlüssel, etwa die E-Mail, markier Wiederholungen innerhalb der Datei als Fehler und kennzeichne Zeilen, deren Schlüssel es in deinen Daten schon gibt. Lass die Person dann entscheiden, ob diese Zeilen übersprungen, aktualisiert oder noch einmal angelegt werden, und gib diese Wahl an den Server weiter.

---

Quelle: https://wingo-ui.com/de/blog/react-csv-importer
