Calendario personalizzato direttamente su foglio
Hai un problema con Excel? 
Calendario personalizzato, direttamente su foglio
di Thyke data: 25/07/2016 17:17:14
Guarda il file che ho allegato, è una mia versione del calendario, non è ancora definitiva in quanto devo curare qualche dettaglio.
Il problema che ho si riassume in questo, ho utilizzato 51 label per la struttura del calendario incorporandole in un foglio, il problema è che i fogli non supportano l'insieme "Controls" e quindi mi tocca chiamarle una ad una per impostarne proprietà e valori...
dammi qualche suggerimento...
di patel data: 25/07/2016 18:31:07
Regolamento
3) Oggetto delle discussioni
Il titolo delle discussioni deve essere chiaro, sintetico, significativo e non generico.
I titoli devono solo dare l'idea dell'argomento che riguarda il problema e non devono contenere domande o parole inutili come "aiuto", "help", "urgente" o "domanda". Nell'apposito spazio si può specificare anche la versione dell'applicativo in uso.
Così facendo si può ottenere una risposta più immediata al problema e si migliora la rintracciabilità della discussione mediante il motore di ricerca.
I messaggi inviati al forum sono rivolti a tutti: non ci si rivolge a una singola persona in particolare, ma a una comunità di partecipanti.
di alfrimpa data: 25/07/2016 18:34:26
Ciao Thyke
In attesa dell'autorevole intervento di Vecchio Frac ti dico che ho sviluppato (per un altro forum) un calendario però su una userform.
Su questa userform ci sono combobox per i mm e anni e 31 togglebutton per i giorni.
La particolarità è che per i togglebutton ho utilizzato i moduli di classe il che mi ha evitato di scrivere tante macro quanti erano i togglebutton ma una sola valevole per tutti.
Ora sono in vacanza ma se ti interessa appena rientro ti allego il file.
Non so se questo file si può trasformare in un add-in (.xlam) in modo da renderlo disponibile sempre; magari su questo chiederemo aiuto a VF.
Complimenti per i tuoi interventi sul forum.
Alfredo
di Thyke data: 25/07/2016 18:43:43
@ patel
mi spiace, non ci ho proprio pensato a tutto quello che hai scritto...come si fa a cambiare il titolo?
di Thyke data: 25/07/2016 18:47:03
@ alfrimpa
in un primo momento avevo pensato anche io ad inserirlo in un form e se lo avessi fatto avrei sicuramente avuto meno problemi
però ho deciso poi di farlo incorporato in un foglio con l'intenzione poi di usarlo come modello per altri lavori...
di patel data: 25/07/2016 18:59:57
prova così
Sub trimlabel()
For Each lb In ActiveSheet.OLEObjects
If InStr(1, lb.Name, "Lab", vbTextCompare) > 0 Then
MsgBox lb.Name
End If
Next
End Sub |
di Vecchio Frac data: 25/07/2016 19:14:26
@Thyke
1) grazie per la fiducia
2) sarò contento di applicarmi
3) è una specie di test per me? :P
4) patel ha ragione nel richiamare il Regolamento (più che altro è utile ricordare che i titoli servono alle ricerche future e inoltre non sempre la persona cui ci si rivolge direttamente può/sa/vuole rispondere in tempi rapidi) ^_^
5) a modificare il titolo del thread ci penso io
di Thyke data: 25/07/2016 19:20:41
@ patel
sarei più interessato ad un ciclo che mi dia la caption delle label, altrimenti devo fare una sub per ognuna di loro
vorrei mettere in evidenza la label del giorno corrente, vorrei fargli segnare le festività compresa la pasqua (il codice per calcolarla l'ho già preparato)
come dicevo sopra l'insieme controls non è supportato dal foglio, ma solo dalle form, dai frame, dalle TabStrip e dal MultiPage...io sto cercando un metodo per modificare le propietà delle label con un ciclo
di Vecchio Frac data: 25/07/2016 19:22:37
Suggerimento: le Labels sul foglio sono Shapes di un certo Type.
Ora la moglie urla "a tavola"... ma magari dopo vedrò di essere meno criptico :)
di Thyke data: 25/07/2016 19:22:52
@ Vecchio Frac
tranquillo, non è un test, solo che con te ho già avuto qualche scambio di opinione, diciamo che sei quello con cui ho più confidenza.
Se qualche buon metodo mi viene da qualcun altro non è che mi faccia schifo...
di Thyke data: 25/07/2016 19:27:49
[cit]Suggerimento: le Labels sul foglio sono Shapes di un certo Type. [/cit]
dici? questa non la sapevo...io ho inserito nel foglio le label controlx...sei sicuro che sono Shapes?
di Vecchio Frac data: 25/07/2016 19:28:18
Al volo.
Sub test()
For Each sh In ActiveSheet.Shapes
If LCase(Left(sh.Name, 5)) = "label" Then
Debug.Print sh.Name, sh.Type
End If
Next
End Sub |
di Thyke data: 25/07/2016 19:45:24
ok...le rileva come shapes e mi dice il loro nome e questo me lo diceva anche il codice di patel...ma come faccio a modificargli la caption, il forecolor, il backcolor se quando gli passo il name in una variabile stringa mi genera un errore di Qualificatore non valido?
di Albatros54 data: 25/07/2016 19:48:45
cit..Se qualche buon metodo mi viene da qualcun altro non è che mi faccia schifo
Ho allegato il file, ho aggiunti nel foglio1 dei commandbutton, potresti sostituire le label con gli stessi, atttiva il foglio1 e click sui button, potrebbe essere una soluzione.
ho creato una classe1, che ti permette di non scrivere centinaia di righe di codice
Vedi codice sotto
In un modulo di classe:
Option Explicit
Public WithEvents cmd As CommandButton
Private Sub cmd_Click()
Dim ctl As Object
Dim fgl As Worksheet
Dim a As Integer
Set fgl = ThisWorkbook.Sheets("foglio1")
For Each ctl In fgl.OLEObjects
If TypeOf ctl.Object Is MSForms.CommandButton Then
ctl.Object.BackColor = &H80000005
End If
Next ctl
cmd.Object.BackColor = RGB(255, 0, 0)
End Sub
nel foglio1:
Private Sub Worksheet_Activate()
Dim ctl As Object
Dim fgl As Worksheet
Set fgl = ThisWorkbook.Sheets("foglio1")
Set colButton = New Collection
For Each ctl In fgl.OLEObjects
If TypeOf ctl.Object Is MSForms.CommandButton Then
Set clsButton = New Classe1
Set clsButton.cmd = ctl.Object
colButton.Add clsButton
End If
Next
ComboBox1.Clear
For a = 1 To 12
ComboBox1.AddItem Foglio3.Cells(a, 1)
Next
ComboBox2.Clear
For a = 2000 To 2099
ComboBox2.AddItem a
Next
Foglio1.ComboBox1.Value = Format(Now, "mmmm")
Foglio1.ComboBox2.Value = Format(Now, "YYYY")
Foglio1.Label1.Caption = ComboBox1.Value
Foglio1.Label2.Caption = ComboBox2.Value
End Sub |
di Thyke data: 25/07/2016 20:01:11
@ Albatros54
ho utilizzato le label al posto dei bottoni per un paio di motivi. il primo per una questione grafica, con quelle dimensioni il testo nei bottoni rimane spostato verso il basso, il secondo per via di un bug che mi ha colpito un paio di volte ed è il motivo per cui ho deciso di non inserire piu bottoni nelle pagine, piuttosto utilizzo delle shape a cui associo una macro
con i commandbutton mi è successo questo:
h t t p://stackoverflow.com/questions/28230436/excel-commandbutton-names-changing
di patel data: 26/07/2016 09:19:33
prova questa
Sub viewlabel()
For Each obj In ActiveSheet.OLEObjects
MsgBox obj.Object.Caption
Next
End Sub |
di Vecchio Frac data: 26/07/2016 10:27:33
Ecco proprio una cosa così, come dice patel (a Thyke interessa cambiare il colore dell'oggetto).
Il codice del tuo file è piuttosto farraginoso (e manca Option Explicit che consiglio di attivare).
'modifica il backcolor del pulsante n° 5 quello con caption "1" se il periodo è luglio 2016.
ActiveSheet.OLEObjects("label14").Object.BackColor = vbred |
di Vecchio Frac data: 26/07/2016 10:30:41
Poi, l'idea della Class Control collection di Albatros è quella più carina da percorrere (ho rinvenuto errori nel dichiarare WithEvents le Label al posto dei Command Button ma penso che si possa rimediare).
di Vecchio Frac data: 26/07/2016 10:41:40
Sarei curioso di sapere come utilizzeresti in pratica un calendario fatto in modo così statico.
Tu dici: "ho deciso poi di farlo incorporato in un foglio con l'intenzione poi di usarlo come modello per altri lavori". Ma non mi sembra molto flessibile.
Il codice poi è particolarmente pesante. Dovresti usare più spesso dei cicli For e giocare con i nomi degli oggetti (chiamandoli ad esempio "day01", "day02" eccetera per i nomi dei giorni in modo che poi li individui subito).
Comunque ho recuperato il mio calendario personalizzato (quello che uso in Access) e che è strutturato con delle label come il tuo. E' piuttosto compatto e il codice abbastanza snello. Se mi dici che sei interessato provo a adattarlo al tuo contesto (i.e., farlo funzionare su Excel).
di Vecchio Frac data: 26/07/2016 11:11:52
Senza voler insegnarti, ecco un esempio di come scriverei la routine di attivazione del foglio.
Come ti dicevo altrove, solo un po' più "VBA moderno" ^_^
Private Sub Worksheet_Activate()
Dim i As Integer, c1(1 To 12) As String, c2(0 To 99) As Integer
For i = 1 To 12
c1(i) = MonthName(i)
Next
ComboBox1.List = c1
For i = 2000 To 2099
c2(i - 2000) = i
Next
ComboBox2.List = c2
ComboBox1 = Format(Now, "mmmm")
ComboBox2 = Format(Now, "YYYY")
Label1.Caption = ComboBox1
Label2.Caption = ComboBox2
End Sub |
di Vecchio Frac data: 26/07/2016 11:26:44
Compattiamo ancora.
Ecco come risulta il codice per ognuna delle Labels che rappresentano i giorni del mese.
Nota che la proprietà Shadow è dell'oggetto OLE, non della sua rappresentazione As Object.
Private Sub Label14_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim i As Integer
If Label14.Caption <> "" Then
For i = 10 To 51
With OLEObjects("Label" & i)
.Object.ForeColor = vbBlack
.Object.BackColor = vbWhite
.Shadow = False
End With
Next
With Label14
.SpecialEffect = fmSpecialEffectSunken
.ForeColor = RGB(200, 0, 0)
.Shadow = True
End With
End If
End Sub |
di Vecchio Frac data: 26/07/2016 11:48:56
Allora Thyke, il trucco dell'array di controlli funziona bene anche con le Labels :)
Ringrazio Albatros per avermi dato lo spunto.
Tutto, e ripeto *tutto* il tuo codice si riduce a una manciata di righe visto che possiamo dire a Excel di simulare l'insieme Controls con nu array di controlli (e la creazione di una classe ad hoc).
Vedo se riesco a farti capire altrimenti allego il file.
Poi c'è da sistemare il codice del Modulo 1... :)
'codice di Foglio1
Option Explicit
Dim colLabel As Collection
Dim clsLabel As Classe1
Private Sub Worksheet_Activate()
Dim i As Integer, c1(1 To 12) As String, c2(0 To 99) As Integer
Dim ctl As Object
Set colLabel = New Collection
For Each ctl In ActiveSheet.OLEObjects
If TypeOf ctl.Object Is MSForms.Label Then
Set clsLabel = New Classe1
Set clsLabel.ctrl = ctl.Object
colLabel.Add clsLabel
End If
Next
For i = 1 To 12
c1(i) = MonthName(i)
Next
ComboBox1.List = c1
For i = 2000 To 2099
c2(i - 2000) = i
Next
ComboBox2.List = c2
ComboBox1 = Format(Now, "mmmm")
ComboBox2 = Format(Now, "YYYY")
Label1.Caption = ComboBox1
Label2.Caption = ComboBox2
End Sub
Private Sub ComboBox1_Click()
Label1.Caption = ComboBox1
Application.ScreenUpdating = False
Call calendario
Application.ScreenUpdating = True
End Sub
Private Sub ComboBox2_Click()
Label2.Caption = ComboBox2
Application.ScreenUpdating = False
Call calendario
Application.ScreenUpdating = True
End Sub
'-----------------------------------------------------------------------------------------
'codice del Modulo di classe: "Classe1"
'ovviamente sai come creare un modulo di classe :)
Option Explicit
Public WithEvents ctrl As MSForms.Label
Private Sub ctrl_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim i As Integer
If ctrl.Caption <> "" Then
For i = 10 To 51
With Sheets("Foglio1").OLEObjects("Label" & i)
.Object.ForeColor = vbBlack
.Object.BackColor = vbWhite
.Shadow = False
End With
Next
With ctrl
.SpecialEffect = fmSpecialEffectSunken
.ForeColor = RGB(200, 0, 0)
.Shadow = True
End With
End If
End Sub
Private Sub ctrl_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If ctrl.Caption <> "" Then
ctrl.SpecialEffect = fmSpecialEffectFlat
ctrl.BorderStyle = fmBorderStyleSingle
ctrl.BackColor = RGB(0, 200, 0)
End If
End Sub
|
di Vecchio Frac data: 26/07/2016 15:28:09
E guarda, volendo ottimizzare, si può anche evitare quel " For i = 10 To 51" nel modulo di classe, basta impostare correttamente una variabile oggetto (pubblica) al controllo Label che era stato cliccato per ultimo, così da riportare solo quella, e non tutte le cinquanta Labels, allo stato originario. Così si evita l'attesa di qualche microsecondo che comunque è fastidiosa :)
Rinominando le labels dei giorni settimana e del mese/anno poi puoi anche evitare che cliccandoci sopra questi cambino colore.
Insomma, un mondo in evoluzione ^_^
di Vecchio Frac data: 26/07/2016 15:44:20
Finisco con la routine "calendario" nel modulo1 così il progetto è completo.
Magari allego il file completo ("calendario_VF.xlsb").
Nota 1: i nomi che avevi assegnato Label1 e Label2 sono diventati DLabel1 e DLabel2 così evito di farli riconoscere al modulo di classe e velocizzo le operazioni
Nota 2: la variabile prevCtrl ha senso se leggi il mio post precedente a questo
Option Explicit
Public prevCtrl As Object
Function calendario()
Dim giorno As String
Dim i As Integer, j As Integer
With Foglio1
.DLabel1 = .ComboBox1
.DLabel2 = .ComboBox2
If .DLabel1 <> "" And .DLabel2 <> "" Then
giorno = Format(CDate(.DLabel1 & " " & .DLabel2), "ddd")
For i = 10 To 51
With .OLEObjects("Label" & i)
.Object.Caption = ""
End With
Next
j = InStr("lunmarmergiovensabdom", giorno) 3
For i = 10 + j To 40 + j
With .OLEObjects("Label" & i)
.Object.Caption = i - (10 + j) + 1
End With
Next
Select Case .DLabel1
Case "febbraio"
If .DLabel2 Mod 4 <> 0 Then j = 28 Else j = 29
For i = 38 To 46
With .OLEObjects("Label" & i)
If .Object.Caption > j Then .Object.Caption = ""
End With
Next
Case "aprile", "giugno", "settembre", "novembre"
For i = 40 To 51
With .OLEObjects("Label" & i)
If .Object.Caption > 30 Then .Object.Caption = ""
End With
Next
End Select
End If
End With
End Function
|
di Albatros54 data: 26/07/2016 16:35:42
La Classe (MODULO!!!) non è acqua
di Vecchio Frac data: 26/07/2016 17:20:57
Bravo al nostro Albatros che ha avuto lo spunto giusto!
Solo che ho voluto andare per gradi anche per mostrare a Thyke un uso evoluto (e più complesso ma più versatile) di VBA. Magari mi diventa un esperto di moduli di classe ;)
di Thyke data: 26/07/2016 18:26:51
bene ragazzi...tanta carne sul fuoco stasera, mi salvo i due file ed il codice, poi domani me li guardo per bene, stasera sono un pochino scoppiatello
@ Vecchio Frac
[cit]Sarei curioso di sapere come utilizzeresti in pratica un calendario fatto in modo così statico.
Tu dici: "ho deciso poi di farlo incorporato in un foglio con l'intenzione poi di usarlo come modello per altri lavori". Ma non mi sembra molto flessibile.
Il codice poi è particolarmente pesante. Dovresti usare più spesso dei cicli For e giocare con i nomi degli oggetti (chiamandoli ad esempio "day01", "day02" eccetera per i nomi dei giorni in modo che poi li individui subito).
Comunque ho recuperato il mio calendario personalizzato (quello che uso in Access) e che è strutturato con delle label come il tuo. E' piuttosto compatto e il codice abbastanza snello. Se mi dici che sei interessato provo a adattarlo al tuo contesto (i.e., farlo funzionare su Excel).
[/cit]
-si il codice è molto pesante, già oggi sul lavoro l'ho alleggerito di qualche migliaio di righe
in ogni caso i controlli incorporati nel foglio fanno decisamente pietà, oggi tra l'altro l'ho rifatto in un form e gira che è una meraviglia.
-certo che mi interessa il tuo, se me lo fai avere poi ci penso io ad adattarlo, sono curioso di vedere come lo hai fatto
-il mio problema è che devo avere un calendario da utilizzare nei miei lavori senza dover avere problemi ci componenti ocx, così ho esplorato alcune strade, l'ho fatto utilizzando solo delle celle (senza nessun controllo) e non gira male solo che mi da il problema di dover dimensionare alcune righe ed alcune colonne per dargli un aspetto gradevole.
l'ho fatto utilizzando un form ed è il migliore (alla fine penso che userò quello).
Questo utilizzando i controlli incorporati nel foglio era più che altro un esercizio di stile per esplorare le possibilità che danno e mi sono trovato davanti al problema di non poter creare array di controlli, è per questo che ho aperto la discussione.
Buono il sistema delle classi, non voglio offendere tutti gli altri ma mi sembra il migliore, lo studierò per bene al momento le sue possibilità mi sembrano molto ampie e mi danno l'idea di aumentare di molto la flessibilità del VBA
grazie a tutti ragazzi, adesso mi studio tutte le soluzioni che mi avete proposto poi se è il caso faccio un up alla discussione, così vi arriva la notifica
di Vecchio Frac data: 26/07/2016 18:43:09
Sì il form è meglio.
Ma studiati l'array di controlli come l'ho implementato nel tuo file e vedrai che alla fine gira lo stesso con codice molto compatto :)
Il mio calendario (che non è il mio, l'ho mutuato da un certo Allen Browne) lo trovi nel foglio2 del file che ho allegato sottoforma di immagine (il codice originale è nel modulo del foglio2). Va su Access e bisogna risistemarlo per Excel. A questo punto non so se ti vale la pena... puoi prenderlo solo come idea.
di Thyke data: 26/07/2016 19:16:46
mi interessa in quanto a me piace vedere le differenti soluzioni per raggiungere lo stesso obiettivo, quindi me lo guarderò per bene, come mi guarderò per bene tutte le soluzioni che mi avete postato.
Nel mio calendario voglio aggiungere le festività (cose che mancano in quasi tutti i calendari che ci sono in circolazione ),per il calcolo della pasqua ho trovato una formula ideata da Gauss che ho già trasformato in codice e che voglio implementare...quasi quasi ci faccio un componente con il visual studio..
di Raffaele_53 data: 26/07/2016 19:31:43
Vi leggo, mà oltre il mio naso non vado.
Ho allegato un calendario fatto per (mac che non supporta gli activeX)
di Vecchio Frac data: 26/07/2016 21:21:28
@Thyke
Non ci sono soluzioni diverse, sono tutti i miei post che man mano aggiornavo per raggiungere l'obiettivo. Una specie di work in progress :) ma alla fine la soluzione è una sola.
Approvo però l'approccio multidisciplinare che hai :)
Sulle festività e la Pasqua, quando tornerò in ufficio (non domani) proverò a postare la mia realizzazione dell'algoritmo così lo confrontiamo e se mi piace di più il tuo metodo, lo adotto :)
@Raffaele
Non c'è niente di complicato in tutta la discussione. Esotico magari e interessante (gli array di controlli sono una soluzione elegante a una mancanza di VBA!) ma non fuori portata.
Vuoi Approfondire?