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

Nella pagina precedente abbiamo esaminato i quattro pulsanti di navidazione nel database ed il pulsante e le due ComboBox per la ricerca dei dati. Questa è la UserForm su cui stiamo lavorando

Continuo con la descrizione degli altri pulsanti

Gli altri pulsanti sono dedicati alla gestione dei dati

Aggiorna DataBase

Può capitare che occorra semplicemente modificare dei dati già esistenti.

Nel codice che ho usato occorre svolgere alcune azioni:

Private Sub CommandButton5_Click()
' aggiorna il record modificato
Dim Cartella, NomeFile, FileNum, R, C
Dim FL As Boolean
' verifica se il record corrente è stato modificato confrontando il contenuto delle TextBox
' coi dati del record corrente della matrice

FL = False
For C = 1 To NumCampi
If Controls("TextBox" & C) <> Matrice(C, RecordCorrente) Then
FL = True
End If
Next
' se non c'è stato alcun cambiamento non occorre effettuare alcun aggiornamento
If FL = False Then
MsgBox "Non è necessario modificare il record"
Exit Sub
End If
' altrimenti si passa agli aggiornamenti necessari
' 1° si aggiorna il RecordCorrente della matrice sovrascrivendo i dati esistenti
' coi nuovi dati prelevati dalle TextBox

MsgBox "aggiornamento record"
For C = 1 To NumCampi
Matrice(C, RecordCorrente) = Controls("TextBox" & C)
Next
' 2° si apre il file di testo sovrascrivendo i vecchi dati con quelli aggiornati
Cartella = ThisWorkbook.Path & "\"
NomeFile = Cartella & "Indirizzario.mik"
NumCampi = UBound(Matrice, 1)
NumRec = UBound(Matrice, 2)
Close
FileNum = FreeFile()
Open NomeFile For Output As #FileNum
For C = 1 To NumCampi - 1
Write #FileNum, Controls("Label" & C).Caption;
Next
Write #FileNum, Controls("Label" & C).Caption
For R = 1 To NumRec
For C = 1 To NumCampi - 1
Write #FileNum, Matrice(C, R);
Next
Write #FileNum, Matrice(C, R)
Next
Close #FileNum
End Sub

 

NB

è da notare il modo che ho adottato per scrivere nel file di testo:

Il file viene aperto in scrittura usando la forma

Open NomeFile For Output As #FileNum

la quale fa sì che i dati vengono sovrascritti

Per scrivere i dati viene usata l'istruzione Write # che scrive i dati una stringa alla volta racchiudendoli tra doppi apici e, se scritti sulla stessa riga, divisi da una virgola (,), come mostrato in questo esempio

"Cognome","Nome","Via","CAP","Città","Prov","nato il","tel","cell"

Siccome la scrittura dei tati viene effettuata in un ciclo ed ogni record deve risiedere sullo stesso rigo nel file di testo, il ciclo lo faccio terminare prima del numero indicato da NumCampi in modo che nel ciclo accompagno l'istruzione di scrittura col punto e virgola ed appena uscito dal ciclo scrivo l'ultimo dato denza il punto e virgola.

 

Per scegliere se scrivere i dati su una stessa riga o su righe diverse viene usata una punteggiatura predefinita:

  1. il punto e virgola
    • con Write # scrive i dati su una stessa riga racchiusi da una coppia di doppi apici ed usando la virgola come carattere separatore
    • con Print # scrive i dati sulla stessa riga senza i doppi apici e senza carattere separatore
  2. la virgola
    • con Write # è uguale al punto e virgola
    • con Print # scrive i dati sulla stessa riga ma separandoli da un tabulatore (alcuni spazi vuoti)
  3. nessuna punteggiatura
    • sia con Write # che con Print # i dati vengono scritti su una nuova riga

 

Elimina il record corrente

Il problema si fa ancora più interessante.

Con questa opzione dobbiamo

Il problema principale è quello che dobbiamo affrontare per aggiornare la matrice.

Io ho risolto in questo modo:

For R = RecordCorrente To NumRec - 1
For C = 1 To NumCampi
Matrice(C, R) = Matrice(C, R + 1)
Next
Next
ReDim Preserve Matrice(1 To NumCampi, 1 To NumRec - 1)
NumRec = NumRec - 1

In pratica è questo che succede:

record 4 da eliminare si fanno scorrere in su i record sottostanti la matrice viene ridimensionata Nuova definizione dei record dopo ridimensionamento
Rec n° 1 Rec n° 1 Rec n° 1 Rec n° 1
Rec n° 2 Rec n°2 Rec n°2 Rec n°2
Rec n° 3 Rec n°3 Rec n°3 Rec n°3
Rec n° 4    X Rec n°5       ^ Rec n°5 Rec n°4
Rec n° 5 Rec n°6       ^ Rec n°6 Rec n°5
Rec n° 6 Rec n°7       ^ Rec n°7 Rec n°6
Rec n° 7 Rec n°8       ^ Rec n°8 Rec n°7
Rec n° 8 Rec n°9       ^ Rec n°9 Rec n°8
Rec n° 9 Rec n° 10    ^ Rec n° 10 Rec n°9
Rec n° 10 Rec n° 11    ^ Rec n° 11 Rec n° 10
Rec n° 11 Rec n° 11           X  

Fatto questo si esegue l'aggiornamento del file di testo nel solito modo.

Private Sub CommandButton6_Click()
Dim R, C
Dim Cartella, NomeFile, FileNum
If MsgBox("sicuro di voler eliminare " & vbCrLf & Matrice(1, RecordCorrente) & "?", _
vbYesNo + vbExclamation) = vbNo Then Exit Sub
If MsgBox("Allora elimino " & vbCrLf & Matrice(1, RecordCorrente) & "?", _
vbYesNo + vbExclamation) = vbNo Then Exit Sub
MsgBox "fatto"
' nella matrice si fanno scorrere in sù i record sottostanti quello da eliminare a partire
' dalla posizione del record corrente che è quello da eliminare
For R = RecordCorrente To NumRec - 1
For C = 1 To NumCampi
Matrice(C, R) = Matrice(C, R + 1)
Next
Next
' la matrice viene ridimensionata usando la clausola Preserve per non perdere i dati eliminando così,
' di fatto, l'ultimo record che è rimasto duplicato a causa dello scorrimento in sù degli ultimi record

ReDim Preserve Matrice(1 To NumCampi, 1 To NumRec - 1)
NumRec = UBound(Matrice, 2)
If RecordCorrente > NumRec Then
RecordCorrente = NumRec
End If
Label12.Caption = NumRec & " record"
' RecordCorrente conserva il valore che aveva prima dell'operazione, se ad essere eliminato
' non è l'ultimo record, per cui viene visualizzato il record che ha preso il posto di quello eliminato

For C = 1 To NumCampi
Controls("TextBox" & C) = Matrice(C, RecordCorrente)
Next
' si procede ora alla registrazione dell'intera matrice sovrascrivendo i vecchi dati
Cartella = ThisWorkbook.Path & "\"
NomeFile = Cartella & "Indirizzario.mik"
Close
FileNum = FreeFile()
Open NomeFile For Output As #FileNum
For C = 1 To NumCampi - 1
Write #FileNum, Controls("Label" & C).Caption;
Next
Write #FileNum, Controls("Label" & C).Caption
For R = 1 To NumRec
For C = 1 To NumCampi - 1
Write #FileNum, Matrice(C, R);
Next
Write #FileNum, Matrice(C, R)
Next
Close #FileNum
End Sub

Nuovo Record

Questa è senz'altro la fase più delicata di questo applicativo.

Quando si entra in fase di inserimento di un nuovo record è opportuno disabilitare tutti i controlli per non creare confusione ed eventuali errori.

