DataBase malleabili con le Matrici...Rubrica (1)

 

Parlando di Matrici, per non rimanere nel teorico, ho preparato un piccolo DataBase in cui cercherò di spiegare come lavorare in modo costruttivo con le Matrici.

Ma, prima di continuare, è necessario scrivere almeno due righe per spiegare il concetto di DataBase.

DataBase

E' una raccolta di elementi omogenei a cui sono associati tipi diversi di informazioni.

Un DataBase è rappresentato da un numero imprecisato di elementi (Record) ognuno dei quali contiene un specificato numero di informazioni (Campi).

Record
E' un elemento di un DataBase e viene utilizzato come sinonimo di "Riga".

I due termini "Record" e "Riga" hanno in realtà un significato leggermente diverso, ma nella maggior parte dei casi sono utilizzati come sinonimi.

Campo
Posizione, all'interno di un Record, in cui vengono memorizzati dati e viene usato come sinonimo di "Colonna".

I due termini "Campo" e "Colonna" hanno un significato leggermente diverso, ma nella maggior parte dei casi sono utilizzati come sinonimi..

Un esempio di piccolo database lo potete vedere in questo file di testo esempio

In questa piccola chiacchierata vedremo come utilizzarlo in Excel senza impostare una sola stringa, ma lavorando esclusivamente con le matrici.

 

La Rubrica

Partiamo col costruire una userform come questa

Dato il database su cui vogliamo lavorare in questa userform abbiamo:

Il lavoro parte da questa piccola routine collegata ad un pulsante posto su uno dei fogli e scritto in un Modulo generico:

Sub Parti()
UserForm1.Show
End Sub

Dichiarazione delle variabili pubbliche

Nel modulo relativo alla UserForm, nella zona della dichiarazione delle variabili dichiariamo alcune variabili che ci debbono accompagnare durante tuoo il lavoro:

Dim RecordCorrente, NumCampi, Matrice(), Campi, NumRec


L'apertura della UserForm

All'apertura della userform, usando l'evento UserForm_Activate, prepariamo l'ambiente. Per ciclare cugli Oggetti Labels si usa l'Insieme Controls. Controls è un insieme i cui elementi rappresentano i controlli di un form.

Il CommandButto8, che alla fine della routine rendiamo invisibile, servirà solo per uscire prem aturamente dalla fase di inserimento di un nuovo record. Per questo motivo, e per non crfearfe confusione con un pulsante che altrimenti è inutile, lo rendiamo invisibile.

Private Sub UserForm_Activate()
Dim Cartella As String, NomeFile As String
Dim FileNum, Campo
Dim MioTest
Dim C, R
Cartella = ThisWorkbook.Path & "\"
NomeFile = Cartella & "Indirizzario.mik"

'leggo solo la prima riga del database per determinare il numero dei campi
Close
FileNum = FreeFile()
Open NomeFile For Input As #FileNum
Line Input #FileNum, MioTest
Close #FileNum
Campi = Split(MioTest, ",")
NumCampi = UBound(Campi) + 1
ReDim Campi(1 To NumCampi)

'il passo seguente è quello di riaprire il database ed iniziare una lettura
'sistematica del suo contenuto

Close
FileNum = FreeFile()
R = 0
Open NomeFile For Input As #FileNum
'inizio a leggere i primi NumCampi elementi che sono i nomi dei campi
'e da usare come Caption per le label

For C = 1 To NumCampi
Input #FileNum, Campi(C)
Next
'continuo la lettura degli altri elementi che sono i dati su cui lavorare
Do While Not EOF(FileNum)
R = R + 1
ReDim Preserve Matrice(1 To NumCampi, 1 To R)
For C = 1 To NumCampi
Input #FileNum, Matrice(C, R)
Next
Loop
Close #FileNum
NumRec = UBound(Matrice, 2)

'finita la lettura inizio ad usare le matrici che ho appena finito di caricare
'la matrice Campi() che contiene i nomi dei campi viene usata per assegnare i nomi alle Label

For C = 1 To NumCampi
Controls("Label" & C).Caption = Campi(C)
ComboBox1.AddItem Campi(C)
Next
'la matrice Matrice() che contiene i valori
RecordCorrente = 1
For C = 1 To NumCampi
Controls("TextBox" & C) = Matrice(C, RecordCorrente)
Next
Label13.Caption = "record n^ " & RecordCorrente
CommandButton8.Visible = False
Label12.Caption = NumRec & " record"
End Sub

Fatto questo siamo pronti per iniziare i lavori usando i comandi presenti sulla UserForm.

Iniziamo ad analizzarfe i 4 pulsanti per la navigazione.

I quattro pulsanti di navigazione

Per andare al primo o all'ultimo record

Per andare al primo record:

