Un problema sulle date

 

Il problema

Non è raro, trattando le date in VBA, trovarci in difficoltà. Alle volte sembrano impazzite. Quando tentiamo di scrivere qualche data prelevandola da fonti esterne quali potrebbero essere una combobox, un file esterno, ecc tendono ad invertire il mese col giorno.

Una data del tipo:

01/05/2006 tende a diventare 05/01/2006

La data:

13/01/1967 invece, sembra non dare problemi13/01/1947

 

Preparazione del test

Per eseguire questo test andiamo in ambiente vba e, inserita una userform , la costruiamo simile a questa.

Ma per inserire il modulo della UserForm facciamo clic destro nella finestra VBAProject e scegliamo Inserisci / UserForm come indicato in questa immagine.

Se vogliamo, disegnamo sul foglio di lavoro anche un pulsante che possiamo prendere dalla barra degli strumenti Modulo e che servirà per richiamare la UserForm con cui lavorare

Questa che segue è una rappresentazione del foglio che ho preparato:

  A B C
1 date da date scritte date scritte
2 trasferire semplicemente usando la funzione
3 in userform userform CDate
4 12/01/1947    
5 01/05/2006    
6 13/01/1947    
7 08/09/2005    
8 04/05/1985    
9 10/02/2005    

 

Nella prima colonna ho scritto alcune date che leggerò con la UserForm

Nella seconda e terza colonna scriveremo le date prendendole dalla UserForm usando due metodi diversi che tra poco vi mostrerò.

Per comodità disegnamo un pulsante sul foglio. Questo pulsante lo possiamo prendere:

Nel primo caso e nell'ultimo caso, dobbiamo preparare un modulo standard. Per inserire il modulo standard ci comportiamo come per l'inserimento del modulo della UserForm, scegliendo dal menù a tendina la voce Modulo.

In questo modulo standard scriviamo questo codice per avviare la nostra UserForm

Sub Avvia()
UserForm1.Show
End Sub

Fatto questo ritorniamo sul foglio di lavoro ed assegnamo la macro al nostro pulsante. Per fare questo:

clic destro sull'oggetto e dal menù a tendina scegliamo Assegna Macro che fa comparire questa finestra di dialogo

Se, invece abbiamo optato per un pulsante prelevato dalla barra degli strumenti Strumenti di controllo, una volta disegnato questo pulsante vi facciamo su un doppio clic per essere trasportati nel modulo relativo al foglio di lavoro su cui sta il pulsante con questa routine iniziata:

Private Sub CommandButton1_Click()

 

End Sub

nella quale basta aggiungere la istruzione:

UserForm1.Show

Ora siamo pronti a preparare il nostro primo test.

Ci rechiamo nel modulo della UserForm. Per brevità facciamo doppio clic sulla userform e ci troviamo nel modulo della UserForm con:

Private Sub UserForm_Click()

End Sub

Questo evento non ci serve. Allora andiamo nella casella Routine e scegliamo Initialize (potremmo scegliere anche Attivate) per vedere questa nuova routine pronta per ricevere il nostro codice:

Private Sub UserForm_Initialize()

End Sub

In questa routine di evento iniziamo a scrivere il nostro codice.

Con questo codice spazzoliamo l'intervallo che va dalla riga 4 alla riga 9 della prima colonna ed aggiungiamo nella ComboBox quel che troviamo in querste celle.

Private Sub UserForm_Initialize()
Dim A
For A = 4 To 9
ComboBox1.AddItem Cells(A, 1)
Next
End Sub

Fatto questo torniamo sulla UserForm e facciamo doppio clic sul pulsante Chiudi. Ci ritroviamo la routine così iniziata:

Private Sub CommandButton1_Click()

End Sub

Qui scriviamo un paio di istruzioni che servono per chiudere la UserForm e scaricarla dalla memoria:

Private Sub CommandButton1_Click()
Unload UserForm1
Set UserForm1 = nothimg
End Sub

Il test

Ora è arrivato il momento di affrontare il nostro problema e di scrivere del codice per trasferire sul foglio di lavoro la data che scegliamo dalla ComboBox. Questa azione verrà determinata dal pulsante OK della nostra UserForm.

Come il solito iniziamo col fare doppio clic su questo pulsante per trovarci nel modulo con questa routine già pronta per accogliere il nostro codice.

Private Sub CommandButton2_Click()

End Sub

Il codice che andremo a scrivere, dopo aver controllato che la combobox contenga un dato significativo (se la ListIndex è uguale a -1, o la lista è vuota o non è stata effettuata alcuna scelta) va a scrivere nella prima cella libera della colonna D il contenuto della combobox.

