Seite 1 von 3

Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 4:08
von DelUser01
Hallo

ich schaffe es einfach nicht herauszufinden wie man das macht:
1. abfragen ob Excal noch geöffnet ist oder vom User geschlossen wurde. Und
2. abfragen ob die geladene Arbeitsmappe (File) noch geöffnet ist oder vom User geschlossen wurde.

Das Excel-Objekt zu erstellen, Files zu laden, mit den Feldern zu arbeiten, und das ganze wieder schließen ist nicht das Problem. Aber wenn der User eingreift stürzt mein Programm ab.

Könnt Ihr mir da bitte auf die Sprünge helfen?

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 5:49
von AUGE_OHR
Roland Gentner hat geschrieben:1. abfragen ob Excal noch geöffnet ist oder vom User geschlossen wurde. Und
2. abfragen ob die geladene Arbeitsmappe (File) noch geöffnet ist oder vom User geschlossen wurde.
zu 1.) du kannst die Tasklist abfragen

Code: Alles auswählen

   aTasklist := GetTaskList( oDlg:gethWnd( ) )
   FOR i = 1 TO LEN( aTasklist )
       IF "Excel." $ aTasklist[i]
           //
       ENDIF  
   NEXT

FUNCTION gettasklist( hWnd )
   LOCAL aList       := {}
   LOCAL cWindowName
   LOCAL nVisible
   DO WHILE hWnd != 0
      cWindowname := SPACE( 100 )
      IF ( getwindowtexta( hWnd, @cWindowName, LEN( cWindowName ) ) <> 0 )
         nVisible := IsWindowVisible( hWnd )
         IF nVisible == 1
            AADD( aList, STR( hWnd, 8 ) + cWindowname )
         ENDIF
      ENDIF
      hWnd = GetWindow( hWnd, GW_HWNDNEXT )
   ENDDO
RETURN aList

FUNCTION GetWindow( hWnd, uCmd )
   LOCAL nDll := DllLoad( "USER32.DLL" )
   LOCAL xRet := DllCall( nDll, DLL_STDCALL, "GetWindow", hWnd, uCmd )
   DllUnLoad( nDll )
RETURN xRet

FUNCTION GetWindowTextA( hWnd, lPstring, nMax )
   LOCAL nDll := DllLoad( "USER32.DLL" )
   LOCAL xRet := DllCall( nDll, DLL_STDCALL, "GetWindowTextA", hWnd, @lPstring, nMax )
   DllUnLoad( nDll )
RETURN xRet
zu 2.) versuche doch ob du die XLS Datei mit FOPEN() "Exklusive" öffnen kannst.

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 8:31
von georg
Hallo, Roland -


Du kannst das ganze aber auch "unsichtbar" ablaufen lassen, dann sind Benutzereingriffe schon schwieriger.

Ansonsten gefallen mir Jimmys Vorschläge aber auch.

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 8:56
von brandelh
Am sichersten und schnellsten ist es das Excel Objekt unsichtbar zu bedienen.

Bei der Version mit der Abfrage ob ein Fenster offen ist, muss man bei Excel und vielen anderen Programmen die Titel jeweils abfragen, da diese auch von der geöffneten Datei abhängen !

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 9:15
von Tom
Die möglichen Problemsituationen sind ziemlich komplex. Sehr originell wird es, wenn eine Trialversion von Excel installiert ist. Dann lässt sich das Objekt zwar initialisieren, aber nicht steuern, weil Excel tatsächlich gerade die Frage stellen möchte, ob der Trial fortgesetzt werden oder das Produkt lizenziert werden soll.

Ich kann nur empfehlen, den gesamten Export- und Steuerungsprozess in eine Sequenz einzubinden. Nur auf diese Weise ist man gegen mögliche Laufzeitfehler gefeit.

Ob eine bestimme Excel-Tabelle bereits geöffnet ist, lässt sich z.B. dadurch ermitteln, dass man die Existenz der Temporärdatei abfragt, die Office grundsätzlich anlegt, wenn ein Word-Dokument, eine Excel-Tabelle oder eine Access-Datenbank geöffnet werden (Excel: ~$<DateiName>). Das ist aber nicht unbedingt verlässlich, weil die Datei - die übrigens den Namen des Nutzers enthält, der das Dokument verwendet - möglicherweise nicht gelöscht worden ist, als Excel beendet wurde. Man kann auch einfach prüfen, ob sich die Datei "shared" öffnen lässt:

