in der Sub A wird versucht, eine API-Verbindung zu einer Datenbank
herzustellen.
Sub A()
Dim iReturn as Integer
iReturn = DatenbankSession.connect 'naja, so �hnlich
...
End sub
iReturn kann +1 oder -1 sein, je nachdem, ob erfolgreich verbunden oder
nicht. Das funktioniert auch meistens.
Gelegentlich kommt es nun vor, dass die Datenbank "besetzt" ist, weil
sie z. B. noch eine Eingabe vom User erwartet. In diesem Fall wird gar
kein iReturn zur�ck gegeben. Die Sub A wartet endlos in der Zeile
iReturn = ... auf eine Antwort. Excel ist blockiert. Sanduhr, sonst
nichts. An dem Verhalten der Datenbank kann ich nichts drehen.
Ich suche jetzt eine zuverl�ssige L�sung, um gleichzeitig mit Sub A eine
Zeitschleife zu starten, die z. B. nach 5 min die Sub A beendet oder
notfalls die ganze Datei schlie�t ohne zu speichern. Die Zeitschleife
muss weiterlaufen, w�hrend die Sub A wartet.
'ne Idee?
Gru�
J�rg
--
LPs auf CD brennen - so geht's: http://www.joergei.de/
E-Mail-Adresse existiert, wird aber nicht gelesen.
Ermittle, ob die Datenbank �berhaupt Zugriff erlaubt, statt ein Aufh�ngen zu
riskieren, weil Du davon ausgehst, dass der Zugriff m�glich ist . Da w�rde
ich in der Access-Gruppe fragen, oder bei Michael Schwimmer suchen, oder
andere Anbieter von API-Funktionen anfragen (Herber).
--
Moin+Gruss Alexander - MVP for MS Excel - www.xxcl.de - mso2000sp3 --7-2
> in der Sub A wird versucht, eine API-Verbindung zu einer Datenbank
> herzustellen.
...
> iReturn kann +1 oder -1 sein, je nachdem, ob erfolgreich verbunden oder
> nicht. Das funktioniert auch meistens.
...
> Gelegentlich kommt es nun vor, dass die Datenbank "besetzt" ist, weil
> sie z. B. noch eine Eingabe vom User erwartet. In diesem Fall wird gar
> kein iReturn zur�ソスck gegeben. Die Sub A wartet endlos in der Zeile
> iReturn = ... auf eine Antwort. Excel ist blockiert. Sanduhr, sonst
> nichts. An dem Verhalten der Datenbank kann ich nichts drehen.
>
> Ich suche jetzt eine zuverl�ソスssige L�ソスsung, um gleichzeitig mit Sub A eine
> Zeitschleife zu starten, die z. B. nach 5 min die Sub A beendet oder
> notfalls die ganze Datei schlie�ソスt ohne zu speichern. Die Zeitschleife
> muss weiterlaufen, w�ソスhrend die Sub A wartet.
Starte die Verbindung in einer Sub via OnTime, dann kannst Du
weiterarbeiten w�ソスhrend Du auf die Verbindung wartest.
Andreas.
Public iReturn As Integer
Public Sub VerbindeZuDB()
'Bitte diese Sub starten und dann zur Excel-Oberfl�ソスche schalten, _
weiterarbeiten, die Statuszeile beobachten, in 5 Sekunden startet _
die Verbindung zur Datenbank.
Application.OnTime Now + TimeValue("00:00:05"), "ConnectDB"
End Sub
Sub Schaltfl�ソスche1_BeiKlick()
'Datenbank ge�ソスffnet?
Select Case iReturn
Case 0
MsgBox "Verbindung zur Datenbank noch nicht hergestellt"
Exit Sub
Case -1
MsgBox "Verbindung zur Datenbank konnte nicht hergestellt " & _
"werden"
Exit Sub
Case 1
'Verbindung hergestellt
Case Else
'Murks gemacht ;-)
End Select
End Sub
Private Sub ConnectDB()
Dim Start As Single
Dim oldStatusBar As Boolean
'Zustand der Statuszeile merken
oldStatusBar = Application.DisplayStatusBar
'Anzeigen das im Hintergrund was l�ソスuft
Application.DisplayStatusBar = True
Application.StatusBar = "Verbinde zur Datenbank..."
'Jetzt merken
Start = Timer
Do
'iReturn = DatenbankSession.connect
DoEvents 'Andere Task wollen auch was tun
'Schleife l�ソスuft 10 Sekunden oder bis DB-Verbunden
Loop Until (Timer - Start >= 10) Or (iReturn > 0)
'Statuszeile wieder herstellen
Application.StatusBar = False
Application.DisplayStatusBar = oldStatusBar
End Sub
>Ermittle, ob die Datenbank �berhaupt Zugriff erlaubt, statt ein Aufh�ngen zu
>riskieren, weil Du davon ausgehst, dass der Zugriff m�glich ist.
Zweifellos die sauberste L�sung. Bisher ist mir nur keine derartige
Funktion der API bekannt. Ich werde den Hersteller kontaktieren.
Notfalls bleibt doch nur die Zeitschleife.
@ Andreas,
klingt gut. �ber Erfolge kann ich erst n�chste Woche berichten.
Euch beiden vielen Dank und einen sch�nen Sonntag.
>> Gelegentlich kommt es nun vor, dass die Datenbank "besetzt" ist, weil
>> sie z. B. noch eine Eingabe vom User erwartet. In diesem Fall wird gar
>> kein iReturn zur�ck gegeben. Die Sub A wartet endlos in der Zeile
>> iReturn = ... auf eine Antwort.
>Starte die Verbindung in einer Sub via OnTime, dann kannst Du
>weiterarbeiten w�hrend Du auf die Verbindung wartest.
So, habe lange probiert und nix zustande gebracht. Eigentlich will ich
nur, dass die Excel-Datei, entweder, sofort nachdem sie die DB abgefragt
hat, oder nach 5 min geschlossen wird ohne zu speichern.
Die von Alexander vorgeschlagene M�glichkeit zur Pr�fung der
Verf�gbarkeit der DB habe ich bis jetzt nicht.
Das Starten On Time hilft bis jetzt auch nicht, weil ich die Sub
ConnectDB() nicht so wie von Dir vorgeschlagen verwenden kann:
>Private Sub ConnectDB()
> ...
> Start = Timer
> Do
> DoEvents
> iReturn = DatenbankSession.connect
> ...
> Loop Until (Timer - Start >= 10) Or (iReturn > 0)
> ...
>End Sub
Ich darf den Befehl DBsession.connect nicht in die Do-Schleife packen,
weil sonst bei jedem Durchlauf versucht wird, eine _neue_, also weitere
Verbindung herzustellen. Nach kurzer Zeit w�rde vermutlich der Server
explodieren.
Dann habe ich versucht:
Erstens)
-------------
Sub Start()
Appl.OnTime (1 s), Warteschleife
Appl.OnTime (2 s), FrageDBab
end sub
Sub FrageDBab()
DatenbankSession.connect
Mache die Abfrage
ThisWB.close false
end sub
Sub Warteschleife()
Do
DoEvents
'sonst nichts
Loop Until (5 min vorbei)
ThisWB.close false
end sub
Ergebnis: Die Do-Loop in Warteschleife() hat angehalten, w�hrend auf
DBsession.connect gewartet wird. Kein Schlie�en nach 5 min.
Zweitens)
-------------
Sub Start()
Appl.OnTime (5 min), CloseDatei
Appl.OnTime (1 s), FrageDBab
end sub
Sub FrageDBab()
DatenbankSession.connect
Mache die Abfrage
ThisWB.close false
end sub
Sub CloseDatei()
ThisWB.close false
end sub
Ergebnis: CloseDatei wurde nicht aufgerufen, w�hrend auf
DBsession.connect gewartet wird, auch nicht nach 5 min. Kein Schlie�en
nach 5 min.
(Anm.: Getestet habe ich nat�rlich mit k�rzeren Zeiten als 5 min.)
Wie kann ich erzwingen, dass die Datei nach 5 min geschlossen wird, wenn
die Sub FrageDBab() an der Stelle DatenbankSession.connect ewig wartet?
> So, habe lange probiert und nix zustande gebracht. Eigentlich will ich
> nur, dass die Excel-Datei, entweder, sofort nachdem sie die DB abgefragt
> hat, oder nach 5 min geschlossen wird ohne zu speichern.
Na das ist ja nun was ganz anderes.
Du öffnest eine Excel-Datei (von Hand?), möchtest eine Verbindung
(wie bitte genau?) zu einer Datenbank machen und die Datei wieder
schließen a.) direkt nachdem die Verbindung hergestellt wurde oder 5
Minuten vergangen sind?
> Das Starten On Time hilft bis jetzt auch nicht, weil ich die Sub
> ConnectDB() nicht so wie von Dir vorgeschlagen verwenden kann:
Das mit OnTime macht nur Sinn wenn Du, während Du auf die Verbindung
wartest, weiterarbeiten möchtest.
> Wie kann ich erzwingen, dass die Datei nach 5 min geschlossen wird, wenn
> die Sub FrageDBab() an der Stelle DatenbankSession.connect ewig wartet?
Heißt das nun das die Zeile "DatenbankSession.connect" nicht
ausgeführt wird wenn die Datenbank besetzt ist? D.h. das Makro "steht"
in dieser Zeile und läuft nicht weiter?
Andreas.
> Du �ffnest eine Excel-Datei (von Hand?), m�chtest eine Verbindung
> (wie bitte genau?) zu einer Datenbank machen und die Datei wieder
> schlie�en a.) direkt nachdem die Verbindung hergestellt wurde oder 5
> Minuten vergangen sind?
Wenn ich J�rg richtig verstehe liegt das problem darin, dass der Befehl, der
versucht eine Verbindung zur Datenbank herzustellen,
iReturn = DatenbankSession.connect
wegen Probleme der Datenbank endlos weiterl�uft und nicht zu VBA/Excel
zur�ckkehrt. Daher l�uft auch das VBA-Programm endlos und Excel ist blockiert.
Dein Ansatz, die Verbindungsroutine mittes OnTime etwas sp�ter erst loslaufen zu
lassen, �ndert an dem ung�nstigen Verhalten des Servers nichts. Auch die
verz�gert aufgerufene Routine wird an der Zeile
iReturn = DatenbankSession.connect
h�ngenbleiben.
J�rg sucht nun nach einer M�glichkeit, den h�ngengebliebenen VBA-Prozess nach
einer gewissen Zeitspanne 'sauber abzuschie�en' (ok, 'sauber' und 'abschiessen'
ist ein gewisser Widerspruch in sich ;-) )
Gru�
Bernhard Sander
> Wenn ich J�rg richtig verstehe liegt das problem darin, dass der Befehl,
> der versucht eine Verbindung zur Datenbank herzustellen,
> iReturn = DatenbankSession.connect
> wegen Probleme der Datenbank endlos weiterl�uft und nicht zu VBA/Excel
> zur�ckkehrt. Daher l�uft auch das VBA-Programm endlos und Excel ist
> blockiert.
Okay, ich hab auch schon in die Richtung vermutet.
> J�rg sucht nun nach einer M�glichkeit, den h�ngengebliebenen VBA-Prozess
> nach einer gewissen Zeitspanne 'sauber abzuschie�en' (ok, 'sauber' und
> 'abschiessen' ist ein gewisser Widerspruch in sich ;-) )
Wohl wahr, aber man k�nnte mal probieren eine zeitgesteuerte Sub zu
starten die das Workbook schlie�t. Die Frage ist ob Excel die Sub
starten kann, denn wenn der DatenbankSession.connect kein TimeSlice
freigibt geht's wahrscheinlich nicht.
Andreas.
Sub CloseMe()
Application.DisplayAlerts = False
ActiveWorkbook.Close
Application.DisplayAlerts = True
End Sub
Sub Main()
'Nach 10 Sekunden wird diese Mappe geschlossen
Application.OnTime Now() + TimeSerial(0, 0, 10), "CloseMe"
'Aufh�ngen
Do
DoEvents
Loop Until False
End Sub
Bernhard hat das Problem exakt beschrieben. Ich hatte gedacht, ich h�tte
das auch.
>Sub CloseMe()
> ...
>End Sub
>
>Sub Main()
> 'Nach 10 Sekunden wird diese Mappe geschlossen
> Application.OnTime Now() + TimeSerial(0, 0, 10), "CloseMe"
> 'Aufh�ngen
> Do
> DoEvents
> Loop Until False
>End Sub
Genau das Prinzip hatte ich auch probiert, siehe meinen Versuch Nr. 2 im
Beitrag vom 2009-10-07T00:02. Nur das "Aufh�ngen" hat gefehlt und die
Sub hie� "CloseDatei()".
Es n�tzt aber nichts., Wenn der Befehl
iReturn = DatenbankSession.connect
eher dran ist als nach 10 s - was ja beabsichtigt ist - wird die Sub
CloseMe() so lange nicht aufgerufen, wie VBA auf iReturn wartet. :-(
Die Frage ist also, ob man die Sub CloseMe() irgendwie in einer Art
"zweiter VBA-Instanz" ablaufen lassen kann, selbst wenn die erste
blockiert ist. Die Warteschleife k�me dann in die CloseMe().
>> Okay, ich hab auch schon in die Richtung vermutet.
> Bernhard hat das Problem exakt beschrieben. Ich hatte gedacht, ich h�tte
> das auch.
Naja, eigentlich schon, aber es entstehen oft Missverst�ndnisse... und
manchmal bin ich auch schwer im kapieren. :))
> Es n�tzt aber nichts., Wenn der Befehl
> iReturn = DatenbankSession.connect
> eher dran ist als nach 10 s - was ja beabsichtigt ist - wird die Sub
> CloseMe() so lange nicht aufgerufen, wie VBA auf iReturn wartet. :-(
>
> Die Frage ist also, ob man die Sub CloseMe() irgendwie in einer Art
> "zweiter VBA-Instanz" ablaufen lassen kann, selbst wenn die erste
> blockiert ist. Die Warteschleife k�me dann in die CloseMe().
2te Instanz? Hmm, keine schlechte Idee, das k�nnte gehen, pass up.
Also Du erstellt eine Dummy-Excel-File in der eine einzige Sub drin
ist, die die Verbindung zu Datenbank herstellt und dann wieder
schlie�t und sich selbst beendet (Application.Quit).
In Deinem normalen Excel-File startest Du mit Shell dieses File in
einem eigenen Task und kuckst was der Task macht.
Irgendwie konnte man den Task auch "wegkillen", Michael Schwimmer
hatte hier mal vor einiger Zeit ein Beispiel gepostet, finde ich aber
leider nicht mehr.
Andreas.
' �2002 by Jost Schwider, http://vb-tec.de/
Public Function ShellX( _
ByVal PathName As String, _
Optional ByVal WindowStyle As VbAppWinStyle = vbNormalFocus, _
Optional ByVal Events As Boolean = True _
) As Long
'Deklarationen:
Const STILL_ACTIVE = &H103&
Const PROCESS_QUERY_INFORMATION = &H400&
Dim ProcId As Long
Dim ProcHnd As Long
'Prozess-Handle holen:
ProcId = Shell(PathName, WindowStyle)
ProcHnd = OpenProcess(PROCESS_QUERY_INFORMATION, True, ProcId)
'Auf Prozess-Ende warten:
Do
If Events Then DoEvents
GetExitCodeProcess ProcHnd, ShellX
Loop While ShellX = STILL_ACTIVE
'Aufr�umen:
CloseHandle ProcHnd
End Function
Private Sub Form_Click()
ShellX "notepad.exe"
Beep ' :-)
End Sub
> 2te Instanz? Hmm, keine schlechte Idee, das k�nnte gehen, pass up.
Ja schon, aber da fehlt doch die H�lfte, Schnarchnase. :-)))
Jetzt aber und den Process-Weg-Killer hab ich auch hingekriegt, sind
aber nur 5 Sekunden, so zum Testen.
Andreas.
Option Explicit
Private Declare Function CloseHandle Lib "kernel32" ( _
ByVal hObject As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" ( _
ByVal hProcess As Long, lpExitCode As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" ( _
ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal _
hProcess As Long, ByVal uExitCode As Long) As Long
Public Function ShellX( _
ByVal PathName As String, _
Optional ByVal WindowStyle As VbAppWinStyle = vbNormalFocus, _
Optional ByVal Events As Boolean = True) As Long
'Deklarationen:
Const STILL_ACTIVE = &H103&
Const PROCESS_QUERY_INFORMATION = &H400&
Const PROCESS_ALL_ACCESS = &H1F0FFF, PROCESS_TERMINATE = &H1
Dim ProcId As Long
Dim ProcHnd As Long
Dim T As Long
'Prozess-Handle holen:
ProcId = Shell(PathName, WindowStyle)
ProcHnd = OpenProcess(PROCESS_QUERY_INFORMATION + _
PROCESS_TERMINATE, True, ProcId)
'Auf Prozess-Ende warten:
T = Timer
Do
If Events Then DoEvents
GetExitCodeProcess ProcHnd, ShellX
Loop While (ShellX = STILL_ACTIVE) And (Timer - T < 5)
'Aufr�umen:
If ShellX = STILL_ACTIVE Then TerminateProcess ProcHnd, 0
Am Wed, 07 Oct 2009 00:02:31 +0200 schrieb J�rg Eisentr�ger:
> So, habe lange probiert und nix zustande gebracht. Eigentlich will ich
> nur, dass die Excel-Datei, entweder, sofort nachdem sie die DB abgefragt
> hat, oder nach 5 min geschlossen wird ohne zu speichern.
> Die von Alexander vorgeschlagene M�glichkeit zur Pr�fung der
> Verf�gbarkeit der DB habe ich bis jetzt nicht.
klar kannst du Excel, wie von Andreas beschrieben, aus einer anderen
Instanz heraus abschie�en, ist aber erst der allerletzte Weg.
Lies doch einmal nach, ob das Objekt >>DatenbankSession<< eine
Timout-Eigenschaft besitzt. Wenn keine Dokumentation verf�gbar ist, setze
doch mal hier >>DatenbankSession.connect<< einen Haltepunkt und schau, wenn
unterbrochen wird, im Lokal-Fenster nach, ob du eine Eigenschaft wie
Timeout, ConnectionTimeout oder CommandTimeout findest.
Wenn du einen Objektverweis gesetzt hast, kannst du dir auch im
Objektkatalog die Eigenschaften des Objektes anschauen und nach Timout
suchen.
Um was f�r ein Objekt f�r die Datenabfrage handelt es sich denn �berhaupt?
Das ist wichtig, denn es ist sicherlich kein Excel-spezifisches Problem und
mit der Kenntnis des Objektes kann dir auch in der entsprechenden Newsgroup
geholfen werden. Ich kann mir einfach nicht vorstellen, dass die Entwickler
ein Blocking nicht ber�cksichtigt haben.
Viele Gr��e
Michael
--
http://michael-schwimmer.de
Masterclass Excel VBA ISBN-10: 3827325250
Das Excel-VBA Codebook ISBN-10: 3827324718
Microsoft Office Excel 2007-Programmierung ISBN-10: 3866454139
ShellX ist mir bekannt und ich nutze es auch bereits anderweitig. Ich
muss mal hirnen, ob es mir hier helfen kann. Das ganze ist etwas tricky,
weil die Mappe, in welcher ich das Problem habe, selbst nur eine
Hilfsdatei ist und erst durch eine andere Hauptmappe ge�ffnet wird. Das
w�re dann Hilfsmappe abschie�en durch secondary Hilfsmappe. Oje.
Vielen Dank f�r die Idee.
danke, dass Du Dich einklinkst.
>Um was f�r ein Objekt f�r die Datenabfrage handelt es sich denn �berhaupt?
Die Datenbank ist ein PDM-System zur Verwaltung von CAD- und anderen
Dateien, Teilestammdaten, St�cklisten etc.
Das Objekt ist ein spezifischer Variablentyp der API.dll, nennt sich
"...API_Client.SessionControlCOM".
>Das ist wichtig, denn es ist sicherlich kein Excel-spezifisches Problem
Exakt. Nur wollte ich es bisher mit Excel l�sen.
>und
>mit der Kenntnis des Objektes kann dir auch in der entsprechenden Newsgroup
>geholfen werden.
Marktanteil 3%. Das ist nix mit Newsgroup. Auf CAD.de gibt es ein Forum.
Muss ich mal schauen. Es gibt aber nur sehr wenige, die die API
�berhaupt nutzen.
>Ich kann mir einfach nicht vorstellen, dass die Entwickler
>ein Blocking nicht ber�cksichtigt haben.
Na, da hoffe ich mal zu Gunsten der Entwickler. Die Anfrage l�uft.
>Lies doch einmal nach, ob das Objekt >>DatenbankSession<< eine
>Timout-Eigenschaft besitzt.
Die API-Doku ist f�r mich (dll-Laie) v�llig unverst�ndlich.
Im Objektexplorer und im IntelliSense gibt es nur folgende Punkte von
"DatenbankSession":
Connect
ConnectSilent
DisConnect
GetGWClientCOM
GetBaseFuncCOM
isConnected (Eigenschaft).
Wenn der Haltepunkt steht an
iRet = DatenbankSession.Connect
steht im Lokalfenster:
DatenbankSession
unter dem Node-Zeichen dann
Wert: <Keine Variablen>
Typ: SessionControlCOM/SessionControlCOM
Leider nichts, was nach TimeOut klingt.
Am Thu, 08 Oct 2009 21:50:40 +0200 schrieb J锟絩g Eisentr锟絞er:
> Das Objekt ist ein spezifischer Variablentyp der API.dll, nennt sich
> "...API_Client.SessionControlCOM".
das ist ja was ganz exotisches.
>>Lies doch einmal nach, ob das Objekt >>DatenbankSession<< eine
>>Timout-Eigenschaft besitzt.
> Die API-Doku ist f锟絩 mich (dll-Laie) v锟絣lig unverst锟絥dlich.
>
> Im Objektexplorer und im IntelliSense gibt es nur folgende Punkte von
> "DatenbankSession":
> Connect
> ConnectSilent
> DisConnect
> GetGWClientCOM
> GetBaseFuncCOM
> isConnected (Eigenschaft).
Das ist nat锟絩lich sehr schlecht!
Wenn deine Nachfrage nichts bringt, hilft wahrscheinlich wirklich nur das
Abschie锟絜n des Prozesses. Wenn du zielgerichtet eine Excel-Instanz abw锟絩gen
m锟絚htest, mach es so, wie von Andreas vorgeschlagen.
Wenn Excel komplett beendet werden kann, w锟絩de ich Scripting (Scripting
muss nat锟絩lich zugelassen sein) benutzen. Einfach im Workbook_Open Ereignis
ein Script (hier aaaaa.vbs) starten:
Sub AufrufVBS()
Dim WSHShell As Object
Set WSHShell = CreateObject("WScript.Shell")
WSHShell.Run """c:\aaaaa.vbs"""
End Sub
In der Textdatei mit dem Namen aaaaa.vbs (die Zeit muss angepasst werden):
WScript.Sleep (30000) ' Millisekunden
KillProcessByExe "excel.exe"
Sub KillProcessByExe(strExe)
Dim objWMI
Dim objProcessList
Dim objProcess
Set objProcessList = GetObject("winmgmts://." _
& "/root/cimv2" _
).ExecQuery("Select * from Win32_Process Where Name = '" & _
strExe & _
"'")
For Each objProcess In objProcessList
objProcess.Terminate (0)
Next
End Sub
Das schie锟絫 dir alle Prozesse mit Namen excel.exe ab.
Viele Gr锟斤拷e
Oh, da w�rden mich meine User wahrscheinlich auch abschie�en, wenn ich
die Dateien zerst�re, an denen sie gerade 'ne Stunde gearbeitet haben.
Aber vielleicht braucht man es mal f�r was anderes.
Ich danke allen, die geantwortet haben. Wenn mir noch was anderes
einf�llt, poste ich es hier. Ansonsten bis zum n�chsten Mal.
Gru�
J�rg
--
LPs auf CD brennen - so geht's: http://www.joergei.de/
E-Mail-Adresse existiert, wird aber nicht gelesen.