Copia di Range (celle, righe o colonne) con il metodo Union. - dal 04/09/04 pagina vista: volte

Abbiamo già visto l'utilizzo del metodo Union nell'articolo "Copia/Incolla 4", sull'altro sito, ma continuano richieste sull'argomento Copia di intere righe o colonne, anche non conseguenti, (non vicine).

Il metodo Union consente di unire due o più intervalli in modo che determinate istruzioni possano agire su tutti gli intervalli così uniti, in pratica serve a gestire più righe o colonne contemporaneamente.

Sappiamo cosa è un intervallo : è un insieme (Range) di celle del foglio di lavoro, che possono essere anche intere righe, o intere colonne o insiemi di intere righe + colonne.

  • Set MiaUnione = Union(Columns(1), Columns(2), Columns(6))  - con MiaUnione si identificano le Colonne A, B e F

  • Set MiaUnione = Union(Columns(1), Columns(2), Rows(5)) - con MiaUnione si identificano le Colonne A, B e la riga 5

  • Set MiaUnione = Union(Rows(3), Rows(7), Rows(10)) - con MiaUnione si identificano le righe 3, 7 e 10

La sintassi del metodo Union è semplice: si citano come argomenti, le righe o colonne con, tra parentesi , il loro numero indice, ed ogni argomento è separato dal successivo con una virgola.

L'unione di più intervalli viene vista dal vba come un Range, se mi è concesso direi: come un unico intervallo, e sarà quindi possibile usare le istruzioni tipiche che si usano su singoli intervalli (o Range di celle). Per esempio sarà possibile assegnare il carattere grassetto a tutte le celle dell'intervallo dichiarato con Union: questa sotto imposta il grassetto a tutte le celle della colonna A, della B e della riga 5

  • Dim MiaUnione As Range   'è necessario definire MiaUnione come oggetto Range
    Set MiaUnione = Union(Columns(1), Columns(2), Rows(5))
    MiaUnione.Font.Bold = True

Sarà possibile quindi, visto che così unito viene visto come un normale intervallo, usare dei cicli che spazzolino tutte le celle dell'intervallo. Nell'esempio sotto, oltre a impostare il grassetto, coloreremo di giallo ( o altro colore) tutte le celle corrispondenti ad un determinato criterio. Sarà così possibile evidenziare celle con valori sopra o sotto un limite, oppure celle con date antecedenti o successive ad una data, o ancora evidenziare nominativi o codici, ecc. ecc.. In questo esempio coloreremo di giallo le celle con un valore superiore a 20:

  • Dim MiaUnione As Range
    Set MiaUnione = Union(Columns(1), Columns(2), Rows(5))
    MiaUnione.Font.Bold = True
    For Each c In MiaUnione 
    'si inizia un ciclo che cercherà in tutte le celle di MiaUnione
    If c.Value > 20 Then         
    'se il valore della cella è maggiore di 20
    c.Interior.ColorIndex = 6  
    'si colora la cella di giiallo
    End If
    Next c

Il metodo Union quindi si rivela efficace quando lavorando su tabelle multicolonna si voglia interessare più colonne, anche distanti tra loro, ad operazioni mirate. Potrebbe essere il caso di colonne contenenti conteggi multipli per ogni riga, tipo: prezzobase - incremento - prezzo unitario - quantità - prezzonetto - % iva - importo iva - totale, e si voglia eseguire istruzioni solo sui campi :  prezzo unitario - prezzonetto - importo iva - totale

