giovedì 16 ottobre 2014

VBA-Office: Aprire un file di Excel da VBA disabilitando le Macro

Capita a volte di dover aprire un file Excel da codice e che questo abbia al suo interno delle macro che possono interferire con il corretto funzionamento del nostro programma. I suggerimenti che ho trovato on-line su questo argomento non sono realmente efficaci in quanto tendono a disabilitare gli eventi dell'applicazione Excel e questo può interferire con il nostro stesso programma VBA. Per esempio se il mio codice VBA sta girando su una applicazione Excel e deve aprire un'altro file Excel e mettiamo in atto la disabilitazione degli eventi, questo impatterà anche sul file contenente il mio codice. Oppure: se debbo aprire due files di cui uno con le macro abilitate e l'altro no la soluzione di disabilitare gli eventi non è valida.
Per fortuna Microsoft ci da una soluzione che salva capra e cavoli. E' sufficiente alzare il livello di protezione macro di Excel a "Disattiva tutte le macro senza notifica" prima di aprire il file in questione e poi ripristinare il livello di protezione a quello che era impostato in precedenza. La proprietà da impostare è l'AutomationSecurity che restituisce dei valori elencati nel tipo MsoAutomationSecurity

Ecco un esempio:

    Dim Exc As Excel.Application
    Dim Wb As Excel.Workbook
    Dim secAutomation As MsoAutomationSecurity
    
    'Istanzio l'applicazione Excel e rilevo il livello di sicurezza corrente
    Set Exc = New Excel.Application
    secAutomation = Exc.AutomationSecurity
    'Imposto il livello di sicurezza a "Disattiva tutte le macro senza notifica"
    Exc.AutomationSecurity = msoAutomationSecurityForceDisable
    'Apro il file Excel con le macro disabilitate
    Set Wb = Exc.Workbooks.Open(FileName:="NomeFile.xlsm")
    'Reimposto il livello di sicurezza precedente

    Exc.AutomationSecurity = secAutomation


Alla prossima! :)

venerdì 3 ottobre 2014

VBA-Excel: Come reperire l'ultima riga/colonna di un foglio che contiene dati

A chi programma in VBA per Excel capita di aver bisogno di sapere qual'è l'ultima riga e/o l'ultima colonna di un foglio contenente dati, magari per fare un ciclo di lettura delle celle.
Spesso si usano accrocchi vari per reperire questa informazione che simulano l'esecuzione manuale come per esempio la pressione dei tasti Fine e Freccia giù, oppure improbabili cicli che leggono le celle una dopo l'altra fino a trovarne una vuota. A parte i tempi lunghi di questo approccio resta il problema che alla prima cella vuota trovata ci si ferma dando per assunto che quella sia la fine dei dati, cosa che non è sempre vera.
Il metodo migliore è di gran lunga più semplice e veloce nonché più sicuro di quelli sopracitati.
VBA per Excel offre una proprietà dell'oggetto Worksheet che è molto utile in questo caso e cioè: UsedRange. Tale proprietà restituisce un oggetto di tipo Range che compre l'intera area di celle utilizzata nel Worksheet a cui è associato.
Pertanto per sapere quali sono l'ultima riga e l'ultima colonna usati è sufficiente fare:

Dim UltimaRiga as Long
Dim UltimaColonna as Long

UltimaRiga = Thisworkbook.Worksheets("MioFoglio").UsedRange.Rows.Count
UltimaColonna = Thisworkbook.Worksheets("MioFoglio").UsedRange.Columns.Count

Facile e veloce! :-D

lunedì 16 giugno 2014

VBA-Excel: Aggiornare le Tabelle Pivot (e relativi Grafici) da codice

A chi scrive codice VBA può capitare l'esigenza di aggiornare le Tabelle Pivot (i Grafici Pivot si appoggiano anch'essi su Tabelle Pivot) dopo aver modificato i dati contenuti nei vari fogli.
Per prima cosa è utile sapere che le Tabelle Pivot si appoggiano su cache di dati e sono quindi queste ultime a dover essere aggiornate. Un modo molto semplice di aggiornare tutte le Pivot del Workbook (file) corrente è un ciclo che passi tutte le cache e ne esegua il Refresh.
Vi riporto di seguito il codice di una semplice Sub che inserita nel codice dell'oggetto ThisWorkbook implementa un metodo richiamabile dal vostro codice per "refreshare" (brutto inglesismo) tutte le Pivot.

Public Sub RefreshPivotTables()

    Dim PT As PivotCache
    For Each PT In ThisWorkbook.PivotCaches
        PT.Refresh
    Next
                
End Sub

Quindi nel vostro codice per richiamare il nuovo metodo sarà sufficiente scrivere:

ThisWorkbook.RefreshPivotTables

Alla prossima :-)

VBA-Excel: La finestra del MsgBox appare nascosta "sotto" la finestra di Excel

Di recente mi è capitato molte volte che la finestra aperta con il comando MsgBox in VBA apparisse "sotto" la finestra di Excel, causando così una sorta di blocco perché l'utente non vedeva il messaggio e l'applicazione restava ferma in attesa di risposta. Unico indizio che c'era un messaggio in attesa era la finestra di Excel "sfarfallante". Per l'utente era sufficiente cliccare il titolo della finestra o premere Alt-Tab per vedere il messaggio e quindi poter rispondere e proseguire, ma certo non è bello.
Ho fatto un po' di ricerche e o trovato una soluzione semplice e che pare efficace. Prima della riga in cui viene eseguito il MsgBox inserite una riga con AppActivate Application.Caption

Esempio:
AppActivate Application.Caption
MsgBox "Mio messaggio"

Spero di essere stato utile :-)