proprietà Name



  • proprietà .Name
    di rambo424 data: 20/02/2014 10:41:17

    Ciao ragazzi!
    piccolo problema:
    Ho la necessità di scrivere una macro che mi consenta di rinominare 11 sheet in base all'anno di una certa data scritta in una cella.
    La cosa che mi complica la mia soluzione è che non so a priori come si chiamano gli sheet, che quindi non posso identificare come worksheets("nome") ma solo con il loro nome interno, ovvero Sheet1, Sheet2, ecc.
    La classe Sheets() non ha la proprietà .name, quindi non mi resta altra scelta.
    Ora, per non ripetere per 12 volte il comando Sheet1.Name = "zzzz", vorrei scrivere un ciclo for. Non riesco a settare una variabile, perchè il codice va in debug.. So di essere stato poco chiaro, ma il codice che vi riporto di sotto vi permetterà sicuramente di capire il problema!
    Aspetto un vostro aiuto!! :D
     
    for i=0 to 11
         label = "Sheet"  & numero + i
         set foglio = label ---> Debug!!!!! 
         foglio.Name = "Anno" & i
    next i



  • di Lucas87 data: 20/02/2014 10:51:40

    Con questo cambia il nome in base a quello scritto in A1 dello stesso foglio.
    Non hai specificato dove si trova la cella con la data da cui dovrebbe prendere l'anno quindi devi adattarla tu.
     
    For i = 1 To Sheets.Count
        Sheets(i).Name = Sheets(i).Range("a1")
    Next



  • di rambo424 data: 20/02/2014 10:58:20

    ciao lucas!
    il problema è che con sheets(number) non mi seleziona lo sheet con code number = number ma uno diverso!!



  • di rambo424 data: 20/02/2014 11:03:57

    credo dipenda dal fatto che l'oggetto sheets() richieda come argomento l' Index del foglio, che è diverso dal CodeName dello sheet!
    per capirci:
    worksheets("pippo") = Sheet1 e ha come Index un numero che non è obbligatoriamente 1 !



  • di Grograman (utente non iscritto) data: 20/02/2014 11:19:16

    Non credo di aver capito il problema, ma prova questo:


     
    Option Explicit
    
    Sub codenameonon()
    Dim ws As Worksheet
    Dim i As Long
    For Each ws In ThisWorkbook.Worksheets
      For i = 1 To ThisWorkbook.Worksheets.Count
        If ws.CodeName = "Foglio" & i Then
          ws.Name = ws.Cells(1, 1) 'qui l'azione da svolgere
          Exit For
        End If
      Next i
    Next ws
    End Sub
    



  • di Lucas87 data: 20/02/2014 11:25:55

    Forse è meglio se alleghi un file di esempio.
    Io ho capito che hai 11 fogli e vuoi rinominarli in base all'anno scritto in una cella.
    Ma questa cella dove si trova? Su quale foglio?
    Se è sul foglio da rinominare il mio codice funziona (ma non credo).
    E se non si trova sul rispettivo foglio in che maniera viene determinato che il foglio "pippo" deve essere rinominato con quella data?



  • di rambo424 (utente non iscritto) data: 20/02/2014 11:44:44

    Allora.. vi allego la semplice macro che avevo fatto in origine (sub test)

    Ora, però, ho necessità di non identificare più il worksheet con l'oggetto Worksheets perchè non so a priori come esso si chiami; ho pensato quindi di identificarlo con il codeName e ho provato a scrivere la sub test2, che però non funziona.

    Spero di essere stato più chiaro!
     
    Sub test()
    data = Sheet1.Cells(1, 1) 'resta fissa
    For i = 0 To 11
        Worksheets("Anno" & i).Name = "test anno" & i
    Next i
    End Sub
    
    Sub test2()
    data = Sheet1.Cells(1, 1) 'resta fissa
    For i = 0 To 11
        nomeSheet = "Sheet" & i
        nomeSheet.Name = "test anno" & i
    Next i
    End Sub
    



  • di Vecchio Frac data: 20/02/2014 11:48:46

    Il grande problema dei nomi di foglio (le caption delle schede per intenderci) e la relativa proprietà che si assegna con la finestra proprietà nell'IDE. Cosa che peraltro si fa raramente o non si dovrebbe fare :)

    Se il primo foglio è "Foglio1", questi riferimenti sono equivalenti:
    Sheets(1).Name
    Sheets("Foglio1").Name
    Foglio1.Name

    Sheets(1).CodeName
    Sheets("Foglio1").CodeName
    Foglio1.CodeName


    Ma se lo rinomino come "pippo", solo questi saranno equivalenti:
    Sheets(1).Name
    Foglio1.Name

    Sheets(1).CodeName
    Foglio1.CodeName


    e restituiranno *sempre* "Foglio1" anche se il foglio si chiama "pippo"!
    Questo perchè il Codename è il riferimento interno e non si può cambiare a runtime... o no? ^_^



     
    foglio1.Parent.VBProject.VBComponents(foglio2.CodeName).Name = "MyNewCodeName"
    






  • di Vecchio Frac data: 20/02/2014 11:49:48

    Errata corrige (ovviamente)...
     
    foglio1.Parent.VBProject.VBComponents(foglio1.CodeName).Name = "MyNewCodeName"
    






  • di Vecchio Frac data: 20/02/2014 11:52:51

    E ricordate di mettere sempre Option Explicit e di dimensionare le variabili.
     
    Option Explicit
    
    Sub test2()
    Dim data as date, i as integer, nomesheet as worksheet
        data = Foglio1.Cells(1, 1) 'resta fissa
        For i = 1 To 12
            Set nomesheet = Sheets(i)
            nomesheet.Name = "test anno" & i
        Next i
    End Sub






  • di rambo424 (utente non iscritto) data: 20/02/2014 11:56:32

    grazie vecchiofrac!
    non ho capito però (scusa la mia ottusaggine) comeposso risolvere il mio problema :(



  • di rambo424 (utente non iscritto) data: 20/02/2014 12:07:24

    Sono riuscito grazie al vostro supporto a risolvere il problema!
    vi posto di sotto la macro, che ora fa il suo dovere
    se avete suggerimenti per migliorarne l'efficacia.. sono sicuramente ben accetti!!!

    Grazie a tutti!!!! :)

    ps.: scusate per i nomi disney, ma non sono dati di mia proprietà!
     
    Sub test()
    option explicit
    dim lastrundate as date, numero as double, i as double
    
    lastrundate = Sheet1.Cells(2, 47).value
    Dim label As String
    
    numero = 33
    i = 0
    '---------------Nomi Fogli Anno------------------------
    For Each ws In ThisWorkbook.Worksheets
       Set foglio = ws
       If ws.CodeName = "Sheet" & numero Then
            cmt = Switch(i < 4, "pippo", i >= 4 And i < 8, "pluto", i >= 8, "paperino")
            '--anno-----
            If i = 0 Or i = 4 Or i = 8 Then anno = 0
            If i = 1 Or i = 5 Or i = 9 Then anno = 1
            If i = 2 Or i = 6 Or i = 10 Then anno = 2
            If i = 3 Or i = 7 Or i = 11 Then anno = 3
            '-----------
            label = cmt & " Report Sell-Buy " & Year(lastrundate) + anno
            ws.Name = label
            numero = numero + 1
            i = i + 1
        End If
    Next ws
    End Sub
    



  • di Grograman (utente non iscritto) data: 20/02/2014 12:22:53

    cit: "vi posto di sotto la macro, che ora fa il suo dovere"

    Non vedo come, avendo le dichiarazioni di opètion explici DENTRO la routine e la mancata dichiarazione della variabile "ws"




  • di Vecchio Frac data: 20/02/2014 14:05:40

    cit. "avendo le dichiarazioni di option explicit DENTRO la routine"
    ---> è colpa mia che non sono stato chiaro: cit. "E ricordate di mettere sempre Option Explicit", ovviamente va inteso "in testa ai moduli di codice".
    ^_^

    Mi piace l'uso di Switch. Proprio nei giorni scorsi dicevo che non ho mai visto nessuno usarlo davvero in produzione (nemmeno io). Di sicuro è più efficiente un Select Case.

    Osservazioni al codice (a parte Option Explicit da mettere come prima riga di codice)
    - tieni insieme tutti i Dim, non aumenta l'efficienza ma il codice è più ordinato (non sparpagliare i Dim nel codice)
    - "Set foglio = ws" non serve, è inutile (tanto vero che nemmeno lo usi nel seguito)
    - usa Select Case invece di Switch
    - tutti i quattro test per anno si possono eliminare:
    anno = i mod 4






  • di rambo424 data: 20/02/2014 14:34:11

    Grazie vecchio frac!! non conoscevo l' operatore Mod! ho imparato una cosa nuova, oggi grazie a te! ^_^

    posso farti una domanda teorica?
    perchè mi suggerisci l'uso di select case invece di switch? è migliore in termini di efficienza ?

    grazie ancora!



  • di Vecchio Frac data: 20/02/2014 15:03:10

    Sì, è più efficiente.
    Proprio qualche giorno fa si discuteva di questo caso.
    In pratica con Switch vengono valutate tutte le condizioni e in fase di compilazione, se una condizione solleva errore, si ferma l'esecuzione
    Con Select Case i singoli rami Case vengono valutati soltanto all'occorrenza.
    Guarda il codice di esempio, apparentemente le due sub fanno la stessa cosa, ma l'eccezione (l'errore dovuto alla divisione per zero) viene gestita diversamente.
     
    Option Explicit
    
    Sub test_select()
    Dim a As Integer, m As String
    
        a = InputBox("Enter a number [1-3]:")
        Select Case a
        Case 1
            m = "Hai inserito 1 " & (1 / 0)
        
        Case 2
            m = "Hai inserito 2"
        
        Case 3
            m = "Hai inserito 3"
            
        Case Else
            m = "Non hai inserito un numero tra 1 e 3."
        
        End Select
        
        MsgBox m
        
    End Sub
    
    
    Sub test_switch()
    Dim a As Integer, m As String
    
        a = InputBox("Enter a number [1-3]:")
        
        If a Like "[!1-3]" Then
            m = "Non hai inserito un numero tra 1 e 3."
        Else
            m = Switch(a = 1, "Hai inserito 1 " & (1 / 0), a = 2, "Hai inserito 2", a = 3, "Hai inserito 3")
        End If
    
        MsgBox m
        
    End Sub
    






  • di rambo424 (utente non iscritto) data: 20/02/2014 16:23:09

    Grazie per la risposta!

    oggi, allora ho imparato due cose nuove nell' universo di VBA! :)



  • di scossa data: 20/02/2014 19:26:31

    Riporto quanto avevo scritto in altro forum riguardo la proprietà Codename, sperando sia di interesse.
    -------------------------
    Una precisazione: la proprietà Codename esiste per tutti e per qualsiasi foglio di qualsiasi cartella di lavoro (es.: ThisWorkbook.Worksheets(1).codename o wb2.Worksheets(1).codename o ActiveWorkbook.Worksheets(2).codename) il punto è che è possibile riferirsi direttamente tramite il codename solo a fogli della cartella a cui appartiene il progetto VBA: in un modulo del nostro file potremo avere un codice tipo:
    Codice:
    Foglio1.cells.clear


    e Foglio1 sarà inequivocabilmente il worksheet con codename uguale a Foglio1, ma se nel nostro progetto aprissimo un'altra cartella di lavoro e questa nel codice dell'evento Open() avesse la stessa istruzione
    Codice:
    Foglio1.Cells.Clear

    ovviamente Foglio1 sarà inequivocabilmente il worksheet con codename uguale a Foglio1 di quest'ultima cartella di lavoro (perchè quell'istruzione appartiene al codice del progetto di quella cartella).


    Codice:
    Public Sub prova()
    Debug.Print Foglio1.Parent.Name
    Workbooks.Open "Pippo.xlsm"
    Debug.Print Foglio1.Parent.Name

    End Sub


    se nel modulo di classe Thisworkbook ("Questa_cartella_di_lavoro") del file "Pippo.xlsm" avessimo:

    Codice:
    Private Sub Workbook_Open()
    Debug.Print Foglio1.Parent.Name
    End Sub


    la finestra immediata mostrerebbe:

    Codice:
    Cartel1
    Pippo.xlsm
    Cartel1

    ------------------------



  • di Vecchio Frac data: 20/02/2014 19:40:17

    Grazie scossa, è interessante e anche importante.