Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   delphi --stream--> excel ?? (https://www.delphipraxis.net/127008-delphi-stream-excel.html)

hyype 6. Jan 2009 14:40


delphi --stream--> excel ??
 
Hiho.
Mit ein wenig Phantasie kann man dem Topic schon entnehmen, worum es geht ^^
Ich möchte von Delphi aus Excel ansteuern, dazu habe ich auch einige Beiträge im Netz gefunden und es auch wie folgt umgesetzt:
Delphi-Quellcode:
procedure TForm1.ExcelViewer(ms:TMemoryStream);
var
  Excel  : Variant;
  strPath : string;
  screened:boolean;
  bmp:TBitmap;
begin
  bmp:=TBitmap.Create;
  try
    try
      ms.Position:=0;
      strPath:=ExtractFilePath(paramstr(0))+'hype.xls';
      ms.savetofile(strPath);
      Excel:=CreateOleObject('Excel.Application');
      try
        Excel.Workbooks.open(strPath);
        Excel.Visible:=true;
        screened:=takescreen(bmp);
      finally
        Excel.quit;
        deletefile(strPath);
      end;
      if screened then
      begin
        image1.Picture.Bitmap.assign(bmp);
        memo1.Visible:=false;
        stringgrid1.Visible:=false;
        image1.Visible:=true;
        image1.Left:=0;
        image1.Top:=0;
        image1.Height:=image1.Picture.Height;
        image1.Width:=image1.Picture.Width;
        form1.clientheight:=image1.Height;
        form1.ClientWidth:=image1.Width;
      end
      else
        showmessage('taking screenshot failed');
    finally
      bmp.Free;
      deletefile(strPath);
    end;
  except
    on e : exception do
    showmessage('das hat nicht geklappt  '+e.message);
  end;
end;
Die Procedure ist nicht wirklich ausgereift, z.Bsp. kriege ich Excel nicht maximiert, falls es noch nicht maximiert ist.
Habe auch schon n Makro aufgezeichnet:
Application.WindowState = xlMaximized
Ich krieg das aber nicht in Delphi übertragen...
Ein weiterer sehr unschöner Sachverhalt ist, dass ich die hype.xls nicht mehr löschen kann, weil sie von irgendwas geöffnet ist.
Habe im TaskManager nachgeguckt, ob da irgendwo noch ein Excel läuft und: nein
Auch nach einem Neustart ist die Datei nicht löschbar... (auch von Hand nicht)
Also wer mir da einen Rat geben kann: immer her damit! ;)
Nun zum eigentlichen Problem:
Mir liegt das Excel-File als MemoryStream vor und ich würde den gern an Excel übergeben, anstatt ihn erst als .xls abzuspeichern und die Datei dann mit Excel zu öffnen - geht das irgendwie?
Vielen Dank schonmal.
mfg
Hype

Chemiker 6. Jan 2009 18:29

Re: delphi --stream--> excel ??
 
Hallo Hype,

Excel maximieren:

Delphi-Quellcode:
Excel.Application.WindowState:= xlMaximized;
Zitat:

Zitat von Hype
Ein weiterer sehr unschöner Sachverhalt ist, dass ich die hype.xls nicht mehr löschen kann, weil sie von irgendwas geöffnet ist.

Das kann an der Einstellung vom Stream liegen. Ich würde die Einstellungen noch mal überprüfen.

Zitat:

Zitat von Hype
Mir liegt das Excel-File als MemoryStream vor und ich würde den gern an Excel übergeben, anstatt ihn erst als .xls abzuspeichern und die Datei dann mit Excel zu öffnen - geht das irgendwie?

Ja, aber um weiterzuhelfen fehlen Informationen, wie ist der Stream Aufgebaut.

Bis bald Chemiker

hyype 7. Jan 2009 08:07

Re: delphi --stream--> excel ??
 
danke, ich hatte es mit excel.windowstate probiert...
der stream ist ein ganz normaler memorystream, ich hab den immer nur benutzt. ich nehme an, dass er die Bytes, aus denen die Datei besteht, einfach kopiert, aber da kenne ich mich auch nicht aus

aus der Hilfe:
"Mit TMemoryStream können Daten in einem dynamischen Speicherpuffer abgelegt werden, der über erweiterte E/A-Funktionalität verfügt. TMemoryStream umfasst die allgemeinen E/A-Merkmale eines Stream-Objekts, führt aber Methoden und Eigenschaften ein, die speziell für die Verwaltung eines dynamischen Speicherpuffers vorgesehen sind.
Speicher-Streams eignen sich gut als temporäre Informationsablage, weil sie Daten speichern können, aber auch Lese- und Schreibvorgänge in/aus anderen Speichermedien zulassen. Sie bieten eine praktikable Möglichkeit, die Inhalte verschiedener Streams zu vergleichen oder gespeicherte Daten auf solchen Medien zu bearbeiten, die nur indirekt zugreifbar sind."

und gefreet wird der ms am ende auch..
habe zu testzwecken (weil es erstmal nur ein testproject ist bis es dann so läuft wie ich es will) einfach ms.loadfromfile gemacht und den pfad einer excel-datei angegeben
aber kann das denn daran liegen? wenn ich den rechner neustarte hat es doch nix mehr mit dem stream zu tun, oder?
bei word-dokumenten mache ich es genauso und die kann ich löschen :/
gib mir mal bitte nen kleinen tip, wie ich nen stream an excel übergeben könnte, dann probier ich n bissl rum :)

edit:
er sagt mir "unbekannter bezeichner xlMaximized"

mkinzler 7. Jan 2009 08:41

Re: delphi --stream--> excel ??
 
xlMaximized hat den Wert -4137

hyype 7. Jan 2009 10:44

Re: delphi --stream--> excel ??
 
Mit -4137 geht es, danke!
Ich habe jetzt einiges geändert, weil das Abscreenen im Endeffekt Schwachsinn ist, da die Excel-Tabelle ja wesentlich mehr Daten enthalten kann als man sieht, auch wenn mans maximiert hat..
Delphi-Quellcode:
procedure TForm1.ExcelViewer(ms:TMemoryStream);
var
  Excel  : Variant;
  strPath : string;
  offen  : boolean;
begin
  offen:=false;
  ms.Position:=0;
  strPath:=ExtractFilePath(paramstr(0))+'hype.xls';
  try
     Excel := GetActiveOleObject('Excel.Application');
     offen:=true;
  except
     Excel := CreateOleObject('Excel.Application');
  end;
  if offen then
    try
      WB.close;
    except

    end;
  try
    ms.savetofile(strPath);
  except
    showmessage('Nicht genügend freier Speicherplatz oder fehlende Schreibrechte');
  end;
  WB:=Excel.Workbooks.open(strPath);
  Excel.visible:=true;
  Excel:=Unassigned;
end;
WB ist eine globale Variable vom Typ Variant. Damit kann ich gegebenenfalls das zuletzt über mein Programm geöffnete Workbook schließen, damit ich die hype.xls wieder benutzen kann. Ich habe leider nicht herausgefunden, wie ich bei Excel.Workbooks.Close den Namen des zu schließenden Workbooks übergeben kann, daher diese unschöne Lösung. Ist schon schwer, ohne Autovervollständigung zu programmieren, ich kann gar nicht gucken, welche Methoden mir zur Verfügung stehen, welche Übergabeparameter die erwarten etc :/
Offene Fragen wären noch die mit dem Stream und obs auch ohne WB geht.
Vielen Dank.

nahpets 7. Jan 2009 12:11

Re: delphi --stream--> excel ??
 
Hallo,

welche Delphiversion hast Du?

Zumindest bei Delphi 7 gibt es Packages dcloffice2k70.bpl und dclofficexp70.bpl. Wenn Du die installierst, bekommst Du einen zusätzlichen Palettenreiter "Server", der diverse Komponenten für die Officeprodukte enthält. Damit funktioniert die Autovervollständigung. Zum Nachgucken reicht das dann immer, auch wenn Du Excel und Co auf dem gewohnten Weg weiter benutzen willst.
Was auch hilft: In Excel ein Makro erstellen, was die gewünschte Aufgabe ausführt, mit ein bisserl Übung und Geduld kann man sich das nach Delphi übersetzen. Ansonsten die Hilfe des Makroeditors von Excel benutzen, ist immer besser, als nur stochern.

Chemiker 7. Jan 2009 14:16

Re: delphi --stream--> excel ??
 
Hallo hyype,

die Konstante xlMaximized funktioniert nicht, wenn Du nicht die entsprechende Excel-Unit mit eingebunden hast.
Welches Excel benutzt Du? Wenn Du z.B. Excel 2000 auf Deinen Rechner laufen hast, muss du die Excel2000-Unit mit einbinden.

Zitat:

