Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Excel - Export ohne Excel - Problem beim erzeugen (https://www.delphipraxis.net/51636-excel-export-ohne-excel-problem-beim-erzeugen.html)

padavan 16. Aug 2005 10:46


Excel - Export ohne Excel - Problem beim erzeugen
 
Hallo Delphianer,

habe folgendes Problem:

mit diesem Code lässt sich mit einer zusätzlichen Unit eine Excel-Datei erzeugen ohne eine lauffähige Installation:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var XLSFile : TXLSExport;
    x, y   : Integer;
begin
  if savedialog1.Execute then begin
    if fileexists(savedialog1.filename) then DeleteFile(savedialog1.filename);
    XLSFile := TXLSExport.Create(savedialog1.filename);
    try
      y := 0;
      table1.DisableControls;
      table1.First;
      while not table1.eof do begin
        if y = 0 then begin // Kopfzeilen
           for x := 0 to table1.FieldCount-1 do XLSFile.Write( x, y, table1.Fields[x].displayname);
        end else for x := 0 to table1.FieldCount-1 do begin
          case table1.Fields[x].DataType of
            ftDate,
            ftTime,
            ftDateTime,
            ftBoolean,
            ftString,
            ftFixedChar : XLSFile.Write( x, y, table1.Fields[x].asstring);
            ftAutoInc,
            ftSmallint,
            ftInteger,
            ftWord      : XLSFile.Write( x, y, table1.Fields[x].asInteger);
            ftFloat,
            ftCurrency  : XLSFile.Write( x, y, table1.Fields[x].asFloat);
          end;
        end;
        inc(y);
        table1.next;
      end;
      XLSFile.free;
    finally
    end;
    table1.EnableControls;
  end;
end;

Diese habe ich abgeändert, da ich im Prinzip das gleiche aber aus einer Stringgrid exportieren möchte:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var XLSFile : TXLSExport;
    x, y   : Integer;
    Spalten, Zeilen: String;
begin
  if savedialog1.Execute then begin
    if fileexists(savedialog1.filename) then DeleteFile(savedialog1.filename);
    XLSFile := TXLSExport.Create(savedialog1.filename);
    try
      y := 0;
      repeat
        Spalten := StringGrid2.Cells[x,y];
        XLSFile.Write(x,y,Spalten);
        x := 0;
        repeat
          Zeilen := StringGrid2.Cells[x,y];
          XLSFile.write(x,y, Zeilen);
          x := x + 1;
        until x = StringGrid2.ColCount;
        y := y + 1;
      until y = StringGrid2.RowCount;
    finally
      XLSFile.free;
    end;
  end;
end;
Nun funktioniert das aber nicht richtig, die Datei wird zwar erzeugt, aber nicht korrekt. Das heißt Excel XP kann sie öffnen, sagt aber, dass die Datei repariert werden musste. Nach dem Öffnen ist sie dann auch so wie sie sein soll.

Dennoch ist dieser Zustand logischerweise unbefriedigend.

Meine Vermutung ist, dass es daran liegt:
Delphi-Quellcode:
XLSFilewrite(x,y, .....asstring);
Obwohl ich dachte, dass ein String nicht extra umgewandelt werden muss, ist wohl doch so, anders kann ich es mir nicht erklären.

Meine Frage ist nun, wie lautet die korrekte Syntax für meinen modifizierten Programmteil?
Habe alles mögliche versucht, Delphi bietet in der IDE sogar was an, meckert dann aber beim Übersetzen.

Delphi-Quellcode:
XLSFilewrite(x,y,asstring(Zeilen);
Danke im Voraus

padavan 17. Aug 2005 06:12

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Kann mir keiner helfen --> ich weiß, es ist viel Text. :cry:

Es geht im Grunde nur um die korrekte Syntax von


Delphi-Quellcode:
.asstring...

alzaimar 17. Aug 2005 06:48

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Die Deklaration von XLSFileWrite wäre ganz sinnvoll.
Wie ist das denn deklariert? Als 'Procedure XLSFileWrite (X,y : Integer; Const s : String)' oder wie?
Und, was ist das für eine XLS-Unit? Klingt interessant.

padavan 17. Aug 2005 06:58

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hallo alzaimar,

ich habe nichts ausgelassen. Da ist der komplette Auschnitt aus dem Programm.
Ich hatte wiegesagt vermutet, dass sich die Deklaration aus dem .asstring ergeben soll....



Hier die Unit:

Delphi-Quellcode:
unit u_ExportEXCEL;

interface
uses classes;

type TXLSExport = class(TObject)
                  private
                     fs : TFilestream;
                  public
                     constructor Create(filename : string);
                     destructor Destroy; override;
                     procedure Write(const Col, Row: Word; const Value: Integer); overload;
                     procedure Write(const Col, Row: Word; const Value: Double); overload;
                     procedure Write(const Col, Row: Word; const Value: string); overload;
                  end;


implementation

const
  CXlsBof   : array[0..5] of Word = ($809, 8, 00, $10, 1, 0);
  CXlsEof   : array[0..1] of Word = ($0A, 00);
  CXlsLabel : array[0..5] of Word = ($204, 0, 0, 0, 0, 0);
  CXlsNumber : array[0..4] of Word = ($203, 14, 0, 0, 0);
  CXlsRk    : array[0..4] of Word = ($27E, 10, 0, 0, 0);


constructor TXLSExport.Create(filename : string);
begin
  inherited Create;
  fs := TFileStream.Create(filename,fmCreate);
  fs.WriteBuffer(CXlsBof, SizeOf(CXlsBof));
end;

destructor TXLSExport.Destroy;
begin
  fs.WriteBuffer(CXlsEof, SizeOf(CXlsEof));
  inherited Destroy;
end;

procedure TXLSExport.Write(const Col, Row: Word; const Value: Integer);
var
  V: Integer;
begin
  CXlsRk[2] := Row;
  CXlsRk[3] := Col;
  fs.WriteBuffer(CXlsRk, SizeOf(CXlsRk));
  V := (Value shl 2) or 2;
  fs.WriteBuffer(V, 4);
end;

procedure TXLSExport.Write(const Col, Row: Word; const Value: Double);
begin
  CXlsNumber[2] := Row;
  CXlsNumber[3] := Col;
  fs.WriteBuffer(CXlsNumber, SizeOf(CXlsNumber));
  fs.WriteBuffer(Value, 8);
end;

procedure TXLSExport.Write(const Col, Row: Word; const Value: string);
var L: Word;
begin
  L := Length(Value);
  CXlsLabel[1] := 8 + L;
  CXlsLabel[2] := Row;
  CXlsLabel[3] := Col;
  CXlsLabel[5] := L;
  fs.WriteBuffer(CXlsLabel, SizeOf(CXlsLabel));
  fs.WriteBuffer(Pointer(Value)^, L);
end;

end.
Vielleicht kannst du dir nun einen Reim drauf machen ?!?!

alzaimar 17. Aug 2005 07:24

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hach, hätt nur hinshauen müssen, kukstu:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var XLSFile : TXLSExport;
    x, y   : Integer;
    Spalten, Zeilen: String;
begin
  if savedialog1.Execute then begin
    if fileexists(savedialog1.filename) then DeleteFile(savedialog1.filename);
    XLSFile := TXLSExport.Create(savedialog1.filename);
    try
      y := 0;
      repeat
        Spalten := StringGrid2.Cells[x,y]; <--- wieso das denn?
        XLSFile.Write(x,y,Spalten);       <-- welchen Wert hat x beim 1.Durchlauf?
        x := 0;
        repeat
          Zeilen := StringGrid2.Cells[x,y];
          XLSFile.write(x,y, Zeilen);
          x := x + 1;
        until x = StringGrid2.ColCount;
        y := y + 1;
      until y = StringGrid2.RowCount;
    finally
      XLSFile.free;
    end;
  end;
end;
Das sollte reichen....

marabu 17. Aug 2005 07:32

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hallo ihr zwei,

niedliche unit - keine Probleme.

Delphi-Quellcode:
procedure TDemoForm.SaveButtonClick(Sender: TObject);
var
  xf: TXLSExport;
  iCol, iRow: integer;
begin
  if not SaveDialog.Execute then Exit;
  if FileExists(Savedialog.Filename) then
    DeleteFile(SaveDialog.Filename);
  xf := TXLSExport.Create(savedialog.filename);
  for iRow := 0 to StringGrid.RowCount - 1 do
    for iCol := 0 to StringGrid.ColCount - 1 do
      if iRow = 0 then // Ausgabe Spaltenköpfe als string
        xf.Write(iCol, iRow, StringGrid.Cells[iCol, iRow])
      else // der Rest sind integer Werte
        xf.Write(iCol, iRow, StrToInt(StringGrid.Cells[iCol, iRow]));
  xf.Free;
end;
Grüße vom marabu

padavan 17. Aug 2005 08:24

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Vielen Dank marabu,

klappt wunderbar.
Musste nur strtoint aus deiner Routine rausnehmen, da ich auch nicht-Zahlenwerte Quer durch die Tabelle hab.
Macht aber nix, da das ganze nur einen Report mehrere Messdateien darstellt, welcher nur zum Gugge is, und nicht zum Rechnen.



Hallo alzaimar

Delphi-Quellcode:
 repeat
        Spalten := StringGrid2.Cells[x,y]; <--- wieso das denn? 
        XLSFile.Write(x,y,Spalten);       <-- welchen Wert hat x beim 1.Durchlauf? 
        x := 0;
        repeat
Das mit den extra Variablen war nur zu Testzwecken, ohne tieferen Sinn.

Vielen Dank nochmal

Padavan

Zerolith 10. Nov 2005 21:27

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hallo!

was müsste man an der Unit groß ändern um Unicode damit zu Exportieren?

hab mal experimentell statt String als Parameter WideString genommen. Nur hab ich dummerweiße dann so doofe Kästchen statt buchstaben... irgendwie klappt das nich ganz.

Daniel

Bernhard Geyer 11. Nov 2005 07:15

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Zitat:

Zitat von Zerolith
...Nur hab ich dummerweiße dann so doofe Kästchen statt buchstaben... irgendwie klappt das nich ganz.

Es klappt schon, bloß der verwendet Font hat an den entsprechenden Stellen keine Zeichen sondern nur ein Kästchen als Platzhalter. Einfach mal den Font ändern wo du weißt das an den entsprechenden Stellen Unicode-Zeichen sind.
Z.B. bei efg findest Du einen entsprechenden Viewer.

Zerolith 11. Nov 2005 08:10

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hmmm eigentl. Hast ja recht. Bloß bin ich davon ausgegangen das ms. Excel unicode unterstützt.

oder nicht?

Bernhard Geyer 11. Nov 2005 08:51

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Zitat:

Zitat von Zerolith
Hmmm eigentl. Hast ja recht. Bloß bin ich davon ausgegangen das ms. Excel unicode unterstützt.

oder nicht?

Macht es. Bloß wenn der gerwählte Font keine Zeichen hat kann Excel auch nichts machen.

Zerolith 11. Nov 2005 09:20

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Tahoma und Arial haben unicode zeichen...
wenn ich die DAtei dann aufmach, und manuell irgendwelche Kyrillischen zeichen oder so eingibt funktioniert das ja auch ganz prima

alphaflight83 10. Jun 2009 12:32

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Muss das hier mal wiederbeleben.
Mit Delphi 2009 brauche ich hier nun auch Unicode.
Wenn ich in der Funktion
Delphi-Quellcode:
procedure TXLSExport.Write(const Col, Row: Word; const Value: string);
für Value AnsiString statt String verwende funktoniert die Funktion wie früher,
allerdings will ich ja nun auch Unicode in den Exports benutzen.
Die Frage von Zerolith wurde damals nicht beantwortet.
Auch ich bekomme Kästchen in den Feldern, allerdings "nur" jedes zweite Zeichen.
Die Länge der Strings wäre an sich richtig, nur dass eben immer ein Kästchen reingequetscht wird,
wodurch die Hälfte des Strings unter den Tisch fällt.
Als Standard Schriftart habe ich in Excel Arial Unicode MS eingestellt,
es liegt also definitiv nicht an Excels Schriftart.

Kann das an der Dereferenzierung liegen?
Delphi-Quellcode:
XlsStream.WriteBuffer(Pointer(AValue)^, L);
Hab unlängst mal gelesen, dass die Dereferenzierung mit "Pointer" nicht so richtig funktioniert !?!

Edit: Anscheinend nicht, auch die Spezifizierung durch PWideString, bzw PUnicodeString bringt keinen Effekt

Chemiker 10. Jun 2009 14:07

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hallo alphaflight83,

in der CodeLib gibt es auch eine Unit um Excel-Dateien, ohne Excel zu erzeugen.

Excel-Unit
Bis bald Chemiker

toms 11. Jun 2009 05:15

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Zitat:

Zitat von Chemiker
in der CodeLib gibt es auch eine Unit um Excel-Dateien, ohne Excel zu erzeugen.

TXLSExport schreibt ja auch direkt ohne OLE etc.

alphaflight83 12. Jun 2009 09:59

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Zitat:

Zitat von Chemiker
In der CodeLib gibt es auch eine Unit um Excel-Dateien, ohne Excel zu erzeugen.

Ah, hab grade gesehen, dass du Änderungen für D2009 eingefügt hast, dann werde ich mir das nochmal zu Gemüte führen.
Danke mal dafür.

GHorn 16. Jun 2009 14:17

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hi,
ich brüte auch gerade über diesem Thema.

@Chemiker:
Setze ich

Delphi-Quellcode:
BIFFVersion:= XLS_BIFFVER  // XLS_BIFFVER = $600
um mit BIFF8 zu arbeiten, bekomme ich auch so niedliche Kästchen.
Allerdings nicht in allen Feldern. Hauptsächlich in Zeichenfeldern, die
Ziffern enthalten.
Die Anpassung an D2009 habe ich auch probiert - allerdings ohne Erfolg.
Die Kästchen und kryptischen Zeichen bleiben.

Grund für die Anpassung an BIFF8 ist die Notwendigkeit, mehr als ein
Worksheet zu erstellen und mit Daten zu füllen. Soweit ich das bisher
in Erfahrung bringen konnte, ist dafür BIFF8 erforderlich. Oder nicht??
Wie erstelle ich weitere Worksheets und gebe ihnen noch treffende Namen?

Im Übrigen ist Dein Tool super. Danke dafür.

Aktuell: D2007, Daten aus BlackFish (Unicode) und Excel 2003 (SP3).

Gruß,
Gerald

alphaflight83 16. Jun 2009 14:41

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
So jetzt kann ich mich wieder mal diesem Thema zuwenden.

Hab das jetzt mal ausprobiert und Chemikers Funktion verwendet,
allerdings bleiben auch hier noch die Kästchen-Steuerzeichen hinter jedem Char in der Tabelle.
Die Änderung bewirkt immerhin, dass die Strings nicht abgeschnitten werden.

Mit TXLSExport erreicht man das durch Änderung der Prozedur Write

Delphi-Quellcode:
procedure TXLSExport.Write(const Col, Row: Word; const Value: String);
var L: Word;
begin
  L := Length(Value) * SizeOf(Char); // <- 
  CXlsLabel[1] := 8 + L;
  CXlsLabel[2] := Row;
  CXlsLabel[3] := Col;
  CXlsLabel[5] := L;
  fs.WriteBuffer(CXlsLabel, SizeOf(CXlsLabel));
  fs.WriteBuffer(Pointer(Value)^, L);
end;
Aber, wie gesagt, die Kästchen sind in beiden Fällen weiterhin da.
Die Stringlänge bei TXLSExport vor der Änderung wäre an sich wie gesagt auch richtig,
wenn die Kästchen den String nicht dehnen würden.

Kann es sein, dass noch ein De-/Codier-Schritt fehlt, um das zum laufen zu bringen?

Edit: Hab grade festgestellt, dass die Exportierung immer noch als Ansi abläuft.
Dann hat der Excel Export an sich erst mal gar nichts damit zu tun und ich muss eine Ebene drunter Fehlersuche betreiben.

Chemiker 16. Jun 2009 20:00

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hallo alphafligt83, GHorn,

Zitat:

Zitat von GHorn
Aktuell: D2007, Daten aus BlackFish (Unicode) und Excel 2003 (SP3).

D2007 ist aber nicht UniCode fähig.

Man kann die Routinen natürlich erweitern um weitere Sheets in einem Workbook anzulegen, allerdings wird dadurch das ganze etwas aufgebläht.
Das gleiche gilt für Formatierungen, Schriftgröße usw.

Ich bin bisher nicht in die Verlegenheit gekommen Unicode zu benutzen, ich habe nur die Unit so angepasst das ich das StringGrid mit den Zufallswerten mit Delphi 2009 benutzen kann und eine Excel-Datei erhalte die alle Übertragen Daten in Excel 2007 anzeigt und nicht zum Teil die Daten abschneidet.

In diesem Link steht wie das Biff-Format aufgebaut ist: BIFF-Format
Bis bald Chemiker

alphaflight83 17. Jun 2009 09:05

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Momentan bin ich immer noch am suchen, wie ich einen TFileStream dazu bringe die Encoding auf UTF8 zu setzen.
Bei einem normalen SaveToFile ist das ja kein Ding
Delphi-Quellcode:
StringList.SaveToFile(ExportFilename, TEncoding.UTF8);
Aber beim Stream hab ich bisher noch keine Option gefunden.
Kann natürlich auch sein, dass ich das an anderer Stelle setzen muss !?!

Bernhard Geyer 17. Jun 2009 09:07

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Zitat:

Zitat von Chemiker
D2007 ist aber nicht UniCode fähig.

D2007 ist sehr wohl Unicode-Fähig (Ist Delphi schon halbwegs seit D3). Jedoch sind große Teile der VCL noch nicht entsprechend Unicode-Enabled!

Chemiker 17. Jun 2009 13:49

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hallo Bernhard Geyer,

Zitat:

Zitat von Bernhard Geyer
D2007 ist sehr wohl Unicode-Fähig

Ich habe gedacht, dass das erst mit Delphi 2009 eingeführt worden ist.

Bis bald Chemiker

alphaflight83 18. Jun 2009 13:15

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Ich komme hier nicht weiter.
Auch nach (oder gerade wegen) zahlreicher Lektüre komme ich nicht darauf,
wie ich meinen File-Stream nach Excel auf UTF8 forcen kann.
Es bleiben Kästchen-Steuerzeichen nach jedem Char,
während die eigentlichen Unicodezeichen (kyrillisch in meinem Fall) nicht übersetzt werden.
Sprich, da werden Ansi-Strings reingebügelt.
Was ich an der Sache nicht verstehe ist, dass die Strings die ich übergebe
(Momentan z.B. an TXLSExport.Write) ja Unicodestrings sein sollen.
Wie gesagt funktioniert der Export in Textfiles ohne Probleme.

Edit: Bin nun soweit, dass ich denke, dass das Ganze relativ einfach mit den definierten Records zusammenhängt.


Delphi-Quellcode:
CXlsBof   : array[0..5] of Word = ($809, 8, 00, $10, 0, 0);
CXlsEof   : array[0..1] of Word = ($0A, 00);
CXlsLabel : array[0..5] of Word = ($204, 0, 0, 0, 0, 0);
CXlsNumber : array[0..4] of Word = ($203, 14, 0, 0, 0);
CXlsRk    : array[0..4] of Word = ($27E, 10, 0, 0, 0);
Kann mir vielleicht jemand sagen, wo die Werte herkommen, bzw. wie die sich zusammensetzen?
Chemiker beschreibt ja in seiner unit zumindest grob, was die Werte darstellen,
aber wie und ob ich die ändern kann/darf leider nicht.
Hab mich blind-gegoogelt, aber bisher nichts gefunden.

Chemiker 18. Jun 2009 20:29

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hallo alphafligt83,

ich habe die Informationen, die Du für Deine Anpassung benötigtst schon im Link von #19 geschrieben. Es reicht leider nicht die Angaben in dem Record zu ändern und schon läuft alles unter UniCode, da muss leider etwas mehr Arbeit hereingesteckt werden.

Bis bald Chemiker

Bernhard Geyer 18. Jun 2009 21:55

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Zitat:

Zitat von Chemiker
Hallo Bernhard Geyer,

Zitat:

Zitat von Bernhard Geyer
D2007 ist sehr wohl Unicode-Fähig

Ich habe gedacht, dass das erst mit Delphi 2009 eingeführt worden ist.

Mit D2009 wurden die "Restarbeiten" in der Visual VCL" (TButton, TListView, ...) durchgeführt. Aber seit D3 seit Delphi halbwegs vernünftig mit COM+OLE arbeitet hat Delphi den WideString-Typ welchen man (bis D2009) für eine Unicode-Enabling der eigenen Anwendung (auf Basis von ElPack oder TNTWare) verwenden kann. Unsere App kann sogar unter Win98 (vor einiger Zeit auch noch Win95) mit Unicode arbeiten. Zur darstellung von Arabisch/Chinesisch auf Deutschen System ist nur der Arial Unicode-Font nötig.

R2009 19. Jun 2009 05:54

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hmm,

wäre ganz nett auch noch eine entsprechende Unit für den Import zu haben.

Viele Grüsse

Chemiker 19. Jun 2009 06:38

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hallo R2009,

das ist mit sehr viel Aufwand verbunden, aber unmöglich ist es nicht. Bisher reichte mir die OLE-Automation, vernünftig programmiert ist sie eigentlich auch relativ schnell.

Bis bald Chemiker

mschaefer 19. Jun 2009 07:27

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Da sollte man sich langfristig aber auf das neue xml-Excelformat konzentrieren... /// Grüße Martin

PS: Dass Biff-Format ist auch bei kommerziellen Komponenten nicht vollständig umgesetzt. Nachdem ich einen Satz von ca. 2000 Excelblättern einlesen mußte, durfte ich im Quellcode von DevExpress einige mal nachfassen, damit das System nicht mit Speicherfehlern ins Nirwana verschwandt...

GHorn 19. Jun 2009 09:26

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
@ alphaflight83:

chemiker hat ja schon auf seinen Link in #19 hingewiesen. Hier
noch einige zusätzliche Erläuterungen zum Quelltext von chemiker:

Delphi-Quellcode:
const
   XLS_WORKBOOK = $5;          // nur Workbook und separate Sheets
   XLS_WORKSSHEET= $10;         // Sheet or dialogue record (s.S.136 Dokument s. oben)
   XLS_BOF      = $809;        // BIFF5 bis BIFF8  (s.S.135 Dokument s. oben)
   XLS_BIFFVER  = $600;        // BIFF8 (s.S.136 Dokument s. oben)
   XLS_LABEL    = $204;        // (s.S.187, 5.63 Dokument s. oben)
   XLS_EOF      = $A0;         // (s.S.161, 5.37 Dokument s. oben)
   XLS_EXCEL_VERSION = 1;

type
  TXLS_BOFRec= packed record    // Start des Datenblockes
    RecCode: Word;              // $809 BOF
    RecLaenge: Word;            // Record Länge // Komplett 16/ normal 8
    BIFFVersion: Word;          // $600 BiffVersions-Nummer 8
    Bereich: Word;              // $10 = Worksheet
    ExcelVersion: Word;         // muss nicht angegeben werden (z.B. 2719=Excel 2000)
    ExcelDatum: Word;           // muss nicht angegeben werden
  end;
Delphi-Quellcode:
procedure TXLS_DateiClass.XLS_BOFRecDatenFuellen;
begin
  with FBOF do
    begin
      RecCode:= XLS_BOF ;           // $809
      RecLaenge:= 8;
      //BIFFVersion:= XLS_BIFFVER;  // $600 BIFF8
      BIFFVersion:= 1;              // kein BIFF8
      Bereich:= XLS_WORKSSHEET;     // $10
      ExcelVersion:= 1;
      ExcelDatum:= 0;
    end;
end;
Setze ich die BIFF-Version auf 8 durch $600, erhalte ich auch diese schmucken
Kästchen und Sonderzeichen. BIFF8 ist Unicodefähig. Aber in der erzeugten Datei
sind die Texte / Daten, die eigentlich in die Zellen geschrieben werden sollen,
unvollständig bzw. verschoben.
Excel liest (parst) diese Streams und erwartet an einer bestimmten Position auch
bestimmte Angaben für die Formatierung usw. Stehen an diesen Stellen aber z.B.
Texte für die Zellen, muß das schief gehen. Das Problem ist also, den Buffer des
Streams korrekt zu füllen. Insbesondere, was die Zeichenlängen und Zeilenendezeichen
betrifft.

Gruß
Gerald

edit: Die Seitenangaben beziehen sich auf das Dokument compdocfileformat.pdf
(s. Beitrag #19).

alphaflight83 19. Jun 2009 09:49

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
@Chemiker: Ich nehme alles zurück und behaupte das Gegenteil :oops:
War gestern Nachmittag wohl einfach zu viel für mich.
@GHorn: Danke für die Zusatzinfos. Das hilft mir mal ein Stück weiter.
Werd mich dann mal wieder meinem Chaos hier zuwenden.

Chemiker 19. Jun 2009 18:17

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hallo mschaefer,

Zitat:

Zitat von mschaefer
Dass Biff-Format ist auch bei kommerziellen Komponenten nicht vollständig umgesetzt.

Was wohl auch daran lag, dass MS das lange unter Verschluss gehalten hat. Ich habe eine Vsiual Studio Version 6 Prof., dort war sogar ein Hex-Edit Programm dabei, um Dateien im BIFF 5 Format zu analysieren, aber auf BIFF 8 – Format angewendet half es nur noch bedingt.

Bis bald Chemiker

alphaflight83 24. Jun 2009 16:19

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Nachtrag: Nachdem ich nun nach weiteren Recherchen feststellen musste, dass das Thema doch komplexer ist als zunächst angenommen,
hab ich mich am Montag dazu entschlossen die TXLSfile Component von SM-Software zu kaufen.
(Hätte ich schon am ersten Tag machen sollen, aber hinterher ist man ja bekanntlich immer schlauer)
Der Test war absolut zufriedenstellend, da die Funktionen und Möglichkeiten umfangreich sind und die Ausgabe jetzt besser aussieht als vorher.
Das Ganze war immerhin in viellerlei Hinsicht lehrreich, deshalb nochmal Danke an Alle.

fs999 11. Mai 2010 08:47

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Zitat:

Zitat von Chemiker
Hallo alphaflight83,

in der CodeLib gibt es auch eine Unit um Excel-Dateien, ohne Excel zu erzeugen.

Excel-Unit
Bis bald Chemiker

Hallo Chemiker,

Ich habe eine kleine Änderung in deiner Excel-Unit gemacht um auch Zahlen einzugeben.

Delphi-Quellcode:
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Unit:      XLSDateiUnit
letz.Ändr.: 11.06.2008
Version:   1.10
Funktion:  In diser Unit werden für das BIFF-Format die Records zur Verfügung
            gestellt.
            Änderungen für die Migration auf Delphi 2009 durchgeführt.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
unit XLSDateiUnit;

interface

uses Grids, Classes;

type
  TXLS_BOFRec= packed record    // Start des Datenblockes
    RecCode: Word;              // $809 BOF
    RecLaenge: Word;            // Record Länge // Komplett 16/ normal 8
    BIFFVersion: Word;          // $ 600 BiffVersions-Nummer:8
    Bereich: Word;              // $10 = Workssheet
    ExcelVersion: Word;         // muss nicht angegeben werden 2719=Excel 2000
    ExcelDatum: Word;           // muss nicht angegeben werden
//    ExcelHistoryFlag: DWord;    // muss nicht angegeben werden
//    LetzteExcelVersion: DWord;  // muss nicht angegeben werden.
  end;

  TXLS_LABELRec= packed record   // String-Record von Excel
    RecCode: Word;               // $204 Bei Biff 8
    RecLaenge: Word;             // Record Länge // muss zuvor berechnet werden
    Row: Word;                   // Zeilen-Nr. beginnt bei 0
    Col: Word;                   // Spalten-Nr. beginnt bei 0
    IndexXFRec: Word;            // noch nicht ganz verstanden // erstmal=0
    ZellenStLeange: Word;        // Nur die ZellenString-Länge
  end;
// FS999 Änderung
  TXLS_NUMBERRec= packed record   // Number-Record von Excel
    RecCode: Word;               // $203 Bei Biff 8
    RecLaenge: Word;             // Record Länge // muss zuvor berechnet werden
    Row: Word;                   // Zeilen-Nr. beginnt bei 0
    Col: Word;                   // Spalten-Nr. beginnt bei 0
    IndexXFRec: Word;            // noch nicht ganz verstanden // erstmal=0
  end;
// Ende
  TXLS_EOFRec= packed record     // Ende des Datenblockes
    RecCode: Word;               // $A0
    RecLaenge: Word;             // 00  hat immer die Länge = 0
  end;

function XLS_BOFRecDatenFuellen(): TXLS_BOFRec;
// FS999 Ânderung
function XLS_FloatFuellen(const Zeile,Spalte: Word):TXLS_NUMBERRec;
// Ende
function XLS_StringFuellen(const Zeile,Spalte: Word; Wert: String):TXLS_LABELRec;
function XLS_EOFRecDatenFuellen(): TXLS_EOFRec;
function ZellenInhalt(Zeile, Spalte: Integer; Tab: TStringGrid): String;
function DatenInXLSDateiUebertragen(const XLS_LWPathDateiName: string;
                                    DatenStringGrid: TStringGrid): boolean;
implementation

uses
  SysUtils;

{------------------------------------------------------------------------------}
function XLS_BOFRecDatenFuellen(): TXLS_BOFRec;
begin
  with Result do
  begin
    RecCode:= $809;
    RecLaenge:= 8;
    BIFFVersion:= 1;  // Kann auch 1 sein
    Bereich:= $10;
    ExcelVersion:= 1;
    ExcelDatum:= 0;
//    ExcelHistoryFlag:=0;
//    LetzteExcelVersion:=0;
  end;
end;
// FS999 Änderung
{------------------------------------------------------------------------------}
function XLS_FloatFuellen(const Zeile,Spalte: Word):TXLS_NUMBERRec;
begin
  with Result do
  begin
    RecCode:= $203;
    RecLaenge:= 14;
    Row:= Zeile;
    Col:= Spalte;
    IndexXFRec:= 0;
  end;
end;
// Ende
{------------------------------------------------------------------------------}
function XLS_StringFuellen(const Zeile,Spalte: Word; Wert: String):TXLS_LABELRec;
begin
  with Result do
  begin
    RecCode:= $204;
    RecLaenge:= 8 + (Length(Wert)*SizeOf(Char)); // Änderung für Delphi 2009
    Row:= Zeile;
    Col:= Spalte;
    IndexXFRec:= 0;
    ZellenStLeange:= (Length(Wert)*SizeOf(Char)); // Änderung für Delphi 2009
  end;
end;
{------------------------------------------------------------------------------}
function XLS_EOFRecDatenFuellen(): TXLS_EOFRec;
begin
  with Result do
  begin
    RecCode:= $A;
    RecLaenge:= 0;
  end;
end;
{------------------------------------------------------------------------------}
function ZellenInhalt(Zeile, Spalte: Integer; Tab: TStringGrid): String;
begin
  Result:= Tab.Cells [Spalte, Zeile];
end;
{------------------------------------------------------------------------------}
function DatenInXLSDateiUebertragen(const XLS_LWPathDateiName: string;
                                    DatenStringGrid: TStringGrid): boolean;
var
  x, i: integer;
  XLSFileStream: TFileStream;
  XLS_BOF: TXLS_BOFRec;
  XLS_EOF: TXLS_EOFRec;
  XLS_St: TXLS_LABELRec;
  Inhalt: String;
begin
  XLSFileStream:= TFileStream.Create(XLS_LWPathDateiName, fmCreate);
  Result:= FALSE;
  try
    // XLS-File Anfang schreiben
    XLS_BOF:= XLS_BOFRecDatenFuellen();
    XLSFileStream.WriteBuffer(XLS_BOF,SizeOf(XLS_BOFRecDatenFuellen()));

    // Werte aus einem StringGrid lesen und in die XLS-Datei eintragen
    for x := 0 to DatenStringGrid.ColCount - 1 do   // Max. 254  Excel-Grenze
    begin
      for I := 0 to DatenStringGrid.RowCount - 1 do // Max 65536 Excel-Grenze
      begin
        Inhalt:= ZellenInhalt(I, x, DatenStringGrid);
        XLS_St:= XLS_StringFuellen(I, x, Inhalt);
        XLSFileStream.WriteBuffer(XLS_St, Sizeof (XLS_St));
        XLSFileStream.WriteBuffer(Inhalt[1], (Length(Inhalt)*SizeOf(Char))); // Änderung für Delphi 2009
      end;
    end;
    // Werte eintragen Ende.

    // XLS-File Ende schreiben
    XLS_EOF:= XLS_EOFRecDatenFuellen();
    XLSFileStream.WriteBuffer(XLS_EOF,SizeOf(XLS_EOFRecDatenFuellen()));
    Result:= TRUE;
  finally
    // Datei wieder schliesen.
    XLSFileStream.Free;
  end;
end;

end.
Um es zu benutzen :

Delphi-Quellcode:
Var
  ...
  XLS_Fl: TXLS_NUMBERRec;
  n: Double;
begin

  ...

  n := 5.42;
  XLS_Fl:= XLS_FloatFuellen(r, c);
  XLSFileStream.WriteBuffer(XLS_Fl, Sizeof(XLS_Fl));
  XLSFileStream.WriteBuffer(n, 8);

  ...

end;
Bis bald,
Frederic

Chemiker 11. Mai 2010 14:10

Re: Excel - Export ohne Excel - Problem beim erzeugen
 
Hallo fs999,

Du kannst bei der Function auch direkt den Wert mitgeben:

Delphi-Quellcode:
// FS999 Änderung
  TXLS_NUMBERRec= packed record   // Number-Record von Excel
    RecCode: Word;               // $203 Bei Biff 8 
    RecLaenge: Word;             // Record Länge // muss zuvor berechnet werden
    Row: Word;                   // Zeilen-Nr. beginnt bei 0 
    Col: Word;                   // Spalten-Nr. beginnt bei 0 
    IndexXFRec: Word;            // noch nicht ganz verstanden // erstmal=0
    Zahl: double;                // Zahl double
  end;
// Ende
Aufruf dann:
Delphi-Quellcode:
// FS999 Änderung
{------------------------------------------------------------------------------} 
function XLS_FloatFuellen(const Zeile,Spalte: Word; aWert: double):TXLS_NUMBERRec;
begin
  with Result do
  begin
    RecCode:= $203;
    RecLaenge:= 14;
    Row:= Zeile;
    Col:= Spalte;
    IndexXFRec:= 0;
    Zahl:= aWert;
  end;
end;
// Ende
Bis bald Chemiker

EccoBravo 2. Jul 2010 10:20

AW: Excel - Export ohne Excel - Daten anhängen
 
Hallo,

wie sieht es aber aus, wenn man an eine bereits erzeugte ExcelFile einige neue Zeilen hinzufügen möchte,
so zum Beispiel über längeren Zeitraum Daten zu sammeln.
Geht das überhaupt mit einem solchen Eccel-Export ?

Danke EB

mkinzler 2. Jul 2010 10:32

AW: Excel - Export ohne Excel - Problem beim erzeugen
 
Notfalls halt Inhalt einladen, neue daten hinzufügen, neu speichern


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:47 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz