Laden...

Exceldateien (xls) binär schreiben - Ohne COM-Interop (PIA)

Erstellt von Ruben vor 13 Jahren Letzter Beitrag vor 13 Jahren 10.153 Views
Ruben Themenstarter:in
61 Beiträge seit 2009
vor 13 Jahren
Exceldateien (xls) binär schreiben - Ohne COM-Interop (PIA)

Hallo erstamal,

also möglich ist diese Sache schon, aber ich wollte nur wissen, ob jemand schonmal irgendwo eine Bibliothek dafür gesehen hat.

Das würde mich sehr interessieren.
Hier gibt es die Dokumentation von Microsoft zu dem binären Aufbau der Excel-Dateien.

Oder wäre das eher eine Idee für ein Community-Projekt?

Im Internet bin ich bislang nur auf anderssprachige und kostenpflichtige Teile gestoßen. Bei OpenOffice schau ich noch. Da sollte es sowas eigentlich geben.

EDIT:
Mir geht es dabei um Dateien von 2003 und älter.

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

1.820 Beiträge seit 2005
vor 13 Jahren

Hallo!

Muss es denn unbedingt binär sein, man kann doch auch über ADO.NET Excel-Dateien lesen und schreiben.

Nobody is perfect. I'm sad, i'm not nobody 🙁

F
10.010 Beiträge seit 2004
vor 13 Jahren

Naja, auf Codeproject gibt es schon lange eine Lib dazu.

1.820 Beiträge seit 2005
vor 13 Jahren

Nobody is perfect. I'm sad, i'm not nobody 🙁

Ruben Themenstarter:in
61 Beiträge seit 2009
vor 13 Jahren

Meine Problemstellung ist folgende:

Ich muss Exceldateien lediglich auslesen können, auch wenn das angegebene Office nicht installiert ist. Jedenfalls ist das schneller als die COM-Interop-Schnittstelle, die ich nur zu gerne umgehen möchte.
Bevorzugen tue ich XML in jedem Fall. Ich habe mir bereits eine angepasste Bibliothek für das generieren von XML-Exceldateien geschrieben und klappt wunderbar - nur beim Auslesen ist das nicht sonderlich hilfreich.

Ein weiterer Punkt ist, dass ich ein Programm habe, welches derzeit Excel-Dateien auf XML-Basis generiert, aber wenn ein Anwender nur Office 2000 hat, dann läuft das leider nicht und ich habe deshalb bereits Anfragen bekommen, ob sich das lösen lässt. Natürlich rate ich lieber auf die bessere Office-Version zu upgraden, aber schaden kann es nicht, wenn ich auch die Möglichkeit hätte die binären Exceldateien zu generieren.

Und vielen Dank für eure bisherigen Antworten 😉

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

2.891 Beiträge seit 2004
vor 13 Jahren

Jedenfalls ist das schneller als die COM-Interop-Schnittstelle, die ich nur zu gerne umgehen möchte.

Was verstehst du genau unter "die COM-Interop-Schnittstelle"?

Und auslesen via OleDbConnection kommt nicht infrage? Dafür brauchst du kein installiertes Office, lediglich die passenden OLE-DB-Treiber.

Gruß,
dN!3L

Ruben Themenstarter:in
61 Beiträge seit 2009
vor 13 Jahren

Und auslesen via OleDbConnection kommt nicht infrage? Dafür brauchst du kein installiertes Office, lediglich die passenden OLE-DB-Treiber.

Gruß,
dN!3L

Gut, ich werde das eventuell so machen.

Ich habe das zwar nicht genannt, aber kann man dann auch Excel 2007 - Dateien (xlsx) auf eine binäre oder andere Art effektiv auslesen?
Der OleDB-Treiber (Microsoft.ACE.OLEDB.12.0) für Excel ist leider nicht vorinstalliert. Gibt es da Alternativen? (außer installieren)

EDIT:
Aber das Problem mit den erstellen von Excel-Dateien (xls) im Format für Excel 2000-2003 besteht damit immer noch.

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