Zitat von hyype
WB ist eine globale Variable vom Typ Variant. Damit kann ich gegebenenfalls das zuletzt über mein Programm geöffnete Workbook schließen, damit ich die hype.xls wieder benutzen kann.

Das kann eigentlich nicht sein, weil Du in Deinem Anfangsbeitrag geschrienen hast, dass auch nach einem Neustart die Dateien nicht mehr aufrufbar ist. Aber Schwamm drüber.
Um Hilfe bei der Eingabe von Delphi zu bekommen musst Du die frühe Bindung der Oleautomation verwenden.

Delphi-Quellcode:
WB:= Unassigned;
  if not VarIsEmpty(Excel) then
  begin
     Excel.DisplayAlerts := False;
     Excel.Quit;
     Excel := Unassigned;
  end;
Damit wird die Verbindung von Deinem Programm zum Workbook beendet.

Für die Oleautomation sollte man nach Möglichkeit die Variabeln mit OLEVariant deklarieren.

Bis bald Chemiker

hyype 7. Jan 2009 14:37

Re: delphi --stream--> excel ??
 
Danke für eure Beiträge!
Ich habe Delphi 2007, Windows Vista und Office 2003.
Das Programm, welches ich schreibe, soll aber unabhängig von der Office-Version funktionieren, wenn das überhaupt geht ^^
@nahpets:
Das mit den Makros machen und dann in Delphi-Code übersetzen habe ich auch gelesen und auch gemacht, allerdings gestaltet sich das mitunter etwas schwierig, wenn man die Delphi-Entsprechung nicht kennt. :/
@Chemiker:
Die in meinem Anfangsbeitrag erwähnten Dateien sind aufrufbar, sie sind aber nicht mehr löschbar. Ich ahne auch, woran das liegt, ich habe nämlich am Anfang Fehler im Code gehabt und dadurch kam zwischen dem Starten von Excel und Excel.Quit eine Exception. Dadurch hatte ich im Taskmanager 3 Prozesse namens EXCEL.EXE, die die beiden Dateien blockiert haben. Die habe ich dann alle 3 abgeschossen, Rechner neu gestartet und so weiter, aber gelöscht krieg ich sie trotzdem nicht mehr...
Überschreiben dagegen geht.
Mit dem WB meinte ich aber etwas ganz anderes:
Da ich jetzt Excel nicht mehr abscreene und schließe, sondern offen lasse, der User aber evtl mehrere Excel-Files hintereinander öffnet, ich den Stream aber immer als hype.xls speichere, muss ich mir das Workbook merken, damit ich gezielt dieses eine Workbook schließe und nicht andere evtl geöffnete mit Excel.Quit mitschließe...

Chemiker 7. Jan 2009 18:42

Re: delphi --stream--> excel ??
 
Hallo hyype,

Zitat:

Zitat von hyype
Ich habe Delphi 2007, Windows Vista und Office 2003.
Das Programm, welches ich schreibe, soll aber unabhängig von der Office-Version funktionieren, wenn das überhaupt geht

Mit der späten Bindung geht das, allerdings können natürlich Neuerungen die z.B. in Excel 2007 vorhanden sind nicht genutzt werden.
Da Du Office 2003 hast würde ich an Deiner Stelle die Unit ExcelXP mit einbinden, damit hast Du ein Teil der Konstanten die in Excel vorhanden sind zur Verfügung und muss nicht mühselig die Konstanten ermitteln (xlMaximized = -4137)
Hilfe kannst Du aber von Delphi dann nicht erwarten.

Zitat:

Zitat von hyype
Mit dem WB meinte ich aber etwas ganz anderes:
Da ich jetzt Excel nicht mehr abscreene und schließe, sondern offen lasse, der User aber evtl mehrere Excel-Files hintereinander öffnet, ich den Stream aber immer als hype.xls speichere, muss ich mir das Workbook merken, damit ich gezielt dieses eine Workbook schließe und nicht andere evtl geöffnete mit Excel.Quit mitschließe...

Warum soll der User in eine Excel – Instanz die vom Programm geöffnet worden ist, weitere Workbooks anlegen? Dann muss Du als Programmier auch dafür sorge tragen das Excel nicht vom User geschlossen wird oder der Dateiname geändert wird und dann unter Speichern unter… gespeichert wird. usw. usw.

Delphi-Quellcode:
WB. saved := FALSE;
WB.Close (saveChanges:=TRUE, FileName:= strPath);
Mit diesen Anweisungen ist es möglich das WorkBook abzuspeichern.