Private Sub CommandButton1_Click()
' il primo record
Dim C
ComboBox1.ListIndex = -1
ComboBox2.Clear
RecordCorrente = 1
For C = 1 To NumCampi
Controls("TextBox" & C) = Matrice(C, RecordCorrente)
Next
Label13.Caption = "record n^ " & RecordCorrente
End Sub

Per andare all'ultimo record

Private Sub CommandButton4_Click()
' l'ultimo record
Dim C
ComboBox1.ListIndex = -1
ComboBox2.Clear
RecordCorrente = NumRec
For C = 1 To NumCampi
Controls("TextBox" & C) = Matrice(C, RecordCorrente)
Next
Label13.Caption = "record n^ " & RecordCorrente
End Sub

 

Per spostarsi di un record in avanti o indietro

Per entrambe le opzioni prima di incrementare o decrementare il valore contenuto in RecordCorrente occorre verificare che non ci si trovi già all'ultima o alla prima posizione.

Per andare avanti di un record

Private Sub CommandButton3_Click()
' vai avanti
Dim C
ComboBox1.ListIndex = -1
ComboBox2.Clear
If RecordCorrente < NumRec Then RecordCorrente = RecordCorrente + 1
For C = 1 To NumCampi
Controls("TextBox" & C) = Matrice(C, RecordCorrente)
Next
Label13.Caption = "record n^ " & RecordCorrente
End Sub

Per andare indietro di un record

Private Sub CommandButton2_Click()
' vai indietro
Dim C
ComboBox1.ListIndex = -1
ComboBox2.Clear
If RecordCorrente > 1 Then RecordCorrente = RecordCorrente - 1
For C = 1 To NumCampi
Controls("TextBox" & C) = Matrice(C, RecordCorrente)
Next
Label13.Caption = "record n^ " & RecordCorrente
End Sub

Lievemente più complessa è la gestione degli altri pulsanti. Ma vediamoli assieme.

 

Il pulsante "Cerca Successivo"

L'uso di questo pulsante è subordinato alle scelte fatte con le due ComboBox.

Il lavoro della prima ComboBox

Il numero del campo in cui cercare i dati ci viene fornito dalla proprietà ListIndex della ComboBox aumentata di una unità.

Occorre effettuare questo calcolo perchè la ListIndex è a base 0 (zero), mentre la matrice dei campi è stata creata a base 1

Trovato il campo da cui prelevare i dati da inserire nella ComboBox2, scorriamo la matrice Matrice leggendono solo i valori relativi a quel campo

Private Sub ComboBox1_Change()
Dim C, R
If ComboBox1.ListIndex = -1 Then Exit Sub
C = ComboBox1.ListIndex + 1
ComboBox2.Clear
For R = 1 To NumRec
If Matrice(C, R) <> "" Then
ComboBox2.AddItem Matrice(C, R)
End If
Next
End Sub

Il lavoro della seconda ComboBox

Il lavoro che compie questa seconda ComboBox è lievemente più complesso di quello della prima

L'ultima istruzione, data la struttura del programma, potrebbe sembrare inutile (in caso di fallimento della ricerca il RecordCorrente viene riportato al valore che aveva prima di iniziare la ricerca). Tuttavia un po' di programmazione difensiva non fa mai male.

Private Sub ComboBox2_Change()
Dim DaCercare, C, VecchioRecord
If ComboBox2.ListIndex = -1 Then Exit Sub
VecchioRecord = RecordCorrente
DaCercare = ComboBox2
C = ComboBox1.ListIndex + 1
For RecordCorrente = 1 To NumRec
If Matrice(C, RecordCorrente) = DaCercare Then
For C = 1 To NumCampi
Controls("TextBox" & C) = Matrice(C, RecordCorrente)
Next
Label13.Caption = "record n^ " & RecordCorrente
Exit Sub
End If
Next
RecordCorrente = VecchioRecord
End Sub

Il pulsante "Cerca Successivo"

Finalmente possiamo passare ad esaminare il codice relativo a questo pulsante che ci aiuta a cercare le altre eventuali occorrenze del dato scelto dalla seconda ComboBox

Questo è un probabile codice da usare per il pulsante "Cerca Successivo"

Private Sub CommandButton9_Click()
If ComboBox2.ListIndex = -1 Then
MsgBox "nulla da cercare"
Exit Sub
End If
Dim R, C, DaCercare
DaCercare = ComboBox2
C = ComboBox1.ListIndex + 1
R = RecordCorrente + 1
For RecordCorrente = R To NumRec
If Matrice(C, RecordCorrente) = DaCercare Then
For C = 1 To NumCampi
Controls("TextBox" & C) = Matrice(C, RecordCorrente)
Next
Label13.Caption = "record n^ " & RecordCorrente
Exit Sub
End If
Next
MsgBox "ricerca terminata"
RecordCorrente = R
End Sub

Gli altri pulsanti sono dedicati alla gestione dei dati ma per comodità li vedremo nella seguente pagina