Confrontare elenchi (colonne) di dati con aree (intervalli) contenenti dati. - pagina vista: volte Requisiti: conoscenza dei cicli For..Next In genere, quando si ricercano e confrontano dati tra due tabelle, si utilizzano cicli For...Next oppure For Each...Next che, scorrendo riga per riga (o colonna per colonna) di una tabella, controlli se il dato in quel momento letto sia presente nelle righe (o colonne) dell'altra tabella, magari utilizzando un secondo ciclo per scorrere ogni riga (o colonna) di questa seconda tabella. Questo modo di agire (con doppi cicli) su intervalli molto ampi possono richiedere molto tempo, specie se il computer è un pò "vecchiotto" o poco potente. Vediamo un possibile esempio in questa immagine: nella colonna E (verde) abbiamo dei nomi; nell 'intervallo A1:D4 un elenco ancora con nomi; in giallo ho evidenziato i nomi simili a quelli presenti nella colonna E. Ora, il modo di impostare istruzioni dipende ovviamente da ciò che vogliamo ottenere da un confronto, ma supponendo, giusto per restare nel tema di un doppio ciclo, di voler sapere in quali celle del Range A1:D4 è presente ogni nome letto nella colonna E, potremmo impostare un'istruzione come questa sotto, dove per ogni nome letto in E dal ciclo esterno (For RigaE = 1 To 4), si effettua un secondo ciclo interno che scorre tutte le celle dell'intervallo A1:D4 (For Each CL ecc.ecc); se il nome letto viene trovato, se ne prende l'indirizzo cella (Address), e lo si concatena alla variabile "Indirizzo" impostata inizialmente a vuota; alla fine di ogni ciclo interno, restituiamo un messaggio (in totale 4 messaggi), tipo quello che vediamo sotto a destra:
Se invece dell'indirizzo cella del valore uguale trovato in A1:D4 si volesse contare quante volte è presente ogni valore letto nell'intervallo colonna E, anzichè usare un doppio ciclo, potremo eseguire un ciclo semplice, che scorra la colonna E e confronti il dato letto con tutto l'intervallo A1:D4 (senza doverlo scorrere cella dopo cella) prendendolo come "insieme" (intervallo) di celle (Range) al quale applicare, in questo caso, la funzione CountIf (Conta.Se), come nella seguente macro dove facciamo restituire per ogni dato letto dal ciclo nella colonna E, il valore del dato letto in E (il nome) concatenato al valore numerico di quante volte è presente:
Come si nota, nella macro Sub Presenza(), non si scorrono tutte le celle dell'intervallo A1:D4 con un ciclo, ma ci si riferisce all'intero intervallo, confrontandolo in un colpo solo con ciò che viene letto nella Cella(R, 5) ottenendo una risposta più rapida e comunque completa. E' questo modo di riferirci ad un intero intervallo che si vuole mettere in evidenza in questo articolo, intervallo che rappresenta un argomento (dove cercare) di una Funzione che useremo (nell'esempio la Funzione CountIf(intervallo dove cercare, cosa cercare)). Quando sia possibile, è dunque preferibile utilizzare un riferimento ad un intero intervallo piuttosto che usare un ciclo che scorra le tutte le celle del medesimo intervallo. Un altra considerazione che dobbiamo fare, è che possiamo usare due sintassi diverse per identificare un'intervallo:
Infatti se modifichiamo la riga sopra in Presenze = Application.CountIf(Range(Cells(1, 1), Cells(4, 4)), Cells(R, 5)) il risultato non cambia. Entrambi identificano lo stesso intervallo, ma l'utilizzo di Cells (che richiede di indicare il numero di riga e il numero di colonna di una specifica cella), risulterà vantaggioso se avremo bisogno di scorrere le celle dell'intervallo o meglio, di modificare gli indici di riga o di colonna. Per evitare contraddizioni, (Ciclo contro Riferimento a intervallo) è necessario precisare che in alcuni casi è necessario utilizzare la sintassi Cells per riferirsi ad un intervallo, quando l'intero intervallo deve variare. Una richiesta di un "pellegrino" ci fornisce il motivo di chiarire. La domanda: "...Ho
scritto questa macro che confronta il contenuto delle celle E1->E4 con il
range A1->D4 e se trova stringhe uguali le cancella. e questa la sua macro:
Come si nota, le istruzioni usano il metodo Replace per rimpiazzare col vuoto ("") le celle in A1:D4 che saranno uguali al valore letto nel ciclo nell'intervallo E1:E4. La sua istruzione funziona egregiamente, ma vista la richiesta, è necessario usare la sintassi Cells per identificare l'intervallo in cui cercare, visto che dobbiamo incrementare di 4 in 4 gli indici di riga; come pure dovremo incrementare di 4 in 4 gli indici di riga dell'intervallo delle celle da cercare (colonna E). Creiamo quindi un doppio ciclo: il ciclo esterno (primo ciclo) che farà scorrere gli indici di riga dell'intervallo dove cercare, con passo 4 (Step 4) e all'interno del ciclo esterno un secondo ciclo che scorrerà le celle della colonna E, confrontandole con l'intervallo in quel momento individuato; questa l'istruzione impostata per 40 righe:
Il bello dell'azione è che l'eliminazione dei dati uguali, nell'intervallo dove cercare (con celle gialle) avviene in contemporanea su tutti i dati simili (la parola "pluto" era presente 3 volte e su righe e colonne diverse, e viene eliminata in contemporanea da tutte le celle dell'intervallo). A questo punto l'esercizio si presta anche ad altri tipi di interventi, oltre a quello di eliminare dati uguali e quelli letti, sarà possibile per esempio, mettere tutto in maiuscolo i dati trovati uguali nell'intervallo, come in questa routine impostata su un Range definito:
o ancora eseguire modifiche a valori numerici, di valori uguali a quelli letti, moltiplicandoli (o altra operazione aritmetica) per un moltiplicatore, come questa sotto, dove moltiplichiamo il valore trovato uguale, per 5:
Buon lavoro. prelevato sul sito www.ennius.altervista.org |