Bis bald Chemiker

hyype 8. Jan 2009 09:36

Re: delphi --stream--> excel ??
 
Mir geht es ja eigentlich nur darum, die Datei anzuzeigen.
Deswegen habe ich auch das Excel-Fenster abgescreent und Excel wieder geschlossen, aber dann habe ich in den meisten Fällen gar nicht alle in der Excel-Tabelle vorhandenen Informationen, weil die Tabellen ja riesig sein können.
Daher öffne ich die Datei einfach in Excel.
Dazu prüfe ich, ob Excel evtl schon offen ist. Wenn das der Fall ist, kann ich ja davon ausgehen, dass auch Workbooks geöffnet sind und speziell kann es sein, dass ein anderes Workbook über mein Programm geöffnet wurde und daher die hype.xls blockiert ist.
D.h. wenn Excel schon offen ist, muss ich zunächst das evtl vorher über mein Programm geöffnete Workbook schließen, damit die hype.xls wieder zur Verfügung steht und ich den Stream wieder als hype.xls speichern kann, ich darf aber nicht Excel komplett schließen, weil ja evtl auch ein ganz anderes Workbook geöffnet sein kann, womit mein Programm gar nix zu tun hat.

Könntest du bitte noch was zum Thema "Stream an Excel übergeben und öffnen" sagen? *liebguck* ^^

Chemiker 9. Jan 2009 00:29

Re: delphi --stream--> excel ??
 
Hallo hyype,

Zitat:

Zitat von hyype
Mir geht es ja eigentlich nur darum, die Datei anzuzeigen.
Deswegen habe ich auch das Excel-Fenster abgescreent und Excel wieder geschlossen, aber dann habe ich in den meisten Fällen gar nicht alle in der Excel-Tabelle vorhandenen Informationen, weil die Tabellen ja riesig sein können.
Daher öffne ich die Datei einfach in Excel.
Dazu prüfe ich, ob Excel evtl schon offen ist. Wenn das der Fall ist, kann ich ja davon ausgehen, dass auch Workbooks geöffnet sind und speziell kann es sein, dass ein anderes Workbook über mein Programm geöffnet wurde und daher die hype.xls blockiert ist.
D.h. wenn Excel schon offen ist, muss ich zunächst das evtl vorher über mein Programm geöffnete Workbook schließen, damit die hype.xls wieder zur Verfügung steht und ich den Stream wieder als hype.xls speichern kann, ich darf aber nicht Excel komplett schließen, weil ja evtl auch ein ganz anderes Workbook geöffnet sein kann, womit mein Programm gar nix zu tun hat.

Das habe ich nicht verstanden?

Du kannst Excel doch einfach öffnen und dann wird eine 2 Instanz von Excel erstellt, die unabhängig von der Excel-Instanz ist die mit Deinem Programm geöffnet worden ist.
Zudem könnte man abprüfen ob das Workbook „hype.xls“ noch in Excel vorhanden ist.

Zitat:

Zitat von hyype
Könntest du bitte noch was zum Thema "Stream an Excel übergeben und öffnen" sagen?

Vielleicht könnte ich, wenn wüsste was Du darunter verstehst.

Also, im Stream sind Daten, wie sehen diese Daten aus? Woher kommen diese Daten? Von einer Datenbank aus einem StringGrid? Oder ist es eine Text-Datei?
Oder, willst Du nur eine XLS-Datei kopieren und dann wieder in Excel aufrufen?

Das sind so einige Möglichkeiten, es gibt sicher noch mehr.


Bis bald Chemiker

WS1976 9. Jan 2009 06:11

Re: delphi --stream--> excel ??
 
Hallo Chemiker,

was prüfst du damit: (Testest du damit ob Excel (als Variable) noch existiert?)
Delphi-Quellcode:
   If VarIsEmpty(Excel)
steh etwas auf der Leitung. Kann dafür keine Hilfe finden.

Grüsse
Rainer

Chemiker 9. Jan 2009 07:04

Re: delphi --stream--> excel ??
 
Hallo,

ob die Variabel existiert wird nicht geprüft, sonder ob sie ihr Unassigned zugewiesen worden ist.

Das bedeutet das Programm hat keine Verbindung mehr zu Excel.

Das Beispiel ist zugegebener maßen konstruiert, aber mir viel auf die Schnelle nichts Besseres ein.

Einmal mit Abfrage:

