Calendario personalizzato direttamente su foglio



  • 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.