Soluzioni varie.    (aggiornabile n. 55) - pagina vista: volte

indice dei paragrafi :

texbox per comporre una data

evidenziare celle su più cartelle

inserimento dati ricerca presenza

verifica dati doppioni

caption di Label per Linkweb

crearsi elenco siti visitati

traccia siti visitati c/data/ora

Label come messaggio

lavorare con fogli affiancati

cambiare colore griglia

selezione del MultiPage

copiare fogli di lavoro

TextBox-valore più alto

usare il "nome" di una cartella

minimizzare excel

no "struttura" con subtotali

dato correlato al valore maggiore

inserire immagine su foglio

copiare una cella come bitmap

add caratteri a numeri

usare il "Titolo"della Cartella

"proprietà" di una cartella

tratteggiare una cella

eliminare macro

salvataggio in corso...

una cella x inserire numeri

routine "contaparole"

funzione Array

funzione MEZZANOTTE()

funzione FINEANNO()

"elenchi" personalizzati

filtro inserito:controllare se..

estrarre numero civico

inibire una cella

Stampare .pdf (Acrobat)da Excel

menù contestuale:lancio macro

Usare un tasto x lanciare macro

Scorrere un Range Selezionato

 Selezionare una stampante  ColumnHeads di ListBox/Combo  Funzione SCRIVI()  Doppi Apici in una stringa  Riferimenti variabili - sintassi
 Conoscere Anni Bisestili  Che numero di Cella sei ?  Convertire JPG in BMP in vba  Evento "Calculate"  Passare al VBE da UserForm

Eliminare Righe o Colonne   nascoste

Proteggi/Sproteggi Foglio

 Numerazione pagine in stampa  Le protezioni Excel sono sicure??  Quando cade la Pasqua?

Aumentare Lunghezza stringa di una Cella

Convertire al volo Euro in Lire

  • 1) - Usare una Textbox per comporre in automatico una data senza necessità di scrivere le barre "/" separatrici (lo fa il codice, e destinazione della data in una cella del foglio di lavoro, o dove vorrete:

Private Sub TextBox1_Change()   'si sfrutta l'evento Change
X = Len(TextBox1)                
 'si misura la lunghezza del testo nella texbox ad ogni digitazione (Change)
y = LTrim(TextBox1.Text)     
'si legge il contenuto della textbox ad ogni digitazione
If X = 2 Then TextBox1 = y & "/"   
'e si concatena testo e una barra quando si è scritto 2 caratteri
If X = 5 Then TextBox1 = y & "/"   
 'poi si concatena testo e seconda barra quando il testo è 5 caratteri
If X = 8 Then                
'quando il testo sarà lungo 8 caratteri (op. mettere 10 se anno a quattro cifre)
[A1] = CDate(TextBox1)  
'si copia il testo come data (CDate) in una cella
TextBox1 = ""               
 'si pulisce la textbox
End If
End Sub

  • 2)  -  Evidenziare celle su più cartelle (aperte) in una colonna (sempre la stessa in ogni cartella) dove sono contenute date, e lanciare un messaggio con indicato ogni cella & cartella trovata,  dove la data sia uguale ad una determinata data, (quella del giorno in corso, nell' esempio). Il colore di evidenzazione nell'esempio è il giallo:

Sub CercaeSeleziona()
For Each w In Application.Workbooks
data = Date 
'la data del giorno
For Each cell In w.Sheets("Foglio1").Range("A1:A100") 
'indicare il nome del foglio e l'intervallo della colonna
If cell.Value = data Then
MsgBox " Trovata Data uguale nella Cartella " & w.Name & " nella cella " & cell.Address
cell.Interior.ColorIndex = 6 
'si colora la cella di giallo
End If
Next: Next
End Sub

  • 3)  -  Inserimento di un dato con ricerca se il dato è già presente in un intervallo: se sarà un doppione, si avvisa con un messaggio e si esce dalla Sub, altrimenti il nuovo dato verrà aggiunto alla fine dell'intervallo. Si sfrutta un ciclo Do While..Loop che è molto veloce anche con elenchi lunghi. Nell'esempio si suppone di inserire un nominativo scritto in una TextBox su una UserForm (ShowModal=False), tramite un CommandButton; condizione necessaria: tutte le celle dell'intervallo dovranno contenere dati:

Private Sub CommandButton1_Click()
gia = TextBox1.Text 
'con la variabile "gia" prendiamo il dato che è nella textbox
fineri = Sheets("FoglioTuo").[A1].End(xlDown).Row 
'poi prendiamo il numero dell'ultima riga occupata in una 'colonna, iniziando dalla cella intestazione di colonna
riga = 2 
'quindi si imposta la riga da cui iniziare il ciclo Do While
Do While Cells(riga, 1) <> "" 
'il ciclo scorrerà tutte le celle occupate (diverse da vuoto)
If Cells(riga, 1) = gia Then     
'si controlla se la cella ora letta è uguale al nome ora nella variabile "gia"
MsgBox "NOME GIA' PRESENTE"  
' se i dati sono uguali si avvisa con un messaggio
TextBox1 = ""   
 'si pulisce la textbox
TextBox1.SetFocus   
'si posiziona il focus sulla textbox
Exit Sub
End If
riga = riga + 1  
'se il nome non è uguale si incrementa di uno l'indice di "riga"
Loop   
 'e si "gira" ritornando all'inizio ciclo per ripetere con la cella successiva, fino a quando si troverà una cella 'libera
Cells(riga, 1) = gia 
 'quindi si rende (si copia) la cella vuota uguale alla variabile "gia"
MsgBox "NOMINATIVO INSERITO"
End Sub

  • 4)  -  Verifica di dati doppioni in un elenco. Ciò che faremo con il dato doppione ev. trovato, cambia con le varie esigenze, e si potrà eliminare l'intera riga contenente il doppione, oppure sostituire il doppione con un trattino "-" come in questo esempio. Si sfrutta un doppio ciclo veloce, che sfrutta un ciclo Do While.. Loop come ciclo esterno, che scorrerà tutte le righe di un elenco, e per ogni cella letta, innesca un ciclo For..Next che partirà dall'ultima cella occupata, scorrendo all'indietro fino alla cella sottostante la cella ora letta; se verrà trovato un doppione il dato verrà sostituito con un trattino "-" e si avvisa con un messaggio indicante il dato trovato e la cella in cui il dato era. Anche in questo caso è necessario che l'elenco da controllare non contenga celle vuote. L'elenco è nella colonna B (la 2) ed inizia con intestazione di colonna dalla riga 5:

Sub VerificaNomi()
If ActiveSheet.Cells(6, 2) = "" Then Exit Sub
'si controlla che almeno la prima cella dopo l'intestazione sia 'occupata, altrimenti si esce
w = ActiveSheet.Cells(5, 2).End(xlDown).Row 
'si prende con "w" il N° dell'ultima riga occupata nell'elenco
riga = 6
 'poi si imposta il numero della riga dalla quale iniziare il controllo
Do While Cells(riga, 2) <> "" 
'indi si inizia il ciclo Do While che scorrerà finchè le celle saranno diverse da vuoto
nome = Cells(riga, 2).Value  
 'quindi con la variabile "nome" prendiamo il dato presente nella cella ora letta
For N = w To riga + 1 Step -1 
'e si inizia un ciclo For che inizierà dall'ultima riga scalando indietro di una cella a 'ciclo fino alla riga ora letta da While +1
If Cells(N, 2).Value = "-" Then GoTo 10
'se la cella fosse già stata visitata e fosse stata trovata con doppione, ora 'conterrebbe il segno "-" e non vogliamo essere avvisati di questo, quindi passiamo con GoTo a Next
If Cells(N, 2).Value = nome Then 
'se la cella ora letta dal ciclo For è uguale alla variabile "nome"
MsgBox "TROVATO " & nome & " NELLA CELLA " & Cells(N, 2).Address 
'si avvisa con un messaggio
Cells(N, 2) = "-" 
'e si sostituisce il doppione con un trattino
End If
10:
Next
riga = riga + 1
'finito il ciclo For si incrementa il numero di riga di 1 e con Loop passiamo alla riga successiva
Loop
End Sub

  • 5)  -  Usare la Caption di una Label per creare un collegamento ad un sito, oppure per inviare una email. Si sfrutta il metodo FollowHyperlink

Private Sub Label1_Click()
Collega = "http://ennius.altervista.org" 
 'indirizzo del sito
On Error GoTo 10
ActiveWorkbook.FollowHyperlink Address:=Collega, NewWindow:=True
Unload Me
Exit Sub
10:
MsgBox "Impossibile aprire " & Collega
End Sub

Per inviare una email, sostituire la stringa della variabile Collega con "mailto:", così:

Collega = "mailto:pippo@nomeserver.it"

  • 6)  -  Se invece vorrete mantenere un'elenco di tutti i siti visitati mentre lavorate su Excel, potrete usare una ListBox posta su UserForm, per farvi aggiungere gli indirizzi visitati; si suppone che gli indirizzi siano stringhe di connessione (HyperLinks) elencate sul foglio attivo. Impostare la proprietà ShowModal della userform a False, altrimenti risulterà impossibile mantenere la userform aperta e continuare nuovi collegamenti

Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
With UserForm1
.ListBox1.AddItem Target.Address
 'si aggiunge l'indirizzo (Address) del sito su cui si è cliccato sul foglio
.Show    
 'si apre la userform
End With
End Sub

  • 7)  -  Oppure, se vorrete tenere traccia dei siti visitati, e della data e ora in cui vi siete collegati, converrà usare un foglio della cartella dove far accodare data e indirizzo visitato. Esempio: gli indirizzi (Hyperlinks) sono sul Foglio1, e la registrazione la faremo sul Foglio2, usando le colonne A per le date e B per gli indirizzi:

Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)  '(evento del Foglio1)
riga = 1 
'si imposta la riga di inizio per copiare
While Sheets("Foglio2").Cells(riga, 1) <> "" 
'si inizia un ciclo While che cerca la prima cella vuota, colonna A
riga = riga + 1
Wend
Sheets("Foglio2").Cells(riga, 1) = Now 
'trovata la cella vuota, si scrive la data e l'ora
Sheets("Foglio2").Cells(riga, 2) = Target.Address 
'e nella colonna B si scrive l'indirizzo visitato
End Sub

  • 8)  - Usare una Label posta su UserForm come un messaggio, oppure un breve help rientrabile. Si sfrutta l'altezza come condizione da verificare se si cliccherà sulla Label stessa. L'altezza standard è 12 punti, se sapremo di inserire 4 righe di testo, ad inizio routine imposteremo l'altezza a 12 x 4 = 48 punti, e quindi modifichiamo la Caption della Label con il nuovo testo; se al successivo click si riscontra che l'altezza è = a 48, si ripristina a 12 punti.

Private Sub Label1_Click()
If Label1.Height = 48 Then 
'se l'altezza è uguale a 48
Label1.Height = 12
 'si imposta a 12
Exit Sub
'e si esce dalla sub
Else 
'altrimenti, se è diversa da 48 punti
Label1.Height = 48
 'la si imposta a 48 e si vedrà così il messaggio sotto