Questa cella vuota viene reperita, in questo caso, con: Range("D1").End(xlDown).Offset(1, 0)

Fatto questo la ListIndex della ComboBox viene riportata a -1 per cancellare il dato appena scelto.

Private Sub CommandButton2_Click()
If ComboBox1.ListIndex = -1 Then Exit Sub
Range("D1").End(xlDown).Offset(1, 0) = ComboBox1.Text
ComboBox1.ListIndex = -1
End Sub

Come si vede da questa immagine, nellaComboBox vengono caricate correttamente tutte le date raccorlte dal foglio.

Per vedere che cosa è stato scritto nel foglio di Excel potete cliccare su questa miniatura:

I risultati scritti nella seconda colonna sono catastrofici. Tutte le date mostrano invertiti i giorni coi mesi eccetto la data 13/01/1947. Non sto a dilungarmi su come possa verificarsi questa situazione, ma una cosa è certa. Occorre porvi rimedio.

Proviamo col formattare la cella prima di scrivere la data:

Range("D1").End(xlDown).Offset(1, 0).NumberFormat = "d/mm/yyyy;@"
Range("D1").End(xlDown).Offset(1, 0) = ComboBox1.Text

Ma nemmeno questo risolve il problema.

Alla fine, dopo tante peripezie che non sto qui ad enumerare, giungo a questa conclusione: invece di leggere semplicemente il dato mostrato dalla ComboBox la leggo usando la funzione CDate in questo modo:

CDate(ComboBox1.Text)

Questo trasforma il valore letto dalla ComboBox, che è sicuramente in formato stringa, in formato Date.

A questo proposito vi posso rimandare alla guida in linea dove si parla di conversione del tipo. Ma se volete in anteprima un elenco delle funzioni usate per la conversione dei dati lo vedrete qui

Allora provo con questa istruzione:

Range("G1").End(xlDown).Offset(1, 0) = CDate(ComboBox1.Text)

e trasformo di conseguenza la routine come mostrato qui di seguito:

Private Sub CommandButton2_Click()
If ComboBox1.ListIndex = -1 Then Exit Sub
Range("G1").End(xlDown).Offset(1, 0) = CDate(ComboBox1.Text)
ComboBox1.ListIndex = -1
End Sub

Mentre osservate questa finestra è possibile scorrere la pagina sottostante per confrontare i commenti con la tabella qui visualizzata.

Nella finestra che avrete aperta, noterete che nella terza colonna le date scritte dalla UserForm, corrisponderanno a quelle lette precedentemente e residenti nella colonna di sinistra.

 

 

 

 

Inserisci UserForm
La UserForm per il test
Inserisci Modulo Standard
La UserForm per il test
la userform
la userform
Scrittura del codice nel Modulo Standard
modulo standard
scelta dell'evento Inizialize
Scelta dell'evento
le date raccolte nella combobox
le date nella combobox
le date scritte in modo errato

la tabella con le date errate

  A B C
1 date da date scritte date scritte
2 trasferire semplicemente usando la funzione
3 in userform userform CDate
4 12/01/1947 01/12/1947  
5 01/05/2006 05/01/2006  
6 13/01/1947 13/01/1947  
7 08/09/2005 09/08/2005  
8 04/05/1985 05/04/1985  
9 10/02/2005 02/10/2005  
le funzioni descritte nella guida

Ciascuna funzione converte un'espressione in un tipo di dati specifico.

Sintassi

CBool(espressione)

CByte(espressione)

CCur(espressione)

CDate(espressione)

CDbl(espressione)

CDec(espressione)

CInt(espressione)

CLng(espressione)

CSng(espressione)

CStr(espressione)

CVar(espressione)

L'argomento obbligatorio espressione può essere una qualsiasi espressione stringa o espressione numerica.


Osservazioni

Se l'espressione passata alla funzione non è compresa nell'intervallo del tipo di dati in cui si sta eseguendo la conversione, verrà generato un errore.

 

 

la tabella con le date esatte

questa la tabella con le date corrette

  A B C
1 date da date scritte date scritte
2 trasferire semplicemente usando la funzione
3 in userform userform CDate
4 12/01/1947 01/12/1947 12/01/1947
5 01/05/2006 05/01/2006 01/05/2006
6 13/01/1947 13/01/1947 13/01/1947
7 08/09/2005 09/08/2005 08/09/2005
8 04/05/1985 05/04/1985 04/05/1985
9 10/02/2005 02/10/2005 10/02/2005
a
barra degli strumenti Moduli
a
barra degli strumenti Moduli
la finestra assegna macro
Assegna Macro