Un'operazione che spesso facciamo è quella di voler copiare i dati delle colonne scelte, in un'altro foglio, che poi è lo scopo di questo articolo. Oppure quello di volere copiare determinate righe in un'altro foglio. Per questo sfrutteremo il metodo Copy. Vedremo entrambi gli esempi, ma prima è necessario fare alcune precisazioni:

  • quando si impostano più intervalli col metodo Union, intervalli che vanno copiati, è necessario che gli intervalli da unire abbiano tutti la stessa dimensione: se sono intervalli che riguardano colonne, dovranno tutti iniziare dalla stessa riga, e non sono ammessi intervalli orizzontali, cioè di righe. Lo stesso dicasi se gli intervalli da unire riguardano righe: tutte le righe dovranno iniziare dalla stessa colonna, e non sono ammessi intervalli verticali. Questo perchè l'area copiata, anche se da colonne (o righe) distanti le une dalle altre, verranno poi incollate una accanto all'altra, e questa "geometria" non potrebbe essere eseguita se l'origine intervalli ha dimensioni diverso di intervallo. Vediamo due esempi per capire: nella tabella a sinistra uniamo le due colonne A e C (verde chiaro) che incolleremo nella tabella destinazione (stesso foglio, o altro foglio): le due colonne copiate separate, verranno incollate adiacenti:

Tabella da copiare

Tebella destinazione

  A B C D E   A B C D E
1           1          
2           2          
3           3          
4           4          
5           5          
6           6          

Questa combinazione sotto, righe 2 e 4 + colonna B non è possibile copiare/incollare, e non andrebbe bene neanche più colonne e una o più righe:

  A B C D E
1          
2          
3          
4          
5          
6          

Come pure non andrebbe bene questa combinazione, dove le colonne (o le righe su colonne diverse) iniziano su righe diverse:

  A B C D E
1          
2          
3          
4          
5          
6          
  • per definire sul foglio destinazione come  (anzi dove) incollare i dati copiati, è sufficiente definire una sola cella : da questa cella inizierà l'incollaggio e la formazione di tante colonne o tante righe, quante erano in origine le colonne o righe copiate.

  • con il metodo Copy, ricordo che verrano copiati anche i formati cella, eventuali colori cella, gli eventuali bordi cella, come pure le formule in esse contenute. Se vorremo invece copiare solo i valori, dovremo ricorre al metodo PasteSpecial, che con l'opzione xlValue consente di incollare solo i valori.

Nella definizione della cella che servirà come cella iniziale per l'incollaggio, è bene tenere presente che la definizione di intervallo di più colonne intere o più righe intere, comprendono un'area che inizia dalla prima riga (o dalla prima colonna per le righe) ed arriva a fine foglio. Questo comporta che anche la destinazione dovrà disporre della stessa dimensione dell'area copiata; in pratica come destinazione potremo solo scegliere o la riga1 per incollare colonne, o la colonna A per incollare righe.

