" Crearsi agenda app.ti parte 1

Crearsi una Agenda Appuntamenti: prima parte. - dal 04/09/04 pagina vista: volte

Di Agende per Appuntamenti, l'universo del software ne è pieno, ma ne faremo una "nostra", usando Excel ed il suo vba. Questo esercizio, oltre a utilizzare Excel e quindi di poter personalizzare al massimo il programma, ognuno se la può realizzare in proprio come meglio crede, rende interessante il vedere come predisporre le opportune istruzioni, e le soluzioni adottate per esempio, per il controllo inserimento dati nelle TextBox della UserForm usata come marchera di introduzione e/o consultazione appuntamenti. Inoltre ci possono servire per familiarizzarci con qui benedetti tipi di dati:  Data e/o Orario.

Infatti uno dei problemini più ostici in vba, è rappresentato dal fatto, lavorando con date od orari,  del riconoscimento del "tipo di dato" inserito in una TextBox, e non scordiamoci che impostando un'agenda appuntamenti, questi sono sempre rappresentati da date e da orari. Inoltre se nella scittura di un orario non rispettiamo una certa sintassi (le ore devono essere separate dai minuti da un punto e NON una virgola, e bisogna sempre scrivere sia l'ora sia i minuti, anche se l'ora è intera: le ore 9 vanno scritte 09.00 o anche 9.00, e NON 9 e basta)) Excel poi si lamenta o fornisce registrazioni sballate.

Vediamo intanto l'impostazione possibile di una tabella campione; i dati inseriti sono di pura fantasia:

  • La colonna A è formattata a Data 14/03/01.

  • Lacolonna B è formattata ad Ora  13.30 (ricordo comunque che questo  formato scelto ci fa vedere solo ore e minuti, ma Excel registra e vede anche i secondi; infatti le 13.30  saranno in effetti viste (da Excel e dal vba) come 13.30.00).

  • La colonna C è lasciata a formato Generale (ma potrà essere "Testo") e serve alla descrizione dell'appuntamento.

  • il CommandButton (ActiveX) sul foglio serve a chiamare la UserForm.

E sotto vediamo la UserForm, che contiene tutte le routine; la freccia rossa indica un "controllo" necessario al progetto: il MonthView. Questo "controllo" è un controllo .ocx e serve per scorrere i mesi (i due pulsantini nella parte superiore) e all'interno del mese scelto, selezionare il giorno di cui vogliamo prendere la data. Il controllo si inserisce dalla "casella degli strumenti" nell'editor di visual basic, cliccandoci sopra col destro del mouse, e scegliendo "Controlli Aggiuntivi": nella finestra dei "Controlli aggiuntivi" bisognerà mettere un segno di spunta al controllo "Microsoft MontView Control 6.0" corrispondente al file MSCOMCT2.OCX contenuto nella cartella C:\Windows\System32 .

Se qualcuno fosse sprovvisto di questo file, necessario al progetto, può qui scaricarlo e poi decomprimerlo nella cartella indicata. File MSCOMCT2.zip 332 Kb

Di questo controllo useremo la proprietà Value per identificare la data corrispondente al giorno che avremo selezionato nel controllo stesso, e sfruttando il suo evento DateClick, traseriremo la data nella TextBox1, così:

  • Private Sub MonthView1_DateClick(ByVal DateClicked As Date)
    TextBox1 = MonthView1.Value

Sfruttiamo quindi l'azione che compiamo cliccando su un giorno, nel MonthView, per ottenere nella TextBox1  la data scelta, e a seguire, inseriamo le istruzioni che cercheranno nella colonna A del database, a partire dalla quinda riga, tutte le date che corrisponderanno a quella che sarà nella TextBox1, caricando per ogni data trovata, nella ListBox1 l'orario di ogni data trovata e il relativo appuntamento. Useremo per cercare le date un Ciclo For Each Next, che trovando una cella corrispondente alla data selezionata, e caricheranno con Offset i dati contenuti nelle due celle a sinistra. Al termine del ciclo, facciamo avvisare con un messaggio: se saranno state trovate date, le contiamo usando un contatore (una variabile che si incrementa di una unità ad ogni ciclo) e ne forniamo il numero, altrimenti avvisiamo che non esistono date. Vediamo un esempio: clicchiamo sulla data 11 (gennaio 2004) (evidenziata in grigio), la vediamo nella TextBox1, e nelle due ListBox vengono caricati con AddItem, i dati correlati alle date trovate, e il messaggio di avviso.