(Beispiel aus Roger Donnays eXpress++-Forum)

Code: Alles auswählen

FUNCTION IsFileOpened( cFileName )

#include "fileio.ch"
LOCAL lStatus := .t.
LOCAL nHandle := FOpen( cFileName, FO_READWRITE+FO_DENYWRITE) )

IF nHandle <= 0
  DCMSGBOX 'Datei '+cFileName+' ist in Benutzung!'
  lStatus := .f.
ELSE
  FClose(nHandle)
ENDIF

RETURN lStatus

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 10:37
von DelUser01
Hallo Jimmy
AUGE_OHR hat geschrieben:du kannst die Tasklist abfragen
Wenn ich die Taskliste abfrage und ein "Excel.exe" gefunden wird heißt das aber nicht dass es das von mir geöffnete Excel-Objekt ist. Der User kann mehrere Excel-Objekte und auch manuell gestartetes Excel geöffnet haben (ist sogar anzunehmen).
AUGE_OHR hat geschrieben:versuche doch ob du die XLS Datei mit FOPEN() "Exklusive" öffnen kannst
Das mache ich schon. Die Abfrage müsste zur Sicherheit vor jedem Excel-Zugriff erfolgen (weiß nicht ob das Gut ist). Und das wäre für das Netzwerk ganz schön belastend. Langsam wäre es vermutlich auch noch.
Beim Testen ist das Programm trotzdem immer wieder abgestürzt. Die FOpen()-Abfrage ist vermutlich zu träge wenn der User [X] anklickt.

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 10:46
von DelUser01
Hallo Georg
georg hat geschrieben:Du kannst das ganze aber auch "unsichtbar" ablaufen lassen, dann sind Benutzereingriffe schon schwieriger
Das geht in diesem Fall nicht. Der Benutzer aktiviert das entsprechende Arbeitsblatt und
positioniert den Cursor. Dann werden automatisch Werte eingetragen wenn im Excel-Sheet noch keine stehen.

Wenn das mit der Abfrage "ob Excel und das Sheet noch geöffnet sind" nicht sauber funktioniert kann ich nur die Automatik abschalten und der User muss jeweils "Start" anklicken (oder so).

Selbst mir passiert es beim Ausarbeiten und Testen immer wieder dass ich Excel mit [X] zumache statt über die Xbase++ App.

@Jimmy:
Ohne permanente Kommunikation mit dem Excel-Objekt reicht FOpen() vollkommen in einer Schleife abzufragen.

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 10:50
von DelUser01
Hallo Hubert
brandelh hat geschrieben:...die Titel jeweils abfragen
OK - an das habe ich nicht gedacht, dass wäre bei der Prozessabfrage noch eine Möglichkeit festzustellen ob auch noch das richtige Fenster geöffnet/vorhanden ist.

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 11:30
von brandelh
Warum muss dein Anwender bestimmen wohin die Daten sollen ?

Wenn irgend möglich, sollte das dein Programm ermitteln und seinen Job machen.
Wenn ER das tatsächlich muss, dann würde ich so vorgehen:

1. Excel anzeigen mit dem Hinweis den Cursor zu positionieren ... natürlich sichtbar
2. In deiner Anwendung den "Starte Übergabe" Button drücken.
3. Nun schaltet deine Anwendung das Excel Objekt auf unsichtbar (das geht !)
4. Werte übertragen
5. Excel Objekt wieder sichtbar machen und Erfolgsmeldung ausgeben.

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 12:02
von DelUser01
Hallo Hubert

das mit dem "Start => unsichtbar machen" würde natürlich gehen. Der User hat aber insbesondere bei einer Neuanlage des Kalkulationsblattes mehreres auszufüllen. D.h. das Blatt muss wieder sichtbar werden für die nächste Position usw.

Es gäbe hier natürlich die Möglichkeit den Ablauf anders aufzubauen, indem der User die Einzutragenden Positionen über eine Xbase++-Liste auswählt und erst wenn alles fertig ist wird das Sheet angezeigt.

