mischn1980
Goto Top

Excel XLS - CSV Import in Sql2005

Excel XLS / CSV Import in Sql2005

Hallo,

ich haben ein kleines aber für mich im Moment nicht lösbares Problem.

Gegeben ist eine "CSV"-Datei die wie folgt aufgebaut ist:

Ansicht in Excel:
Feld1 [Tab] Feld2 [Tab] Feld3 [Tab] Feld4 [Tab] etc.....

Ansicht in

Im Quellcode ( C# 2008 ) hab ich das im Moment so gelöst:

string con = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + PFAD+ @";Extended
Properties=""text;HDR=Yes;FMT=Delimited\t;RMT=""";

using (OleDbConnection connection = new OleDbConnection(con))
{
OleDbCommand command = new OleDbCommand("SELECT * FROM [" + DATEINAME+ "]", connection);
connection.Open();

using (OleDbDataReader reader = command.ExecuteReader())
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy("Data Source=RECHNERNAME\\SQLEXPRESS;Initial
Catalog=DATENBANKNAME;Integrated Security=SSPI;"))
{
bulkCopy.DestinationTableName = "TABELLENNAME";
bulkCopy.WriteToServer(reader);
}
}
connection.Close();
}

Die Datei wird importiert jedoch werden alle Werte in die erste Spalte geschrieben.
Der Tabulator wird schön als Quadrat angezeigt.

Was mach ich falsch?
Was kann ich noch versuchen?

Bin wirklich um jeden Info dankbar.

Gruss

Michael

Content-Key: 88331

Url: https://administrator.de/contentid/88331

Printed on: April 19, 2024 at 08:04 o'clock

Member: Biber
Biber May 24, 2008 at 16:39:54 (UTC)
Goto Top
Moin mischn1980,

na ja, Dein Schnipsel works as designed... das wäre die gute Nachricht.
"Bulkcopy" ist ja neudeutsch für "Klumpenkopie"... und der ganze Klump wird eben as is in das erst(best)e Feld reingesemmelt.

Ändere es so, das Deine DB-Engine eine Chance hat, Splaten/Felder zu differenzieren.
OleDbCommand command = new OleDbCommand("SELECT Feld1, feld2, feld3 FROM [" + DATEINAME+ "]", connection);  
connection.Open();

using (OleDbDataReader reader = command.ExecuteReader())
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy("Data Source=RECHNERNAME\\SQLEXPRESS;Initial   
Catalog=DATENBANKNAME;Integrated Security=SSPI;"))  
{
bulkCopy.DestinationTableName = "TABELLENNAME";  
// ab hier neuer:
    SqlBulkCopyColumnMapping mapFeld1 =
    new SqlBulkCopyColumnMapping("Feld1", "ZielFeld1");  
        bulkCopy.ColumnMappings.Add(mapFeld1);

    SqlBulkCopyColumnMapping mapName =
        new SqlBulkCopyColumnMapping("Feld2", "ZielFeld2");  
         bulkCopy.ColumnMappings.Add(mapFeld2);

        SqlBulkCopyColumnMapping mapFeld3 =
             new SqlBulkCopyColumnMapping("Feld3", "ZielFeld3");  
         bulkCopy.ColumnMappings.Add(mapFeld3);



bulkCopy.WriteToServer(reader);
}
[ungetestete Skizze)

P.S. BulkCopy ist zwar ein nettes neues Feature, aber man/frau MUSS es nicht immer nehmen.
Es bringt doch nur dort etwas, wo bei einem satzweisen Schreiben sonst viele Index/Constraint-Prüfungen laufen (würden).
Andererseits kannst Du nur BulkCopys machen (bzw. verantworten), wenn Du vorher den Index DROPst und hinterher neu aufbaust UND auch alle Constraints deaktivierst.

Wat sich auch alles Zeit kosten tut... abgesehen davon, dass Du beim BulkCopy erst hinterher feststellen kannst, ob und was für einen Müll da reingesaugt hast (siehe Deine eigene Beschreibung).

Tipp: Nicht alles benutzen, was neu ist und von M$ als "Feature" bezeichnet wird.

Wie groß ist denn diese XLS-Datei, dass Du ein BulkCopy für sinnhaft gehalten hast?

Grüße
Biber
Member: mischn1980
mischn1980 May 26, 2008 at 06:41:25 (UTC)
Goto Top
Hallo Biber,

vielen Dank schon mal für deine Antwort.

Die Excel-Datei ist nicht so groß aber ich muss rund 3000 importieren.

Die Dateien haben zwischen 30 und 300 Zeilen.

War / Bin der Meinung, dass ich durch den BulkImport Zeit einsparen kann.

Nach dieser Zeile [using (OleDbDataReader reader = command.ExecuteReader())] bekomme ich einen FieldCount von 1.

Hab noch ne weitere Info:


Gruss

Michael
Member: Biber
Biber May 26, 2008 at 07:54:23 (UTC)
Goto Top
Moin michael,

dann ist der (oder ein weiterer) Fehler hier drin.

string con = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + PFAD+ @";Extended Properties=""text;HDR=Yes;FMT=Delimited\t;RMT=""";

  • Entweder bist Du mit der Anzahl oder Position der Anführungszeichen durcheinandergekommen
  • oder das IMHO merkwürdig aussehende "Fmt=Delimited\t;" wird nicht richtig interpretiert. Schreibt man/frau das laut Doku so im Falle TAB is sich Feldtrenner?
  • Und sind auch ganz,ganz sicher TABs drin (nur der Vollständigkeit halber)?

P.S. Unter Deinem "Info folgt" seh ich nur meine Rentenprognose...

Grüße
Biber
Member: mischn1980
mischn1980 May 26, 2008 at 08:09:02 (UTC)
Goto Top
Hi Biber,

ich komm im Moment nicht wirklich drauf was ich da noch schreiben wollte. Ist ein Tel dazwischen gekommen.

Aber zu deiner Frage. Tab ist wirklich der Feldtrenner.
Der Zeilentrenner ist ".

Na ich werd nochmal den con aufbauen und kucken was passiert.

Gruss

Michael
Member: mischn1980
mischn1980 May 26, 2008 at 09:58:08 (UTC)
Goto Top
Also ich kann anstellen was ich will.

Bekomm als ColCount immer 1.

Hab den Delimiter nochmal kontrolliert und es ist Tab.

Gruss

Michael
Member: Biber
Biber May 26, 2008 at 13:20:19 (UTC)
Goto Top
Moin mischn1980,

hast Du auch "Fmt=Delimited" ohne
"\t" schon probiert?
string con = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + PFAD+ @";Extended
Properties=""text;FMT=Delimited;RMT=""";

Grüße
Biber
Member: mischn1980
mischn1980 May 27, 2008 at 07:13:33 (UTC)
Goto Top
Moin,

ja hab ich auch schon versucht.

Das Problem mit dem Trenner ist weg.

Hab im Web noch eine Routine gefunden mit der kann ich alles auslesen.

Dann sind allerdings alle Werte vom Typ String.

Schaffe es im Moment nicht den String in einen Double umzuwandeln.

Bisher hab ich es mit diesem Code versucht:

if (column.DataType == typeof(Double))
{
DataColumn bcol = dtbl.Columns[column.ColumnName];
foreach (DataRow row in dtbl.Rows)
{
if (row[bcol].Equals(""))
row[bcol] = "0.00";
else
row[bcol] = Convert.ToDouble(row[bcol],new
System.Globalization.CultureInfo("en-GB"));
}
}

Am Anfang Frag ich ab ob die "Zelle" keinen Inhalt hat und wenn ja soll er 0,00 eintragen. Wenn etwas drinn steht soll es von String in Double umgewandelt werden.

Das geht allerdings noch nicht. Stell mich im Moment an als ob ich noch nie Code geschrieben hab. Naja ist ja auch mein erstes Projekt seit fast 1,5 Jahren.

Gruss

Michael
Member: mischn1980
mischn1980 May 27, 2008 at 09:58:23 (UTC)
Goto Top
So ich dreh am Rad.

Bekomm Die Umwandlung nicht wirklich hin.

Kann ich da noch eine Hilfestellung bekommen?

Gruss

Michael
Mitglied: 14695
14695 May 28, 2008 at 13:27:11 (UTC)
Goto Top
Hm... an welcher Stelle hakt es denn?
foreach (DataRow row in dtbl.Rows)
{
   if (row[bcol].Equals(""))  
     row[bcol] = "0.00";  
   else
     row[bcol] = Convert.ToDouble(row[bcol], new 
                     System.Globalization.CultureInfo("en-GB"));  


Wird die foreach-Schleife vollständig durchlaufen? Kommt er über If...Else hinweg? Trägt er Werte in die DR ein? Oder wandelt er nur nicht um?
Mitglied: 14695
14695 May 28, 2008 at 13:29:24 (UTC)
Goto Top
Hätte bei genauerem Hinsehen auch drauf kommen können. Du sagst, dass alle Spalten vom Typ "String" sind dann kann

   If(DataColumn.DataType == typeof(Double))

nie true zurück geben.

Auch kannst du in einer Spalte vom Typ String keinen Wert vom Typ Double ablegen...
Member: mischn1980
mischn1980 May 29, 2008 at 06:55:40 (UTC)
Goto Top
Hallo Leute,

jetzt muss ich mich ersteinmal bedanken.

Eure Hilfe war wirklich extrem gut.

Die Software läuft und alle sind Glücklich.

Der Fehler beim double umwandeln war, dass einige Felder

den Wert "" hatten. Die Coodierung en-GB war auch falsch

musste de-GER sein.

Also dann mal vielen Dank an alle.

Gruss

Michael