Poichè queste istruzioni si attivano ad ogni click sul MonthView, cambiando giorno, abbiamo bisogno di "vuotare" le due ListBox dei dati che contengono, per predisporle a ricevere i dati che la nuova ricerca reperirà. Per "vuotare" le ListBox usiamo il metodo RemoveItem. Per non creare una routine molto lunga, anzichè inserire le istruzione di "vuotatura" ad inizio della routine Private Sub MonthView1_DateClick(ByVal DateClicked As Date) usiamo un'altro evento collegato: l'evento Change della TextBox1, attivato appunto dalla prima istruzione dell'evento DateClick, la TextBox1 = MonthView1.Value

Poi vedremo le routines, ma continuiamo l'analisi dei procedimenti. Come ogni Agenda che si rispetti, dobbiamo prevedere la possibilità di inserire nuovi appuntamenti, per questo ci affideremo all'unico CommandButton presente sulla UserForm, di cui sfrutteremo l'evento Click per eseguire delle istruzioni.

Abbiamo bisogno, per l'inserimento di nuovi appuntamenti, di scrivere una data, e ce l'abbiamo cliccando sul MonthView, poi dovremo scrivere l'orario nella TextBox2, e quindi il motivo dell'appuntamento nella TextBox3. Per evitare dimenticanze per la data e per l'orario, useremo delle istruzioni che controllino che le TextBox contengano dati, ma dovremo controllare anche che l'orario sia scritto con la giusta sintassi (tipo 09.30), e che l'orario sia scritto usando il punto come separatore, e non la virgola: per quest'ultimo controllo, sfrutteremo l'evento Change della TextBox2, così la verifica avviene mentre stiamo scrivendo; verremo fermati e costretti a digitare la correzione. Per il controllo della sintassi invece sfrutteremo il Click del Commandbutton..

Dobbiamo però compiere un ulteriore controllo prima che avvenga la registrazione sul foglio: dobbiamo controllare che non esista già un appuntamento allo stesso giorno e alla stessa ora. Sfrutteremo per questo un ciclo che legga prima tutte le date esistenti uguali alla data scelta, e per ogni data controlliamo se esiste già un orario uguale: se esiste, usciamo dalla routine e avvisiamo con un messaggio, altrimenti usiamo un ciclo While che reperisca la prima riga libera e lì incolli i dati.

Abbiamo quasi finito: manca ancora un'ultima cosa; un ordinamento basato prima sulle ore, e a seguire sui giorni: questo ci consente di avere le date ordinate per data e gli orari ordinati per ora. Non possiamo agire viceversa in quanto l'ultimo ordinamento è determinante, e farlo per ultimo sulle date ordinerebbe queste, ma non gli orari..

Vediamo ora le routine:

  • routine connessa al click nel MonthView

Private Sub MonthView1_DateClick(ByVal DateClicked As Date)
TextBox1 = MonthView1.Value

data = CDate(TextBox1)
Dim CL As Object
riga = Sheets(1).Range([A5], [A5].End(xlDown)).Rows.Count
Set zona = Sheets(1).Range(Cells(5, 1), Cells(riga + 4, 1))
For Each CL In zona
If CL = data Then
W = CDate(CL.Offset(0, 1).Value)
ListBox1.AddItem W
ListBox2.AddItem CL.Offset(0, 2).Value
i = i + 1 
'la variabile "i" è il contatore
End If
Next
If i > 0 Then
MsgBox "Sono Presenti " & i & " Appuntamenti"
Else
MsgBox "Nessun Appuntamento per questa data"
End If