Nichts desto trotz ist bei einem permanenten Info-Austausch zwischen Xbase++ und dem Excel-Objekt die Ermittlung des Objekt-Status unabdingbar.

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 12:08
von DelUser01
Habe die Prüfung ob das Excel-Sheet noch geöffnet ist gerade so gelöst:

Code: Alles auswählen

Function ExcelTestIfBookIsOK1( oBook )
Local lObjOK := .F.
Local oSheets
Local nSheets
* Break hier setzen
Begin Sequence
   oSheets := oBook:Sheets
   nSheets := oSheets:Count
   lObjOK   := .T.
End Sequence
* Break zurücksetzen
Return( lObjOk )
Die Sheet-Abfrage scheint "verlässlich" einen Error zu produzieren wenn keine Arbeitsmappe geladen ist (File).

Eine "verlässliche" Prüfung ob das Excel-Objekt noch mit Excel.exe verbunden ist habe ich noch nicht gefunden.
oExcel:Visible scheint immer zu antworten,

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 12:55
von brandelh
Wenn möglich würde ich alle Werte in einem Xbase Fenster abfragen und auf einmal in Excel eintragen ... möglichst das Ziel errechnen.

Es ist eine Weile her, aber ich mache das so:

VOR der Excel-Datenübergabe oExcel:visible := .F. // das Fenster wird versteckt, der Anwender kann nicht mehr stören
NACH der Excel-Datenübergabe oExcel:visible := .T. // zeigt das Fenster wieder an, der Anwender kann prüfen, neue Position bestimmen etc.

Das Programm kann immer hin und herschalten !

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 13:03
von DelUser01
Hubert, so wie Du schreibst soll es ja auch gemacht werden.
Nur wenn der User Excel schließt sollen auch automatisch alle Excel-Funktionen in meinem Programm deaktiviert werden.

Da ich das (noch) nicht herausgefunden habe wie man das erkennt dass der User Excel beendet hat "hänge" ich das im Moment an die Überprüfung ob die Arbeitsmappe noch geladen ist. Wenn nicht dann schließe ich auch das Excel-Objekt.

Hier ein Text zu diesem Thema von MS, hat mich aber (noch) nicht schlauer gemacht:
http://support.microsoft.com/kb/192348/de

Ergänzung:
laut dem o.g. MS-Text scheint es wirklich nur über die Methode "den Fenstertext finden" zu gehen (=> Hubert).

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 13:21
von brandelh
OK, was passiert wenn der Anwender Excel schließt und du auf das Excel Objekt zugreifst ?

Erhälst du einen Laufzeitfehler ? Wenn ja, dann könntest du die Fehlerbehandlung so ändern, dass dieser Laufzeitfehler ignoriert wird und deine Excel Routine endet.
Da ich meinen Ablauf nur selbst bediene und "Narrensicher" gemacht habe, kommt das bei mir nicht vor.

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 13:37
von DelUser01
Hallo Herbert

das ist ja der Springende Punkt: alles nur weil der User geführt werden muss und möglichst früh nicht "ordnungsgemäße" Vorgehensweisen erkannt werden sollten.

Laufzeitfehler:
Wenn eine Arbeitsmappe in Excel geöffnet ist kann alles mögliche abgefragt und getan werden. Ist keine Mappe geöffnet (User hat die geschlossen) kommt es beim Zugriff auf oBook usw. zu Laufzeitfehlern. das lässt sich abfangen.

Man kann die Mappe neu laden wenn der User diese geschlossen hat.
Das geht seltsamer Weise auch wenn der User Excel bereits geschlossen hat - also eigentlich das Excel-Objekt eigentlich nicht mehr verwendbar sein sollte. Dann geht Excel erneut auf! Ohne vorherige Anforderung eines neuen Automation-Objekts.

