chiudere excel da word



  • chiudere excel da word
    di sgmmar data: 15/10/2013 20:58:41

    Buona sera a tutti,
    ho trovato in rete un codice e l'ho adattato alle mie esigenze, ma non riesco a chiudere il processo di excel:
    in pratica in un form di word è presente una combobox alimentata dalla colonna A del file di excel,
    ed il codice che riporto funziona ed alimenta la combobox, ma non chiude excel nè tanto meno il relativo processo che rimane nel task manager di Windows.

    L'unico modo per chiuderlo è utilizzare l'istruzione END nell'evento QUERYCLOSE del form di Word.
    C'è unaltro modo per chiuderlo??? Oppure come devo modificare il codice?
    Grazie in anticipo a tutti
     
    Private Sub UserForm_Initialize()
    Application.ScreenUpdating = False
    'Dichiaro le variabili 
    Dim xlApp As Excel.Application
    Dim xlBook As Excel.Workbook
    Dim xlSheet As Excel.Worksheet
    Dim ValoreCella As String
    Dim i As Integer
    
    'Creo la nuova applicazione
    Set xlApp = New Excel.Application
     
    'apro il file di excel
    Set xlbook = xlApp.Workbooks.Open("percorso
    ome_file.xlsm")
    'Decido quale foglio utilizzare
    Set xlSheet = xlbook.Worksheets("Foglio1")
    ur = xlSheet.Range("a" & Rows.Count).End(xlUp).Row
    
    ciclo la colonna A
    For i = 1 To ur
        ValoreCella = xlSheet.Cells(i, 1).Value
        inserimenti.ComboBox2.AddItem ValoreCella
        inserimenti.ComboBox2.SpecialEffect = fmSpecialEffectFlat
    Next i
    'Chiudo il file di excel
    xlBook.Close savechanges:=True
    'chiudo excel
    xlApp.Quit
    'Annullo le variabili 
    'Set xlSheet = Nothing
    'Set xlBook = Nothing
    'Set xlApp = Nothing
    Application.ScreenUpdating = True
    End Sub



  • di Vecchio Frac data: 16/10/2013 10:24:28

    A me sembra che dovrebbe funzionare, così a occhio e croce.
    Decommenta le righe dove annienti gli oggetti.
    Excel non dovrebbe rimanere appeso (poi, sai, sono talmente tanti i misteri legati ai processi windows in esecuzione che ormai non mi stupisco più di niente).

    Per il codice invece, puoi togliere dal ciclo for l'istruzione che riguarda Specialeffect, perchè basta impostarla una volta sola (fuori dal ciclo), altrimenti ad ogni passaggio del for la reimposti inutilmente.
    Inoltre è da valutare se non sia possibile alimentare la combobox impostandone la proprietà RowSource invece che aggiungendo un elemento alla volta, risparmiando così un sacco di tempo nell'esecuzione.





  • di sgmmar data: 16/10/2013 10:41:14

    Ciao VecchioFrac,
    grazie per la risposta, dal codice facendo delle prove, ho dimenticato di decommentare le righe con le quali
    annullo le variabili....
    Grazie per la segnalazione riguardo allo SpecialEffect

    Purtroppo il processo di Excel rimane in esecuzione, ed in effetti ieri sera dopo avere inserito la mia richiesta, ho pensato come tu hai suggerito, di alimentare la combobox tramite una tabella da inserire direttamente nel file di Word, ma indovina un pò......
    In Excel so come fare: definisco un nome per il range in questione e fare rowsource = "nome_definito" è facile........ ma con Word come gli dico che gli item della combobox sono uguali alle celle della tabella (tables(1))????
    In ogni caso grazie per la disponibilità, vediamo se qualcuno ha già affrontato il problema.




  • di Vecchio Frac data: 16/10/2013 10:52:34

    Sto provando, non ho nessun problema.
    Nessuna istanza di Excel rimane appesa.
    Mi resta capire perchè non riesco ad alimentare la combo direttamente con RowSource :(
     
    Option Explicit
    
    Private Sub UserForm_Initialize()
        Application.ScreenUpdating = False
        'Dichiaro le variabili
        Dim xlApp As Excel.Application
        Dim xlBook As Excel.Workbook
        Dim xlSheet As Excel.Worksheet
        Dim ValoreCella As String
        Dim i As Integer
        Dim ur As Long
        
        On Error GoTo gest_err
        
        'Creo la nuova applicazione
        Set xlApp = New Excel.Application
         
        'apro il file di excel
        Set xlBook = xlApp.Workbooks.Open("g:pippo.xls")
        'Decido quale foglio utilizzare
        Set xlSheet = xlBook.Worksheets("Foglio1")
        ur = xlSheet.Range("a" & xlSheet.Rows.Count).End(xlUp).Row
        
        For i = 1 To ur
            inserimenti.ComboBox2.AddItem xlSheet.Cells(i, 1).Value
        Next i
    
        'stranamente questo non riesco a farlo funzionare! sarebbe utile per eliminar eil for precedente :(
        'inserimenti.ComboBox2.RowSource = "A1:A" & ur
    
        inserimenti.ComboBox2.SpecialEffect = fmSpecialEffectFlat
        
    gest_err:
        If Err <> 0 Then
            MsgBox "Errors occurred:" & vbCrLf & Err.Description
        End If
        
        'Chiudo il file di excel
        xlBook.Close savechanges:=True
        'chiudo excel
        xlApp.Quit
        'Annullo le variabili
        Set xlSheet = Nothing
        Set xlBook = Nothing
        Set xlApp = Nothing
        Application.ScreenUpdating = True
    
    End Sub






  • di Vecchio Frac data: 16/10/2013 12:03:47


    Ho risolto il problema... bastava usare List e non RowSource.
    Così evito il ciclo For e velocizzo tutto.
    In ogni modo non ho più errori di Excel appesi e questa è la cosa importante.
     
    Option Explicit
    
    Private Sub UserForm_Initialize()
        Application.ScreenUpdating = False
        'Dichiaro le variabili
        Dim xlApp As Excel.Application
        Dim xlBook As Excel.Workbook
        Dim xlSheet As Excel.Worksheet
        Dim ValoreCella As String
        Dim i As Integer
        
        Dim ur As Long
        
        On Error GoTo gest_err
        
        'Creo la nuova applicazione
        Set xlApp = New Excel.Application
         
        'apro il file di excel
        Set xlBook = xlApp.Workbooks.Open("g:pippo.xls")
        'Decido quale foglio utilizzare
        Set xlSheet = xlBook.Worksheets("Foglio1")
        ur = xlSheet.Range("a" & xlSheet.Rows.Count).End(xlUp).Row
        
        inserimenti.ComboBox2.List = xlSheet.Range("A1:A" & ur).Value   '<<<<<<<<
        inserimenti.ComboBox2.SpecialEffect = fmSpecialEffectFlat
        
    gest_err:
        If Err <> 0 Then
            MsgBox "Errors occurred:" & vbCrLf & Err.Description
        End If
        
        'Chiudo il file di excel
        xlBook.Close savechanges:=True
        'chiudo excel
        xlApp.Quit
        'Annullo le variabili
        Set xlSheet = Nothing
        Set xlBook = Nothing
        Set xlApp = Nothing
        Application.ScreenUpdating = True
    
    End Sub
    






  • di sgmmar data: 16/10/2013 13:22:41

    VecchioFrac, sei un mitooo
    con questa è la seconda volta che mi fai passare il mal di testa
    In questo momento sono in ufficio e come dici, excel si chiude e non rimane in esecuzione.
    Appena posso lo provo a casa ma sono certo che sarà la stessa cosa.
    Io stavo cercando come fargli leggere una tabella creata direttamente nel file di Word, ma a sto punto
    adotto la tua soluzione.
    Grazie ancora



  • di sgmmar data: 16/10/2013 13:24:56

    ho dimenticato il "RISOLTO" grazie a VecchioFrac



  • di Vecchio Frac data: 16/10/2013 14:17:51

    cit. "Io stavo cercando come fargli leggere una tabella creata direttamente nel file di Word"
    ---> Che forse è la soluzione migliore. Sei dentro Word, fai tutto da Word.
    Scorri ogni riga della tabella con For Each r in Activedocument.Tables(n).Rows, recuperi con Cells i singoli dati di ogni campo (colonna) e sei a posto.
    Poi per carità, ogni situazione è peculiare, ma basta definire bene la struttura della tabella (righe e soprattutto colonne fisse) e sei a posto.





  • di sgmmar data: 16/10/2013 14:48:01

    Ciao VecchioFrac,
    grazie per il suggerimento relativo al For Each:

    For Each r in Activedocument.Tables(n) (fino a qui c'ero arrivato)
    ma non era completo
    For Each r in Activedocument.Tables(n).Row

    In questo periodo ho poco tempo, ma appena riesco voglio provare a fare tutto da word,
    anche se grazie a te, già com'è adesso funziona.

    Ti faccio sapere più avanti.
    Grazie



  • di sgmmar data: 30/10/2013 18:54:45

    Ciao a tutti
    ho provato a popolare la combobox da una tabella di Word, ma con il consiglio di Vecchio Frac (grazie ancora) non ci sono riuscito
    Allego un file nel quale ho inserito un For Next , ma ho un "problema" che non riesco a risolvere:
    popola la combobox ma aggiunge il simbolo paragrafo alla fine di ogni item.

    Sono riuscito a "toglierlo" dalla textbox del documento attivo che viene aggiornata dal Change della ComboBox del Form,
    ma NON RIESCO a toglierlo dagli item della Combobox del Form.
    Qualcuno ha qualche idea?

    Grazie a tutti in anticipo



  • di sgmmar data: 02/11/2013 09:45:30

    ciao
    ho trovato in rete un altro pezzo di codice:
    l'ho adattato come sotto riportato e adesso è come volevo

    Ciao
     
    Private Sub ComboBox1_Change()
    
    ThisDocument.TextBox1.Text = UserForm1.ComboBox1
    End Sub
    
    Private Sub UserForm_Initialize()
    Dim r As Variant
    
    For r = 1 To ActiveDocument.Tables(1).Rows.Count
        Set myrange = ActiveDocument.Tables(1).Cell(r, 1).Range
        myrange.MoveEnd Unit:=wdCharacter, Count:=-1
        UserForm1.ComboBox1.AddItem myrange.Text
    Next r
    
    End Sub



  • di Vecchio Frac data: 04/11/2013 10:36:42

    Purtroppo a causa di tristi problemi al pc non ho potuto intervenire prima.
    Invece di selezionare il range e spostarti indietro di un carattere, puoi recuperare il testo della cella e sostituire i ritorni a capo con un Replace.
    In questo modo eviti la fastidiosa situazione che se batti due volte Invio a fine riga te ne toglie uno solo e ti resta l'altro o, peggio, se batti Invio in cella e continui a digitare ti ritrovi non solo con il ritorno a capo ma anche con un carattere di testo in meno :)

    p.s. "r" non è Variant ma Long perchè cicli da 1 fino al conto totale delle righe in tabella.
     
    Private Sub ComboBox1_Change()
    
    ThisDocument.TextBox1.Text = UserForm1.ComboBox1
    End Sub
    
    Private Sub UserForm_Initialize()
    Dim r As Long, s as string 
    
    For r = 1 To ActiveDocument.Tables(1).Rows.Count
        s = ActiveDocument.Tables(1).Cell(r, 1).Range.Text
        UserForm1.ComboBox1.AddItem Replace(s, vbCrLf, "")
    Next r
    
    End Sub






  • di sgmmar data: 04/11/2013 20:57:58

    ciao a tutti,
    prima di tutto un nuovo grazie a Vecchio Frac

    aggiornamento:
    considerando che nel file che devo utilizzare la tabella che popola la combobox è formata da più di 1500 righe in costante aumento, e che la sub ad inizio post (quella che utilizza un file excel esterno al file di word, per intenderci)
    alimenta la combox molto velocente, mentre il for next dal file di word con tabella in word, data la mole di dati da aggiunngere ad ogni item della combo, è molto lenta.......,

    ho cercato ancora in internet ed ho trovato quella sotto riportata che ho dovuto adattare leggermente.
    Nella logica sequenziale mi sembra scritta molto bene e semplicemente (riesco a leggere ma non a scrivere, ) ma a sua volta è molto più lenta rispetto a quella usando il file esterno di excel.

    Che ve ne pare? Si può migliorare in termini di velocità di esecuzione?
    Come sempre, grazie in anticipo a tutti.

     
    Private Sub UserForm_Initialize()
    Dim oTable As Table
    Dim i As Long, j As Long, m As Long, n As Long
    Dim myArray() As Variant
    Dim oData As Range
    Dim oCell As Range
    Dim oRow As Row
    
    
    Application.ScreenUpdating = False
    
        Set oTable = ThisDocument.Tables(1)
        i = oTable.Rows.Count
        j = oTable.Columns.Count
        ReDim myArray(i - 1, j - 1)
        For n = 0 To j - 1
            For m = 1 To i - 1
                Set oData = oTable.Cell(m + 1, n + 1).Range
                oData.End = oData.End - 1
                If oData.Text <> "" Then
                    myArray(m, n) = oData.Text
                Else
                    myArray(m, n) = " "
                End If
            Next m
        Next n
        With UserForm1
            With .ComboBox1
                 .List = myArray
            End With
        End With
    Application.ScreenUpdating = True
    
    End Sub



  • di Vecchio Frac data: 05/11/2013 08:37:34

    Ci credo davvero che sia lenta, due cicli for annidati eseguiti r * c volte, con un If / Then / Else dentro a peggiorare le cose ^_^
    Però hai cambiato le carte in tavola: adesso vuoi popolare la combobox con più di una colonna. E questo naturalmente rallenterebbe un po' anche il codice eseguito in Excel.

    cit. "Si può migliorare in termini di velocità di esecuzione? "
    ---> A questo punto direi che dipende dalla capacità del sistema. Forse si può ottimizzare giocando con l'unione delle celle in una riga ma poi bisogna comunque spalmarla in una combobox multicolonna.

    p.s. siamo andati più lontano rispetto al quesito iniziale.





  • di sgmmar data: 05/11/2013 12:45:38

    ciao VecchioFrac,
    non l'ho specificato ma la colonna è una sola.

    Ho postato la macro come l'ho trovata nella sequenza di comandi modificando solo i riferimenti che non
    rientravano in quello che mi interessava.
    Come hai detto, il for sulle colonne non serve, e neanche l'if.
    Ci voglio lavorare un pò sopra eliminando il superfluo e se riesco a fare una cosa del genere

    primariga = thisdocument.tables(1).cell(1,1).range
    ultimariga = thisdocument.tables(1).rows.count

    e quello che non riesco a fare:
    userform.combobox1.list = da primariga a ultimariga

    Non so come fare, ma sono sicuro che un modo c'è!

    Grazie a tutti



  • di Vecchio Frac data: 05/11/2013 13:45:32

    Una colonna sola, bè allora si può ottimizzare :)
    Ti do un altro spunto su cui ragionare.

    v = activedocument.Tables(1).Range
    x = replace(replace(v, chr(13)+chr(7), ";"), ";;", "-")
    x = left(x, len(x)-1)
    UserForm1.ComboBox1.List = x


    La prima riga legge la tabella 1 del documento. Poichè è composta da una sola colonna, è sufficiente "Range" che si identifica con l'intera tabella (naturalmente comprende anche l'eventuale riga di intestazione: problema su cui si può fare un distinguo). Il risultato, rozzamente, è assegnato alla variabile Variant "v". Ogni dato conterrà in sè necessariamente ritorni a capo e caratteri di fine cella (ASCII 13 e 7). Che quindi bisogna ripulire.
    La seconda riga assegna pertanto a un'altra variabile intermedia di tipo Variant, "x", il risultato di una trasformazione in due passaggi del contenuto di "v", che prima viene depurata dei caratteri di return e fine cella e poi viene ricostruita con un trattino in mezzo (viene scartato il trattino finale nella terza riga di codice). Questo è propedeutico al passaggio finale.
    La quarta riga *dovrebbe* assegnare alla combobox l'array risultante. Dico "dovrebbe" perchè non l'ho testato, ma siccome il codice è molto simile ad altro che ho già provato, sono fiducioso che il concetto espresso sia giusto :)

     






  • di sgmmar data: 06/11/2013 08:36:42

    Ciao VecchioFrac,
    grazie di nuovo per il nuovo spunto...
    come già detto, "leggendolo" lo capisco..... applicandolo meno
    ieri l'ho "provato" di corsa in ufficio ma mi dava errore 381 e purtroppo oggi non ho tempo.
    Ti faccio sapere appena posso.
    Grazie



  • di Vecchio Frac data: 06/11/2013 13:37:51

    cit. "mi dava errore 381"
    ---> Fammi sapere con maggiori dettagli.





  • di sgmmar data: 07/11/2013 20:12:45

    Ciao Vecchio Frac,
    dunque, vediamo se ho capito quello che doveva passare....
    lo UserForm1.ComboBox1.List = x
    dovrebbe avere la stessa funzione del
    inserimenti.ComboBox2.List = xlSheet.Range("A1:A" & ur).Value
    del file che utilizza il file excel esterno.

    Se è così, la Sub che inizializza lo UserForm non dovrebbe contemplare un For Next.

    Ma se ho capito bene il tuo ultimo spunto, "basterebbe" copiarlo nella Sub sopra citata.
    Il fatto che così facendo mi dia l'errore:

    errore di run-time '381'
    Impossibile impostare la proprietà List. Indice della matrice di proprietà non valido.

    mi fa pensare che purtroppo non capito niente o che mi manchi ancora parecchio da sapere.
    A presto e grazie per la disponibilità.



  • di sgmmar data: 08/11/2013 08:20:19

    Ciao Vecchio Frac,
    come puoi vedere , appena posso mi dò da fare..... ma non riesco a risolvere

    Il codice che riporto mi sembra una buona base, non dà errori, ma popola la combobox solo con
    la prima riga della colonna e con il simbolo paragrafo.

    il simbolo sappiamo come toglierlo, ma se inseriamo un For Next siamo di nuovo a capo.
    Allego file
    Hai altri "suggerimenti"?
    Grazie
     
    Private Sub UserForm_Initialize()
    
    Dim myCells As String, ocells As Range
    ur = ActiveDocument.Tables(1).Rows.Count
    
        With ThisDocument
            Set ocells = .Range(Start:=.Tables(1).Cell(1, 1).Range.Start, _
                End:=.Tables(1).Cell(ur, 1).Range.End)
               
            
            myCells = ocells.Text
            x = Array(myCells)
            UserForm1.ComboBox1.List = x
            
            
        End With
    End Sub
    



  • di Vecchio Frac data: 08/11/2013 08:52:50

    Se così veloce che non ti sto dietro ^_^
    Appena posso mi guardo con calma le tue osservazioni.





  • di Vecchio Frac data: 08/11/2013 14:50:33

    Mi arrendo all'evidenza che List agisce su array bidimensionali.
    Fare a meno di un For non si può o meglio io non ci riesco :)
     
    Private Sub UserForm_Initialize()
    Dim ocells As Variant, itm As Variant
    
        With ActiveDocument
            
            Set ocells = .Tables(1).Range
          
            For Each itm In Split(ocells, Chr(13) + Chr(7))
                If itm <> "" Then ComboBox1.AddItem itm
            Next
        
        End With
        
    End Sub






  • di Vecchio Frac data: 08/11/2013 15:06:42

    Però questa versione che allego funziona anche con List.
    E non fa uso di For.
    Mah :)
     
    Private Sub UserForm_Initialize()
    Dim ocells As Variant, x As Variant
    
        With ActiveDocument
            
            Set ocells = .Tables(1).Range
            x = Replace(Replace(ocells, Chr(13) + Chr(7), ";"), ";;", "-")
            x = Left(x, Len(x) - 1)
            ComboBox1.List = Split(x, "-")
        
        End With
        
    End Sub






  • di sgmmar data: 08/11/2013 19:49:10

    Ciao Vecchio Frac,
    non ne avevo dubbi e direi che HAI RISOLTO
    In un file di prova ho aggiunto la tabella con circa 1500 righe ed ENTRAMBE le tue proposte funzionano
    benissimo.
    Se tra le due, c'è differenza di velocità di esecuzione è praticamente impercettibile, anche se mi sembra più logico optare per quella senza For.

    Posso proseguire nel progetto, anche se il grosso è già fatto utilizzando il file esterno di excel, credo debba fare degli aggiustamenti per l'ordinamento della tabella in ordine alfabetico in caso di aggiunta di righe, ed altri piccoli dettagli, ma spero di cavarmela senza disturbarti.

    Grazie per l'aiuto, la disponibilità ed per l'avermi risolto un altro problema.




  • di Vecchio Frac data: 09/11/2013 21:20:34

    Ma non devi pensare di disturbare qualcuno :)
    Comunque sono certissimo che una differenza di performances c'è.
    Sarebbe da esaminare anche molto semplicemente con dei debug.timer all'inizio e alla fine dell'import.





  • di sgmmar data: 11/11/2013 21:06:59

    Ciao Vecchi Frac,
    ogni volta che mi dai un suggerimento, mi stimoli la curiosità e nello stesso tempo lo sbattimento:
    Debug.timer??? e che accidenti è?!?!??!?
    conosco a mala pena il debug (menù dell'editor), il debug.print di cui conosco l'esistenza ma no conosco assolutamnente come utilizzare, ed allora via con Google per il debug.timer (si sà, la curiosità è femmina e picendomi le femmine, è stato un attimo!)
    Non ho trovato niente di specifico, ma cambiando la ricerca ho trovato il codice di seguito, l'ho inserito nell'evento Initialize del Form, ed ha evidenziato un vantaggio di cira 117 millesimi a favore di quello senza For.
    Tanto per aggiornare il Thread
    Alla prossima
     
    Dim sngStartTime As Single
    Dim sngTotalTime As Single
    sngStartTime = Timer
    
    'istruzioni
    
    sngTotalTime = Timer - sngStartTime
    MsgBox "Tempo impiegato:  " & Round(sngTotalTime, 4) & " secondi"



  • di Vecchio Frac data: 11/11/2013 21:18:16

    cit. "Non ho trovato niente di specifico"
    ---> Allora, per non farti sentire un cretino ti dirò che debug.timer non esiste ^_^ ho semplicemente contratto per pigrizia la frase "inserendo un debug.print timer all'inizio e alla fine dell'import".
    Giustamente ci sei arrivato da solo, era un piccolo test di velocità che tu hai risolto in favore dell'import con List invece che con For ^_^






  • di sgmmar data: 11/11/2013 23:16:58

    Ciao Vecchio Frac,
    Cit. "per non farti sentire un cretino"
    ---------> azzzzzz... c'eri quasi riuscito. LOL Posso dormire più sereno ah ah ah