+ Rispondi al messaggio
Visualizzazione dei risultati da 1 a 9 su 9

Macro Dinamica Copia-Incolla

  1. #1
    Simoncino93 non è in linea Novello
    Ciao a tutti,

    sono un novello quindi mi scuso nel caso dovessi commettere qualche errore.

    Vorrei richiedere il vostro aiuto per completare una macro che necessito per un progetto.

    Premessa: ho un database composto dalle prime 3 colonne che sono un elenco di competenze, mentre dalla 4° colonna in poi ci sono dei ruoli che, incrociando le competenze delle prime 3 colonne, verifico se le possiedono o meno, e così riesco a creare un grafico radiale.

    Richiesta: vorrei sviluppare una macro che mi possa permettere di copiare le prime 3 colonne per n° fogli. Questo n° fogli è determinato dal numero di colonne dalla 4° (compresa) in poi. Non ho un numero specifico di colonne perché il numero di ruoli può variare. E in ciascun foglio, sia copiata la colonna adiacente scalando di 1. Es.: nel primo foglio ho il database, nel secondo le prime 3 colonne con la 4° colonna adiacente, nel terzo foglio sempre le prime 3 colonne con la 5° colonna adiacente, nel quarto foglio ho le prime 3 colonne con la 6° colonna adiacente e così via, finchè non si esauriscono le colonne del database. (spero l'esempio sia chiaro).

    Il codice: finora ho scritto qualche riga, spulciando tra i miei appunti e qualcosina trovata su internet ma non è per nulla completo, anzi, ha molte carenze. Io poi mi sono bloccato e non so come procedere.

    'Sub Splitta_E_Vai()
    '
    'Dim i As Integer
    'Dim Col As Integer
    'Dim rs As Worksheet
    '
    'RwRng = Foglio1.Cells(Rows.Count, 1).End(xlUp).Row
    'ColRng = Foglio1.Cells(1, Columns.Count).End(xlToLeft).Column
    '
    'Worksheet("Area Operativa").Activate
    'For i = 4 To ColRng
    'Range(Cells(1, 1), Cells(RwRng, 3)).Copy Sheets(i)
    'For Each rs In Sheets
    'rs.Name = rs.Range("B5")
    'Next rs
    'Next i
    '
    'End Sub
    
    P.s.: "Area Operativa è il nome del foglio in cui inserire il database iniziale. Ho aggiunto anche un codice per far sì che ogni foglio prenda il nome presente nella propria cella B5.
    Credo che ci sia una base comprensibile però non so come mettere giù i comandi per selezionare la colonna desiderata e poi scalare colonna per il nuovo foglio.


    Ringrazio in anticipo chiunque voglia darmi una mano, ve ne sarò grato.
    Accrescerete anche le mie conoscenze sul VBA che sto cercando di imparare come posso.

    Grazie!
    Ultima modifica di AntonioG; 04-07-2021 17:44  Motivo: Tag CODE per il codice

  2. #2
    Marius44 non è in linea Scolaretto
    Ciao
    Mi permetto un consiglio che ritengo basilare: Metti sempre in testa a qualsiasi modulo Option Explicit e dichiara tutte le variabili che utilizzerai. Ti eviterai molti "mal di testa".

    Veniamo al tuo esempio.
    Sei sicuro che la macro che hai postato funzioni? Io credo di no.
    Questa riga di codice cosa dovrebbe fare: Range(Cells(1, 1), Cells(RwRng, 3)).Copy Sheets(i)
    A mio avviso copia le prime 3 colonne e dovrebbe bloccarsi perchè non hai detto ad Excel DOVE incollare. Manca la cella.
    Il ciclo successivo mi sembra errato (o, meglio, non corretto). Vorresti passare tutti i fogli presenti ma non credo basti mettere For Each rs in Sheets (dovrebbe dare errore) ma mettere Sheets.Count. Ma non hai necessità del ciclo: metti il nome al foglio mentre lo crei.

    Se ho detto corbellerie scusami ma sono ancora assonnato.
    Ciao,
    Mario

  3. #3
    Simoncino93 non è in linea Novello
    Ciao Marius44,

    ti ringrazio per la risposta e i consigli.

    Quote Originariamente inviato da Marius44 Visualizza il messaggio
    Metti sempre in testa a qualsiasi modulo Option Explicit e dichiara tutte le variabili che utilizzerai. Ti eviterai molti "mal di testa".
    Grazie la applico immediatamente


    Quote Originariamente inviato da Marius44 Visualizza il messaggio
    Sei sicuro che la macro che hai postato funzioni? Io credo di no.
    Ma infatti non ho mai detto che funzioni, anzi, ho iniziato a scrivere però non ero sicuro né di come continuare né della sua correttezza, perciò ho scritto sul forum!

    Quote Originariamente inviato da Marius44 Visualizza il messaggio
    Questa riga di codice cosa dovrebbe fare: Range(Cells(1, 1), Cells(RwRng, 3)).Copy Sheets(i)
    A mio avviso copia le prime 3 colonne e dovrebbe bloccarsi perchè non hai detto ad Excel DOVE incollare. Manca la cella.
    Appunto! Vorrei far sì che si incolli sempre dalla cella A1 per tutti i fogli successivi, che sono pari al numero di colonne al di là della terza! È che non lo so fare

    Quote Originariamente inviato da Marius44 Visualizza il messaggio
    Il ciclo successivo mi sembra errato (o, meglio, non corretto). Vorresti passare tutti i fogli presenti ma non credo basti mettere For Each rs in Sheets (dovrebbe dare errore) ma mettere Sheets.Count. Ma non hai necessità del ciclo: metti il nome al foglio mentre lo crei.
    Ho preso questo codice mentre cercavo su internet come fare ad assegnare automaticamente un nome al foglio partendo da una cella in esso contenuta. Quindi basterebbe un Sheets.Count = "D2" senza ciclo?

    Grazie ancora e spero di aver colto i tuoi suggerimenti!

  4. #4
    Sgrubak non è in linea Scribacchino
    Quote Originariamente inviato da Simoncino93 Visualizza il messaggio
    finora ho scritto qualche riga, spulciando tra i miei appunti e qualcosina trovata su internet ma non è per nulla completo, anzi, ha molte carenze. Io poi mi sono bloccato e non so come procedere.
    Come dice Marius, questo codice non funziona per quel che cerchi di fare tu.

    Oltre ai validissimi suggerimenti che ti son già stati dati, ti suggerirei di approcciare alla scrittura del codice partendo con carta e penna. Organizza bene la successione di operazioni da fare (magari con un diagramma di flusso, anche alla buona) e POI comincia a pigiare sulla tastiera.


    Quote Originariamente inviato da Marius44 Visualizza il messaggio
    Vorresti passare tutti i fogli presenti ma non credo basti mettere For Each rs in Sheets (dovrebbe dare errore) ma mettere Sheets.Count.
    È sintatticamente corretto. Ciclando la collection Sheets, scorre regolarmente tutti i fogli. Peccato non li abbia ancora creati... Trovo non abbia senso, allo scorrere di ogni colonna, riscorrere tutti i fogli nuovamente. L'idea del ciclo annidato la scarterei a priori. Come dici tu, una volta creato il foglio di copia, gli si assegna il nome e basta. Un ciclo è sufficiente.

    Quote Originariamente inviato da Simoncino93 Visualizza il messaggio
    Quindi basterebbe un Sheets.Count = "D2" senza ciclo?
    Forse anche un ripasso delle basi non guasterebbe. Questa cosa che hai scritto proprio non si può leggere. Sheets.Count dovrebbe essere proprietà in sola lettura. Non dovresti poter assegnarli nulla. Meno che mai una stringa, dato che è di tipo Long
    Ultima modifica di Sgrubak; 05-07-2021 09:24  Motivo: Aggiunto ultimo quote

  5. #5
    Simoncino93 non è in linea Novello
    Ciao Sgrubak,

    grazie del link e scusami per quanto scritto. Sto cercando di fare quello che posso

    Quindi è inutile un secondo ciclo For per il nome. Perfetto. Aggiornando il codice con i vostri suggerimenti verrebbe una cosa del genere, credo:

    Option Explicit
    
    'Sub Splitta_E_Vai()
    '
    'Dim i As Integer
    'Dim rs As Worksheet
    '
    'RwRng = Foglio1.Cells(Rows.Count, 1).End(xlUp).Row
    'ColRng = Foglio1.Cells(1, Columns.Count).End(xlToLeft).Column
    '
    'Worksheet("Area Operativa").Activate
    'For i = 4 To ColRng
    'Range(Cells(1, 1), Cells(RwRng, 3)).Copy (Cells(1, 1), Cells(RwRng, 3))
    'Next i
    '
    'End Sub
    
    Ho capito di aver sbagliato lo Sheets.Count ma non so dove poterlo inserire visto che scartiamo l'idea di un secondo ciclo

  6. #6
    Sgrubak non è in linea Scribacchino
    Quote Originariamente inviato da Simoncino93 Visualizza il messaggio
    Sto cercando di fare quello che posso
    Che è comprensibile, ma non scrivere codice a casaccio...
    Hai sfruttato il suggerimento dell'Option Explicit. Sai cosa fa? A cosa serve? Perché finche hai il codice commentato, non ne vedi gli effetti.

    Inoltre sarebbe necessario che tu, come ti accennavo prima, riveda la logica dei passaggi che la macro deve svolgere lontano dal VBE. Vuoi creare enne fogli, assegnarli un nome e copiarci dentro dei dati. Dov'è il codice che fa tutto questo?

    Vai con calma e procedi con ordine. Fai dei tentativi a scrivere il codice e lo testi. Quando trovi un'errore specifico che non riesci a risolvere ti si aiuta.

  7. #7
    Marius44 non è in linea Scolaretto
    Ciao a tutti
    Fai conto che quanto appresso sia in un Modulo standard di VBA

    Option Explicit

    Sub Main() 'questo è quello che si tenta di fare
    crea un duplicato del Foglio("Area Operativa") e inseriscilo alla fine
    nel Foglio appena creato
    a) elimina tutte le colonne dalla quarta in poi
    b) scrivi in B5 il nome da assegnare al Foglio
    c) cerca nel Foglio("Area Operativa") la colonna (la stessa del nome che hai scritto in B5)
    che vuoi far apparire nel nuovo Foglio
    d) una volta individuata la colonna copiala e incollala nel Nuovo Foglio
    credo sia tutto
    End Sub

    Non credo sia molto complicato ma può essere utile (magari dopo si depura di tanti fronzoli) aiutarsi con il registratore di macro. Avvialo, esegui tutti i passi sopra descritti e, alla fine, chiudi la registrazione. Ecco il codice.

    Ciao,
    Mario

  8. #8
    Simoncino93 non è in linea Novello
    Buongiorno a tutti!

    Vi ringrazio tutti per i suggerimenti di ieri. Ho creato la macro e funziona, però ci sono ancora alcuni punti da levigare che non ho ancora trovato spulciando su internet e non viene replicata con il registratore di macro.

    Questo è il codice:
    Option Explicit
    Sub GeneraFogli()
    Dim RwRng As Integer    'dichiarazioni variabili
    Dim ColRng As Integer
    Dim i As Integer
    Dim Nome As Variant
    Dim Grafico As Shape
    
    Application.ScreenUpdating = False   'evitiamo il saltellamento a schermo
    
    RwRng = Foglio2.Cells(Rows.Count, 1).End(xlUp).Row
    ColRng = Foglio2.Cells(1, Columns.Count).End(xlToLeft).Column ' otteniamo il numero dell'ultima colonna occupata, Foglio 2
    
    
    For i = 4 To ColRng        'iniziamo un ciclo che scorre le celle dalla colonna 4 fino all'ultima colonna occupata
    Worksheets.Add After:=Sheets(Sheets.Count) 'aggiungiamo un nuovo foglio alla fine dei fogli presenti
    ActiveSheet.Name = "Nome"
    Sheets("Area Operativa").Activate                              'ritorniamo sul foglio1 (l'ultimo foglio creato sarebbe il foglio attivo)
    Sheets("Area Operativa").Range(Cells(1, 1), Cells(RwRng, 3)).Copy 'copiamo il Range delle intestazioni di campo
    Sheets("Nome").Select
    ActiveSheet.Paste 'e incolliamo le intestazioni nello stesso Range sul nuovo foglio
    Application.CutCopyMode = False   'eliminiamo il tratteggio intorno alle celle copiate, foglio2
    Sheets("Area Operativa").Activate
    Sheets("Area Operativa").Range(Cells(1, i), Cells(RwRng, i)).Copy
    Sheets("Nome").Activate
    ActiveSheet.Paste Destination:=Range("D:D") 'e incolliamo le intestazioni nello stesso Range sul nuovo foglio
    Application.CutCopyMode = False
    ActiveSheet.Name = Cells(2, 4)
    ActiveSheet.Range(Cells(1, 1), Cells(RwRng, 4)).Select
    Set Grafico = ActiveSheet.Shapes.AddChart2(381, xlSunburst)
    Sheets("Area Operativa").Activate
    
    Next i
    
    End Sub
    
    Alcuni pezzi saranno sicuramente superflui ai vostri occhi ma già mi stupisco che funzioni dopo le premesse di ieri!

    Punti da levigare:
    1) Alcuni titoli che dovrebbe assumere come nome anche la scheda sono più lunghi del limite massimo consentito, quindi vorrei impostare un limite di caratteri da "prendere" qualora questo venisse superato. Questo tentativo avevo pensato di iniziarlo scrivendo in questo modo
    'If Len(Sheets.Name.Value) > 31 Then
    '
    'End If
    
    ma non so come continuare e dire di prendere solo i primi 31 caratteri e non sforare.

    2) Un altro limite riguarda il grafico. Vorrei che tutti i grafici (in questo caso si parla di Radiali) nelle schede avessero gli stessi colori e come titolo quello che è il ruolo e che va a sostituire il nome del foglio. Ho provato a utilizzare il registratore di Macro ma poi quando vado ad applicare le righe di codice nella mia macro, queste non funzionano.
    ActiveChart.FullSeriesCollection(1).Select
    ActiveChart.FullSeriesCollection(1).Points(1).Select
    ActiveChart.FullSeriesCollection(0).Points(0).ApplyDataLabels
    ActiveChart.FullSeriesCollection(1).Points(43).Select
    ActiveChart.FullSeriesCollection(0).Points(42).ApplyDataLabels
    Range("D2").Select
    ActiveSheet.ChartObjects("Grafico 1").Activate
    ActiveChart.ChartTitle.Select
    Selection.Caption = "XXXX"
    Selection.Copy
    
    Questo è quanto mi esce e non funziona nella mia macro.


    Detto questo, sapete come poter migliorare la mia macro, soprattutto per quanto concerne questi ultimi due punti? Anche conisgliarmi un sito dove approfondire.

    Grazie in anticipo e nuovamente per ieri!

  9. #9
    Sgrubak non è in linea Scribacchino
    Andiam con ordine per le cose che noto:
    1)[Dim Nome As Variant] è dichiarata ma non la usi;
    2)[Application.ScreenUpdating = False] Ok, ma dove ritorna a True? Potrebbe farti comodo anche la Application.Calculation. Prova a dare uno sguardo;
    3)Il metodo Worksheets.Add ritorna il foglio appena inserito. Salvalo in una variabile, ad esempio come fai per il grafico più avanti nel codice e usa poi questa variabile per riferirti al foglio appena inserito. Eviti di abusare dell'ActiveSheet che, saltando da un foglio all'altro rende il codice poco leggibile.
    3.1) Richiamare gli Activate sui fogli, lo trovo soltanto un dispendio di calcolo inutile. A gusto preferisco, come al punto 3, creare una variabile ed usare quella;
    4)[ActiveSheet.Name = "Nome"] assegna una costante, che poi cambi di nuovo con [ActiveSheet.Name = Cells(2, 4)]. Assegna il nome giusto da subito e raggiungi il foglio come suggerito al punto 3;
    5) il tuo punto 1 con l'If è giusto. Per prendere una sottostringa usa la funzione Left.
    6) I grafici li uso poco... Azzardo che l'ActiveChart non sia quello che credi. Sfrutta la variabile [Grafico] che popoli quasi a fine macro.

+ Rispondi al messaggio

Potrebbero interessarti anche ...

  1. macro per copia/incolla
    Da quicksteep nel forum Microsoft Excel
    Risposte: 4
    Ultimo Post: 18-08-2016, 11:20
  2. Macro copia incolla da file diversi
    Da niccoflo nel forum Microsoft Excel
    Risposte: 3
    Ultimo Post: 29-07-2014, 16:14
  3. copia incolla con una macro
    Da ennios nel forum Microsoft Word
    Risposte: 1
    Ultimo Post: 10-12-2010, 23:38
  4. [Excel]Macro...copia e incolla
    Da ghost69 nel forum Microsoft Excel
    Risposte: 15
    Ultimo Post: 14-01-2009, 18:11