Das ist alles sehr seltsam...

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 13:51
von brandelh
Roland Gentner hat geschrieben:Das geht seltsamer Weise auch wenn der User Excel bereits geschlossen hat - also eigentlich das Excel-Objekt eigentlich nicht mehr verwendbar sein sollte.
Dann geht Excel erneut auf! Ohne vorherige Anforderung eines neuen Automation-Objekts.
Das ist alles sehr seltsam...
Nö das ist logisch, denn obwohl die sichtbare Arbeitsmappe beendet wird, bleibt der Servertask von Excel aktiv und wird solange nicht beendet, bis Xbase++ seine Resourcen freigibt.

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 13:59
von DelUser01
brandelh hat geschrieben:...bleibt der Servertask von Excel aktiv und wird solange nicht beendet, bis Xbase++ seine Resourcen freigibt.
Das passiert wenn das Automation-Objekt auf NIL gesetzt wird?
Und vermutlich beim Verlassen der Xbase++-App.

Deshalb interessiert mich ja schlussendlich der Excel-Objektstatus um diesen sauber abschließen zu können.

Das bringt mich zu der Frage:
wenn ich mehrere Arbeitsmappen aufmache, ist das dann immer dasselbe Excel-Objekt oder wird mit CreateObject() jedes Mal ein neues Objekt erstellt?

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 14:08
von brandelh
Wenn es ein Objekt wäre, würden die sich gegenseitig stören !

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 14:28
von DelUser01
OK - also nur ein Excel-Objekt.

Hast Recht - würde mit den Arbeitsmappen nur Ärger geben.

Und wird beim Verlassen der Xbase++-App auch nicht automatisch gelöscht (gerade aufgefallen).

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 14:56
von Herbert
brandelh hat geschrieben:
Roland Gentner hat geschrieben:Das geht seltsamer Weise auch wenn der User Excel bereits geschlossen hat - also eigentlich das Excel-Objekt eigentlich nicht mehr verwendbar sein sollte.
Dann geht Excel erneut auf! Ohne vorherige Anforderung eines neuen Automation-Objekts.
Das ist alles sehr seltsam...
Nö das ist logisch, denn obwohl die sichtbare Arbeitsmappe beendet wird, bleibt der Servertask von Excel aktiv und wird solange nicht beendet, bis Xbase++ seine Resourcen freigibt.
Das sind sehr heikle Fragen. Es kann sein, dass der Anwender vor Programmaufruf bereits ein Excel selber geöffnet hat. Schiesst du nun aus der Applikation heraus das Excel ab, so zerstörst du auch das vorgängig durch den User geöffnete Sheet, was nicht gerade freundschaftlich wäre.
Daher zuerst nachsehen (Jimmy hat's gezeigt), ob Excel bereits läuft. Anchliessend nur noch Shetts öffnen und schliessen.

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 15:31
von DelUser01
Hallo Herbert
Herbert hat geschrieben:Es kann sein, dass der Anwender vor Programmaufruf bereits ein Excel selber geöffnet hat. Schiesst du nun aus der Applikation heraus das Excel ab, so zerstörst du auch das vorgängig durch den User geöffnete Sheet
Habe das gerade getestet:
- Excel geöffnet und eine Arbeitsmappe geladen,
- Xbase++-App gestartet,
- CreateObject(),
- Arbeitsmappe laden -> neues Excel-Fenster erscheint,
- Arbeitsmappe und Excel schließen,
=> das zuvor bereits geöffnete Excel-Fenster und die Arbeitsmappe bleiben weiter geöffnet.
=> wird die selbe Arbeitsmappe geöffnet ist die im 2. Fenster schreibgeschützt.

Also erst einmal nicht ganz so kritisch...

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 16:50
von Herbert
Was passiert, wenn du dein Programm schliesst? Bleibt Excel offen?

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 17:03
von DelUser01
Hallo Herbert

wird die Xbase++-App geschlossen bleibt alles geöffnet, Excel + Mappe(n).

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 18:08
von Koverhage
oBook:BeforeClose := {||lExcelFinished := .T.}
lExcelFinished := .F.

oExcel:Interactive := .T.


Do WHILE !lExcelFinished
// Just wait
nEvent := AppEvent( @mp1, @mp2, , 1)
EndDo
endif

// Quit Excel
oExcel:Quit()
sleep(100)
oExcel:Destroy()
oExcel := NIL

Re: Excel-Object: Excel geöffnet? Arbeitsblatt geladen?

Verfasst: Mo, 17. Nov 2014 18:29
von DelUser01
Hallo Klaus

das mit o:BeforeClose() werde ich probieren...