Label1.Caption = "Leggimi" & vbCrLf _
& "Questo è un" & vbCrLf _
& "breve messaggio" & vbCrLf _
& "di saluto"
End If
End Sub

  Label a riposo

  Label cliccata

 

  • 9)  -  Lavorare con due Fogli di lavoro affiancati (in verticale op. orizzontale). A volte può servire consultare dati che abbiamo su un'altro foglio, mentre stiamo lavorando sul foglio attivo. In Excel non è possibile tenere due fogli aperti contemporaneamente se non si creano due diverse finestre (Window). La cosa è possibile scegliendo dal menù Finestra/Nuova finestra, e a seguire Finestra/Disponi, scegliendo il tipo di affiancamento. Il tutto è gestibile anche dal vba. In questo esempio che segue, stando sul foglio1, faremo aprire il foglio2 ed allineare nella nuova finestra, in alto a sinistra, una cella, la E5, che presumiamo sia la cella iniziale dell'area che vogliamo visualizzare; per questa operazione, dopo aver selezionato il foglio2, usiamo lo ScrollColumn e lo ScrollRow:

Sub ApriFinestra()
ActiveWindow.NewWindow    
'dal foglio attivo, apriamo una nuova finestra, che prenderà il nome della cartella 'di lavoro aperta, seguita dal numero 2
Windows.Arrange arrangestyle:=xlArrangeStyleHorizontal 
'si affiancano le due finestre orizzontalmente
Sheets(2).Select  
'nella nuova finestra, si seleziona il foglio 2
ActiveWindow.ScrollColumn = 5
 'in questo foglio ci spostiamo alla colonna 5 del foglio2
ActiveWindow.ScrollRow = 5  
 'e alla riga 5, facendo corrispondere in alto a sinistra riga 5 e colonna 5
End Sub

 

e questa l'istruzione per ritornare al Foglio 1 chiudendo la finestra 2 ora aperta:

 

Sub Ritornaallovile()
Windows("NomeCartella.xls:2").Close    'su usa il nome della cartella seguito dal numero della finestra, e si chiude
ActiveWindow.WindowState = xlMaximized  
'indi si rende il foglio1, ora attivo, a tutta finestra (pagina)
End Sub

 

  • 10)  -  Cambiare il colore della "griglia" (GridLines) di un foglio, in automatico. E' possibile intervenire sul colore della griglia dal menù Strumenti/Opzioni/Visualizza, scegliendo un colore nell'apposita voce "Colore griglia". Questa scelta agisce su tutti i fogli della cartella aperta. E' possibile però scegliere un colore diverso della griglia, per ogni foglio della cartella, usando una semplice istruzione vba: ActiveWindow.GridlineColorIndex = 5 , e coloriamo la griglia di blu (ognuno sceglierà il colore che vorrà). Per automatizzare questa istruzione potremo scegliere un'evento del foglio di cui vogliamo modificare il colore; possiamo scegliere l'evento Activate, e quando selezioneremo quel foglio attiveremo l'istruzione, oppure il SelectionChange, o ancora legare il colore della griglia se un certo valore compare in una determinata cella. Possiamo pure randomizzare il colore, che cambierà di volta in volta. Vediamo tre esempi:

Evento Activate di un foglio:

Private Sub Worksheet_Activate()
ActiveWindow.GridlineColorIndex = 3
'coloriamo di rosso la griglia
End Sub

 

Evento SelectionChange, randomizzando il colore tra il n. 3 e il n. 12 (i colori più usati, escludendo il nero (1) e il bianco (2)

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Randomize
N = Int((9 * Rnd) + 3)
With ActiveWindow
.DisplayGridlines = True
.GridlineColorIndex = N 
'N sarà uguale ad un numero compreso tra 3 e 12
End With

End Sub

 

Evento Change di un foglio, se si verifica una condizione:

Private Sub Worksheet_Change(ByVal Target As Range)
If [A1].Value = "pippo" Then 
 'se la cella A1 conterrà la parola "pippo", allora
ActiveWindow.GridlineColorIndex = 3 
'si colora la griglia di rosso
Else   
'altrimenti
ActiveWindow.GridlineColorIndex = xlColorIndexAutomatic
 'si rispristina il colore di default
End If
End Sub

  • 11)  -  Quando si usa un "controllo" MultiPage (lo stesso vale anche per il controllo TabStrip) posto su una UserForm, per poter selezionare e rendere attiva una delle pagine (Page, o Tab sul TabStrip) tramite vba, è necessario sfruttare la proprietà Value del MultiPage (o del TabStrip), indicando come valore un numero che identifica l'index di Page, tenendo presente che l'indice delle Pages inizia da zero (che corrisponde alla Page1). In questo esempio, sfruttiamo un commandbutton posto sulla stessa UserForm, e attiviamo la Pagina 2:

Private Sub CommandButton1_Click()
MultiPage1.Value = 1 
'attiviamo la pagina2 nel Multipage
End Sub

  • 12)  -  Copiare Fogli di lavoro. Quando si voglia creare copie (che è diverso dall'aggiungere (Add ) nuovi fogli)di un foglio contenente dati, all'interno della stessa cartella.xls, teniamo presente che Excel rinomina la copia col nome del foglio di origine, aggiungendo al "nome" di questo foglio un numero progressivo posto tra parentesi tonde. Se il foglio di origine sarà il "Foglio1" la prima copia copia si chiamerà "Foglio1 (2)", la seconda copia si chiamerà "Foglio1 (3)", ecc. Questa routine aggiunge tanti fogli quanti ne scriveremo nell'InputBox che appare ad inizio routine, e li pone in ordine progressivo dopo il Foglio di origine. Il contatore N del ciclo, identifica al tempo stesso l'indice del foglio da usare come origine, nell'esempio il primo foglio (che ha il valore indice 1). Se dovessimo copiare il foglio indice 3, dovremmo iniziare il ciclo For Next da 3, addizionando 3 al valore ottenuto dall'inputbox.

Sub Copiafoglio()
dimmi = InputBox("Scrivi il numero di quante copie vuoi")
If dimmi = "" Then Exit Sub
For N = 1 To Val(dimmi)
 'oppure se iniziamo dal'indice foglio 3 : For N = 3 To Val(dimmi) + 3
Sheets(N).Copy After:=Sheets(N)
Next
End Sub

  • 13)  -  TextBox : ottenere il valore numerico più alto. Quando sia necessario reperire il valore più alto contenuto tra più TextBox poste su UserForm (ma anche su un Foglio) contenenti numeri, possiamo usare la funzione Array, sfruttando i nomi delle textbox come argomenti della matrice, ed usare un contatore inizializzato a zero che, scorrendo con un ciclo For Next la matrice e leggendo ogni valore (delle textbox), si aggiorni se il valore in quel momento letto dal ciclo è maggiore del valore del contatore. Al termine del ciclo otterremo il valore massimo tra quelli presenti nelle TextBox; esempio con tre TextBox:

q = 0  'usiamo la variabile "q" come contatore iniziandolo a zero
A = Array(Val(TextBox1), Val(TextBox2), Val(TextBox3))
 'impostiamo la matrice "A" con i nomi delle Textbox
For n = LBound(A) To UBound(A)
' iniziamo un ciclo che legga la matrice dall'indice minore al maggiore
b = A(n) 
'usiamo la variabile "b" come contenitore del valore letto nella matrice, al suo indice n
If b > q Then  
 'se il valore ora in "b" sarà maggiore di "q", allora
q = b 
'si rende il contatore "q" uguale al valore rappresentato da "b"
End If
Next
'si passa al successivo indice della matrice
MsgBox q
 'alla fine del ciclo si utilizza "q" (in questo esempio si fa uscire un messaggio)

  • 14)  -  Usare il "nome" di una cartella per istruire istruzioni condizionali. Spesso, nel lavorare su più cartelle contemporaneamente aperte, possiamo desiderare di attivare (o limitare/escludere) condizioni operative diverse a secondo la cartella  che in quel momento sarà attiva. Possiamo usare un evento della cartella "pilota". Quando attiviamo una cartella diversa da quella attualmente aperta, attiviamo l'evento Deactivate (per contro si verifica l'evento Activate della cartella che prende lo stato attivo) relativo alla cartella che perde lo stato attivo : è in questo evento che inseriremo istruzioni che verificando il "nome" di una cartella, attivino le istruzioni che decideremo. In questo esempio, simuliamo che una UserForm (con la proprietà ShowModal impostata a False) aperta dalla cartella "miacartella.xls", si chiuda se rendiamo attiva un'altra cartella:

Private Sub Workbook_Deactivate()  'si sfrutta l'evento Deactivate della cartella "miacartella.xls"
If ActiveWorkbook.Name <> "miacartella.xls" Then 
'se il nome della cartella che si attiva è diverso, si chiude 'l'userform
Unload UserForm1
End If
End Sub

e questa l'istruzione per riaprire l'UserForm all'attivazione di "miacartella.xls":

Private Sub Workbook_WindowActivate(ByVal Wn As Window)
UserForm1.Show 
'si richiama l'userform
End Sub

  • 15) - Minimizzare Excel (rendere ad icona excel) all'apertura del programma, lasciando a video una UserForm, sfruttando l'evento Workbook_Open  (l'userform dovrà avere la proprietà ShowModal impostata a False):

Private Sub Workbook_Open()
Application.WindowState = xlMinimized
UserForm1.Show
End Sub

  • 16)Non visualizzare la "Struttura" quando si applica "Subtotali" ad un range di valori. Excel di default, visualizza la Struttura quando si eseguono Subtotali (dal menù Dati/Subtotali, oppure via codice vba). E' possibile deselezionare questa opzione dal menù Strumenti/Opzioni, e nella finestra "Visualizza", togliere il segno di spunta alla voce "Simboli di struttura". Ovviamente è possibile usare in alternativa un'istruzione vba, magari inserita dopo istruzioni vba per l'applicazioni di Subtotali. Tenere presente che questa istruzione agisce sull'opzione predetta rendendo permanente la scelta, a meno che non si ripristini l'opzione inserendola nelle istruzioni che toglieranno i subtotali. Questa l'istruzione:

ActiveWindow.DisplayOutline = False

e per ripristinare l'opzione:

ActiveWindow.DisplayOutline = True

  • 17)Trovare un dato correlato al valore maggiore contenuto in un'intervallo. Esempio: trovare il nome (posto nella colonna A), relativo al valore MAX tra i valori posti nella colonna D. Si deve cercare il valore massimo  in un intervallo, memorizzando il numero di riga della cella contenente questo valore
    Si può quindi realizzare usando una variabile contatore, iniziata a zero, e creare un ciclo che scorrendo le celle con i valori , aggiorni il contatore se legge una cella con un valore maggiore presente nel contatore. Di quella cella si prende il numero riga, e alla fine si usa la sintassi Cells(riga, colonna) dove il numero riga sarà quello del numero riga corrispondente al valore maggiore trovato, e come "colonna" dovremo indicare la colonna con i nomi (la A ):

Sub TrovaNomeMax()
Dim CL as Object
cont = 0
'si usa un contatore impostandolo a zero
Set x = Range(Cells(1, 4), Cells(1, 4).End(xlDown))
'con "x" si imposta l'area ricerca valori (colonna D)
For Each CL In x   
'poi si inizia il ciclo che scorre le celle nell'intervallo "x"
valore = CL.Value 
 'con "valore" si prende il valore letto nella cella attuale
If valore > cont Then
  'e si confronta con "cont" se valore è maggiore; se è maggiore
cont = valore           
 'si assegna a "cont" il valore di "valore"
riga = CL.Row        
 'e di questa cella (CL) si prende il numero di riga assegnandolo a "riga"
End If
Next 
'si prosegue a leggere le celle fino a fine intervallo "x". A fine ciclo "riga" corrisponderà alla riga della cella col 'valore maggiore trovato.
nome = Cells(riga, 1).Value
'quindi con "nome" si ottiene il nome posto nella cella "riga", colonna 1
MsgBox nome
  'e si usa "nome"; io faccio uscire un messaggio, ma si può inviarlo ad una cella, es [G5] = nome
End Sub

  • 18) - Inserire un'immagine su un foglio. E' consigliabile prima di inserire un'immagine, selezionare una cella che verrà usata come cella iniziale per l'importazione dell'immagine, altrimenti l'immagine verrà posizionata a partire dalla cella in quel momento attiva. Per importare l'immagine dobbiamo indicare il percorso completo che mira al file immagine, e sfruttiamo il metodo Insert della proprietà Pictures dell'oggetto Worksheet. Nel primo esempio indichiamo nel codice il percorso che mira al file immagine, nel secondo invece facciamo aprire, tramite GetOpenFilename, la finestra "Apri file" e reperiamo tramite la variabile NewFile il percorso del file che selezioneremo; useremo poi questa variabile come vettore del percorso:

Sheets(1).[C4].Select
Sheets(1).Pictures.Insert ( "C:\Vs Cartella Immagini\Vs immagine.jpg")

secondo esempio:

NewFile = Application.GetOpenFilename
Sheets(1).[C4].Select
Sheets(1).Pictures.Insert ("" & NewFile & "")

  • 19) - Copiare una cella o un'intervallo di celle esportandola (anche in Excel stesso) come immagine bmp. Si sfrutta il metodo CopyPicture che consente appunto di "scattare" una foto ad un'area indicata nelle istruzioni, e poi incollare questa "foto" dove vorremo. In questo esempio fotografiamo e copiamo l'intervallo A6:F16 del foglio 1:

Worksheets(1).Range("A6:F16").CopyPicture xlScreen, xlBitmap

  • 20) - Aggiungere caratteri (testo) a numeri. In alcuni casi, può necessitare far apparire una cifra racchiusa tra delimitatori, per esempio come una cifra su un assegno dove la cifra si "barra" per evitare possibili manomissioni. Supponiamo di avere la cella F10 dove scriveremo la cifra 2.200,00 e vogliamo che la stessa appaia posta tra "cancelletti" (i delimitatori) così : #2.200,00# . Si tratta in definitiva di una Concatenazione, ma dobbiamo tenere presente che la cifra, pur essendo in origine un valore numerico o valutario, dopo la concatenazione verrà trasformata in stringa di testo, (quindi poco adatta ad essere usata in operazioni numeriche) ma excel concatena il numero facendogli perdere la formattazione (separatore delle migliaia e due decimali) e vedremmo in realtà la cifra 2.200,00 come #2200#. per ovviare a ciò, è sufficiente "prelevare" la cifra da concatenare non come valore, ma come testo (text). Se il tutto lo vogliamo in automatico, potremo scegliere l'evento Worksheet_Change, in modo che le istruzioni avvengano dopo che quella cella  (la F10, o un'altra a vostra scelta) subisca un cambiamento. Per evitare che le istruzioni si attivino sempre per quella cella, istruiamo una condizione da verificare: se la cella è diversa da vuota e conterrà un valore numerico(una cifra) , allora attiviamo le istruzioni, negli altri casi, quindi anche dopo che avremo ottenuto il concatenamento, le istruzioni non si attiveranno.

Private Sub Worksheet_Change(ByVal Target As Range)
Dim Cifra As String
If [F10] <> "" And IsNumeric([F10]) = True Then
Cifra = [F10].Text  
'con Cifra otteniamo il contenuto di F10 visto però come testo (Text anzichè Value)
[F10] = "#" & Cifra & "#" 
'concateniamo
End If
End Sub

  • 21) - Usare il "Titolo" (Title) assegnato/da assegnare ad una cartella. In alcuni casi è possibile utilizzare il Titolo di una cartella, per esempio, per identificare la stessa tra più cartelle aperte. Il "Titolo" lo si può assegnare in Excel, dal menu File/Proprietà/Riepilogo/Titolo (nella stessa finestra dove appare la proprietà "Autore"). Le istruzioni sono semplici, e sfruttano la proprietà Title dell'oggetto Workbook.

Per ottenere il valore assegnato a Title della cartella attiva:

MsgBox ThisWorkbook.Title

Per impostare o cambiare un valore alla proprietà Title della cartella attiva:

ThisWorkbook.Title = "pippus"

Per selezionare una cartella (tra le cartelle aperte) identificandola dal suo Titolo:

For Each ws In Workbooks
If ws.Title = "pippus" Then ws.Activate
Next

  • 22) - Registrare le Proprietà di una cartella di Excel. Un esercizio che sfrutta il CreateObject per accedere alle "Proprietà" di un file. Può necessitare di voler registrare, all'interno di un foglio di una cartella di excel, alcuni dati quali: il nome del file stesso, il percorso, l'autore, la data di creazione, la data
    dell'ultima modifica, ecc... dati che possono servire all'utente come controllo o verifica. Potremo lanciare la routine a mano, oppure sfruttare un'evento della cartella stessa, tipo il Workbook_Open, meglio ancora il Workbook_BeforeClose, in modo che venga registrata l'ultima modifica se avremo appunto apportato modifiche al file. Nelle istruzioni, per comodità, presumo che si voglia reperire le proprietà della cartella al momento attiva (ThisWorkbook) ed uso le celle dalla A1 alla A7 come destinazione dei dati; ognuno deciderà le celle a lui soddisfacenti:

Sub Proprieta()
ActualName = ThisWorkbook.Name 
' prendiamo il nome della cartella attiva con ActualName
FName = ThisWorkbook.Path & "\" & ActualName  '
Con FName prendiamo il percorso completo, necessario 'da assegnare come argomento del metodo GetFile
Dim fs, f
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.GetFile(FName)    
'la variabile "f" ora è il vettore dell'oggetto file rappresentato dalla variabile "fs"
[a1] = "Nome del File: " & ActualName  
'nome del file
[a2] = "Percorso: " & f.Path                    
'percorso completo
[a3] = "Creazione: " & f.DateCreated     
 'data di creazione del file
[a4] = "Ultimo accesso: " & f.DateLastAccessed  
 'data dell'ultimo accesso
[a5] = "Ultima modifica: " & f.DateLastModified    
'data dell'ultima modifica
[a6] = "Utilizza: " & Int(f.Size / 1000) & " Kb. di spazio su HD"   
'dimensione del file in kb
[a7] = "Autore: " & ThisWorkbook.Author      
 'nome dell'autore (corrisponde all'utente del sistema operativo)
Set fs = Nothing
Set f = Nothing
End Sub

----------------------------------

è altresì possibile registrare le "proprietà" di cartelle xls chiuse, su altre cartelle aperte; è sufficiente indicare con la variabile ActualName il nome della cartella xls chiusa, e con FName prendere il percorso che mira a quella cartella chiusa, e registrare i dati di quella cartella nella cartella attiva.

L'unica proprietà che non può venire letta da una cartella chiusa è la proprietà "Author", perchè detta proprietà si riferisce sempre al Workbook attivo ed è relativo al nome con il quale è registrato l'utente del sistema operativo, a meno che un utente della cartella (chiusa, in questo caso) abbia modificato volutamente detta proprietà inserendo un proprio identificativo. (Dal menù di Excel: File/Proprietà/Riepilogo/Autore).

un'alternativa sarà quella di aprire la cartella chiusa, leggerne il nome dell'autore, richiudere la cartella e registrare anche l'autore nella cartella ora attiva, oppure di NON registrare il nome dell'autore.

questo un esempio :

Sub ProprietaChiusa()
ActualName = "TuoFileChiuso.xls"
'prendiamo il nome della cartella chiusa assegnandola a ActualName
FName = "C:\TuaCartella\" & ActualName
'Con FName prendiamo il percorso completo che porta alla cartella chiusa
Dim fs, f
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.GetFile(FName)
'la variabile "f" ora è il vettore dell'oggetto file rappresentato dalla variabile "fs"
[a1] = "Nome del File: " & ActualName
'in A1 scriviamo il nome del file
[a2] = "Percorso: " & f.Path
'in A2 il percorso completo
[a3] = "Creazione: " & f.DateCreated
'la data di creazione del file
[a4] = "Ultimo accesso: " & f.DateLastAccessed
'la data dell'ultimo accesso
[a5] = "Ultima modifica: " & f.DateLastModified
'la data dell'ultima modifica
[a6] = "Utilizza: " & Int(f.Size / 1000) & " Kb. di spazio su HD" '
e la dimensione del file in kb

'----------modifica
Workbooks.Open Filename:=FName  
 'apriamo la cartella xls chiusa facendola diventare la cartella attiva
autor = ActiveWorkbook.Author      
'ne leggiamo il nome dell'autore assegnandolo alla variabile "autor"
ActiveWorkbook.Close                  
 'richiudiamo la cartella chiusa che era attiva

'---------termine modifica
[a7] = "Autore: " & autor          
 'nome dell'autore in A7 (o dove vorrete, come pure per gli altri dati)
Set fs = Nothing
Set f = Nothing
End Sub

  • 23)Tratteggiare una cella (o più celle) . Per rendere la cella con i bordi tratteggiati simili all'effetto che si ottiene con il Copia. Si utilizza la proprietà LineStyle dell'insieme Borders: un insieme di quattro oggetti Border che rappresentano i quattro bordi di un oggetto Range o Style. (Vedi Guida in Linea).

questo esempio imposta il tratteggio sui bordi della cella B3

Worksheets(1).Range("B3").Borders.LineStyle = xlDash

questo esempio imposta il tratteggio sui bordi della cella D4 e colora il tratteggio in rosso

With Range("D4").Borders
.LineStyle = xlDash
.ColorIndex = 3
End With

questo esempio imposta il tratteggio sui bordi della cella D6, lo colora di rosso, e lo rende in grassetto

