Nell'ultima
lezione ci eravamo lasciati con un paio di errori da correggere;
questo era il codice "sbagliato":
Dim
strCartelle() As String
Dim intPos As
Integer
Dim intPosPrec As
Integer
Dim strPath As
String
strPath = "C:\documenti\immagini\esempio.jpg"
Do
IntPosPrec = intPos
IntPos = instr(intPos+1, strPath, "\")
Redim Preserve strCartelle(Ubound(strCartelle)+1)
As String
StrCartelle(Ubound(strCartelle))
= Mid$(strPath, intPosPrec+1, intPos- _ intPosPrec)
Loop While intPos |
Se
proviamo a eseguire questo codice (ad esempio inserendolo
nella routine dell'evento Load di un form), otterremo questo
errore:
L'errore
si verifica nella riga in cui si ridimensiona il vettore strCartelle,
perché nella prima iterazione del ciclo esso non ha
una dimensione definita, pertanto ad andare in errore è
la funzione Ubound(strCartelle): risolvere questo errore è
molto semplice, infatti basta inizializzare il vettore prima
del ciclo Do. Poiché all'inizio il vettore deve essere
vuoto, possiamo ridimensionarlo assegnandogli un solo elemento,
in questo modo:
Redim
strCartelle(0) As String |
Così
facendo, però, sprechiamo un elemento del vettore (l'elemento
zero, appunto), perché nel ciclo il ridimensionamento
avviene aumentando di 1 l'indice superiore del vettore: quindi
il primo elemento del vettore riempito con il nome di una
cartella sarebbe l'elemento 1, mentre l'elemento 0 resterebbe
inutilizzato. Per rimediare a questo piccolo inconveniente
(che a dire il vero potremmo anche trascurare), basta invertire
le ultime due istruzioni del ciclo, in modo che prima si assegni
un valore all'ultimo elemento del vettore, e poi si proceda
al ridimensionamento di quest'ultimo:
Dim
strCartelle() As String
Dim intPos As
Integer
Dim intPosPrec As
Integer
Dim strPath As
String
strPath = "C:\documenti\immagini\esempio.jpg"
Redim strCartelle(0) As
String
Do
IntPosPrec = intPos
IntPos = instr(intPos+1, strPath, "\")
StrCartelle(Ubound(strCartelle))
= Mid$(strPath, intPosPrec+1, intPos- _ intPosPrec)
Redim Preserve strCartelle(Ubound(strCartelle)+1)
as String
Loop While intPos |
Il
primo "bug" è risolto, ma ce n'è ancora
un altro: se proviamo ad eseguire il ciclo appena modificato,
otterremo il seguente messaggio:
Questa
volta l'errore non si verifica all'inizio, ma alla fine del
ciclo: infatti, quando sono finiti i "\" da cercare,
la variabili intPos sarà uguale a zero, mentre la variabile
intPosPrec è diversa da zero; pertanto il terzo parametro
della funzione Mid$() è negativo, e ciò genera
l'errore appena visto.
Anche in questo caso la risoluzione è abbastanza semplice,
basta usare il costrutto if
then:
Dim
strCartelle() As String
Dim intPos As
Integer
Dim intPosPrec As
Integer
Dim strPath As
String
strPath = "C:\documenti\immagini\esempio.jpg"
Redim strCartelle(0) As
String
Do
IntPosPrec = intPos
IntPos = instr(intPos+1, strPath, "\")
If intPos Then
StrCartelle(Ubound(strCartelle))
= Mid$(strPath, intPosPrec+1, intPos- _ intPosPrec)
Else
StrCartelle(Ubound(strCartelle))
= Mid$(strPath, intPosPrec+1)
End If
Redim Preserve strCartelle(Ubound(strCartelle)+1)
As String
Loop While intPos |
Se
intPos è diversa da zero (cioè se è stato
trovato un ulteriore "\"), si prendono solo i caratteri
tra il penultimo e l'ultimo backslash, altrimenti si prendono
tutti i caratteri dall'ultimo backslash in poi. Questa soluzione,
benché semplice, è però poco elegante
perché costringe a effettuare un controllo che risulta
sostanzialmente inutile in tutte le iterazioni tranne che
nell'ultima; se il ciclo dovesse eseguire numerose iterazioni,
il rallentamento derivante da questo controllo potrebbe farsi
consistente. Una possibile alternativa è quella di
spostare la ricerca del successivo backslash alla fine del
ciclo, anziché porla all'inizio: così quando
non ci sono più backslash il ciclo termina direttamente;
in questo caso però occorre effettuare la ricerca del
primo backslash prima dell'inizio del Do e assegnare l'ultimo
elemento del vettore dopo la sua fine, in questo modo:
Dim
strCartelle() As String
Dim intPos As
Integer
Dim intPosPrec As
Integer
Dim strPath As
String
strPath = "C:\documenti\immagini\esempio.jpg"
Redim strCartelle(0) As
String
IntPos = instr(intPos+1, strPath, "\")
Do
StrCartelle(Ubound(strCartelle))=Mid$(strPath,
intPosPrec+1, intPos- _ intPosPrec)
Redim Preserve strCartelle(Ubound(strCartelle)+1)
As String
IntPosPrec = intPos
IntPos = instr(intPos+1, strPath, "\")
Loop While intPos
StrCartelle(Ubound(strCartelle))
= Mid$(strPath, intPosPrec+1)
For
intPos=0 To Ubound(strCartelle)
Debug.Print strCartelle(intPos)
Next intPos
|
Il
piccolo ciclo For finale serve solo a visualizzare i nomi
delle cartelle che abbiamo estrapolato dal percorso originale:
come noterete, tutti i nomi delle cartelle (tranne il nome
del file) terminano con "\", perché alla
funzione Mid abbiamo chiesto di prendere tutti i caratteri
compresi tra il penultimo e l'ultimo backslash, e in questi
caratteri c'è anche l'ultimo backslash. Questo non
è un vero e proprio errore, dipende più che
altro dall'uso che vogliamo fare del vettore strCartelle;
comunque, se volessimo solo il nome della cartella puro e
semplice dovremmo chiamare la funzione Mid in questo modo:
StrCartelle(Ubound(strCartelle))
= Mid$(strPath, intPosPrec+1, intPos- _ intPosPrec-1) |
Il
"-1" aggiunto al terzo parametro fa sì che
l'ultimo backslash sia escluso dai caratteri da assegnare
agli elementi del vettore strCartelle. Ci possono essere vari
modi per risolvere problemi come quelli visti fin qui: l'importante
è sapersi ingegnare e trovare la soluzione più
adatta alle proprie esigenze.
Terminato il discorso sui cicli, passiamo a considerare un'altra
istruzione utilizzata spesso per controllare il flusso del
programma: l'istruzione Select Case.
Essa analizza un'espressione ed esegue istruzioni differenti
in base al suo valore. Detto così sembra che l'istruzione
Select case sia del tutto simile all'istruzione If, e in effetti
è così: infatti è possibile esprimere
una Select case come un blocco If con un adeguato numero di
clausole ElseIf.
La scelta tra le due di solito dipende da considerazioni di
convenienza e di leggibilità del codice, perché
spesso un blocco Select risulta strutturalmente più
semplice di un blocco If.
La sintassi dell'istruzione Select Case è la seguente:
Select
Case espressione
Case valore-1
Istruzioni-1
Case valore-2
Istruzioni-2
[Case Else
istruzioni-else]
End Select |
Espressione
è una variabile, una proprietà o una qualunque
espressione che può assumere diversi valori e che va
confrontata coi valori elencati nei vari "casi";
nel caso in cui il valore dell'espressione sia valore-1, saranno
eseguite le istruzioni istruzioni-1 (che ovviamente possono
essere più di una).
Se il valore è valore-2, saranno eseguite le istruzioni
istruzioni-2, e così via, per tutti i casi elencati.
Se espressione assume un valore che non rientra in quelli
specificati, sarà eseguito il blocco di istruzioni
istruzioni-else, se è presente: infatti, come per l'istruzione
If, anche nella Select Case il blocco Else è
facoltativo.
Inoltre, come si è visto più volte, anche per
questa istruzione vale la regola di indicarne la fine con
l'istruzione End Select. Ecco un esempio di istruzione
Select Case:
Select
Case
lblEtichetta.Caption
Case "Testo1"
lblEtichetta.FontSize = 12
Case Else
lblEtichetta.FontName = "Arial"
lblEtichetta.FontSize = 11
End Select |
Nel
caso in cui fosse necessario eseguire lo stesso blocco di
istruzioni in corrispondenza di più valori di espressione,
l'elenco di questi valori va separato con la virgola.
Ad esempio, il blocco precedente può essere modificato
in questo modo:
Select
Case
lblEtichetta.Caption
Case "Testo1",
"Testo2", ""
lblEtichetta.FontSize = 12
Case Else
lblEtichetta.FontName = "Arial"
lblEtichetta.FontSize = 11
End Select |
L'elenco
di valori con cui va confrontata l'espressione può
assumere anche altre forme, che risultano particolarmente
utili quando l'espressione da controllare è di tipo
numerico: è possibile infatti indicare un intervallo
di valori usando l'operatore To o usando l'operatore Is seguito
da un operatore di confronto, come nell'esempio seguente
Select
Case
lblEtichetta.FontSize
Case Is < 8, 12 To 14,
18
lblEtichetta.FontSize = 12
Case Else
lblEtichetta.FontName = "Arial"
End Select |
In
questo esempio la dimensione del carattere dell'etichetta
sarà impostato a 12 punti se esso è minore di
8, compreso tra 12 e 14 (estremi inclusi), oppure uguale a
18; altrimenti la dimensione del font non sarà modificata
ma il tipo di carattere diventerà Arial.
La clausola Else, pur non essendo obbligatoria, è comunque
opportuna per gestire i casi "imprevisti", ad esempio
generando un messaggio di errore per notificare all'utente
che il valore dell'espressione non rientra in quelli previsti.
Infine, come per l'istruzione If, anche le istruzioni Select
Case possono essere nidificate: ovvero, dopo ogni clausola
Case le istruzioni da eseguire possono includere un altro
blocco Select Case, il quale a sua volta ne può contenere
un altro, e così via.
|