Valutazione 4.87/ 5 (100.00%) 5838 voti

Condividi:        

[vba access 2003]: capire se l'istanza di excel è aperta

Vuoi potenziare i tuoi documenti Word? Non sai come si fa una macro in Excel? Devi creare una presentazione in PowerPoint?
Oppure sei passato a OpenOffice e non sei sicuro di come lavorare al meglio?

Moderatori: Anthony47, Flash30005

[vba access 2003]: capire se l'istanza di excel è aperta

Postdi karug64 » 14/01/13 21:24

Salve a tutti.
Nel mio programma ho le seguenti istruzioni:

Codice: Seleziona tutto
 Set objExcel = CreateObject("Excel.Application")
    Set objWorkbook = objExcel.Workbooks.Open(nomedifileout)
    Set objWorksheet = objWorkbook.Worksheets(1)


Nonostante l'intercettazione degli errori potrebbe capitare che l'utente "fermi" il programma di sua iniziativa, dopo che sono stati eseguiti i superiori comandi e poi riparta.

Ebbene, in questo caso, il processo Excel rimane apreto cosi' come il file e andando a lavorarci di nuovo ottengo errore del tipo "accesso negato", oppure, a seconda dell'eleborazione, arrivo alla fine e al salvataggio mi chiede se voglio salvare uan "copia" del file (considerato che gia' una in memoria esiste).

La domanda:

Esiste un modo per controllare, all'inizio del programma (apertura form), se esiste gia' un'istanza di excel aperta, nel qual caso potrei provvedere a chiuderla senza avere errori e proseguire ?

Grazie
Office 2010
karug64
Utente Senior
 
Post: 580
Iscritto il: 20/11/11 21:22

Sponsor
 

Re: [vba access 2003]: capire se l'istanza di excel è aperta

Postdi Flash30005 » 14/01/13 21:46

E' un po' complesso ma leggendo le descrizioni e inserendo il percorso del file dovresti risolvere
Codice: Seleziona tutto
Sub GetExcel()
    Dim MyXL As Object    ' Variabile in cui viene
                                ' memorizzato il riferimento a Microsoft Excel.
    Dim ExcelWasNotRunning As Boolean    ' Flag per il rilascio finale.

' Prova per verificare se vi è già una copia di Microsoft Excel in esecuzione.
    On Error Resume Next    ' Rimanda l'intercettazione degli errori.
' La funzione Getobject chiamata senza il primo argomento restituisce un riferimento a un'istanza dell'applicazione. Se l'applicazione non è in esecuzione viene generato un errore.
    Set MyXL = Getobject(, "Excel.Application")
    If Err.Number <> 0 Then ExcelWasNotRunning = True
    Err.Clear    ' Cancella l'oggetto Err in presenza di errori.

' Ricerca Microsoft Excel. Se Microsoft Excel è in esecuzione, lo inserisce nella tabella Running Object.
    DetectExcel

' Imposta la variabile oggetto in modo che faccia riferimento al file che si desidera visualizzare.
    Set MyXL = Getobject("c:\Temp\Miofile.xls")  '<<<<< percorso completo del file

' Visualizza Microsoft Excel tramite la proprietà Application, quindi visualizza la finestra effettiva che contiene il file utilizzando l'insieme Windows del riferimento all'oggetto MyXL.
    MyXL.Application.Visible = True
    MyXL.Parent.Windows(1).Visible = True
    ' Posizione per operazioni di modifica del file ...
' Se questa copia di Microsoft Excel non era già in esecuzione dall'inizio, la chiude utilizzando il metodo Quit della proprietà Application.
' Nota che quando si cerca di uscire da Microsoft Excel, la barra del titolo lampeggia e viene visualizzato un messaggio per richiedere se si desidera salvare i file caricati.
    If ExcelWasNotRunning = True Then
        MyXL.Application.Quit
    End IF

    Set MyXL = Nothing    ' Rilascia il riferimento alla
                                ' applicazione e al foglio di lavoro.
End Sub

Sub DetectExcel()
' La routine individua un'istanza di Excel in esecuzione e la registra.
    Const WM_USER = 1024
    Dim hWnd As Long
' Se Excel è in esecuzione questa chiamata API restituisce l'handle corrispondente.
    hWnd = FindWindow("XLMAIN", 0)
    If hWnd = 0 Then    ' 0 significa che Excel non è in esecuzione.
        Exit Sub
    Else               
    ' Poiché Excel è in esecuzione è necessario utilizzare la funzione API SendMessage per inserirlo nella tabella Running Object.
        SendMessage hWnd, WM_USER + 18, 0, 0
    End If
End Sub


Ciao
Flash
Win7 + Office 2010 Ita
"Fotografica" al servizio dell'immagine

Ottime opportunità di lavoro (part-time o full-time) con guadagni immediati. Info in MP
Avatar utente
Flash30005
Moderatore
 
Post: 8460
Iscritto il: 27/09/07 11:44
Località: Roma +o-

Re: [vba access 2003]: capire se l'istanza di excel è aperta

Postdi karug64 » 14/01/13 22:08

Intanto grazie.

Ho un errore a questa riga :

Codice: Seleziona tutto
hWnd = FindWindow("XLMAIN", 0)


Sub o Function non definita

(non so dopo).

Ti preciso che mi trovo in access 2003.
Office 2010
karug64
Utente Senior
 
Post: 580
Iscritto il: 20/11/11 21:22

Re: [vba access 2003]: capire se l'istanza di excel è aperta

Postdi Flash30005 » 14/01/13 23:00

Bisogna dichiarare le routine API all'inizio del modulo (come prima riga)
Codice: Seleziona tutto
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As Long) As Long
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long


Prova e fai sapere

ciao

EDIT ore 23:05 - Modificata seconda dichiarazione
Flash
Win7 + Office 2010 Ita
"Fotografica" al servizio dell'immagine

Ottime opportunità di lavoro (part-time o full-time) con guadagni immediati. Info in MP
Avatar utente
Flash30005
Moderatore
 
Post: 8460
Iscritto il: 27/09/07 11:44
Località: Roma +o-

Re: [vba access 2003]: capire se l'istanza di excel è aperta

Postdi karug64 » 14/01/13 23:22

Ok. Fatto.
Ma le routine (mi sembra) funzionano al contrario. Mi spiego:
Chiamo GetExcel (NomeDiFilein) (dove nomedifilein= "c:\test\test.xls") all'inizio del programma. Prima di quel momento nel task manager non ho nessuna istanza di excel.

Quando il codice arriva qui:

Codice: Seleziona tutto
If hWnd = 0 Then    ' 0 significa che Excel non è in esecuzione.
    Exit Sub
Else
' Poiché Excel è in esecuzione è necessario utilizzare la funzione API SendMessage per inserirlo nella tabella Running Object.
SendMessage hWnd, WM_USER + 18, 0, 0
End If


come leggo da nota

Codice: Seleziona tutto
' Poiché Excel è in esecuzione è necessario utilizzare la funzione API SendMessage per inserirlo nella tabella Running Object.


lo inserisce nei processi ( e lo trovo nel task manager) e cosi' appena apro il file con le precedenti linee mi da errore "accesso negato" e nel task manager trovo due processi excel....

In effetti se non c'e' nessun processo non dovrebbe fare nulla, altrimenti dovrebbe cancellarlo inece di inserirlo.

Spero di essermi spiegato bene.

Grazie

Edit: a domani.
Office 2010
karug64
Utente Senior
 
Post: 580
Iscritto il: 20/11/11 21:22

Re: [vba access 2003]: capire se l'istanza di excel è aperta

Postdi Flash30005 » 14/01/13 23:38

Sostituisci solo la macro DetectExcel con questa
Codice: Seleziona tutto
Sub DetectExcel()
' La routine individua un'istanza di Excel in esecuzione e la registra.
    Const WM_USER = 1024
    Dim hWnd As Long
' Se Excel è in esecuzione questa chiamata API restituisce l'handle corrispondente.
    hWnd = FindWindow("XLMAIN", 0)
    If hWnd = 0 Then    ' 0 significa che Excel non è in esecuzione.
        Exit Sub
    Else
    ' Poiché Excel è in esecuzione è necessario utilizzare la funzione API SendMessage per inserirlo nella tabella Running Object.
        SendMessage hWnd, WM_USER + 18, 0, 0
        Set MyXL = GetObject("c:\test\test.xls")  '<<<<< percorso completo del file
        MyXL.Application.DisplayAlerts = False
        MyXL.Application.Quit
        MyXL.Application.DisplayAlerts = True
        Set MyXL = Nothing
    End If
End Sub


Ciao
N.B. nel post delle declare ho modificato (dopo qualche minuto) le dichiarazioni e non so se hai corretto il codice riportando queste ultime
Flash
Win7 + Office 2010 Ita
"Fotografica" al servizio dell'immagine

Ottime opportunità di lavoro (part-time o full-time) con guadagni immediati. Info in MP
Avatar utente
Flash30005
Moderatore
 
Post: 8460
Iscritto il: 27/09/07 11:44
Località: Roma +o-

Re: [vba access 2003]: capire se l'istanza di excel è aperta