With Range("D6").Borders
.LineStyle = xlDash
.Weight = xlMedium
.ColorIndex = 3
End With

  • 24)Eliminare Macro - Nel caso che vengano eliminate una o più macro presenti in un modulo standard, Excel, anche le le macro sono state eliminate, alla riapertura della cartella chiederà se si voglia o meno "disabilitare le macro" (con protezione macro impostata a media). Questo perchè Excel riconosce la presenza di un modulo (modulo = macro) e pone la richiesta. Se vorrete eliminare macro e non ricevere più il messaggio, dovrete eliminare anche il modulo che conteneva le macro.

 

  • 25) - Salvataggio In Corso... -  Una possibile soluzione per tutti coloro che vorrebbero far visualizzare una barra di  avanzamento per segnalare il salvataggio in corso del file xls quando lo stesso salvataggio (in genere per le "generose" dimensioni del file stesso) richiede diversi secondi o addirittura minuti. Non mi risulta sia possibile intercettare, tramite istruzioni vba, l'azione del salvataggio come un valore di iterazione da assegnare ad una normale ProgressBar (o almeno io non le conosco). Un'alternativa quindi potrebbe essere questo suggerimento: usare una UserForm da richiamare nell'evento Workbook_BeforeClose (ma anche da un apposito CommandButton preposto al salvataggio della cartella).

                   a - Impostare la proprietà ShowModal = False della UserForm impiegata per consentire lo svolgersi di operazioni sulla cartella.
                   b - Inserire il seguente controllo Gif89.dll (qui scaricabile in formato zip) , decomprimerlo nella cartella Sistem32 di Windows, indi dalla casella
                        degli strumenti della UserForm  , caricare questa libreria come "Componente aggiuntivo", e dopo posizionare il controllo sulla
                        UserForm, dimensionandolo opportunamente.
                        Questa libreria consente l'utilizzo di gif animate, e sarà appunto una gif animata a simulare il trascorrere del tempo.
                   c - questa è la gif animata   che potrete salvare cliccandoci sopra col destro del mouse e scegliendo "Salva immagine con
                         nome" . La Gif andrà posta nella stessa directory dove risiede il file xls che ne deve fare uso. L'effetto sarà simile a questa immagine:

          E queste le istruzioni: la prima andrà inserita nell'evento Activate della UserForm che ospita la gif animata, e fornisce il percorso che mira al file "scorri.gif", 

Private Sub UserForm_Activate()
Gif89a1.Filename = ThisWorkbook.Path & "\scorri.gif"
 'stesso path della cartella xls.
End Sub

e queste le istruzioni poste nell'evento Workbook_BeforeClose, evento che si verifica un'attimo prima della chiusura del file, e provvede al salvataggio del file stesso :

Private Sub Workbook_BeforeClose(Cancel As Boolean)
UserForm5.Show 
' chiamiamo la userform da noi usata per l'occasione, che simulerà lo scorrimento
DoEvents             
 'passiamo il controllo all'esecuzione di altre procedure (il salvataggio del file)
If Me.Saved = False Then Me.Save   
'salviamo la cartella
Unload UserForm5  
'chiudiamo la userform in contemporanea alla cartella
End Sub

 

  • 26) - Usare una cella per inserire numeri, con somma in altra cella dei numeri inseriti. Può necessitare di usare una cella come maschera di introduzione numeri, e si voglia però totalizzare i numeri inseriti. Sfruttiamo il metodo Intersect per l'imitare l'azione di somma all'introduzione dati in una sola cella: simuliamo la cella A1 come introduzione numeri (interi o decimali) e la cella B1 per ottenere la somma dei numeri immessi in A1

Private Sub Worksheet_Change(ByVal Target As Range)  'usiamo l'evento Change del Worksheet
If Intersect(Target, [A1]) Is Nothing Then
Exit Sub
Else
x = [A1].Value
[B1] = [B1] + x
End If
End Sub

 

  • 27) - Routine ContaParole - Una interessante soluzione per ovviare alla mancanza della funzione "Conta Parole" presente in MS Word, ma assente in MS Excel, trovata sul sito www.cpearson.com/excel.htm . Le istruzioni eseguono un ciclo su tutte le celle di un foglio che contengono dati (il foglio attivo, nell'esempio) (ActiveSheet.UsedRange) e per ogni cella, contano la lunghezza (Len) del contenuto, letto come stringa (Text). Poichè in una cella possono esserci più parole, e le parole sono divide da spazi vuoti, viene usato il metodo Replace per eliminare gli spazi (" ") dalla stringa, quindi si misura la lunghezza di questa, sottraendo il valore dalla lunghezza totale, aggiungendo 1; in questo modo si ottiene il numero di parole presenti nella stringa stessa. Un contatore provvede ad incrementare il totale di ogni cella.

Sub ContaParole()
Dim ContaParola As Long
Dim CL As Range
Dim Testo As String
Dim N As Long
For Each CL In ActiveSheet.UsedRange.Cells
Testo = Trim(CL.Text) 
'Testo è uguale al contenuto della cella letta, senza gli spazi iniziali e finali (Trim)
N = 0 
'ad ogni ciclo N viene reiniziato a zero
If Testo <> "" Then 
'se testo è diverso da vuoto, allora la variabile N sarà uguale al valore della lunghezza di Testo 'meno la stessa lunghezza ma senza gli spazi; quindi per differenza si ottiene il numero degli spazi più 1, che 'corrisponde al numero di parole presenti nella stringa "Testo"
N = Len(Testo) - Len(Replace(Testo, " ", "")) + 1
End If
ContaParola = ContaParola + N 
'si incrementa il contatore "ContaParola" aggiungendo il valore "N"
Next CL
MsgBox "L'AREA CONTIENE N° " & ContaParola & " PAROLE"
End Sub

 

  • 28)Funzione Array - In molte occasioni, quando dobbiamo cercare o confrontare dati con un elenco di dati fissi, sempre gli stessi, come ad esempio un elenco di mesi, o di giorni, oppure una combinazione di lettere alfabetiche, o ancora una serie di codici numerici, o ancora di date, o di orari, ecc., può convenire di creare una "matrice" contenente l'elenco, ed assegnare, tramite la Funzione Array, detta matrice, ad una variabile. Sarà  così possibile scorrere gli "indici" di  matrice, alla ricerca o confronto di un dato presente in matrice, tramite un Ciclo For...Next. Facciamo un esempio per creare una routine che leggendo un codice fiscale, ci restituisca il nome del mese corrispondente alla nona lettera del codice fiscale (lettera appunto che identifica il mese di nascita). Impostiamo due matrici, una contenente l'elenco delle 12 lettere usate nella creazione di un codice fiscale (A, B, C, D, E, H, L, M, P, R, S, T) per identificare il mese, l'altra contenente i nomi dei 12 mesi dell'anno. Usiamo la funzione Mid per ottenere la nona lettera di un codice fiscale assegnata alla variabile "a", indi scorriamo con un ciclo (contatore "N") la matrice contenente le lettere corrispondenti ai mesi (LM) e confrontiamo la lettera letta con LM(N) con la lettera contenuta in "a"; trovata una corrispondenza, si esce dal ciclo (Exit For) e si avvisa con un messaggio. Cosa otteniamo: se si controllasse l'ipotetico codice fiscale di Ludovico Sforza (detto il Moro, nato a Vigevano il 27/07/1452) "SRZLVC14L27L872O", abbiamo che la nona lettera è la "L" , quindi il ciclo cerca la corrispondenza tra il contenuto della matrice LM e la "a", e si interrompe quando il contatore "N" è alla settima posizione di matrice (infatti in 7 posizione troviamo la "L"); quindi "N" è uguale a 7 (e potremmo fermarci qui se cercavamo il numero del mese corrispondente) oppure ottenere anche la settima posizione nella matrice "MS" dove con MS(N) otteniamo "LUG".

Option Compare Text    'queste due istruzioni vanno nella sezione Generale - Dichiarazioni del modulo
Option Base 1   'impostiamo ad 1 l'inizio dell'indice di matrice (altrimenti inizia da zero)

Sub DimmiMese()
Dim a As String
Dim LM As Variant
Dim MS As Variant
Dim N As Integer
a = Mid("SRZLVC14L27L872O", 9, 1)
'opp. Mid(Sheets(1).[A1], 9, 1) opp. Mid(TextBox1, 9, 1) o altra prov.
LM = Array("A", "B", "C", "D", "E", "H", "L", "M", "P", "R", "S", "T")
MS = Array("GEN", "FEB", "MAR", "APR", "MAG", "GIU", "LUG", "AGO", "SET", "OTT", "NOV", "DIC")
For N = LBound(LM) To UBound(LM)
If LM(N) = a Then
Exit For
End If
Next
'otteniamo un messaggio, ma potremmo usare N (=7) o MS(N) (="LUG") da inviare ad una cella o dove ci pare
MsgBox N & " - " & MS(N)
End Sub

  • 29) - Funzione "Mezzanotte" (MZT) - Tra le varie soluzioni possibili per svolgere calcoli su orari, ho preparato questa Funzione MZT() che restituisce la differenza tra due orari quando si accavalla la mezzanotte. Utile quindi in quei casi dove si voglia ottenere il totale delle ore lavorate in turni notturni. Il concetto è semplice: Excel considera un giorno composto da 24 ore, anzi: 23.59.59 visto che le 24 non esistono in quanto superate le 23.59.59 scattano le ore 00.00.00 che sono l'inizio di un nuovo giorno. La funzione quindi separa il primo orario (di ingresso turno) dalle 23.59.59, poi conteggia l'orario di uscita aggiungendolo alle ore 00.00.00, infine somma i due orari ottenuti restituendo il numero totale di ore intercorse tra ingresso/uscita. Per evitare risultati inesatti le celle che ospitano gli orari dovranno essere formattati come formato cella, a Ore. Se in A1 scriveremo l'orario di inizio turno 20.30.00 e in B1 quello di fine turno 4.00.00, in C1 metteremo la funzione = MZT(A1;B1) ed otterremo 7.30.00. Questa la funzione:

Function MZT(OP As Date, OF As Date) As Date
LimiteSup = TimeSerial(23, 59, 59)
Mezzogiorno = TimeSerial(12, 0, 0)
LimiteInf = TimeSerial(0, 0, 1)
Select Case OP
Case Is <= Mezzogiorno
PrimoOrario = OP - LimiteInf + TimeValue("00.00.001")
Case Is > Mezzogiorno
PrimoOrario = LimiteSup - OP + TimeValue("00.00.001")
End Select
Select Case OF
Case Is <= LimiteSup
SecondoOrario = OF + LimiteInf - TimeValue("00.00.001")
End Select
MZT = LimiteSup - OP + LimiteInf + OF
End Function

  • 30) - Funzione FINEANNO - Ancora una funzione "fai da te" (cioè una Funzione Utente). Utile quando si voglia ottenere la data di Fine Anno relativa ad una data immessa in una cella o in una TextBox. Presento due funzioni: la funzione FINEANNO(data) che richiede un solo argomento (la data su cui calcolare il fine anno e che restituirà la data di fine anno dello stesso anno di "data", e la funzione FINEANNI(data;anni) che richiede due argomenti: la data da cui iniziare il calcolo di fine anno, e il numero di anni a scadere, utile per calcoli di fine anno futuri; questa seconda funzione può essere comunque usata al posto della prima semplicemente fornendo 0 (zero) come secondo argomento. Le funzioni dovranno essere poste in un modulo standard, per essere visibili sia sul foglio di lavoro, sia su UserForm o procedure vba. Con le celle: se in A1 avremo la data 22/03/05 e in B1 inseriamo la funzione =FINEANNI(A1;0), in B1 otterremo 31/12/05. Con le TextBox : se nella TextBox1 scriviamo 31/03/05 e destiniamo la TextBox2 come risultato della funzione, l'istruzione sarà: TextBox2 = FINEANNO(TextBox1) . Vediamo le due funzioni:

Function FINEANNO(Data As Date) As Date
Anno = Year(Data)
GiornoMese = "31/12/"
FINEANNO = CDate(GiornoMese & Anno)
End Function

 

Function FINEANNI(Data As Date, Anni As Long) As Date
Y = Year(Data)
Z = Y + Anni
FINEANNI = CDate("31/12/" & Z)
End Function

 

  • 31)Elenchi personalizzati - rimando alla sezione "Primi passi/Elenchi personalizzati" per una breve trattazione dell'argomento. Qui vediamo le istruzioni vba per la realizzazione di Elenchi Personalizzati. Sfruttiamo il metodo AddCustomList che richiede come argomento la ListArray alla quale va assegnato o un'intervallo di celle, se l'elenco deve essere preso da celle di un foglio di lavoro, oppure da una matrice (Array) nella quale scriveremo i valori, racchiusi tra doppi apici e separati da una virgola (sono gli elementi della matrice). Una volta creato l'elenco, potremo usarlo sfruttando il metodo AutoFill

