![]() |
Problem mit Excelexport
Hallo,
ich habe ein Problem mit dem Exportieren einer Datenmenge nach Excel, also meine procedure läuft wunderbar auf Rechnern auf denen Excel installiert ist, aber wen Excel nicht installiert ist kommt eine Fehlermeldung das die classID (oder so ähnlich) nicht registriert ist. Also meine Frage jetzt: Wie kann ich meine procedure möglichst einfach verändern das sie auch auf Rechnern angewandt werden kann auf denen kein Excel installiert ist :?: Hier mal mein derzeitiger Code:
Delphi-Quellcode:
Ich weiß, die Sache mit der Stringlist und dem hinzufügen der Felder ist nicht gerade die eleganteste Methode aber es musste einfach schnell gehn und mit ist nichts besseres eingefallen, falls hier jemand etwas besseres kennt würde ich mich über Tipps freun. :)
procedure ExcelExport(SaveDialog : TSaveDialog; ExcelAppli : TExcelApplication;
ExcelWb : TExcelWorkbook; ExcelWsht : TExcelWorksheet; Query : TVddQuery); var Filename, CoordCounter: String; oleArray1, oleArray2:OleVariant; i, z, flcid : Integer; sl, sl2 : TStringlist; begin Screen.Cursor := crHourglass; SaveDialog.Execute; case SaveDialog.FilterIndex of 1: Filename := ChangeFileExt(SaveDialog.FileName,'.xls'); 2: Filename := ChangeFileExt(SaveDialog.FileName,'.xls'); end; if Filename <> '' then begin flcid:=GetUserDefaultLCID; ExcelAppli.Connect; ExcelAppli.Visible[flcid]:=true; ExcelAppli.UserControl:=true; CreateFile(@Filename[1], 0, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); ExcelWb.ConnectTo(ExcelAppli.Workbooks.Open(filename, False, False, EmptyParam, '', False, False, EmptyParam, EmptyParam, false, false, EmptyParam, EmptyParam, EmptyParam, false, 0)); ExcelWsht.ConnectTo(ExcelWb.Sheets.Item[1] as ExcelWorkSheet); sl := TStringList.Create; sl2 := TStringList.Create; Query.GetFieldNames(sl); OleArray1 := VarArrayCreate([0, Query.RecordCount], varVariant); OleArray2 := VarArrayCreate([0, sl.Count], varVariant); for z := 0 to sl.Count - 1 do begin OleArray2[z] := sl.Strings[z]; end; sl2.Add('A'); sl2.Add('B'); sl2.Add('C'); sl2.Add('D'); sl2.Add('E'); sl2.Add('F'); sl2.Add('G'); sl2.Add('H'); sl2.Add('I'); sl2.Add('J'); sl2.Add('K'); sl2.Add('L'); sl2.Add('M'); sl2.Add('N'); sl2.Add('O'); sl2.Add('P'); sl2.Add('Q'); sl2.Add('R'); sl2.Add('S'); sl2.Add('T'); sl2.Add('U'); sl2.Add('V'); sl2.Add('W'); sl2.Add('X'); sl2.Add('Y'); sl2.Add('Z'); sl2.Add('AA'); sl2.Add('AB'); sl2.Add('AC'); sl2.Add('AD'); sl2.Add('AE'); sl2.Add('AF'); sl2.Add('AG'); sl2.Add('AH'); sl2.Add('AI'); sl2.Add('AJ'); sl2.Add('AK'); sl2.Add('AL'); sl2.Add('AM'); sl2.Add('AN'); sl2.Add('AO'); sl2.Add('AP'); sl2.Add('AQ'); sl2.Add('AR'); sl2.Add('AS'); sl2.Add('AT'); sl2.Add('AU'); sl2.Add('AV'); sl2.Add('AW'); sl2.Add('AX'); sl2.Add('AY'); sl2.Add('AZ'); ExcelWsht.Range[sl2[0]+'1', sl2[sl.Count-1]+'1'].Value[EmptyParam] := OleArray2; if sl.count > sl2.Count then begin ExcelWsht.Range[sl2[0]+'1', sl2[sl.Count-1]+'1'].Value[EmptyParam] := OleArray2; end; Query.First; for i := 0 to Query.RecordCount - 1 do begin for z := 0 to sl.Count - 1 do begin OleArray1[z] := Query.FieldByName(sl[z]).AsString; end; CoordCounter := IntToStr(i+2); ExcelWsht.Range[sl2[0]+CoordCounter, sl2[sl.Count-1]+CoordCounter].Value[EmptyParam]:=OleArray1; Query.Next; end; ExcelWsht.Cells.EntireRow.AutoFit; ExcelWsht.Cells.EntireColumn.AutoFit; end; Screen.Cursor := crDefault; sl.Free; sl2.Free; end; Also dann ich hoffe ihr könnt mir weiterhelfen. mfg Alex |
Re: Problem mit Excelexport
Hi,
wenn's hilft: Jet kann von naturaus EXCEL Dateien schreiben:
Delphi-Quellcode:
adoconn := TADOConnection.Create(Application);
try adoconn.ConnectionString := ('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=' + temp); adoconn.CursorLocation := clUseClient; adoconn.LoginPrompt := false; adoconn.Connected := true; adoconn.Execute('SELECT * INTO TestTabelle IN "' + FileName + '" "Excel 8.0; HDR=Yes;" FROM ' + TableName, 1); adoconn.Connected := false; finally adoconn.Free; end; |
Re: Problem mit Excelexport
Hmm eher weniger :( habe gehofft man könnte vielleicht was bei den Parametern für FileCreate ändern.
Aber komplett neue Komponenten zu benutzen wäre der allerletzte Ausweg. |
Re: Problem mit Excelexport
Zum Verständnis: Mit Deinem Beispielcode aus dem Originalposting machst Du nichts anderes, als Excel "fernzusteuern". Deshalb muß Excel auf dem jeweiligen PC logischerweise installiert sein.
|
Re: Problem mit Excelexport
|
Re: Problem mit Excelexport
Nebenbei bemerkt: CreateFile gibt ein Handle zurück, das man schließen sollte.
|
Re: Problem mit Excelexport
Schonmal danke für die hilfreichen Antworten.
Ich habe mal nach TXLsExport gesucht, wie Roga gesagt hatte, nun bin ich da auf einen recht interessanten ![]() Hier habe ich mir diese Unit kopiert:
Delphi-Quellcode:
Also ich habe mir den Aufruf den Marabu gepostet hat schon so umgebaut das ich meine Query benutzen kann. Ein kleines Problem bleibt allerdings noch, und zwar das der linken Seite nichts zugwiesen werden kann. Die betroffenen Stellen habe ich kommentiert.
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; //Der linken Seite kann nichts zugewiesen werden. CXlsLabel[2] := Row; //" CXlsLabel[3] := Col; //" CXlsLabel[5] := L; //" fs.WriteBuffer(CXlsLabel, SizeOf(CXlsLabel)); fs.WriteBuffer(Pointer(Value)^, L); end; end. Ich denke es liegt an der Konstantendeklaration, wie kann ich das ändern damit die Unit auch das weiterhin tut wofür sie geschrieben worden ist? Ich hoffe das war halbwegs verständlich. mfg Alex |
Re: Problem mit Excelexport
Hallo Borschti,
also bei mir läufts mit der Unit "u_ExportEXCEL" ohne Probleme. Das folgende Beispiel speichert eine ListView in eine Excel-Datei:
Delphi-Quellcode:
Leider kann man die Spaltenbreite nicht ändern.
procedure ExportDataToExcel(ExportFileName: string;
ExportListView: TListView); var XLSFile: TXLSExport; XLSFileName: string; ColumnsCount, ItemsCount, i, x, y: Integer; begin // Excel-Tabelle erstellen XLSFileName := ExportFileName; XLSFile := TXLSExport.Create(XLSFileName); if FileExists(XLSFileName) then DeleteFile(XLSFileName); try ColumnsCount := ExportListView.Columns.Count; ItemsCount := ExportListView.Items.Count; // Kopfzeilen for i := 0 to ColumnsCount -1 do XLSFile.Write(i, 0, ExportListView.Columns[i].Caption); // Daten y := 1; for i := 0 to ItemsCount -1 do begin XLSFile.Write(0, y, ExportListView.Items[i].Caption); for x := 0 to ColumnsCount -2 do XLSFile.Write(x + 1, y, ExportListView.Items[i].SubItems.Strings[x]); inc(y); end; finally end; XLSFile.Free; // Excel starten und Tabelle anzeigen if MessageDlg('Soll die Excel-Tabelle jetzt angezeigt werden?', mtConfirmation, [mbYes,mbNo], 0) = mrYes then try ShellExecute(0, nil, PChar(ExportFileName), nil, nil, SW_NORMAL); except MessageDlg('Excel-Programm konnte nicht gestartet werden!', mtError, [mbOk], 0); end; end; Gruß RoGa |
Re: Problem mit Excelexport
Hmm also ich habe auch nochmal ein bisschen rumprobiert und habe das jetzt so:
Delphi-Quellcode:
Mein Aufruf sieht so aus:
unit u_ExportEXCEL;
interface uses classes; type TXLSExport = class(TObject) private fs : TFilestream; CXlsBof : array[0..5] of Word; CXlsEof : array[0..1] of Word; CXlsLabel : array[0..5] of Word; CXlsNumber : array[0..4] of Word; CXlsRk : array[0..4] of Word; 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 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.
Delphi-Quellcode:
Also es werden auch schon sachen in die Exceldatei geschrieben aber leider vollkommen unleserlicher kram wie z.B. 500 etc.
procedure TForm1.ExportierenExcel1Click(Sender: TObject);
var xf: TXLSExport; iCol, iRow: integer; Fields : TstringList; TempVal : String; begin VddQuery1.First; if not SaveDialog1.Execute then Exit; if FileExists(Savedialog1.Filename) then DeleteFile(SaveDialog1.Filename); xf := TXLSExport.Create(savedialog1.filename); Fields := TStringList.Create; VddQuery1.GetFieldNames(Fields); for iRow := 0 to VddQuery1.RecordCount - 1 do begin for iCol := 0 to Fields.Count - 1 do begin TempVal := VddQuery1.FieldByName(Fields[iCol]).AsString; xf.Write(iCol, iRow, TempVal); end; VddQuery1.Next; end; xf.Free; Fields.Free; end; Mir wird beim öffnen der .xls auch angezeigt das das Format der Datei nicht erkannt werden konnte :? Woran liegt das denn? :( mfg Alex |
Re: Problem mit Excelexport
Hallo Borschti,
zu Deiner Eingangsfrage:
Delphi-Quellcode:
Wenn Auf dem Rechner kein excel installiert ist, dann bekommst Du eine Fehlermeldung.
excel : variant;
begin try excel:=createoleobject('EXCEL.APPLICATION'); except showmessage('Excel kann nicht gestartet werden!'); exit; end; Wenn Du unbedingt eine Ausgabe erstellen willst oder mußt, dann nimm doch CSV . Deine letzte Frage von hinten aufgedröselt: Wenn Das excel auf Deinem Rechner das Dateiformat nicht richtig erkennen kann, dann ist es entweder zickig oder aber es kennt das Format nicht. In beiden Fällen sollte die Datenanzeige nicht sehr zuverlässig sein. Da ich nicht die vollständige Unit gesehen habe mit der Du arbeitest, kann ich wenig konkretes hierzu sagen, aber die excel-Dateien, die auf meinem Rechner liegen, können damit nicht erstellt werden. Ansonsten kann ich Dir nur den Tip geben die Erstellungsroutine mit bekannten Daten zu testen. Bekannt heißt "im Programm generiert" und nicht über irgendeine obskure Query irgendwoher geholt. Gruß K-H |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:12 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz