Chiusura di processo Excel

di il
19 risposte

Chiusura di processo Excel

Buongiorno a tutti,
Sto sviluppando una applicazione WindosForm tramite VisulaSudio 2022 (VB).
Il programma deve aprire in background un file di excel, scrivere dei dati all'interno di alcune celle, salvare il file di excel così aggiornato e chiudere tutto. Sono riuscito ad aprire, scrive e salvare il file di excel, ma non riesco a rilasciare il processo che, dopo la chiusura del file excel, continua a rimanermi appeso (verificato da gestione attività).
Riesco solo a chiudere tutti i processi di excel eventualmente attivi sulla macchina, ma io vorrei chiudere solo quello che ho fatto aprire dal mio programma.
Un aiuto? Posto il codice che ho scritto. Grazie in anticipo.

Public Sub LogCrcCRTT(mtr1() As Single, mtr2() As Single, mtr3() As Single, mtr4() As Single, mtr5() As String, mtr6() As String, mtr7() As String, ByVal qlDIR As String, ByVal opnXLS As Boolean, ByVal clsXLS As Boolean)
        ' mtr1 ==> Carico
        ' mtr2 ==> brLNG
        ' mtr3 ==> brTRS
        ' mtr4 ==> brVER
        ' mtr5 ==> Descrizione
        ' mtr6 ==> Cetegoria
        ' mtr7 ==> Tipo

        Dim oXL As Excel.Application
        Dim oWB As Excel.Workbook
        Dim oSheet As Excel.Worksheet

        Dim cXLS As Integer
        Dim rXLS As Integer
        
        ' Apertura file excel e posizionamento nella sheet desiderata
        oXL = CType(CreateObject("Excel.Application"), Excel.Application)
        oWB = oXL.Workbooks.Open(My.Application.Info.DirectoryPath & "\ModelloCARICHI1.xlsx")
        oSheet = CType(oWB.Sheets("ValoriCARATTERISTICI"), Excel.Worksheet)
        
        For i = 0 To UBound(mtr1)
           ' Impostazione delle coordinate della cella di riferimento
            If mtr7(i) = "PERM" Or mtr7(i) = "PERM_NS" Then
                cXLS = 2
                rXLS = oSheet.Range("B" & oSheet.Rows.Count).End(Excel.XlDirection.xlUp).Row + 1
            ElseIf mtr7(i) = "VAR" Then
                cXLS = 10
                rXLS = oSheet.Range("J" & oSheet.Rows.Count).End(Excel.XlDirection.xlUp).Row + 1
            Else
                cXLS = 18
                rXLS = oSheet.Range("R" & oSheet.Rows.Count).End(Excel.XlDirection.xlUp).Row + 1
            End If
            
            ' Scrittura nelle celle a partire da quella di riferimento
            oSheet.Cells(rXLS, cXLS) = mtr1(i)
            oSheet.Cells(rXLS, cXLS + 1) = mtr2(i)
            oSheet.Cells(rXLS, cXLS + 2) = mtr3(i)
            oSheet.Cells(rXLS, cXLS + 3) = mtr4(i)
            oSheet.Cells(rXLS, cXLS + 4) = mtr5(i)
            oSheet.Cells(rXLS, cXLS + 5) = mtr6(i)
            oSheet.Cells(rXLS, cXLS + 6) = qlDIR
        Next

	' salvo e chiudo il file excel
        oWB.Save()
        oWB.Close()
        oXL.Quit()

       ' chiudo tutti i processi excel aperti.
       ' funziona ma non è quello che voglio.
       ' vorrei chiudere solo il processo excel associato a oXL
        Dim myProcesses() As Process
        Dim myProcess As Process

        ' Restituisce un'array con tutti i processi
        myProcesses = Process.GetProcessesByName("excel")
        'chiude ogni processo
        For Each myProcess In myProcesses
                myProcess.CloseMainWindow()
            End If
        Next
        
        ' rilascio le variabili associate ad excel
        oSheet = Nothing
        oWB = Nothing
        oXL = Nothing

    End Sub
    

19 Risposte

  • Re: Chiusura di processo Excel

    Quando esegui oXL.Quit() non si chiude un istanza di Excel ?
  • Re: Chiusura di processo Excel

    Ciao surfernet
    No. Da "Gestione Attività" l'applicazione Excel non compare più, indice che il programma è stato chiuso, ma rimane appeso un processo excel in background.
  • Re: Chiusura di processo Excel

    Mi stavo chiedendo se non sia possibile identificare in qualche modo il processo associato a oXL e quindi fare kill solo di quel mirato processo.
    Parlo perchè ho la lingua in bocca, sono un "programmatore" della domenica!
  • Re: Chiusura di processo Excel

    Prova a fare
    oSheet.Dispose()
    oWB.Dispose()
    oXL.Dispose()
    al posto di
    oSheet = Nothing
    oWB = Nothing
    oXL = Nothing
  • Re: Chiusura di processo Excel

    Ciao SirJo,
    ho provato ma Dispose non sembra essere piacergli e me lo segnala come errore. Non credo faccia parte dei metodi associati a questi tipo di oggetto.
    Non so se si possono allegare immagini così da farvo vedere uno screenshot.
  • Re: Chiusura di processo Excel

    1 "dopo la chiusura del file excel, continua a rimanermi appeso (verificato da gestione attività)."
    2 Da "Gestione Attività" l'applicazione Excel non compare più, indice che il programma è stato chiuso
    3 ma rimane appeso un processo excel in background.

    mi sembra che il punto 2 sia quello che cercavi inizialmente

    al punto 3 intendi che c'è ancora un eseguibile excel in esecuzione , con la sua finestra?
  • Re: Chiusura di processo Excel

    Puoi vedere qual'è il processo di oXL passando il valore di oXL di tipo Excel.Application al metodo GetExcelProcess
    using Excel = Microsoft.Office.Interop.Excel;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    
    class Sample
    {
        [DllImport("user32.dll")]
        static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);
    
        Process GetExcelProcess(Excel.Application excelApp)
        {
            int id;
            GetWindowThreadProcessId(excelApp.Hwnd, out id);
            return Process.GetProcessById(id);
        }
    }
    una volta che hai il process puoi ottenere l'id che è univoco , il codice non l'ho provato ma dovrebbe essere corretto ,
    P.S. in realtà l'id ce l'hai già dentro il metodo...
  • Re: Chiusura di processo Excel

    Ciao gian82
    in realtà il programma apre il file di excel, lo modifica, lo salva e lo chiude tutto in backgroud. L'utente di tutto questo non vede nulla. Se poi vuole può andare ad aprirsi il file di excel manualmente. Quindi in realtà, erroneamente a quanto scritto da me, l'applicazione non si apre mai e infatti da "Gestione attività" non risulta anche facendo interrompere il codice in debug quando ancora il programma non ha finito di modificare l'excel.
    Il problema è che quando ha finito mi ritrovo un processo aperto su excel in backgroud che prima non c'rea, ma nessuna finestra di excel aperta, che, peraltro, non è mai stata aperta.
  • Re: Chiusura di processo Excel

    gian82 ha scritto:


    Puoi vedere qual'è il processo di oXL passando il valore di oXL di tipo Excel.Application al metodo GetExcelProcess
    using Excel = Microsoft.Office.Interop.Excel;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    
    class Sample
    {
        [DllImport("user32.dll")]
        static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);
    
        Process GetExcelProcess(Excel.Application excelApp)
        {
            int id;
            GetWindowThreadProcessId(excelApp.Hwnd, out id);
            return Process.GetProcessById(id);
        }
    }
    una volta che hai il process puoi ottenere l'id che è univoco , il codice non l'ho provato ma dovrebbe essere corretto ,
    Ecco si, era una cosa del genere che pensavo ma non saprei proprio come fare.
    Provo il tuo codice e vi faccio sapere.
  • Re: Chiusura di processo Excel

    Non penso sia una buona cosa killare il processo;
    dovrebbe chiudersi da solo.
    Personalmente proverei a fare il dispose (ove possibile) e chiudere
    *tutti* gli oggetti in ordine inverso a come sono stati istanziati

    HTH
  • Re: Chiusura di processo Excel

    Ciao sspintux,
    concordo con te. Sicuramente non posso chiudere tutti i processi excel perchè l'utente potrebbe avere file aperti che non vuole vedersi chiudere così, oltre al fatto che forzarne la chiusura si rischia di lasciare comunque porcherie in memoria.
    Ecco perchè vorrei agire solo sul processo interessato come suggerito da gian82: rimane il fatto che si tratta sempre comunque di una forzatura e che non ho ancora capito come utilizzare quel codice. Devo inserirlo in un modulo di classe?
    Come funziona il dispose? Anche SirJo lo ha proposto, ma è un metodo non contemplato dal tipo Excel.Application.
    Provo ad approfondire.
  • Re: Chiusura di processo Excel

    Vai su questo sito https://converter.telerik.com e converti il codice che ti inviato in vb.net , penso che così ti risulti più facile,in pratica aggiungi una classe al tuo progetto per individuare quale processo hai creato,
    per la verità sono piuttosto d'accordo con sspintux ,
  • Re: Chiusura di processo Excel

    Il Santo ha scritto:


    ...
    Provo ad approfondire.
    Potrebbe essere il mancato rilascio del Range ( rXLS) che tiene aperto excel.
    Aggiungilo in testa al codice di @SirJo
  • Re: Chiusura di processo Excel

    Prova ad usare Close invece di Dispose

    vedi qui:
    https://stackoverflow.com/questions/17777545/closing-excel-application-process-in-c-sharp-after-data-access
Devi accedere o registrarti per scrivere nel forum
19 risposte