Application.AddCustomList ListArray:=Range("B1:B10") 'prendiamo gli elementi dell'elenco da valori contenuti in 'un'intervallo.

Application.AddCustomList ListArray:=Array("Cognome", "Nome", "Indirizzo", "Città", "P.iva", "telefono")  'usiamo una matrice scrivendo i componenti l'elenco

 

Questa una possibile istruzione per inserire tutto l'elenco a partire da una determinata cella:

Range("G1") = "Cognome"  'inseriamo in una cella la parola di inizio elenco, e usiamo AutoFill come un 'trascinamento
Range("G1").AutoFill Destination:=Range("G1:G6"), Type:=xlFillDefault

 

  • 32) - Filtro: colore linguetta - Quando applichiamo un filtro ad una tabella, spuntano fuori i menù contestuali, (quei pulsantini con un triangolino nero) uno per ogni campo che forma la tabella. Se selezioniamo un menù di un campo per eseguire una filtrazione, il colore della linguetta (cioè del triangolino sul menù) diventa di colore blu. La funzione del cambio di colore dovrebbe facilitarci nell'individuazione di quale campo è stato scelto per la filtrazione, ma come molti segnalano (me compreso) solo con una lente di ingrandimento si riesce a notare il cambiamento di colore. Purtroppo non mi risulta sia possibile modificare l'opzione colore del triangolo del menù del filtro selezionato, impostandola ad esempio ad un bel rosso, ben distinguibile rispetto al nero. Ho pensato ad una soluzione (che propongo e che il lettore potrà modificare sia nel colore, che nell'indirizzo cella da colorare) che, riconoscendo a quale campo è stato applicata la filtrazione, colori la prima cella (quella di intestazione di campo) di rosso; risulterà chiaramente identificabile la colonna su cui si è scelta la filtrazione. Unica necessità: definire un automatismo che scatti al momento della filtrazione per lanciare le istruzioni; la selezione di un campo del filtro non viene rilevata da nessun evento (oppure io non ne conosco), ma possiamo sfruttare una condizione che risulta abbastanza naturale dopo aver applicato la filtrazione: quella di selezionare una qualsiasi cella del foglio di lavoro. Per questo sfrutteremo il Worksheet_SelectionChange dove inserire le istruzioni. Le istruzioni sfruttano la proprietà On dell'oggetto Filters che restituisce il valore True se un filtro specifico è attivo; creiamo quindi un ciclo che rilevi la posizione di quale filtro è attivo, ne prenda il valore index, che ci servirà per determinare il numero di colonna nella sintassi Cells; il numero di riga lo conosciamo a priori ( se la tabella non inizia dalla colonna 1, al valore reperito con la variabile "n" dovremo aggiungere il numero di tante colonne quante sono tra inizio colonna (1) e inizio tabella). Una volta che toglieremo il filtro selezioniamo di nuovo una cella per rilanciare l'istruzione che in questo caso, riportando le celle a neutre, non troverà nessun filtro attivo:

Private Sub Worksheet_SelectionChange(ByVal Target AsRange)
Set w = Worksheets("Foglio1")
 'foglio ipotetico con tabella da filtrare
w.Cells.Interior.ColorIndex = xlNone 
'riportiamo il colore di tutte le celle a neutro
If w.AutoFilterMode Then  
'se il filtro risulta inserito
x = w.AutoFilter.Filters.Count 
con x contiamo da quanti campi è formato
For n = 1 To x 
'si inizia il ciclo che controllerà quale indice di filtro è attivato
If w.AutoFilter.Filters(n).On Then 
'la variabile "n" restituisce l'indice del filtro attivo
Cells(1, n).Interior.ColorIndex = 3
'quindi si colora di rosso la cella 1, colonna "n"
End If
Next
End If
End Sub

 il triangolino è blu???

con l'effetto della macro

 

  • 33) - Numero Civico: estrarlo da un indirizzo. Può capitare la necessità di ottenere il solo numero civico contenuto in un campo "Indirizzo"; spesso nelle tabelle dati di nominativi, clienti, fornitori, amici, ecc. usiamo una colonna dove scriviamo l'indirizzo relativo ad un nome, e, almeno da noi, usiamo scrivere il numero civico alla fine dell'indirizzo, esempio "Via Giolitti, 13" o ancora "Via Verdi 87", o ancora "L.go Colombo nr. 8", ecc. ecc. In tutti i casi, separiamo con uno spazio vuoto il numero dal resto del testo. Questo tipo di sintassi non consente di usare la funzione Val(stringa) che restituisce il numero presente in una stringa di testo (l'indirizzo, appunto) come avviene con la sintassi anglosassone che usa mettere il numero all'inizio dell'indirizzo (1088 Park Lane), infatti è necessario che il valore numerico si trovi all'inizio della stringa perchè la funzione Val restituisca il numero.  Questa sotto è una piccola macro che sfruttando la funzione InStrRev(dovecercare, cosacercare) ci restituisce il valore numerico relativo alla posizione dell'occorrenza cercata all'interno della stringa dove cercare, a partire dalla fine della stringa. Noi cercheremo quindi il primo spazio vuoto a partire da destra, e la posizione di questo spazio vuoto ci servirà per estrarre tramite la funzione Mid tutto ciò che e oltre questa posizione, verso destra, quindi il numero civico. Se l'elenco è lungo, useremo un ciclo che scorra tutta la colonna "Indirizzi" e metta, in un'altra colonna, i numeri civici estratti. La macro la lanceremo dal foglio con gli indirizzi: (non utilizzando il dimensionamento delle variabili (Ultimo, n,y,a,c), le stesse sono assimilate come di tipo Var (quindi stringa o numero)).

Sub EstraiCivico()
Ultimo = [C65536].End(xlUp).Row
 'con Ultimo prendiamo il numero dell'ultima riga occupata nella colonna C
For n = 2 To Ultimo 
'si inizia un ciclo che inizia dalla prima riga contenente gli indirizzi  e scorre fino all'ultima riga
y = Trim(Cells(n, 3))
'eliminiamo con Trim ev. spazi vuoti iniziali e finali dalla cella ora letta, colonna C
a = InStrRev(y, " ")
'con InStrRev cerchiamo la posizione del primo spazio vuoto in "y" , partendo da destra
c = Mid(y, a)
 ' quindi "c" tramite Mid sarà uguale al numero civico
Cells(n, 5) = c 
' e poniamo il valore di "c" nella stessa riga, ma colonna E
Next
End Sub

  • 34) - Inibire una cella - Se vogliamo impedire che si possa scrivere in una cella (contenente una formula, o un valore che deve restare fisso), possiamo sfruttare l'evento Worksheet_SelectionChange : dato che per scrivere in una cella è necessario selezionarla, sfruttiamo l'evento , e attraverso Intersect, limitiamo l'azione alla sola cella Target (quella ce ci interessa proteggere) inibendo (impediamo) l'accesso alla cella, spostando la selezione su un'altra cella:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Intersect(Target, Range("F5")) Is Nothing Then 
'se non selezioniamo la cella F5 (di esempio) usciamo dalla sub
Exit Sub
Else            
 'altrimenti
[G5].Select 
 'selezioniamo la cella a lato (o un'altra a vostro piacere)
End If
End Sub

  • 35) - Stampare .pdf (Acrobat) da Excel - un lettore (Antonello Manca), adattando suggerimenti reperiti sul web, invia queste istruzioni per la stampa, da Excel, di documenti realizzati con Acrobat ®. Le istruzioni sfruttano il metodo Run applicato alla Shell di sistema, tramite il CreateObject. ( vedi articolo ) e necessitano di una versione recente del programma Acrobat Reader (versione libera scaricabile da internet) installato sul computer. Le istruzioni sono state testate con la versione 6.0.1 di Acrobat Reader. Poichè il metodo Run richiede di dichiarare il nome esatto dell'eseguibile da lanciare, ognuno dovrà verificare sul proprio computer l'esatto nome dell'eseguibile relativo alla versione Acrobat Reader installata: il percorso è: C:\Programmi\Adobe\Acrobat 6.0\Reader\nome eseguibile, che nella versione 6 è AcroRd32.exe, seguito dal nome, completo di percorso, del file .pdf da inviare in stampa; è possibile inviare una sequenza di nomi di file .pdf, in modo da stampare uno dopo l'altro, tutti i file. Vediamo due esempi:

Stampare un solo documento .pdf :

Sub StampaUnPDF()
Dim Percorso, Esegui
Percorso = "C:\Prova\NomeDocumento.pdf"
Set Esegui = CreateObject("WScript.Shell")
Esegui.Run "AcroRd32.exe /p /h " & (Percorso)
End Sub

Stampare più documenti .pdf - è opportuno creare un elenco dei nomi dei documenti (senza estensione), per esempio nella colonna A di un foglio, e iniziamo l'elenco dalla riga 1; usiamo un ciclo For..Next che scorra tutti i nomi nell'elenco, e li invii alla stampante; i documenti verranno accodati nella coda di stampa e stampati uno ad uno.

Sub StampaMultiPDF()
Dim Percorso, NomeFile
Dim Esegui
Percorso = "
C:\Prova\"  'indichiamo il percorso della cartella contenente i filese .pdf
Set Esegui = CreateObject("WScript.Shell")
'iniziamo un ciclo che scorre le celle contenenti i nomi dei files .pdf senza estensione (nell'esempio, 5 righe)
For N = 1 To 5
NomeFile = Range("A" & N) & ".pdf"
 'leggiamo il nome del file nella cella e lo concateniamo all'estensione .pdf
NomeFile = (Percorso & NomeFile)   
'concateniamo percorso e nomefile
'l'eseguibile da lanciare sul mio computer è il seguente: basta specificare solo l'eseguibile, ci pensa la Shell a trovarlo
Esegui.Run "AcroRd32.exe /p /h " & (NomeFile)
Next N

MsgBox "Tutti i files sono stati inviati alla stampante"  'al termine del ciclo si avvisa con un messaggio
End Sub