End Sub

  • routine per cancellare il contenuto delle due ListBox  attivata da un Cambio della TextBox1 (quella delle date). (in realtà per "pulire" una ListBox è sufficiente una sola riga di istruzione, questa ad esempio: ListBox1.Clear - i due cicli li ho inseriti solo per far abituare il lettore all'impiego di cicli)

Private Sub TextBox1_Change()
n = ListBox1.ListCount - 1
If n >= 1 Then
For Z = n To 0 Step -1
ListBox1.RemoveItem Z
Next
End If
n = ListBox2.ListCount - 1
If n >= 1 Then
For Z = n To 0 Step -1
ListBox2.RemoveItem Z
Next
End If
End Sub

  • routine per il controllo inserimento nella TextBox2 : intercetta se scriviamo una virgola anzichè il punto, ed evidenzia l'orario scritto errato; si attiva ad ogni digitazione nella TextBox2 (appunto: ad ogni cambio di stato)

Private Sub TextBox2_Change()
virg = ","
cosa = TextBox2.Text
x = InStr(cosa, virg)
If x > 0 Then
MsgBox "Orario non corretto. Scritto con virgola anzichè punto"
Cancel = True
With TextBox2
.SelStart = 0
.SelLength = Len(TextBox2.Text)
End With
End If
End Sub

  • routine connessa alla pressione sul CommandButton, che attiva il secondo tipo di controllo sull'orario, contando la lunghezza dei caratteri immessi, poi  i controlli che le textbox non siano vuote, indi il ciclo per controllare che data e ora siano disponibili, in caso si possa registrare, inizia il ciclo della ricerca della prima cella libera nella colonna A, e qui incolla i dati delle TextBox:

Private Sub CommandButton1_Click()
On Error Resume Next
'------- si controlla che l'orario sia scritto con un punto, se assente usciamo dalla routine
punt = "."
cosa = TextBox2.Text
Y = InStr(cosa, punt)
If Y = 0 Then
MsgBox "Orario non corretto. Scritto senza il punto"
TextBox2.SetFocus
With TextBox2
.SelStart = 0
.SelLength = Len(TextBox2.Text)
End With
Exit Sub
End If
'-------si controlla che l'orario sia scritto 09.30  oppure 9.30 (con la lunghezza)
lunghezza = Len(TextBox2)
If lunghezza < 4 Or lunghezza > 5 Then
MsgBox "Orario scritto errato." & vbLf _
& "Usare la forma: 09.30"
TextBox2.SetFocus
With TextBox2
.SelStart = 0
.SelLength = Len(TextBox2.Text)
End With
Exit Sub
End If
'-----------si controlla che le TextBox contengano dati
If TextBox1 = "" Then
MsgBox "Devi scegliere la data"
Exit Sub
End If


If TextBox2 = "" Then
MsgBox "Devi scrivere l'orario"
Exit Sub
End If

'----------dichiarazione di variabili come tipo di dati Data/Orario
data = CDate(TextBox1)
ora = CDate(TextBox2)
'-----------ciclo per la ricerca di appuntamento se già esistente
Dim CL As Object
riga = Sheets(1).Range([A5], [A5].End(xlDown)).Rows.Count
Set zona = Sheets(1).Range(Cells(5, 1), Cells(riga + 4, 1))
For Each CL In zona
miotime = CDate(CL.Offset(0, 1).Value)
If CL = data And TimeValue(miotime) = ora Then
MsgBox "Esiste già un appuntamento fissato"
Exit Sub
End If
Next

'--------ciclo che cerca la prima riga libera partendo dalla riga 5
Dim iRow As Integer
iRow = 5
While Cells(iRow, 1) <> ""
iRow = iRow + 1
Wend
Cells(iRow, 1) = data
Cells(iRow, 2) = ora
Cells(iRow, 3) = TextBox3.Value
'----------istruzioni per l'ordinamento dati
Set ordina = Sheets(1).Range(Cells(5, 1), Cells(riga + 4, 3))

ordina.Sort Key1:=Range("B4"), Order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom

ordina.Sort Key1:=Range("A4"), Order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom

Resume
End Sub

Le routine non le commento, trattandosi di routine già ampliamente usate e commentate in altri articoli sui nostri siti.

File scaricabile e consultabile  :    Appuntamenti.zip   15 Kb

Buon lvoro.

prelevato sul sito www.ennius.altervista.org