In questa fase gli unici controlli che ci servono sono:

  1. il CommandButton7 svolge una duplice funzione:
    • la prima volta che viene premuto fa entrare in modalità inserimento
    • la seconda volta che viene premuto esegue l'aggiornamento della matrice e del database e riporta tutto in modalità consultazione
    • per fare questo viene cambiata alternativamente la sua caption: "Registra" e "Nuovo Record"
  2. il CommandButton8 annulla l'operazione ritornando in modalità consultazione
Private Sub CommandButton7_Click()
Dim C, R
Dim FileNum, Cartella, NomeFile
Dim CTRL As Control
ComboBox1.ListIndex = -1
ComboBox2.Clear
If CommandButton7.Caption = "Nuovo Record" Then
' ci si prepara all'inserimento del nuovo record
' vengono cancellate tutte le TextBox
' vengono disabilitati i CommandButton e le ComboBox

For Each CTRL In Me.Controls
If (TypeName(CTRL) = ("TextBox")) Then
CTRL = ""
ElseIf (TypeName(CTRL) = ("CommandButton")) Then
CTRL.Enabled = False
ElseIf (TypeName(CTRL) = ("ComboBox")) Then
CTRL.Enabled = False
End If
Next
' vengono riattivati solo questi due CommandButton
CommandButton7.Enabled = True
CommandButton7.Caption = "Registra"
CommandButton8.Enabled = True
CommandButton8.Visible = True
TextBox1.SetFocus

Else
' si registra il nuovo record
If TextBox1 = "" Or TextBox2 = "" Then
MsgBox "Inserire almeno nome e cognome"
Exit Sub
End If
MsgBox "registrazione dati"
' viene aggiornata la matrice aggiungendo il nuovo record
NumRec = UBound(Matrice, 2) + 1
ReDim Preserve Matrice(1 To NumCampi, 1 To NumRec)
For C = 1 To NumCampi
Matrice(C, NumRec) = Controls("Textbox" & C)
Next
' quindi viene aggiornato anche il file di testo
' questa volta viene aperto in modalità append
' in questo modo è sufficiente aggiungere solo l'ultimo record anzichè tutta la matrice

Cartella = ThisWorkbook.Path & "\"
NomeFile = Cartella & "Indirizzario.mik"
Close
FileNum = FreeFile()
Open NomeFile For Append As #FileNum
For C = 1 To NumCampi - 1
Write #FileNum, Matrice(C, NumRec);
Next
Write #FileNum, Matrice(C, NumCampi)
Close #FileNum
' vengono ora riattivati tutti i controlli riportandosi in modalità consultazione
RecordCorrente = UBound(Matrice, 2)
For Each CTRL In Me.Controls
If (TypeName(CTRL) = ("CommandButton")) Then
CTRL.Enabled = True
ElseIf (TypeName(CTRL) = ("ComboBox")) Then
CTRL.Enabled = True
End If
Next
CommandButton7.Caption = "Nuovo Record"
CommandButton8.Visible = False
' le TextBox vengono riempite coi dati dell'ultimo record inserito
For C = 1 To NumCampi
Controls("TextBox" & C) = Matrice(C, RecordCorrente)
Next
Label12.Caption = NumRec & " record"
End If
End Sub

Annulla

Questo pulsante è abbinato al pulsante Nuovo Record e normalmente viene tenuto nascosto.

Il suo compito è quello di uscire dalla modalità inserimento e riportare alla modalità consultazione. Quindi il suo compito è molto semplice

Private Sub CommandButton8_Click()
Dim C
Dim CTRL As Control
For Each CTRL In Me.Controls
If (TypeName(CTRL) = ("CommandButton")) Then
CTRL.Enabled = True
ElseIf (TypeName(CTRL) = ("ComboBox")) Then
CTRL.Enabled = True
End If
Next
CommandButton7.Caption = "Nuovo Record"
CommandButton8.Visible = False
For C = 1 To NumCampi
Controls("TextBox" & C) = Matrice(C, RecordCorrente)
Next
End Sub