2.891 Beiträge seit 2004
vor 13 Jahren

Der OleDB-Treiber (
>
) für Excel ist leider nicht vorinstalliert. Gibt es da Alternativen? (außer installieren)

Mal den JET-Treiber installiert? Im verlinkten Snippet sind beide Varianten drin, weil je nach 32/64 bit mal der eine, mal der andere funktioniert. Treiber sollten z.B. Microsoft Access Database Engine 2010 Redistributable reichen.

Aber das Problem mit den erstellen von Excel-Dateien (xls) im Format für Excel 2000-2003 besteht damit immer noch.

Ich kann damit sowohl XLS- als auch XLSX-Dateien lesen und schreiben...

Gruß,
dN!3:

Ruben Themenstarter:in
61 Beiträge seit 2009
vor 13 Jahren

Mal den JET-Treiber installiert? Im verlinkten Snippet sind beide Varianten drin, weil je nach 32/64 bit mal der eine, mal der andere funktioniert. Treiber sollten z.B.
>
reichen.

Also der Jet-Treiber ist - denke ich - nur für 2003 geeignet. Jedenfalls benutzt du doch in deinem Ausschnitt den Microsoft.ACE.OLEDB.12.0 für xlsx-Mappen. Ich habe mit dem Jet-Treiber kein Ergebnis bei 2007-Mappen erreichen können.

Ich kann damit sowohl XLS- als auch XLSX-Dateien lesen und schreiben...

Auch formatieren? ?(

Muss dazu eine Datei vorhanden sein bzw. müsste ich am besten eine Datei im Format 2000-2003 speichern und in mein Projekt in den Storage packen oder kann ich damit sogar die Dateien ganz erstellen?

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

2.891 Beiträge seit 2004
vor 13 Jahren

Also der Jet-Treiber ist - denke ich - nur für 2003 geeignet. [...] Ich habe mit dem Jet-Treiber kein Ergebnis bei 2007-Mappen erreichen können.

Ich hatte es extra nochmal probiert - mit dem JET konnte ich problemlos eine mit Excel2010 erstellte (xslx-)Datei auslesen.
Excel Connection String Samples - ConnectionStrings.com kennst du?

Auch formatieren?

Nein. Jedenfalls wüsste ich momentan nicht, wie... 😉

Muss dazu eine Datei vorhanden sein [...] oder kann ich damit sogar die Dateien ganz erstellen?

Wenn du im Connectionstring einen nicht vorhandenen Dateinamen angibst, wird sie automatisch erstellt.

Gruß,
dN!3L

Ruben Themenstarter:in
61 Beiträge seit 2009
vor 13 Jahren

Unterstützt der JET-Treiber mit OLEDB kein ALTER TABLE oder habe ich was im Syntax falsch?


ALTER TABLE [Tabelle1$]
	CHANGE F1 Spalte1 varchar(255);
	ADD Spalte2 varchar(255);

Standardmäßig ist in einem leeren Tabellenblatt das Feld F1.
Leider kann ich weder etwas ändern noch hinzufügen.

Kennt wer das Problem?

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

2.891 Beiträge seit 2004
vor 13 Jahren

Wenn du den Befehl so, wie er da steht, absetzt, würde ich drauf tippen, dass er nicht geht. Da steht das Semikolon hinter der Change-Zeile dürfte falsch sein.

Hast du es denn erstmal einfach versucht? Also _entweder _ändern _oder _hinzufügen. Nicht gleich alles in einem Befehl.
Mögliche andere Fehlerquellen, die ich sehe:
Das $ nach dem Tabellennamen will er manchmal, manchmal nicht. Muss man ausprobieren.
Wenn du Spalte "F1" referenzierst, geht das nur bei "HDR=No" im Connectionstring. Mit "HDR=Yes" haben die Spalten als Name den Text aus der ersten Zeile.

Bekommst du eine Fehlermeldung? Wenn ja, welche?

Gruß,
dN!3L

Ruben Themenstarter:in
61 Beiträge seit 2009
vor 13 Jahren

Das Semikolon ist nur hier im Beitrag 😉

Aber ich habe deinen Rat beherzigt und alle einmal durchgetestet.
Einmal HDR=Yes und dann HDR = No

ConnectionString


String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Persist Security Info=False;Extended Properties=\"Excel 8.0;HDR=No\"", filepath)