'al termine bisognerà chiudere il Programma Reader che è stato aperto e posto nascosto (non in primo piano)

  • 36) - Menù contestuale : lanciare macro -  quando clicchiamo col destro del mouse su una cella di un foglio di lavoro, appare un menù con una serie di opzioni (voci) da poter selezionare: quella finestrina è il "menù contestuale". In vba di excel quella "finestrina" è una "CommandBars", ed il suo nome è "Cell", e come in ogni CommandBars che si rispetti, è possibile aggiungere "Voci" (Controls) per associarle a macro da lanciare. Per aggiungere una voce (Control) sfruttiamo il metodo Add, e visto che desideriamo aggiungere voci di menù ad ogni apertura della cartella, sfruttiamo l'evento Workbook_Open per inserire le nostre istruzioni; ma, poichè excel memorizzerebbe le voci aggiunte, riaggiungendole nuovamente ad ogni apertura cartella, inseriamo l'istruzione di resettare le voci di default del menù contestuale "Cell". Inoltre, per evitare che excel presenti il menù contestuale modificato anche su altre cartelle, sfrutteremo anche la chiusura della cartella per resettarlo

Private Sub Workbook_Open()
Application.CommandBars("Cell").Reset  
'si reimposta il menù contestuale alle voci di default
With Application.CommandBars("Cell").Controls 
'quindi, con l'insieme Controls (voci) del menù contestuale
With .Add                               
'aggiungiamo una "voce"
.Caption = "TuaMACRO1"             
'specifichiamo la caption, cioè il nome che leggeremo come "voce"
.OnAction = "nomemacro1"            
  'con OnAction indichiamo  il nome della macro da lanciare
.BeginGroup = False
End With

With .Add                    
'continuiamo ad aggiungere un'altra voce
.Caption = "TuaMACRO2"         
'specifichiamo la caption, cioè il nome che leggeremo come "voce"  
.OnAction = "nomemacro2"      
 'con OnAction indichiamo  il nome della macro da lanciare
End With
End With
End Sub

 

e questa l'istruzione necessaria se non vogliamo riempirci di voci aggiunte, all'infinito....

 

Private Sub Workbook_BeforeClose(Cancel As Boolean)
Application.CommandBars("Cell").Reset
End Sub

  • 37) - Uso di tasti per lanciare macro - Usare tasti per attivare istruzioni (lanciare macro) non è una novità (vedi articolo "Il Metodo OnKey" sull'altro sito) ma qui vediamo un esempio impostato su una condizione : usare il tasto F2 (o quello che preferite) per lanciare una macro, SOLO se siamo su un determinato Foglio. La soluzione è semplice: sfruttiamo l'evento Workbook_SheetActivate (NON WorkSheet_Activate) e inseriamo le istruzioni che sfruttano il metodo OnKey; solo quando avremo selezionato il foglio il cui "nome" è inserito, il tasto F2 lancerà la macro associata:

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
If ActiveSheet.Name = "Foglio2" Then    
'se il nome del foglio attivo è quello previsto (nell'esempio: "Foglio2")
Application.OnKey "{F2}", "NomeMacrodalanciare"      
 'la pressione sul tasto F2 lancerà la macro
Else                                                                          
'negli altri casi
Application.OnKey "{F2}", ""                              
'con F2 non otteniamo niente
End If
End Sub

  • 38) - Quando sia necessario identificare un'area che abbiamo selezionato, magari per scorrere le celle dell'area con un ciclo For Each Next, possiamo impostare (tramite l'istruzione Set) una variabile come identificativo dell'area selezionata, e quindi agire sulla variabile. Questo ci consentirebbe di poter variare di volta in volta l'area su cui agire in funzione dell'area selezionata. Oppure potremmo selezionare un'area solo per impostare una formattazione specifica, come un "Formato Cella", un tipo di font, o ancora un colore, ecc. ecc.

Sub Scorri()
Dim Cell As Object
Set RangeDaUsare = Selection  
'la variabile "RangeDaUsare" sarà uguale all'area che avremo selezionato
For Each Cell In RangeDaUsare 
'per ogni cella dell'area selezionata
..istruzioni di cosa fare
Next
End Sub

In questo secondo esempio impostiamo il "grassetto" ed il colore rosso ai font dell'area che avremo selezionato:

Sub Scorri2()
Dim Cell As Object
Set RangeDaUsare = Selection  
'la variabile "RangeDaUsare" sarà uguale all'area che avremo selezionato
RangeDaUsare.Cells.Font.Bold = True    
'impostiamo il "grassetto" ai font dell'area selezionata
RangeDaUsare.Cells.Font.Color = vbRed  
'e coloriamo i font di rosso
End Sub

Se poi volessimo eseguire un controllo per essere sicuri di lanciare istruzioni SOLO SE avremo selezionato un intervallo maggiore di una sola cella, possiamo contare il numero di quante celle formano la selezione, e se questo numero è uguale a 1, avvisiamo con un messaggio ed usciamo dalla routine: (usiamo l'esempio col ciclo For Next)

Sub ScorriSe()
Dim Cell As Object
Set RangeDaUsare = Selection
'la variabile "RangeDaUsare" sarà uguale all'area che avremo selezionato
NCelle = RangeDaUsare.Cells.Count  
'ora con NCelle otteniamo da quante celle è formata l'area selezionata
If NCelle = 1 Then       
'se NCelle sarà uguale ad una sola cella, avvisiamo con un messaggio
MsgBox "hai selezionato una sola cella"
Exit Sub  
'ed usciamo dalla routine senza eseguire le istruzioni sottostanti
End If
For Each Cell In RangeDaUsare 'per ogni cella dell'area selezionata
'..istruzioni di cosa fare
Next
End Sub

  • 39) - Selezionare una stampante - Quando si voglia poter decidere quale stampante (tra le disponibili nel sistema) utilizzare per l'invio del documento in stampa, conviene utilizzare una DialogBox (vedi articolo "Finestre di dialogo-costanti"). Le istruzioni sono semplici, e possono essere inserite all'interno delle nostre routine per stampare; le sottostanti istruzioni fanno aprire la classica finestra di selezione stampante, dove scegliendo la stampante e premendo OK, si invierà la stampa alla stampante scelta:

istruzioni:

effetto:

.....
With Application.Dialogs(
xlDialogPrint)
.Show
End With
.....

 

  • 40) - ColumnHeads delle ListBox o di ComboBox - Credo esista un pò di confusione su come usarle. Intanto si deve impostare la proprietà ColumnHeads del controllo a True, quindi sarà sufficiente tenere presente che la ListBox/ComboBox caricherà come "intestazioni di colonna" i valori che si trovano nella riga immediatamente superiore alla prima riga dell'intervallo che forma il RowSource. In questo esempio sotto, vediamo una tabella che inizia dalla riga 3, dove esistono le "intestazioni di campo", mentre i dati veri e propri iniziano dalla riga 4; al RowSource verrà assegnato quindi l'intervallo A4:E10 mentre i valori nella riga 3 formeranno le "intestazioni di colonna" nella ListBox. Sembra quindi che se i dati verranno caricati non tramite l'assegnazione del RowSource, ma tramite il metodo Additem, non sarà possibile ottenere intestazioni di colonna in quanto il controllo non riesce a identificare l'indice di riga di inizio dati.

  • 41) - Funzione SCRIVI(arg) - Sappiamo che quando inseriamo il segno di uguale (=) iniziale in una cella excel lo interpreta come inserimento di una formula, ma se volessimo "scrivere" la composizione di una formula per visualizzarla solo come testo compreso il segno di uguale, dovremmo anteporre un singolo apice ( ' ) al segno di uguale; in alcuni casi però vorremmo poter disporre di una Funzione che provveda da sola alla conversione formula:testo . Questa sotto soddisfa lo scopo: è una "funzione fai da te" molto semplice che restituisce il valore in formato Testo: viene richiesto come argomento il riferimento della cella contenente la formula (Origine), per cui sul foglio si userà (se la formula da visualizzare è in C1):   =SCRIVI(C1)

Function SCRIVI(Origine As Range) As String
SCRIVI = Origine.Formula
End Function

 

  • 42) - Doppi Apici ( "" ) in una stringa. - Quando si voglia evidenziare una parola all'interno di una stringa di testo, che è gia necessariamente compresa tra due doppi apici (tutta la stringa), la parola (o frase) da evidenziare va posta tra 4 doppi apici. Tipica applicazione una finestra di messaggio dove vogliamo far risaltare una parola; esempio: nella stringa "Se vedete questo messaggio "NON" premete "AVANTI"", dove vogliamo che le parole NON e AVANTI compaiano tra doppi apici, dovremo compilare l'istruzione così:

  • MsgBox "Se vedete questo messaggio ""NON"" premete ""AVANTI"""

 

  • 43) - Sintassi per i riferimenti variabili quando si usa lo "Stile A1"  e per chiarire tipo: Range("C15") dove con la lettera C si intende la colonna mentre con il numero ci riferiamo alla riga, o anche con gli intervalli (sempre in Stile A1), esempio Range("A1:D10");  come si nota i riferimenti alle celle o agli intervalli sono compresi tra doppi apici e visti quindi dal vba, come stringhe di testo; se vogliamo rendere variabile uno dei due elementi di un riferimento (la colonna o la riga) diventa necessario quindi usare delle variabili che dovranno essere "legate" con il segno di concatenazione ( & ) come si fa appunto con l'unione di testo con testo o testo con numeri; vediamo alcuni esempi: attenzione a come si posizionano gli apici, gli spazi, il segno di concatenazione (il segreto è tutto li):

miavar = 10             'rendiamo variabile il numero di riga
Range("D" & miavar)            ' restituisce, è simile a:  Range("D10"), leghiamo la stringa "D" (la lettera D è posta tra 'doppi apici) con un numero 10 (che non richiede di essere racchiuso tra doppi apici)

oppure:

miavar = "D"             'rendiamo variabile la lettera di colonna
Range(miavar & 10)      'restituisce, è simile a:  Range("D10"), in questo caso la variabile miavar è già una stringa '(quindi già vista tra doppi apici) e come tale viene letta dal codice e NON necessita di altri doppi apici.

'----------altro esempio con variabilità di colonne su intervalli:

var1 = "B"   ' impostiamo due variabili che rappresentano le lettere di colonna degli estremi dell'intervallo
var2 = "F"
Range(var1 & 10 & ":" & var2 & 20)  
'equivale ad avere scritto Range("B10:F20")

'--------- ora un esempio con 4 variabili: due di colonna e due di riga:

var1 = "B"   ' impostiamo due variabili che rappresentano le lettere di colonna degli estremi dell'intervallo
var2 = "F"

riga1 = 10   ' impostiamo due variabili che rappresentano i numeri di riga degli estremi dell'intervallo
riga2 = 20
Range(var1 & riga1 & ":" & var2 & riga2) 
'equivale ad avere scritto Range("B10:F20")

'---------altro esempio con variabilità numero di riga su intervalli:

riga1 = 10   ' impostiamo due variabili che rappresentano i numeri di riga degli estremi dell'intervallo
riga2 = 20
Range("B" & riga1 & ":" & "F" & riga2) 
'equivale ad avere scritto Range("B10:F20"), ma va bene anche scritto:

