La prima routine chiamata nel modulo relativo alla formattazione del foglio si chiama
scriviIntestazioni e serve per ottenere queste prime righe del foglio:
Da notare, però, che il nome del mese non viene aggiunto ancora, perché se ne occuperà la routine successiva per l'aggiunta delle date.
Il codice è questo:
Private Sub scriviIntestazioni()
'ALTEZZA GENERALE DELLE RIGHE
Cells.Select
Selection.RowHeight = 12
'AGGIUNTA DELL'INTESTAZIONE RIGA 1
Range(Cells(Riga, Colonna), Cells(Riga, Colonna + 3)).Select
Selection.Merge
Selection.RowHeight = 17
Selection.VerticalAlignment = xlCenter
Selection.HorizontalAlignment = xlCenter
Selection.Font.Bold = True
Selection.FormulaR1C1 = "GUARDIA MEDICA AREA FUNZIONALE OMOGENEA"
Riga = Riga + 1
'AGGIUNTA DELL'INTESTAZIONE RIGA 2
Range(Cells(Riga, Colonna), Cells(Riga, Colonna + 3)).Select
Selection.Merge
Selection.RowHeight = 17
Selection.VerticalAlignment = xlCenter
Selection.HorizontalAlignment = xlCenter
Selection.Font.Bold = True
Selection.FormulaR1C1 = "MEDICINA-CARDIOLOGIA"
Selection.Font.ColorIndex = 48
Riga = Riga + 1
'SCRIVE LE PRIME 2 RIGHE DELLA TABELLA
Columns(Colonna).HorizontalAlignment = xlLeft
With Cells(Riga, Colonna)
.FormulaR1C1 = "DATA"
.ColumnWidth = 10
.HorizontalAlignment = xlCenter
End With
With Cells(Riga, Colonna + 1)
.FormulaR1C1 = "Nominativo turno"
.ColumnWidth = 30
.HorizontalAlignment = xlCenter
End With
With Cells(Riga, Colonna + 2)
.FormulaR1C1 = "Unità Operativa"
.ColumnWidth = 20
.HorizontalAlignment = xlCenter
End With
With Cells(Riga, Colonna + 3)
.FormulaR1C1 = "Nominativo turno"
.ColumnWidth = 30
.HorizontalAlignment = xlCenter
End With
Riga = Riga + 1
With Cells(Riga, Colonna + 1)
.FormulaR1C1 = "08.00 - 20.00"
.ColumnWidth = 30
.HorizontalAlignment = xlCenter
End With
With Cells(Riga, Colonna + 2)
.FormulaR1C1 = ""
.ColumnWidth = 20
.HorizontalAlignment = xlCenter
End With
With Cells(Riga, Colonna + 3)
.FormulaR1C1 = "20.00 - 8.00"
.ColumnWidth = 30
.HorizontalAlignment = xlCenter
End With
Riga = Riga + 1
End Sub
...tutto lavoro bruto e ripetitivo, niente di particolare da commentare, ad eccezione del fatto che la variabile
Riga aumenta ogni volta che il programma passa a sistemare la riga successiva.
La variabile è definita a livello di modulo, così sarà lasciata, per le routines successive, già modificata da questa routine.
La seconda routine si chiama
aggiuntaDate, e serve ad aggiungere le date per creare il calendario del mese.
E' ovvio che si serve delle variabili locali
Mese e
Anno che sono state eguagliate ai valori passati come parametri dalla routine che aggiungeva il foglio, nella quale è stata calcolata la data.
Private Sub aggiuntaDate()
'stabiliamo la data del mese
Dim Dat As Date, primaData As Date
Dat = CDate("01/" & Mese & "/" & Anno)
With Cells(Riga - 1, Colonna)
.FormulaR1C1 = MonthName(Mese)
.Font.Bold = True
End With
Do While Month(Dat) = Mese
With Cells(Riga, Colonna)
.FormulaR1C1 = Day(Dat)
If WeekdayName(Weekday(Dat, vbUseSystemDayOfWeek)) = "domenica" Then .FormulaR1C1 = .FormulaR1C1 & " D"
.Font.Bold = True
End With
Dat = Dat + 1
Riga = Riga + 1
Loop
End Sub
Dichiara una variabile locale
Dat di tipo Date, e un'altra chiamata
primaData, sempre di tipo Date.
Ricostruisce la data del primo giorno del mese successivo dai valori di mese e anno, e la pone nella variabile
Dat.
Ora, credo di aver fatto un lavoro un po' cervellotico: innanzitutto la variabile
primaData deve essere uno di quei residui di un qualche procedimento cui avevo pensato prima, in quanto mi sembra completamente inutilizzata in tutta la routine.
Provo a eliminarla...
Private Sub aggiuntaDate()
'stabiliamo la data del mese
Dim Dat As Date
Dat = CDate("01/" & Mese & "/" & Anno)
...
...e come avevo capito già, funziona ugualmente!
Ma adesso mi viene in mente un'altra cosa: anziché passare, quando chiamo la prima routine del modulo, mese e anno, non potrei passare come un unico parametro direttamente la data del mese successivo?
Provo a ingegnarmi in tal senso...
No, non è che poi il codice si semplifichi più di tanto, sta bene così...
With Cells(Riga - 1, Colonna)
.FormulaR1C1 = MonthName(Mese)
.Font.Bold = True
End With
La riga del foglio su cui ci troviamo, indicata dalla variabile di modulo
Riga, avanzata dalla routine precedente, è la quinta.
Ma dobbiamo posizionare il nome del mese su una cella della quarta riga, per cui riduciamo momentaneamente il valore di Riga per posizionare il nome del mese al posto dovuto.
Quindi...
Do While Month(Dat) = Mese
With Cells(Riga, Colonna)
.FormulaR1C1 = Day(Dat)
If WeekdayName(Weekday(Dat, vbUseSystemDayOfWeek)) = "domenica" Then .FormulaR1C1 = .FormulaR1C1 & " D"
.Font.Bold = True
End With
Dat = Dat + 1
Riga = Riga + 1
Loop
Finché il mese della data è uguale al nome del mese che abbiamo memorizzato nella variabile
Mese, scriviamo il numero del giorno (Day(Dat)) nella prima colonna.
La riga:
If WeekdayName(Weekday(Dat, vbUseSystemDayOfWeek)) = "domenica" Then .FormulaR1C1 = .FormulaR1C1 & " D"
serve a ad aggiungere la D nel caso in cui il giorno sia domenica (come da modello datomi).
A ogni aggiunta di giorno si aumenta di un giorno la data, e il numero di riga, in modo che aumentando ogni riga aumenti il giorno del mese, fin quando, come specificato sopra, il mese non cambi (month(Dat = Mese) rispetto a quello memorizzato nella variabile.
A questo punto, il processo finisce.
La routine successiva si chiama
creazioneGriglia
Private Sub creazioneGriglia()
'CREAZIONE DELLA GRIGLIA COI BORDI
Range(Cells(primaRiga + 2, primaColonna), Cells(Riga, primaColonna + 3)).Select
Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
With Selection.Borders(xlEdgeLeft)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideVertical)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideHorizontal)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
End Sub
Qui è successo
qualcosa di singolare: analizziamo le prime righe:
Private Sub creazioneGriglia()
'CREAZIONE DELLA GRIGLIA COI BORDI
Range(Cells(primaRiga + 2, primaColonna), Cells(Riga, primaColonna + 3)).Select
...
Ecco, qui ho delle variabili che ho eliminato, ossia
primaRiga e
primaColonna.
Mancando queste, mi si genera un errore, che però non appariva, ma semplicemente il programma non mi caricava il foglio col calendario del mese.
Perché?
Eseguendo passo-passo con F8 il programma, ho visto che da questa riga il flusso del programma passava direttamente alla routine
aggiungiFoglio nella sezione di gestione dell'errore che elimina il foglio:
X: 'gestione dell'errore di tentata rinominazione del foglio: elimina il foglio senza suscitare avvisi di eliminazione.
Application.DisplayAlerts = False
ActiveSheet.Delete
Application.DisplayAlerts = True
End Sub
eliminandomi il foglio.
Questo perché, essendo tutte queste routines chiamate dalla routine
aggiungiFoglio, sono soggette tutte alla clausola
On Error GoTo X, e quindi l'errore non mi appariva ma veniva gestito da quella istruzione con eliminazione del foglio.
La griglia deve essere creata nel Range che va dalla cella che sta alla terza riga e prima colonna, per terminare in basso a destra con la cella che sta all'ultima riga e quarta colonna.
Ecco quindi che, per ovviare all'inconveniente di prima, trasformo così il codice:
Range(Cells(3, 1), Cells(Riga, 4)).Select
eliminando i nomi delle variabili che non esistono più.
Il resto:
Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
With Selection.Borders(xlEdgeLeft)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideVertical)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideHorizontal)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
è tutto lavoro bruto di creazione delle linee, copiato pedissequamente dalle macro generate automaticamente, su cui non bisogna fare un granché di lavoro intellettuale.
Unica cosa notevole, che il valore di Riga, essendo stato aumentato a uno più della cella con l'ultimo giorno, è stato lasciato così, creando uno spazio vuoto sotto l'ultimo giorno, semplicemente per rispettare la similitudine con il foglio originale che mi è stato consegnato come modello.
Andiamo alla scritta di coda con la routine
scrittaDiCoda
Private Sub scrittaDiCoda()
Riga = Riga + 2
Range(Cells(Riga, primaColonna), Cells(Riga, primaColonna + 3)).Select
Selection.Merge
Selection.RowHeight = 35
Selection.VerticalAlignment = xlTop
Selection.WrapText = True
Selection.FormulaR1C1 = "N.B. Gli eventuali cambi turno di Guardia Medica AFO devono essere comunicati, ai fini di riscontro, alla scrivente Direzione Sanitaria, sig.ra XXXXX XXXXXX, 38XXX fax 38XXX"
Cells(1, 5).Select
End Sub
Aumento di 2 il numero della riga corrente e mi ritrovo ancora una di quelle variabili fantasma, primaColonna, che serve per delimitare le caselle da fondere insieme per ospitare la scritta.
E infatti ottengo ancora l'eliminazione spontanea del foglio sempre per quel gioco di gestione dell'errore.
La sostituisco:
Private Sub scrittaDiCoda()
Riga = Riga + 2
Range(Cells(Riga, 1), Cells(Riga, 4)).Select
Selection.Merge
Selection.RowHeight = 35
Selection.VerticalAlignment = xlTop
Selection.WrapText = True
Selection.FormulaR1C1 = "N.B. Gli eventuali cambi turno di Guardia Medica AFO devono essere comunicati, ai fini di riscontro, alla scrivente Direzione Sanitaria, sig.ra XXXXX XXXXX, 38XXX fax 38XXX"
Cells(1, 5).Select
End Sub
Anche qui, come è successo prima, la prima volta che provo con le variabili sostituite il codice sembra funzionare, ma al secondo tentativo ritorna a mostrare l'eliminazione spontanea del foglio.
Stavolta è dovuto al fatto che le variabili appaiono ancora più sotto nel codice.
Questo non me lo so spiegare.
Bene, adesso c'è la routine
copiaMenu, che fa qualcosa di
completamente nuovo: copia la lista dei medici di guardia che ho su un foglio che, con l'intenzione di renderlo invisibile, ho chiamato
Nascosto:
Sub copiaMenu()
Dim k As Integer
k = primaRiga
Do While Sheets("Nascosto").Cells(k, primaColonna) <> ""
ActiveSheet.Cells(k - primaRiga + scartoMenu + 1, primaColonna + 5).FormulaR1C1 = _
Sheets("Nascosto").Cells(k, primaColonna).FormulaR1C1
ActiveSheet.Cells(k - primaRiga + scartoMenu + 1, primaColonna + 6).FormulaR1C1 = _
Sheets("Nascosto").Cells(k, primaColonna + 1).FormulaR1C1
k = k + 1
Loop
With ActiveSheet
With .Cells(primaRiga + scartoMenu - 1, primaColonna + 5)
.Interior.ColorIndex = 6
.FormulaR1C1 = "NOME"
.HorizontalAlignment = xlCenter
End With
With .Cells(primaRiga + scartoMenu - 1, primaColonna + 7)
.Interior.ColorIndex = 8
.FormulaR1C1 = "GIORNO"
End With
With .Cells(primaRiga + scartoMenu - 1, primaColonna + 8)
.Interior.ColorIndex = 5
.Font.ColorIndex = 2
.FormulaR1C1 = "NOTTE"
End With
.Columns(6).ColumnWidth = 26
With .Columns(7)
.ColumnWidth = 6
.HorizontalAlignment = xlCenter
.Font.Bold = True
End With
With .Columns(8)
.ColumnWidth = 6
.HorizontalAlignment = xlCenter
.Font.Bold = True
End With
End With
End Sub
Questa è una
selva di nomi delle variabili che ho eliminato!
Non so nemmeno se le ho evidenziate tutte in rosso, perché sono ripetute troppe volte.
Sostituiamole...
Sub copiaMenu()
Dim k As Integer
k = 1
Do While Sheets("Nascosto").Cells(k, 1) <> ""
ActiveSheet.Cells(k - 1 + scartoMenu + 1, 1 + 5).FormulaR1C1 = _
Sheets("Nascosto").Cells(k, 1).FormulaR1C1
ActiveSheet.Cells(k - 1 + scartoMenu + 1, 1 + 6).FormulaR1C1 = _
Sheets("Nascosto").Cells(k, 1 + 1).FormulaR1C1
k = k + 1
Loop
With ActiveSheet
With .Cells(1 + scartoMenu - 1, 1 + 5)
.Interior.ColorIndex = 6
.FormulaR1C1 = "NOME"
.HorizontalAlignment = xlCenter
End With
With .Cells(1 + scartoMenu - 1, 1 + 7)
.Interior.ColorIndex = 8
.FormulaR1C1 = "GIORNO"
End With
With .Cells(1 + scartoMenu - 1, 1 + 8)
.Interior.ColorIndex = 5
.Font.ColorIndex = 2
.FormulaR1C1 = "NOTTE"
End With
.Columns(6).ColumnWidth = 26
With .Columns(7)
.ColumnWidth = 6
.HorizontalAlignment = xlCenter
.Font.Bold = True
End With
With .Columns(8)
.ColumnWidth = 6
.HorizontalAlignment = xlCenter
.Font.Bold = True
End With
End With
End Sub
Mi sembra di averle sostituite tutte, ma il programma continua ad eliminare il foglio, e infatti appaiono ancora in un'altra routine...
Aggiusto meglio questa routine...
C'è anche una variabile che si chiama
scartoMenu, la quale l'ho creata sempre nell'ottica di una flessibilità nel posizionamento della tabella.
E' una variabile globale, definita nel modulo delle variabili globali:
Public Const scartoTabella = 4
Public Const scartoMenu = 3
Public Bersaglio As Range
Public Const Centralina = "Foglio1"
Che faccio, la elimino?
Vediamo di analizzare il codice...
Sub copiaMenu()
Dim k As Integer, z As Integer
k = 1
z = 4
Do While Sheets("Nascosto").Cells(k, 1) <> ""
ActiveSheet.Cells(z, 6).FormulaR1C1 = _
Sheets("Nascosto").Cells(k, 1).FormulaR1C1
ActiveSheet.Cells(z, 7).FormulaR1C1 = _
Sheets("Nascosto").Cells(k, 2).FormulaR1C1
k = k + 1
z = z + 1
Loop
With ActiveSheet
With .Cells(3, 6)
.Interior.ColorIndex = 6
.FormulaR1C1 = "NOME"
.HorizontalAlignment = xlCenter
End With
With .Cells(3, 8)
.Interior.ColorIndex = 8
.FormulaR1C1 = "GIORNO"
End With
With .Cells(3, 9)
.Interior.ColorIndex = 5
.Font.ColorIndex = 2
.FormulaR1C1 = "NOTTE"
End With
.Columns(6).ColumnWidth = 26
With .Columns(7)
.ColumnWidth = 6
.HorizontalAlignment = xlCenter
.Font.Bold = True
End With
With .Columns(8)
.ColumnWidth = 6
.HorizontalAlignment = xlCenter
.Font.Bold = True
End With
End With
End Sub
L'ho
riscritta completamente perché era scritta con un codice incredibilmente cervellotico, sempre con l'intenzione di posizionare dinamicamente la tabella, cosa del tutto inutile.
Ho eliminato la variabile globale
scartoMenu, che non serve più.
E funziona egregiamente!
Però avendo appreso una nuova funzionalità di Excel, ossia la possibilità di dare un nome ai ranges, ho ancora dei miglioramenti da fare per eliminare quel codice tipo
ActiveSheet.Cells(z, 6).FormulaR1C1 = _
Sheets("Nascosto").Cells(k, 1).FormulaR1C1
ActiveSheet.Cells(z, 7).FormulaR1C1 = _
Sheets("Nascosto").Cells(k, 2).FormulaR1C1
che facilmente può risultare confusivo.
Ma questo lo vedrò in seguito.
C'è poi la routine
scorri, che serve per presentare il foglio all'operatore avendo sotto gli occhi tutti i giorni del mese, in modo da poter seguire le modifiche dei turni sull'elenco dei medici.
Sub scorri()
ActiveWindow.SmallScroll Down:=2
End Sub
...copiata dalle Macro automatiche, regolando a 2 il numero di riga al quale far scorrere il foglio.
Nessun ragionamento particolarmente intelligente da fare.
L'ultima routine del modulo formattazioneFoglio è
impostazioniStampa, che serve per preparare le giuste dimensioni del foglio per la stampa.
Private Sub impostazioniStampa()
'IMPOSTAZIONI PER LA STAMPA
With ActiveSheet.PageSetup
.LeftMargin = Application.InchesToPoints(0.5)
.RightMargin = Application.InchesToPoints(0)
.PrintArea = "$A$" & primaRiga & ":$D$44"
End With
End Sub
E qui ho copiato ampiamente dalle Macro automatiche, ma mi salta all'occhio che c'è ancora la fantomatica variabile
primaRiga.
La eliminiamo:
Private Sub impostazioniStampa()
'IMPOSTAZIONI PER LA STAMPA
With ActiveSheet.PageSetup
.LeftMargin = Application.InchesToPoints(0.5)
.RightMargin = Application.InchesToPoints(0)
.PrintArea = "$A$" & 1 & ":$D$44"
End With
End Sub
Bene: andiamo a provare il tutto, compresa l'anteprima di stampa per saggiare questa ultima routine.
Tutto OK! (che faticaccia!)