Hallo Walter,
super, dass es geklappt hat.
Hier mal mein Skript. Mittlerweile habe ich das aber doch einigermaßen “aufgebohrt”. Als Goodie wird nun zumindest für unsere deutschen Kunden auch noch das passende Bundesland aus der Plz ermittelt und eingetragen - ist ganz nett 
Es ist auch immer noch nicht ganz fertig (das Feld “Sonstiges” meiner alten Kartei wird bspw. noch nicht übernommen), aber mein altes System läuft ja auch noch und wenn dann alles bei Dolibarr eingerichtet ist, dann wird migriert.
Natürlich ist es auch nicht optimiert - aber meine knapp 9000 Kunden wurden in knapp einer Minute übernommen.
Meine CSV hat folgende Spalten:
„Kd.-Nr.“,„R-Anrede“,„R-Vorname“,„R-Nachname“,„R-Unternehmen“,„R-Anschrift 1“,„R-Anschrift 2“,„R-Anschrift 3“,„R-Plz“,„R-Ort“,„R-Land“,„L-Anrede“,„L-Vorname“,„L-Nachname“,„L-Unternehmen“,„L-Anschrift 1“,„L-Anschrift 2“,„L-Anschrift 3“,„L-Plz“,„L-Ort“,„L-Land“,„E-Mail“,„Telefon“,„Telefax“,„USt.-IDNr.“,„Gutschriften“,„Werbung“,„Rechnungen“,„Sonstiges“
Ich hoffe, soweit reichen die Kommentare. Bei Fragen: fragen!
Und auch Verbesserungen und Korrekturen werden gerne gesehen 
Viele Grüße,
Christoph
<?php
// Nur CLI erlauben
if (php_sapi_name() !== 'cli')
{
die("Nur CLI erlaubt\n");
}
define('NOLOGIN', 1);
define('NOCSRFCHECK', 1);
define('NOREQUIREMENU', 1);
define('NOREQUIREHTML', 1);
define('NOIPCHECK', 1);
require __DIR__ . '/../dolibarr/htdocs/main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
global $db, $user;
// Admin-User laden (wichtig für create/delete Rechte)
$user = new User($db);
$user->fetch(1);
//$file = fopen('kundenadressen-test.csv', 'r');
$file = fopen('kundenadressen et-faktura.csv', 'r');
if (!$file)
{
die("CSV nicht gefunden\n");
}
// Header lesen (Komma-getrennt!)
$header = fgetcsv($file, 0, ',');
print "Starte Import...\n";
// Hole die Typenummern für die Standardkontakteinträge für Rechnung und Lieferadresse
$typeBilling = 0;
$typeShipping = 0;
$sql = "SELECT rowid, code
FROM ".MAIN_DB_PREFIX."c_type_contact
WHERE element='facture'
AND source='external'
AND code IN ('BILLING','SHIPPING')";
$res = $db->query($sql);
while ($obj = $db->fetch_object($res))
{
if ($obj->code === 'BILLING') {
$typeBilling = $obj->rowid;
}
if ($obj->code === 'SHIPPING') {
$typeShipping = $obj->rowid;
}
}
// Debug
echo "\nRechnung: " . $typeBilling . "\n";
echo "Lieferung: " . $typeShipping . "\n\n";
$plzMap = [
'01'=>'Sachsen',
'02'=>'Sachsen',
'03'=>'Brandenburg',
'04'=>'Sachsen',
'05'=>'Nordrhein-Westfalen',
'06'=>'Sachsen-Anhalt',
'07'=>'Thüringen',
'08'=>'Sachsen',
'09'=>'Sachsen',
'10'=>'Berlin',
'11'=>'Berlin',
'12'=>'Brandenburg',
'13'=>'Brandenburg',
'14'=>'Brandenburg',
'15'=>'Brandenburg',
'16'=>'Brandenburg',
'17'=>'Mecklenburg-Vorpommern',
'18'=>'Mecklenburg-Vorpommern',
'19'=>'Mecklenburg-Vorpommern',
'20'=>'Hamburg',
'21'=>'Hamburg',
'22'=>'Hamburg',
'23'=>'Schleswig-Holstein',
'24'=>'Schleswig-Holstein',
'25'=>'Schleswig-Holstein',
'26'=>'Niedersachsen',
'27'=>'Niedersachsen',
'28'=>'Bremen',
'29'=>'Niedersachsen',
'30'=>'Niedersachsen',
'31'=>'Niedersachsen',
'32'=>'Nordrhein-Westfalen',
'33'=>'Nordrhein-Westfalen',
'34'=>'Hessen',
'35'=>'Hessen',
'36'=>'Hessen',
'37'=>'Niedersachsen',
'38'=>'Niedersachsen',
'39'=>'Sachsen-Anhalt',
'40'=>'Nordrhein-Westfalen',
'41'=>'Nordrhein-Westfalen',
'42'=>'Nordrhein-Westfalen',
'43'=>'Nordrhein-Westfalen',
'44'=>'Nordrhein-Westfalen',
'45'=>'Nordrhein-Westfalen',
'46'=>'Nordrhein-Westfalen',
'47'=>'Nordrhein-Westfalen',
'48'=>'Nordrhein-Westfalen',
'49'=>'Niedersachsen',
'50'=>'Nordrhein-Westfalen',
'51'=>'Nordrhein-Westfalen',
'52'=>'Nordrhein-Westfalen',
'53'=>'Nordrhein-Westfalen',
'54'=>'Rheinland-Pfalz',
'55'=>'Rheinland-Pfalz',
'56'=>'Rheinland-Pfalz',
'57'=>'Nordrhein-Westfalen',
'58'=>'Nordrhein-Westfalen',
'59'=>'Nordrhein-Westfalen',
'60'=>'Hessen',
'61'=>'Hessen',
'62'=>'Hessen',
'63'=>'Hessen',
'64'=>'Hessen',
'65'=>'Hessen',
'66'=>'Saarland',
'67'=>'Rheinland-Pfalz',
'68'=>'Baden-Württemberg',
'69'=>'Baden-Württemberg',
'70'=>'Baden-Württemberg',
'71'=>'Baden-Württemberg',
'72'=>'Baden-Württemberg',
'73'=>'Baden-Württemberg',
'74'=>'Baden-Württemberg',
'75'=>'Baden-Württemberg',
'76'=>'Baden-Württemberg',
'77'=>'Baden-Württemberg',
'78'=>'Baden-Württemberg',
'79'=>'Baden-Württemberg',
'80'=>'Bayern',
'81'=>'Bayern',
'82'=>'Bayern',
'83'=>'Bayern',
'84'=>'Bayern',
'85'=>'Bayern',
'86'=>'Bayern',
'87'=>'Bayern',
'88'=>'Baden-Württemberg',
'89'=>'Bayern',
'90'=>'Bayern',
'91'=>'Bayern',
'92'=>'Bayern',
'93'=>'Bayern',
'94'=>'Bayern',
'95'=>'Bayern',
'96'=>'Bayern',
'97'=>'Bayern',
'98'=>'Bayern',
'99'=>'Thüringen'
];
// -----------------------------
// Bundesland aus PLZ ermitteln (nur für DE)
// -----------------------------
function getStateIdFromZip($zip, $country_code, $plzMap, $db)
{
if (strtoupper($country_code) !== 'DE') return 0; // nur Deutschland
$state_name = '';
$zipPrefix = substr($zip, 0, 2); // nur die ersten 2 Ziffern
if (isset($plzMap[$zipPrefix])) {
$state_name = $plzMap[$zipPrefix];
}
if ($state_name) {
$sql = "SELECT rowid
FROM ".MAIN_DB_PREFIX."c_departements
WHERE LOWER(nom) LIKE LOWER('%".$db->escape($state_name)."%')
LIMIT 1";
$res = $db->query($sql);
if ($res) {
if ($obj = $db->fetch_object($res)) {
return (int)$obj->rowid;
}
} else {
// Abfrage fehlgeschlagen – Debugausgabe
dol_syslog("getStateIdFromZip SQL-Fehler: ".$db->lasterror()." SQL=".$sql, LOG_ERR);
}
}
return 0; // fallback
}
// Mapping CSV Anrede → Dolibarr Code
$anredeMapping = [
'Herr' => 'MR',
'Mr.' => 'MR',
'Frau' => 'MME',
'Mrs.' => 'MME'
];
// Für Tests eine maximale Anzahl an Datensätzen einlesen
$max_data = 100;
$nr_of_data = 0;
while (($data = fgetcsv($file, 0, ',')) !== false)
{
// Anzahl der Testdatensätze erreicht?
$nr_of_data ++;
if ($nr_of_data >= $max_data) break;
$row = array_combine($header, $data);
$db->begin();
try {
// -----------------------------
// Kundennummer 5-stellig
// -----------------------------
$code_client = trim($row['Kd.-Nr.'] ?? '');
if (ctype_digit($code_client)) {
$code_client = sprintf('%05d', $code_client);
}
// -----------------------------
// Name bestimmen
// -----------------------------
$firma = trim($row['R-Unternehmen'] ?? '');
$vorname = trim($row['R-Vorname'] ?? '');
$nachname = trim($row['R-Nachname'] ?? '');
// Anrede bei Rechnungsadresse
$r_anrede = trim($row['R-Anrede'] ?? '');
$civilityCodeBilling = $anredeMapping[$r_anrede] ?? '';
// Anrede bei Lieferadresse
$l_anrede = trim($row['L-Anrede'] ?? '');
$civilityCodeShipping = $anredeMapping[$l_anrede] ?? '';
// Wenn Kein Namen angegeben war, dann setze id eFirmenadresse in den Kontaktnamen/-bezeichnung
// Dann gibt es auch keine Anrede
if ($vorname === '' && $nachname === '' && $firma !== '')
{
$nachname = $firma;
$civilityCodeBilling = '';
$civilityCodeShipping = '';
}
$name = ($firma !== '') ? $firma : trim($vorname . ' ' . $nachname);
// -----------------------------
// Rechnungsadresse zusammenbauen
// -----------------------------
$addressParts = [];
foreach (['R-Anschrift 1','R-Anschrift 2','R-Anschrift 3'] as $field)
{
$val = trim($row[$field] ?? '');
if ($val !== '') {
$addressParts[] = $val;
}
}
$address = implode("\n", $addressParts);
$zip = trim($row['R-Plz'] ?? '');
$town = trim($row['R-Ort'] ?? '');
$country = trim($row['R-Land'] ?? 'DE');
$email = trim($row['E-Mail'] ?? '');
$phone = trim($row['Telefon'] ?? '');
$fax = trim($row['Telefax'] ?? '');
$vat = trim($row['USt.-IDNr.'] ?? '');
// -----------------------------
// Firma anlegen
// -----------------------------
$soc = new Societe($db);
$soc->name = $name;
$soc->code_client = $code_client;
$soc->address = $address;
$soc->zip = $zip;
$soc->town = $town;
$soc->country_code = $country;
$soc->email = $email;
$soc->phone = $phone;
$soc->fax = $fax;
$soc->tva_intra = $vat;
$soc->state_id = getStateIdFromZip($zip, $country, $plzMap, $db); // nur DE
$soc->client = 1; // Kunde
$soc->fournisseur = 0; // Kein Lieferant
$soc->status = 1;
$result = $soc->create($user);
// Debug
//if ($code_client == "08696") echo ">>>>>>>>>>";
//echo " Kundennr.: " . $code_client . " " . $soc->state_id . "\n";
if ($result <= 0) {
throw new Exception($soc->error);
}
$socid = $soc->id;
// -----------------------------
// Vertriebsmitarbeiter ENTFERNEN
// -----------------------------
$db->query("DELETE FROM ".MAIN_DB_PREFIX."societe_commerciaux WHERE fk_soc = ".((int)$socid));
// -----------------------------
// Hauptkontakt = Rechnungsadresse
// -----------------------------
$billing = new Contact($db);
$billing->socid = $socid;
$billing->firstname = $vorname;
$billing->lastname = $nachname;
//$billing->poste = 'Rechnungsadresse';
$billing->address = $address;
$billing->zip = $zip;
$billing->town = $town;
$billing->country_id = getCountry($country, '3'); // ISO2 aus CSV → interne ID
$billing->email = $email;
$billing->phone_pro = $phone;
$billing->status = 1;
$billing->civility_code = $civilityCodeBilling;
$billing->state_id = getStateIdFromZip($zip, $country, $plzMap, $db); // nur DE
// Nach Anlegen setze den Standardkontakttyp auf Rechnung
if ($billing->create($user) > 0)
{
$db->query("
INSERT INTO ".MAIN_DB_PREFIX."societe_contacts
(entity, date_creation, fk_soc, fk_c_type_contact, fk_socpeople)
VALUES
(1, NOW(), ".$socid.", ".$typeBilling.", ".$billing->id.")
");
}
$billing->update($billing->id, $user); // Erst jetzt wird country_code gespeichert (bei create nicht!)
// -----------------------------
// Lieferadresse
// -----------------------------
$shipParts = [];
foreach (['L-Anschrift 1','L-Anschrift 2','L-Anschrift 3'] as $field)
{
$val = trim($row[$field] ?? '');
if ($val !== '') {
$shipParts[] = $val;
}
}
$shippingAddress = implode("\n", $shipParts);
if ($shippingAddress === '') {
$shippingAddress = $address;
}
$shipping = new Contact($db);
$shipping->socid = $socid;
$shipping->firstname = $vorname;
$shipping->lastname = $nachname;
//$shipping->poste = 'Lieferadresse';
$shipping->address = $shippingAddress;
$shipping->zip = trim($row['L-Plz'] ?? $zip);
$shipping->town = trim($row['L-Ort'] ?? $town);
$l_country = trim($row['L-Land'] ?? $country);
$shipping->country_id = getCountry($l_country, '3');
$shipping->email = $email;
$shipping->phone_pro = $phone;
$shipping->status = 1;
$shipping->civility_code = $civilityCodeShipping;
$shipping->state_id = getStateIdFromZip($shipping->zip, $l_country, $plzMap, $db);
// Nach Anlegen setze den Standardkontakttyp auf Rechnung
if ($shipping->create($user) > 0)
{
$db->query("
INSERT INTO ".MAIN_DB_PREFIX."societe_contacts
(entity, date_creation, fk_soc, fk_c_type_contact, fk_socpeople)
VALUES
(1, NOW(), ".$socid.", ".$typeShipping.", ".$shipping->id.")
");
}
$shipping->update($shipping->id, $user); // Erst jetzt wird country_code gespeichert (bei create nicht!)
$db->commit();
print "Importiert: $code_client\n";
}
catch (Exception $e)
{
$db->rollback();
print "Fehler bei ".$row['Kd.-Nr.'].": ".$e->getMessage()."\n";
}
}
fclose($file);
print "Fertig.\n";