'Range("B" & riga1 & ":F" & riga2)  'abbiamo unito come unica stringa i due punti e la lettera di colonna F

'------chiaramente le variabili possono essere reperite da valori scritti in celle, oppure da inputbox; in questo secondo caso non sarebbe male ricordarsi di usare una "funzione di conversione del tipo di dati" sulla variabile della inputbox.

vediamo l'esempio di reperimento variabili da celle del foglio per assegnazione numeri riga all'origine dati che formano un grafico:

R1 = [A1]    ' R1 sarà uguale al numero contenuto nella cella A1 di cui si usa il "riferimento abbreviato"
R2 = [B1]   
' R2 sarà uguale al numero contenuto nella cella B1 di cui si usa il "riferimento abbreviato"
ActiveChart.SetSourceData Source:=Sheets("Calcolo").Range
("F" & R1 & ":F" & R2)

'------ ma andrà bene comunque anche se useremo direttamente i riferimenti alle celle che contengono i numeri di riga necessari, come variabili nella stringa, così:

ActiveChart.SetSourceData Source:=Sheets("Calcolo").Range("F" & [A1] & ":F" & [B1])

'------ vediamo ancora un paio di esempi con il RowSource (o ListFillRange) di una ListBox o ComboBox, che spesso richiedono una variabilità sulla base di origini dati che cambiano. In questo caso il riferimento da assegnare al RowSource è una pura stringa di testo, esempio:

ListBox1.RowSource = "A1:A15"    ' intervallo racchiuso tra doppi apici e senza parentesi di contenimento

'----- rendiamo variabile la riga iniziale ( o finale, il concetto non cambia):

R1 = 5
ListBox1.RowSource = "A" & R1 & ":A15"
  'abbiamo concatenato la variabile numerica R1

'--ora rendiamo variabile la colonna (giusto per vedere):

Col = "A"
ListBox1.RowSource = Col & "1:A15"
   ' l'intervallo sarà uguale a "A1:A15"  (la variabile Col è già una stringa)

'ora invece rendiamo variabili colonna e riga:

Col = "A"
R1 = 3
ListBox1.RowSource = Col & R1 & ":A15"
   ' l'intervallo sarà uguale a "A3:A15"

insomma, fate anche voi le vostre prove; basta ricordare che le variabili numeriche vanno concatenate senza porle tra doppi apici, a differenza delle variabili stringa .

  • 44) - Conoscere gli anni bisestili - Una veloce routine per chi ha necessità di conoscere in anticipo quali anni sono o saranno bisestili; si sfrutta l'operatore Mod che restituisce il quoziente di una divisione; se quindi la divisione di un anno per 4 restituirà zero, ci troveremo in presenza di un anno bisestile; per comprendere anche gli anni di centenario dovremo dividere anche per 400 anzichè solo per 4. Usiamo quindi una InputBox per scrivere il periodo in numero di anni che vogliamo verificare, e inseriamo due controllini per uscire se non scriveremo nulla e/o se non scriveremo un numero. Il conteggio inizia dall'anno in corso. Se poi si volessero controllare a ritroso quali sono stati gli anni bisestili, basta sostituire il segno di addizione (+) con quello di sottrazione (-), oppure inserire una seconda InputBox per chiedere la direzione di ricerca (in avanti o indietro) ed usare quindi la seconda routine, dove si usa il Select Case per individuare se avremo scritto + oppure - :

Sub Bisestili()
Quantianni = InputBox("Scrivi il numero di quanti anni vuoi controllare")
If Quantianni = "" Then Exit Sub
If IsNumeric(Quantianni) = False Then Exit Sub
anno = Year(Now)
For Bisestile = 1 To Quantianni
If anno Mod 4 = 0 Or anno Mod 400 = 0 Then
MsgBox "L'anno " & anno & " è bisestile"
End If
anno = anno + 1
Next
End Sub

'seconda routine:

Sub AvantiIndietro()
Quantianni = InputBox("Scrivi il numero di quanti anni vuoi controllare")
If Quantianni = "" Then Exit Sub
If IsNumeric(Quantianni) = False Then Exit Sub
Direz = InputBox("Scrivi il segno  +  per anni futuri o  -  per anni passati")
If Direz = "" Then Exit Sub
anno = Year(Now)
For Bisestile = 1 To Quantianni
If anno Mod 4 = 0 Or anno Mod 400 = 0 Then
MsgBox "L'anno " & anno & " è bisestile"
End If
Select Case Direz
Case Is = "+"
anno = anno + 1
Case Is = "-"
anno = anno - 1
Case Else
End Select
Next
End Sub

 

 

  • 45) - Che numero di cella sei ? - sappiamo che un foglio di lavoro di excel è come un'enorme scacchiera contenente 16.777.616 celle (256 colonne x 65536 righe) e che è possibile identificare, puntare, mirare ad una cella in particolare facendo riferimento al suo numero (Indice) all'interno delle oltre 16 milioni di celle. Se noi scriviamo Activesheet.Cells(1027).Select oppure Cells(2311) = QuelCheTiPare avremmo identificato la Cella C5 nel primo caso e la cella G10 nel secondo caso. Excel infatti riconosce il numero della cella iniziando a contare da 1 dalla cella A1, proseguendo verso destra fino alla fine della riga, quindi passando all'inizio della seconda riga e scorrendola fino alla fine, e così via fino alla fine del foglio. In pratica sfrutta la proprietà Item dell'oggetto Range; proprietà che richiede di indicare il numero di indice della cella alla quale si desidera accedere. Ma se invece che accedere ad una cella indicando il suo Item(Index), lo volessimo ricavare per nostro diletto o piacere (detto "Index") ? Personalmente sono incappato in una "guerra tra i mondi" tra me e il debugger nel tentativo di usare "oggetti", "proprietà", sintassi, e mi scoppiavano "Errori" in ogni direzione, cercando risalire al "numero" di una qualsiasi cella selezionata; le ho tentate di tutte, anche una subdola manovra di accerchiamento, in puro stile "marines", ma sono stato individuato, debuggerato e sconfitto; al che rimando al "Buon Pellegrino"  il compito di "illuminarmi" (che sarà "benemerito"). Nel contempo propongo una semplice routine che restituisce, senza lamentarsi, il benedetto numero indice di una cella selezionata, ma ovviamente non era quello che cercavo: per la prova ho scelto l'evento SelectionChange del foglio, così ad ogni selezione di cella ne vediamo il suo "indice". La cosa è sfruttabile anche in esecuzione ricavando la "x" e la "y" dagli indici riga e colonna di una ev. Cells(x, y).

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
x = ActiveCell.Row
y = ActiveCell.Column
ciccio = (256 * (x - 1)) + y
MsgBox Format(ciccio, "#,###")
End Sub

 

  • 46) - Convertire un immagine .Jpeg in .Bmp tramite il vba - Sfruttiamo un'istruzione tipica del VB e non conosciuta, ma eseguibile, in VBA; è l'istruzione SavePicture che consente ad un una immagine caricata in un controllo (ActiveX) Image o PictureBox, di essere salvata in un nuovo file che avrà l'estensione BMP. Se un'immagine grafica viene caricata da un file e assegnata alla proprietà Picture di uno dei due oggetti, in fase di progettazione o in fase di esecuzione, e si tratta di una bitmap, un'icona, un metafile o un enhanced metafile, verrà salvata con lo stesso formato del file originale. Se si tratta di un file GIF o JPEG, verrà salvato come un file bitmap.

    Le immagini grafiche create dalla proprietà Image verranno sempre salvate come file bitmap (.bmp) a prescindere dal formato originario. Useremo quindi un controllo Image che posizioneremo su una UserForm, e sfrutteremo l'evento Activate della UserForm per caricare un'immagine; affideremo ad un Command button posto sulla stessa userform il compito di convertire il formato. Per caricare e poi salvare l'immagine dovremo fornire il percorso dell'immagine Jpeg e indicare percorso e nome dove salvare l'immagine convertita in bmp. Non è difficile, si usano istruzioni già utilizzate in diversi esempi su questi siti, e comunque:

per "caricare" l'immagine sul controllo Image posto su Userform:

Private Sub UserForm_Activate()
Image1.Picture = LoadPicture("C:\TuaCartella\TuoFile.jpg")
  'si fornisce il percorso del file ,jpeg (o jpg) da caricare
End Sub

per convertirla si sfrutta l'evento Click di un commandbutton e si usa l'istruzione SavePicture

Private Sub CommandButton1_Click()
SavePicture Image1.Picture, "C:\TuaCartella\TuoFile.bmp"
'si fornisce nome e percorso del file da convertire come
End Sub                                                                          
 ' bmp

 

 

  • 47) - Usare l'evento "Calculate" - Spesso usiamo o consigliamo, per lanciare istruzioni vba, l'evento "Change" di un Worksheet, che si verifica appunto quando in una qualsiasi cella del foglio "cambiamo" il contenuto, inserendo o modificando valori (numeri, testo, date/orari). Ma quando cambiano valori nelle celle NON per nostra azione diretta, ma come risultato di una formula, dovremo usare l'evento Worksheet_Calculate (infatti se in una cella contenente una formula, cambia il risultato che la formula svolge, non cambia la formula stessa e non si verifica l'evento Change). (Vedi anche articolo "Sfruttare gli eventi")

 

  • 48) - Passare nell'Editor di Visual Basic (VBE) - Quando sia necessario passare nel VBE per raggiungere o visualizzare codice vba provenendo da un foglio di lavoro o da una UserForm, possiamo sfruttare il comando da tastiera ALT + F11, lanciato sfruttando il SendKeys; se lanciato da Userform, poichè non risulta eseguibile il comando stante la UserForm attiva, neppure con la sua proprietà ShowModal impostata a False, aggiriamo l'ostacolo chiudendo la Userform e lanciando a seguire l'istruzione; usiamo per l'occasione un CommandButton posto sulla UserForm, e questa l'istruzione:

Private Sub CommandButton1_Click()
Unload Me
SendKeys "%{F11}", True
End Sub

         

  • 49) - Eliminare righe e/o colonne nascoste - Una Riga o Colonna è nascosta (Hidden in inglese) se ha la sua proprietà Hidden = True . Intervenire quindi su queste righe o colonne diventa quindi facile: basta verificare con l'istruzione If...Then se sono nascoste e quindi applicare l'azione desiderata. Risulta quindi possibile anche "scoprirle", non solo eliminarle. Per intercettare le righe (o colonne) nascoste in un Foglio di lavoro, potremo usare un ciclo For...Next, che scorrendo un certo numero di righe (o di colonne), controlli se le righe sono Hidden = True, trovate le righe (o colonne) nascoste le elimineremo (o le scopriremo). Alcuni esempi:

Sub EliminaRigheNascosteUno()
For N = 1 To 300
'iniziamo un ciclo che scorrerà dalla riga 1 fino ad una riga da definire, 300 come esempio. La 'variabile N è il contatore del ciclo; se la Riga N (Rows(N)) sarà nascosta, la eliminiamo (EntireRow.Delete)
If Rows(N).Hidden = True Then Rows.EntireRow.Delete
Next
End Sub

 