Folgende (unerfreuliche) Ergebnisse:


HDR = Yes

ALTER TABLE [Tabelle1$] ADD Spalte2 WChar(255);
Exception.Message: Syntaxfehler in Felddefinition.

ALTER TABLE [Tabelle1$] ADD Spalte2 varchar(255);
Exception.Message: Unzulässige Operation.

ALTER TABLE [Tabelle1] ADD Spalte2 varchar(255);
Exception.Message: Tabelle/Einschränkung kann nicht gefunden werden.


HDR = No

ALTER TABLE [Tabelle1$] ADD Spalte2 varchar(255);
Exception.Message: Unzulässige Operation.

ALTER TABLE [Tabelle1$] ADD F2 varchar(255);
Exception.Message: Unzulässige Operation.

ALTER TABLE [Tabelle1] ADD F2 varchar(255);
Exception.Message: Tabelle/Einschränkung kann nicht gefunden werden.

Du hast nicht zufällig auch ein Beispiel, dass ich testen könnte?

siehe Unten

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

2.891 Beiträge seit 2004
vor 13 Jahren

Du hast nicht zufällig auch ein Beispiel, dass ich testen könnte?

Ich helfe ja gern. Aber langsam sieht es so aus wie "mach mal für mich". Du hast schon mehrfach im Forum mein Codesnippet zum Erstellen von Exceldateien mit OLE-DB verlinkt. Das funktioniert einwandfrei (bei mir). Und soweit ich es verstanden habe, auch bei dir.
Und ebendieses Beispiel hättest du zum Testen nehmen können. Du hättest dann auch leicht festgestellt, dass da nirgends ein "varchar(255)" steht.

Also bitte etwas mehr Sorgfalt und systematisches Vorgehen. Wir geben gern Hilfestellung, aber machen hier nicht die Arbeit von anderen...

Da haste ein Snippet mit ALTER TABLE:


string connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source="""+fileName+@""";Extended Properties=""Excel 8.0;HDR=Yes""";
using (OleDbConnection oleDbConnection = new OleDbConnection(connectionString))
using (OleDbCommand oleDbCommand = oleDbConnection.CreateCommand())
{
       oleDbConnection.Open();
#if false
       oleDbCommand.CommandText = "CREATE TABLE [Tabelle6]([Text] Char,[Zahl] Integer,[Datum] Date,[Text2] Char)";
       oleDbCommand.ExecuteNonQuery();
#else
       oleDbCommand.CommandText = "CREATE TABLE [Tabelle6]([Text] Char)";
       oleDbCommand.ExecuteNonQuery();
       oleDbCommand.CommandText = "ALTER TABLE [Tabelle6] ADD [Zahl] Integer";
       oleDbCommand.ExecuteNonQuery();
       oleDbCommand.CommandText = "ALTER TABLE [Tabelle6] ADD [Datum] Date";
       oleDbCommand.ExecuteNonQuery();
       oleDbCommand.CommandText = "ALTER TABLE [Tabelle6] ADD [Text2] Char";
       oleDbCommand.ExecuteNonQuery();
#endif
       oleDbCommand.CommandText = "INSERT INTO [Tabelle6$] ([Text],[Zahl],[Datum]) VALUES (@text,@zahl,'"+DateTime.Now+"')";
       oleDbCommand.Parameters.AddWithValue("@text","1234");
       oleDbCommand.Parameters.AddWithValue("@zahl",1234);
       oleDbCommand.Parameters.AddWithValue("@datum",DateTime.Now);
       for (int i=0;i<5000;i++)
             oleDbCommand.ExecuteNonQuery();

       oleDbCommand.CommandText = "UPDATE [Tabelle6$] SET [Text2]='Hallo'";
       oleDbCommand.ExecuteNonQuery();
}

dN!3L

Ruben Themenstarter:in
61 Beiträge seit 2009
vor 13 Jahren

EDIT: @dN!3L
Entschuldige, dN!3L.
Ich wollte keinesfalls, dass du meine Arbeit übernimmst.
Ich habe lediglich noch nicht alle Ergebnisse meiner Testläufe gepostet.
Schließlich habe die nicht die Geduld immer zu warten bis mir jemand anwortet, sondern versuche derweil selber weiter zu kommen.


Create Table Daten
(
   SPALTENNAME varchar(255)
);

Das ist meine Alternative, dann habe ich eine Tabelle, aber es kommen noch mehr Probleme.

Es ist nicht möglich mehr als einen Datensatz in einem SQL-Statement hinzuzufügen.
Das habe ich auf zwei Arten versucht:
VERSUCH 1 - Mehrfach Values


INSTERT INTO Daten
VALUES
(
     WERT1, WERT2
),
(
     WERT1, WERT2
);

Fehlermeldung: Fehlendes Semikolon.
Jedoch habe ich ein Semikolon gesetzt.
Vermutung: Der Interpreter erwartet das Semikolon nach dem ersten Values-Block, wo jedoch ein Komma steht.

VERSUCH 2 - Mehrere SQL Statements in einem String


INSERT INTO Daten VALUES (WERT1, WERT2);
INSERT INTO Daten VALUES (WERT1, WERT2);
...

Fehlermeldung: Nach der SQL-Anweisung stehen noch weitere Zeichen.
Damit ist es nicht möglich, nachdem man mit einem Semikolon abgeschlossen hat noch weitere SQL-Anweisungen zu schreiben.
Einzige Lösung (das wohl schlimmste überhaupt) die SQL-Anweisungen pro Datensatz in eine For-Schleife packen.
Da kann die Datenbankschnittstelle schon gut mehrere 1000+ mal angesprochen werden. Wie ich finde, nicht die beste Lösung.

Zudem bin ich noch auf ein anderes Problem gestoßen:
Feldgröße zu klein
Leider kann ich nur 255 Zeichen in ein Feld schreiben, aber es kommt vor, dass manche Felder zumindest ein bisschen mehr brauchen. Damit hätte ich noch Datenverlust.

EDIT3:

Da haste ein Snippet mit ALTER TABLE:

Demnach kann ich nur bei selbst erstellten Tabellen ALTER TABLE verwenden und nur über mehrere NonExcecuteQuery() in einer For-Schleife zum hinzufügen von Datensätzen benutzen, richtig?

Gibt es eigentlich eine Lib oder ähnlich, über die man Excel-Dateien binär schreiben kann oder muss man die selber schreiben?

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

2.891 Beiträge seit 2004
vor 13 Jahren

Einzige Lösung (das wohl schlimmste überhaupt) die SQL-Anweisungen pro Datensatz in eine For-Schleife packen. Da kann die Datenbankschnittstelle schon gut mehrere 1000+ mal angesprochen werden. Wie ich finde, nicht die beste Lösung.

Warum? Performance? 1000+ Datensätze einfügen merkst du gar nicht.

Zudem bin ich noch auf ein anderes Problem gestoßen: "Feldgröße zu klein"

Nimm den Datentyp "Text".

Demnach kann ich nur bei selbst erstellten Tabellen ALTER TABLE verwenden

Woraus schlussfolgerst du denn das nun schon wieder? Probier es einfach aus und teil uns das Ergebnis aus.

und nur über mehrere NonExcecuteQuery() in einer For-Schleife zum hinzufügen von Datensätzen benutzen, richtig?

Halte ich für wahrscheinlich. Du kannst ja mal nach einem SQL-Befehl für BulkInsert suchen, der für Excel/OleDB funktioniert.

dN!3L

F
10.010 Beiträge seit 2004
vor 13 Jahren

@Ruben

Gibt es eigentlich eine Lib oder ähnlich, über die man Excel-Dateien binär schreiben kann oder muss man die selber schreiben?

Könnte es sein das Du diesen Post nicht wirklich gelesen hast?
Wir haben dir so etwas schon gleich zu Anfang gepostet.

Ruben Themenstarter:in
61 Beiträge seit 2009
vor 13 Jahren

Zudem bin ich noch auf ein anderes Problem gestoßen: "Feldgröße zu klein"
Nimm den Datentyp "Text".

dN!3L

Danke, das ist das eingzige, dass ich wirklich wissen musste.
Leider wusste ich nicht, dass der Datentyp "Text" heißen muss, aber vermutlich habe ich nicht lange danach gesucht.

Woraus schlussfolgerst du denn das nun schon wieder? Probier es einfach aus und teil uns das Ergebnis aus. KORREKTUR
:::

Das ist leicht: varchar(255) und Char ist im SQL dasselbe. Beides funktioniert in deinem Beispiel mit dem Erstellen von Tabellen.
Und in meinem Post mit den ALTER TABLE [Tabelle1$] ADD Spalte2 ist es dasselbe Prinzip.

Nebenbei: Ich benutzte zusätzlich den Server-Explorer um die Ergebnisse einzusehen und natürlich trenne ich jedes mal die Verbindung, damit die Datei nicht blockiert wird (bin ja nicht blöd - zumindest nicht ganz ^^)

Jetzt habe ich folgenden Test gemacht:


SQL: ALTER TABLE [Tabelle1$] ADD Spalte2 Text;
Error: Unzulässige Operation.
Eine Ausnahme (erste Chance) des Typs "System.Data.OleDb.OleDbException" ist in System.Data.dll aufgetreten.
SQL: ALTER TABLE [Tabelle1] ADD Spalte2 Text;
Error: Tabelle/Einschränkung kann nicht gefunden werden.:
Eine Ausnahme (erste Chance) des Typs "System.Data.OleDb.OleDbException" ist in System.Data.dll aufgetreten.
SQL: ALTER TABLE Tabelle1$ ADD Spalte2 Text;
Error: Syntaxfehler in ALTER TABLE-Anweisung.
Eine Ausnahme (erste Chance) des Typs "System.Data.OleDb.OleDbException" ist in System.Data.dll aufgetreten.
SQL: ALTER TABLE Tabelle1 ADD Spalte2 Text;
Error: Tabelle/Einschränkung kann nicht gefunden werden.

Funktioniert nicht im Server-Explorer und natürlich auch nicht im Code.

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

Ruben Themenstarter:in
61 Beiträge seit 2009
vor 13 Jahren

Könnte es sein das Du diesen Post nicht wirklich gelesen hast?
Wir haben dir so etwas schon gleich zu Anfang gepostet.

Das war etwas unabsichtlich und mein Fehler. Deshalb ja auch ausgegraut.

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

Ruben Themenstarter:in
61 Beiträge seit 2009
vor 13 Jahren

Jetzt treffe ich allmählich an die Grenzen des OleDB-Treibers denke ich ^^.

Beim Schreiben in eine Excel-Datei erhalte ich folgenden Fehler:

Das Datenbankmodul kann '[SpaltennameDerGenau65ZeichenLangIst]' nicht finden. Stellen Sie sicher, dass es sich um einen gültigen Parameter oder Alias-Namen handelt, der keine ungültigen Zeichen oder falsche Zeichensetzung enthält und dessen Name nicht zu lang ist.

Ich vermute das Problem ist klar: 65 Zeichen sind einfach zu viel für den.
Dann wohl doch binär.

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

R
103 Beiträge seit 2009
vor 13 Jahren

Du könntest auch mal das hier ausprobieren:

http://www.codeproject.com/kb/office/ExcelReader.aspx

Sieht auf jeden Fall vielversprechend aus.