Ad ogni lancio macro, verranno sovrascritti i dati esistenti, per cui, se vorremo accodare dati, dovremo usare un diverso sistema per unire intervalli, (quindi non basato su intere colonne o intere righe, ma su intervalli  più "ristretti".), e un ciclo che cerchi, data la cella iniziale, la prima riga libera (se si incollano dati copiati da righe) dove eseguire l'incollaggio, oppure la prima colonna libera se si incollano dati copiati da colonne. Vediamo una prima routine che copierà i dati dalle colonne A e C (intere) e l'incollerà sul foglio2 a partire dalla cella A1 ( ma poteva essere la cella D1, l'importante è in questo caso, iniziare dalla prima riga):

  • Dim MiaUnione As Range
    Set MiaUnione = Union(Columns(1), Columns(3))
    MiaUnione.Copy Worksheets("Foglio2").[A1]

Come si nota, il metodo Copy consente di "mirare" ad una cella del foglio2 senza attivare il foglio stesso. Visto che abbiamo indicato come cella inizio incollaggio la cella A1, verranno incolati i dati nelle colonne A e B.

In questo caso, dove copiamo colonne intere, ma solo due (o 3 o 4), potremo sfruttare tutte le colonne disponibili di un foglio (255) per "accodare" incollando dati senza sovrascrivere quelli esistenti. Dovremo modificare l'istruzione sopra con la selezione del Foglio su cui si incolla, e l'inserimento di un ciclo che scorra le colonne, alla ricerca della prima colonna vuota. Attenzione: condizione determinante sarà che le celle iniziali delle colonne copiate (origine) contengano dati, altrimenti il ciclo di ricerca sul foglio destinazione, cercando la prima cella libera sulla riga 1, scaricherà i dati dove trova la prima cella vuota. Vediamo la routine:

  • Sub MulticopiaColonne()
    Worksheets("Foglio1").Activate
    Dim MiaUnione As Range
    Set MiaUnione = Union(Columns(1), Columns(3))
    Worksheets("Foglio2").Activate
    Dim iCol As Integer
    iCol = 1
    While Cells(1, iCol) <> ""
    iCol = iCol + 1
    Wend
    MiaUnione.Copy Cells(1, iCol)
    Worksheets("Foglio1").Activate
    End Sub

Si potrà inserire anche un controllo che ci impedisca di andare oltre le 255 colonne, inserendo la condizione (sotto wend) che se iCol  è uguale o maggiore di 253 (255 meno il numero di colonne copiate, in questo caso: 2) si esca dalla routine, senza incollare.

La stessa routine la potremo usare se copieremo intervalli di più righe, modificando ovviamente il ciclo While per trovare la prima riga libera, nella prima colonna, dove effettuare l'incollaggio, quindi:

  • Sub MulticopiaRighe)
    Worksheets("Foglio1").Activate
    Dim MiaUnione As Range
    Set MiaUnione = Union(Rows(4), Rows(7), Rows(12))
    'uniamo tre righe complete
    Worksheets("Foglio2").Activate
    Dim iRow As Integer
    iRow = 1
    While Cells(iRow, 1) <> ""
    iRow = iRow + 1
    Wend
    MiaUnione.Copy Cells(iRow, 1)
    Worksheets("Foglio1").Activate
    End Sub

In questo esempio, l'incollaggio riunirà le tre righe inizialmente, a partire dalla riga uno, mettendole su tre righe conseguenti.

Diversa sarà l'impostazione delle istruzioni se, anzichè righe o colonne intere, vorremo copiare e incollare più intervalli, orizzontali o verticali, ma limitati da lunghezze o altezze precise. In questo caso, dovremo definire prima di Union, delle variabili che identifichino gli intervalli, poi richiameremo queste variabili come argomenti nel metodo Union. Il concetto che le aree da copiare abbiano tutte la stessa dimensione è sempre da tenere presente; sarà quindi possibile unire intervalli che NON iniziano tutti nella stessa colonna (se orizzontali) o nella stessa riga (se verticali): l'importante sarà che se un intervallo è composto da 7 celle, tutti gli altri prevedano lo stesso numero di celle, e inizino tutti dalla stessa riga (o colonna per intervalli orizzontali). Vediamo quindi una routine su questo esempio, con intervalli posti su colonne

  • Dim C1, C2, C3, MiaUnione As Range 'dichiariamo come Range tutte le variabili
    Set C1 = Range("A1:A10") 
    'primo intervallo di 10 celle che inizia dalla riga 1
    Set C2 = Range("D1:D10") 
    'secondo intervallo che inizia sulla stessa riga e sempre di 10 celle
    Set C3 = Range("G1:G10") 
    'terzo intervallo che inizia sulla stessa riga e sempre di 10 celle
    Set
    MiaUnione = Union(C1, C2, C3)
    MiaUnione.Copy Worksheets("Foglio2").[A1]

e troveremo i tre intervalli incollati e riuniti sul foglio 2, nelle colonne A, B, C. 

Lo stesso sistema useremo se gli intervalli saranno sulla stessa riga. Oppure potrete inserire se necessario, un ciclo While per la ricerca della prima cella vuota, assicurandovi che ciclo venga solto sulla colonna o riga che contenga tutte celle occupate.

Buon lavoro.

prelevato sul sito www.ennius.altervista.org