Delphi-Quellcode:
Excel.DisplayAlerts := False;
Excel.Quit;
Excel := Unassigned;
if not VarIsEmpty(Excel) then
  begin
    Excel.DisplayAlerts := False;
    Excel.Quit;
    Excel := Unassigned;
  end;
Einmal ohne Abfrage:

Delphi-Quellcode:
Excel.DisplayAlerts := False;
Excel.Quit;
Excel := Unassigned;

Excel.DisplayAlerts := False;
Excel.Quit;
Excel := Unassigned;
Mit der Abfrage läuft das Programm ohne Fehlermeldung durch.

Bis bald Chemiker

hyype 9. Jan 2009 10:38

Re: delphi --stream--> excel ??
 
Hallo Chemiker!
Zitat:

Zitat von Chemiker
Oder, willst Du nur eine XLS-Datei kopieren und dann wieder in Excel aufrufen?

Im Endeffekt will ich das machen.
Ich mache ms.loadfromfile('D:\beispiel.xls') und dann ist in dem Stream eine exakte Kopie einer Excel-Datei.
Den will ich dann an Excel übergeben.
Noch eine Frage:
Wenn ich, wie du gesagt hast, eine neue Instanz von Excel öffne, um meine Datei anzuzeigen, kriegt Delphi dann irgendwie mit, wenn ich das Excel schließe?
Weil nur dann bringt mir das was.
Lata

edit:
Noch ein Problem...:
Wenn der User in eine Zelle geht und irgendwas eingibt ohne Enter zu drücken und dann wieder zu meinem Programm switcht und sich die nächste Excel-Datei anzeigen will, kann ich das alte Workbook nicht schließen.
Wenn der Cursor in einer Zelle steht, ist Excel lahmgelegt...
Was kann ich da machen? ^^

Chemiker 12. Jan 2009 18:25

Re: delphi --stream--> excel ??
 
Hallo hyype,

Zitat:

Zitat von hyype
Im Endeffekt will ich das machen.
Ich mache ms.loadfromfile('D:\beispiel.xls') und dann ist in dem Stream eine exakte Kopie einer Excel-Datei.
Den will ich dann an Excel übergeben.

Warum wird nicht direkt die XLS-Datei in Excel geladen? Für mich mach es nur Sinn, eine Datei in Delphi zu laden die Daten zu manipulieren und dann nach Excel für die weitere Verarbeitung zu laden. Eine Kopie kann man doch auch Betriebssystem-Ebene von der Datei anfertigen.

Zitat:

Zitat von hyype
Noch eine Frage:
Wenn ich, wie du gesagt hast, eine neue Instanz von Excel öffne, um meine Datei anzuzeigen, kriegt Delphi dann irgendwie mit, wenn ich das Excel schließe?
Weil nur dann bringt mir das was.

Dann würde ich aber die frühe Bindung einsetzen, weil dann Dir die Komponenten von Delphi zur Verfügung stehen. Unter Ereignisse kann man dann auf das schließen des Workbook z.B. reagieren, oder sogar unterbinden.

Zitat:

Zitat von hyype
Wenn der User in eine Zelle geht und irgendwas eingibt ohne Enter zu drücken und dann wieder zu meinem Programm switcht und sich die nächste Excel-Datei anzeigen will, kann ich das alte Workbook nicht schließen.

Das ist aber kein ungewöhnliches Verhalten von Excel. Du kannst ja mal Excel normal aufrufen (nicht durch Dein Programm) so wirst Du feststellen, wenn Du die Zelleneingabe nicht durch TAB oder Return (usw.) abschließt das Du das Workbook nicht schließen kannst.

Bis bald Chemiker

hyype 22. Jan 2009 13:05

Re: delphi --stream--> excel ??
 
Hi Chemiker!

Zitat:

Zitat von Chemiker
Das ist aber kein ungewöhnliches Verhalten von Excel. Du kannst ja mal Excel normal aufrufen (nicht durch Dein Programm) so wirst Du feststellen, wenn Du die Zelleneingabe nicht durch TAB oder Return (usw.) abschließt das Du das Workbook nicht schließen kannst.

Ja, das habe ich getestet und eben drum versucht, diesen Fall zu behandeln.
Aber egal, ich habe es jetzt aufgegeben, ich speichere die Datei einfach ab und shellexecute sie.. unschön, aber unkompliziert.

Vielen Dank für deine Mithilfe.

MfG

hyype


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:50 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