Postdi Anthony47 » 15/01/13 01:53

Penso che funzioni anche il codice di Flash, aggiornato come da suo ultimo messaggio (vedi sopra).
Comunque nel "gadget Natalizio 2012" (vedi viewtopic.php?f=26&t=97968#p562997) avevo usato la funzione IsProcessRunning per determinare se il processo wmplayer.exe e' aperto, e allora killarlo, oppure no; mi pare che karug debba fare una cosa analoga sul processo excel.exe, per cui lo rimando alla consultazione del file.
Il cuore del lavoro e' fatto da questo codice, di facile comprensione e adattabilita':
Codice: Seleziona tutto
If IsProcessRunning("wmplayer.exe") Then
    On Error Resume Next
    Shell "CMD /C TASKKILL /IM wmplayer.exe"
    On Error GoTo 0
    myT2 = Timer
    Do
        If Not IsProcessRunning("wmplayer.exe") Then Exit Do
        DoEvents: If Timer > (myT2 + 2) Or Timer < myT2 Then Exit Do
        Loop
End If
(il codice della funzione IsProcessRunning, anche lui da inserire tra il tuo codice, e' nel modulo "Funzioni" del file "natalizio").

Nel tuo caso suggerirei un approccio piu' morbido rispetto a quanto fa quel codice (chiusura del processo senza nessun riguardo)

Quindi magari NON
On Error Resume Next
Shell "CMD /C TASKKILL /IM excel.exe"
On Error GoTo 0
' etc etc
ma
On Error Resume Next
rispo = MsgBox("Il programma Excel risulta gia' aperto, e deve essere terminato" & vbCrLf _
& "Confermi??", vbYesNo)
If rispo <> vbYes Then GoTo XXXXX
Shell "CMD /C TASKKILL /IM excel.exe"
On Error GoTo 0
' etc etc

Sostituisci XXXX con un riferimento a un' area in cui gestisci l' eventuale diniego da parte dell' utente a chiudere la sessione excel.

Ciao a tutti
Anthony
Win7 + Office 2010 Ita; Win 7 + Office 2013 Ita
Xp + Office 2003 Ita
E voi cosa usate? (per istruzioni vedere viewtopic.php?f=26&t=97449)
Avatar utente
Anthony47
Moderatore
 
Post: 13899
Iscritto il: 21/03/06 16:03
Località: Ivrea

Re: [vba access 2003]: capire se l'istanza di excel è aperta

Postdi karug64 » 15/01/13 21:40

Ciao Anthony.

Ho provato con la tua rotuine, ma non ottengo il risultato. Allego due immagini

http://imageshack.us/a/img267/687/cattura1r.jpg

Ho creato intenzionalmente un errore cosi' ha creare un'istanza di excel che non viene chiusa.

Nell'immagine puoi vedere come, dopo il passaggio dall'istruzione di killaggio, l'istanza ad excel continua ad esserci sempre.

Inoltre sui pc in ufficio l'istanza e' EXCEL.EXE *32 (essendo su sistemi a 64bit) cambierebbe qualcosa ?

Grazie
Office 2010
karug64
Utente Senior
 
Post: 580
Iscritto il: 20/11/11 21:22

Re: [vba access 2003]: capire se l'istanza di excel è aperta

Postdi Flash30005 » 16/01/13 00:41

Non so nello specifico la tua esigenza ma per anni ho lavorato con dei database di access che interagivano con fogli di excel e poi dato il tutto "in pasto" a degli utenti anche io ho avuto l'esigenza di verificare se un determinato file di excel fosse aperto (per lo stesso tuo problema) mai e poi mai ho cercato una soluzione che chiudesse l'applicativo excel e ho sempre optato a chiudere il file che il database richiamava in maniera tale da evitare che un utente si trovasse excel chiuso magari con tutti i sui file che avesse modificato e non salvato prima di utilizzare il mio programma.
Quindi pensaci bene prima di optare per una soluzione che nel tempo potrebbe darti problemi non avendo previsto ciò che normalmente e in pratica succede.

ciao
Flash
Win7 + Office 2010 Ita
"Fotografica" al servizio dell'immagine

Ottime opportunità di lavoro (part-time o full-time) con guadagni immediati. Info in MP
Avatar utente
Flash30005
Moderatore
 
Post: 8460
Iscritto il: 27/09/07 11:44
Località: Roma +o-

Re: [vba access 2003]: capire se l'istanza di excel è aperta

Postdi Anthony47 » 16/01/13 00:58

Non usando Access ho collaudato il codice in una macro di Word, ottenendo il killaggio di excel.
Prova a modificare la riga in
Codice: Seleziona tutto
myPid = Shell("CMD /C TASKKILL /IM  excel.exe /F")
L' opzione /F causa un "forzaggio" del kill, utile in casi di applicazione effettivamente bloccata. Poi, se ancora non e' risolto, lavora passo-passo e verifica il contenuto di myPid dopo l' esecuzione della riga: dovrebbe restituirti un numero intero oppure un Errore, dicci quale e' il tuo caso.

Infine una constatazione: la documentazione in rete descrive una abbondanza di situazioni in cui un processo non si riesce a killare (fai una google search con la stringa "taskkill doesn't kill process", senza virgolette). Saranno quindi necessarie due cose:
1) il Do /Loop che segue l' On Erro Goto 0 deve includer anche una uscita per timeout; questo era fatto dalla riga DoEvents: If Timer > (myT2 + 5) Or Timer < myT2 Then Exit Do 'che hai omesso nel tuo codice e che quindi ti raccomando di ripristinare.
2) se la presenza di un processo impiccato (che non si riesce a killare nemmeno con l' opzione Forza) e' bloccante per la tua macro allora e' bene inserire in coda al codice che dovrebbe aver killato quel processo un controllo che effettivamente il processo non sia piu' presente, e se invece lo e' abortire la macro con suggerimento all' utente di chiudere i file eventualmente aperti prima di riprovare.

TUTTAVIA....
Sposo le considerazioni di Flash (vedi sopra).
Rileggendo la tua discussione, il problema non e' l' avere excel aperto, quanto eventualmente che sia gia' aperto il file che la tua macro deve "lavorare".
Pertanto il mio suggerimento e' di testare se un Excel e' gia' aperto; se No lo crei e procedi. Se invece Si allora controlli se il tuo fatidico file e' aperto in quella sessione excel; se Si lo chiudi, e poi scegli se creare una nuova istanza di Excel (a), oppure agganciarti all' istanza corrente (b).

Tutto questo (ipotesi b) potrebbe corrispondere a un codice come questo:
Codice: Seleziona tutto
Dim myEx As Object
On Error Resume Next
'tentativo di agganciare applicazione excel
Set myEx = GetObject(, "excel.application")
On Error GoTo 0
'il file da non avere aperto
myCriticalFile = "QUESTO_FILE.xls"   '<<< Il nome corretto del file
'Verifica se Excel aperto & file critico presente
If Not myEx Is Nothing Then
    myEx.Visible = True
    'cerco il file:
    For I = 1 To myEx.Workbooks.Count
        If myEx.Workbooks(I).Name = myCriticalFile Then
            myEx.Workbooks(I).Close savechanges:=False
            Exit For
        End If
    Next I
Else
'non c'e', creo l' applicazione
    Set myEx = CreateObject("Excel.Application")
    myEx.Visible = True
End If
'
'procedi con la tua macro

Ciao
Anthony
Win7 + Office 2010 Ita; Win 7 + Office 2013 Ita
Xp + Office 2003 Ita
E voi cosa usate? (per istruzioni vedere viewtopic.php?f=26&t=97449)
Avatar utente
Anthony47
Moderatore
 
Post: 13899
Iscritto il: 21/03/06 16:03
Località: Ivrea

Re: [vba access 2003]: capire se l'istanza di excel è aperta

Postdi karug64 » 17/01/13 21:25

Grazie per le risposte. Non vi ho dimenticati !!!
Ma in questi giorni impegni di lavoro non mi hanno permessso di intervenire sul programma.
Non appena posso applico i suggerimenti e vi faccio sapere.

Grazie.
Office 2010
karug64
Utente Senior
 
Post: 580
Iscritto il: 20/11/11 21:22

Re: [vba access 2003]: capire se l'istanza di excel è aperta

Postdi karug64 » 21/01/13 23:35

Anthony47 ha scritto:
Codice: Seleziona tutto
myPid = Shell("CMD /C TASKKILL /IM  excel.exe /F")


TUTTAVIA....
Sposo le considerazioni di Flash (vedi sopra).



Allora. rieccomi qua.
La soluzione della "forzatura" della chiusura di excel, per quanto brutale, e' quella che ha funzionato e, quindi, e' stata quella adottata.
Ho provveduto, in ogni caso, a richiedere all'utente se si vuole la chiusura di excel ....

Grazie.
Office 2010
karug64
Utente Senior
 
Post: 580
Iscritto il: 20/11/11 21:22


Torna a Applicazioni Office Windows


Topic correlati a "[vba access 2003]: capire se l'istanza di excel è aperta":


Chi c’è in linea

Visitano il forum: Nessuno e 8 ospiti

cron