Se invece non sappiamo quanto righe sono occupate sul foglio, possiamo o scorrerle tutte (quindi N = 1 To 65536), oppure cercare l'ultima cella occupata, prenderne il numero di riga, ed usare questo numero come limite superiore del ciclo, così:

Sub EliminaRigheNascostedue()
Dim QuanteRighe 
'variabile che rappresenterà il numero di quante righe sono occupate sul foglio
QuanteRighe = ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Row 
'ne prendiamo il numero di riga
For N = 1 To QuanteRighe    
 'e lo usiamo come limite superiore del ciclo
If Rows(N).Hidden = True Then Rows.EntireRow.Delete
Next
End Sub

 

la sintassi per le colonne è:

If Columns(N).Hidden = True Then Columns.EntireColumn.Delete

 

se invece volessimo scoprirle (righe o colonne)

If Rows(N).Hidden = True Then Rows(N).Hidden = False

If Columns(N).Hidden = True Then Columns(N).Hidden = False

 

  • 50) - Protezione/Sprotezione Foglio con le macro - Di default tutte le celle di ogni foglio di lavoro sono protette da scrittura, protezione che si attiva SOLO se si sceglie di proteggere TUTTO il foglio di lavoro (con o senza password). Di fatto questa protezione impedisce all'utente di poter scrivere o comunque modificare le celle protette (nel caso si vogliano celle non protette basta selezionare le celle che interessano e dal menù "Formato celle/Protezione", togliere il segno di spunta alla voce "Bloccata"). A volte comunque si desidera lasciare come celle protette anche quelle celle dove si voglia intervenire tramite istruzioni vba, ma se le celle sono "bloccate" le istruzioni vba non possono intervenire e si genera un errore di run-time. La soluzione è semplice: tramite la macro che dovrà agire su quelle celle, inseriamo ad inizio routine, una istruzione che toglie la protezione al foglio e quindi lascia le celle "bloccate" libere di poter essere modificate, a seguire vengono le istruzioni della macro, ed in chiusura le istruzioni per riproteggere il foglio; vediamo un esempio:

Sub TuaMacro()
Sheets("FoglioTuo").Unprotect Password = "TuaPassword"
 'togliamo la protezione comprensiva di password

'...istruzioni per agire sulle celle

Sheets("FoglioTuo").Protect Password = "TuaPassword"   
 'rimettiamo la protezione comprensiva di password
End Sub

 

se invece il o i fogli non possiedono password ma solo una protezione:

Sub TuaMacro()
Sheets("FoglioTuo").Unprotect  
'togliamo la protezione

'...istruzioni per agire sulle celle

Sheets("FoglioTuo").Protect   
'rimettiamo la protezione
End Sub

 

  • 51) - Numerazione pagine in fase di stampa - Può necessitare di voler stampare alcuni lavori con le pagine numerate, es: pag. 1 di 9. In Excel, senza istruzioni vba, si può seguire questa semplice procedura: prima di stampare, dal menù File scegliere "anteprima di stampa", nel menù di quella pagina, scegliere "Imposta...", nella finestrina che si apre, scegliere: "Intestaz/Piè di pag.",  in questa pagina troviamo un menù a tendina sotto la voce"Intestazione", cliccare sul triangolino nero del menu a tendina, e scegliere la voce "Pagina 1 di ? " e quindi premi ok, quindi il pulsante "stampa" sul menù dell'anteprima. Per coloro che desiderano invece adottare istruzioni vba, possono leggere il paragrafo "Area di stampa - PageSetup" dell'articolo "Stampa pagine di un foglio" http://ennius.altervista.org/vba/vba44.php dove trovate istruzioni su come procedere e i simboli usati per alcuni tipi di queste formattazioni.

 

  • 52) - Le modalità di protezione messe a disposizione da Excel sono facilmente superabili oppure sono molto affidabili? Dipende dalla preparazione di chi cerca di forzare la protezione, ma comunque secondo me NON esiste nessuna protezione degna di tale nome; esistono molti programmi nati proprio per scoprire e rivelare, annullandole, ev. password usate dagli utenti sia con la cartella, sia per i fogli, sia per il progetto vba (più protette sono le componenti originali Microsoft usate, come ad esempio atpvbaen.xla o funcres.xla, ecc.).
    Alcuni di questi programmi sono facilmente reperibili. (basta cercare con google: "protezione excel" e ad esempio trovate  anche questo:
    http://italian.eazel.com/lv/group/view/kl35681/Accent_Excel_Password_Recovery.htm  che è shareware, in prova gratuita.)
    Sotto questo aspetto (protezione) Excel è molto poco affidabile.

 

  • 53) - Conoscere la data in cui cade la Pasqua Cristiana - Routine per conoscere la scadenza della Pasqua Cristiana secondo il calendario Gregoriano (il nostro) . Potete leggere tutte le spiegazioni alla seguente pagina : "http://it.wikipedia.org/wiki/Calcolo_della_Pasqua" e seguendo il Metodo aritmetico di Gauss; tra le varie versioni circolanti in internet, presento questa mia soluzione nella quale si sfrutta una InputBox per scrivere l'anno di cui si vuol conoscere la data in cui cadrà la Pasqua, ottenendo la risposta tramite una messagebox; chiunque potrà modificare le istruzioni decidendo che anzichè un messaggio ottenga il risultato in una cella:

Sub DimmiLaPasqua()
Dim Anno, giorno
Dim M, N, A, B, C, D, E
Anno = InputBox("SCRIVI L'ANNO DI CUI VUOI SAPERE LA PASQUA")
If Anno = "" Then Exit Sub
Select Case Anno
Case 1583 To 1699
M = 22
N = 2
Case 1700 To 1799
M = 23
N = 3
Case 1800 To 1899
M = 23
N = 4
Case 1900 To 2099
M = 24
N = 5
Case 2100 To 2199
M = 24
N = 6
Case 2200 To 2299
M = 25
N = 0
Case 2300 To 2399
M = 26
N = 1
Case 2400 To 2499
M = 25
N = 1
Case Else
MsgBox "IMPOSSIBILE CALCOLARE"
Exit Sub
End Select

A = Anno Mod 19
B = Anno Mod 4
C = Anno Mod 7
D = (19 * A + M) Mod 30
E = (2 * B + 4 * C + 6 * D + N) Mod 7
If D + E < 10 Then
MsgBox "Pasqua cade il " & 22 + D + E & " di Marzo dell'anno " & Anno
Else
giorno = (D + E - 9)
Select Case giorno
Case 26
MsgBox "Pasqua cade il " & 19 & " di Aprile dell'anno " & Anno
Case 25 And D = 28 And E = 6 And A > 10
MsgBox "Pasqua cade il " & 18 & " di Aprile dell'anno " & Anno
Case Else
MsgBox "Pasqua cade il " & giorno & " di Aprile dell'anno " & Anno
End Select
End If
End Sub

 

  • 54) - Variare lunghezza di una stringa (testo) in una cella. - Un esercizio già descritto in alcuni articoli, ma ripreso qui esemplificando al massimo; quando per necessità diverse, si voglia disporre di stringhe di testo che abbiano tutte la stessa lunghezza, per ogni cella presente in un intervallo di celle, possiamo aggiungere tanti spazi vuoti " " (oppure caratteri come trattini "-" ad esempio) quanti ne mancano tra la lunghezza reale di una stringa e la lunghezza voluta. Sotto un esempio impostato per una specifica cella, ma sarà possibile utilizzare un ciclo che scorra tutte le celle di un'intervallo, e per ogni cella applicare l'istruzione:

Sub CompletaStringa()
Dim LEC, LT, SV, LDiff, T 
 'dichiarazione variabili
SV = " "
'spazio vuoto
LT = 50
'lunghezza totale che dovrà avere la stringa compreso gli spazi vuoti
LEC = Len(Cells(1, 1))
'lunghezza effettiva della stringa nella cella A1
LDiff = LT - LEC
'facciamo la differenza che usiamo come limite superiore del ciclo
If LEC < LT Then 
 'se la lunghezza effettiva è inferiore alla lunghezza totale preventivata, allora:
For T = 1 To LDiff  
 'iniziamo un ciclo che "girerà" per la differenza di caratteri trovata con LDiff
Cells(1, 1) = Cells(1, 1) & SV 
'e rendiamo a cella A1 pari a 50 caratteri (LT)
Next
End If
End Sub

'----------------------------

Esempio con ciclo che scorre l'intervallo celle da A1 a A100

 

Sub CompletaIntervalloStringa()
Dim LEC, LT, SV, LDiff, T, N
'dichiarazione variabili
SV = " "
'spazio vuoto
LT = 50
'lunghezza totale che dovrà avere la stringa compreso gli spazi vuoti
For N = 1 to 100 
'inizio ciclo per scorrere l'intervallo dalla cella A1 alla A100


LEC = Len(Cells(N, 1))
'lunghezza effettiva della stringa nella cella iniziale (Cells(N, 1)) ossia la A1
LDiff = LT - LEC
'facciamo la differenza che usiamo come limite superiore del ciclo per aggiungere spazi vuoti
If LEC < LT Then
'se la lunghezza effettiva è inferiore alla lunghezza totale preventivata, allora:


For T = 1 To LDiff
'iniziamo un ciclo che "girerà" per la differenza di caratteri trovata con LDiff
Cells(N, 1) = Cells(N, 1) & SV
'e rendiamo a cella ora letta pari a 50 caratteri (LT)
Next   
 'aggiungiamo uno spazio vuoto fino alla fine di questo ciclo


End If


Next    
'passiamo alla cella riga successiva, fino alla fine del primo ciclo
End Sub


 

  • 55) - Convertire al volo Euro in Lire - E' possibile avere l'effetto tooltips, cioè cliccando sulla cella contenente cifra in euro, avere la finestrella che appare e indica il valore contenuto espresso in lire?  Risposta: si ; possiamo ottenere come risposta un messaggio che riguarda la cella "Target", cioè quella su cui  eseguiremo un doppio click (quindi doppio click di sinistro) o potremo sfruttare anche il semplice click del pulsante destro del mouse; vediamo entrambe le procedure,  dove cambiano gli eventi del foglio di lavoro da sfruttare:

istruzioni per il doppio click di sinistro:


Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
MsgBox "Importo in LIRE:   " & Format(CLng(Target * 1936.27), "#,###")
End Sub


istruzioni per il semplice click destro: ATTENZIONE poichè l'evento Click destro mouse è l'evento predefinito per far apparire il menu contestuale, verremmo avvisati con il messaggio, sì, ma poi apparirebbe il menù contestuale che non ci servirebbe e dovremo cliccare  di sinistro un'altra cella vuota per farlo sparire. Possiamo quindi disabilitare la comparsa del menù contestuale disabilitando la CommandBars("Cell"), tale è il nome del menù contestuale. Nessun problema a farlo, solo che poi rimarrà disabilitato anche quando ci servirà per altri motivi, salvo usare a quel momento l'istruzione alla rovescia (Application.CommandBars("Cell").Enabled = True).

 

Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
Application.CommandBars("Cell").Enabled = False
MsgBox "Importo in LIRE: " & Format(CLng(Target * 1936.27), "#,###")
End Sub

 

 

 

prelevato sul sito www.ennius.altervista.org

- Ritorna in cima ^^