Ordinamento delle matrici in base a più campi
Il problema
Sul problema delle matrici abbiamo già parlato abbondantemente, ma ci sono certi argomenti un po' difficili da essere compresi, per cui, anche se precedentemente ne abbiamo già parlato, ci torniamo su guardando il problema da un altro punto di vista.
Stiamo parlando dell'ordinamento di una matrice basato su un campo e dell'ordinamento di una matrice su più campi.. E' ovvio che la matrice di cui stiamo parlando è a 2 dimensioni: una per record ed una per campi.
Per Ordinamento di una matrice basato su un campo intendiamo dire che, data una matrice i cui campi sono: nome, cognome, CAP, città, prov, via, possiamo decidere di ordinare i dati contenuti nella matrice in base al Nome, o al Cognome, ecc.
Per Ordinamento di una matrice basato su più campi intendiamo dire che la stessa matrice possiamo ordinarla prima per un campo, poi per un secondo campo, quindi per un terzo campo e così via.
Nell'immagine che osserviamo qui sotto vediamo due tabelle: una a destra e l'altra a sinistra.
La tabella su cui lavoriamo sarà quella di destra. La tabella di sinistra ci servirà soltanto per controllare le modifiche avvenute nella matrice dopo i due ordinamenti effettuati ed esternate nella tabella di destra e servirà poi per essere trasferita così com'è nella zona di destra per un ulteriore test.

Soluzione
Qui di seguito vengono esposte le due procedure per ottenere l'uno o l'altro tipo di ordinamento.
Per l'ordinamento ho usato il classico, in entrambi i casi, l'algoritmo basato su Bubble Sort (ordinamento a bolle), anche se tra tutti gli algoritmi è il più lento, perchè tra tutti è quello di più semplice comprensione.
Le due routine le scriviamo nel Primo Modulo standard
Ordinamento di una matrice in base ad un unico campo
Questa sarà la InputBox dalla quale verrà effettuata la scelta del campo da ordinare:

In questa routine (la routine Sub OrdinaMatrice() ) ci comportiamo in questa maniera:
vengono memorizzati nella matrice i dati contenuti nella seconda tabella (quella di destra)
si chiede quale deve essere la colonna da ordinare e la colonna scelta verrà memorizzata nella variabile Campo che indicherà quale sarà il campo da ordinare
si procede con l'ordinamento secondo il metodo Bubble Sort
vengono confrontati i dati residenti nella colonna precedentemente indicata
se il confronto risulta positivo (If Matr(R, Campo) > Matr(R1, Campo) Then)
si procede allo scambio dei due record coinvolti scambiando tra loro tramite un ciclo un campo alla volta
For C = 1 To NCamp
VarTemp = Matr(R, C)
Matr(R, C) = Matr(R1, C)
Matr(R1, C) = VarTemp
Next
Fatto questo la missione è compiuta e l'istruzione successiva è solo una
dimostrazione di come si trovano i dati nella matrice ordinata
Ordinamento di una matrice in base a più campi
Questa sarà la UserForm dalla quale si sceglieranno i campi e l'ordine con cui questi saranno ordinati:

Lievemente più complessa è la seconda routine (Sub OrdinaMatrice2() ). Nella routine che effettua l'ordinamento su più campi la procedura è quasi la stessa anche se, inizialmente, meno intuitiva.
vengono memorizzati nella matrice i dati contenuti nella seconda tabella (quella di destra)
tramite una UserForm vengono scelti i campi e l'ordine con cui la matrice dovrà essere ordinata; infatti i campi possono essere presi con un ordine qualsiasi
all'uscita dalla UserForm si raccolgono in una matrice gli indici delle ComboBox da cui si è effettuata la scelta ( ICampi(R) = Controls("ComboBox" & C1).ListIndex + 1) che si riferiscono alle colonne dei vari campi
si torna con questa seconda matrice nella procedura che elabora la matrice
a questo punto se la matrice è vuota non succede nulla, ma se la matrice contiene 1 o più elementi si effettua l'ordinamento
l'algoritmo che viene eseguito dalle istruzioni successive si basa sul confronto non più tra i singolo dati contenuti nella matrice ma sul confronto delle stringhe che si sono create con
For CRec = 1 To CampiRec 'sono i campi scelti per l'ordinamento
Nome1 = Nome1 & Matr(R, ICampi(CRec))
Nome2 = Nome2 & Matr(R1, ICampi(CRec))
Next
tenendo presente che in ICampi(CRec) ci sono le coordinate dei campi scelti e nell'ordine scelto nella UserForm
il successivo confronto non sarà fatta direttamente sui dati residenti nella matrice ma su una stringa che contiene più dati raccolti dalla matrice nell'ordine precedentemente scelto:
CarloBoscatiNapoli e CarloBoscatiMilano
oppure
VerezzoBoscatiAndrea e NapoliZazzeraCarlo
lo scambio successivo avviene secondo la solita maniera
For C = 1 To NCamp
VarTemp = Matr(R, C)
Matr(R, C) = Matr(R1, C)
Matr(R1, C) = VarTemp
Next
Anche qui l'azione si conclude con la visualizzazione del contenuto della
matrice ordinata
Trasferimento del contenuto della matrice sul
foglio di Excel
Degna di attenzione è il metodo usato per trasferire la matrice in un
intervallo del foglio di Excel:
Tabella.Offset(0, 8) = Matr
dove Tabella.Offset(0, 8) è un Range, spostato di 8 colonne rispetto all'intervallo chiamato "Tabella", di uguale dimensione della matrice.
Se l'intervallo di destinazione dovesse rivelarsi di proporzioni inferiori a quelle della matrice i dati della matrice non verrebbero semplicemente visualizzati
Se l'intervallo di destinazione dovesse rivelarsi di proporzioni superiori a
quelle della matrice nelle celle eccedenti verrebbe visualizzato
il messaggio #ND
Alcune note esplicative sul codice relativo all'ordinamento
Vorrei ora mettere a confronto le istruzioni principali usate per i due tipi di ordinamento.
|
Il cuore dell'ordinamento in base ad un campo sta in queste istruzioni:
For R = 1 To NRec - 1
|
La routine per l'ordinamento basato su più campi usa queste istruzioni:
For R = 1 To NRec - 1
|
Prima osservazione: nello schema di sinistra, ordinamento in base ad un campo, vengono confrontati i valori contenuti nella matrice, mentre nello schema di destra, ordinamento basato su più campi, prima di eseguire il confronto viene eseguito un concatenamento di tutti i valori contenuti nei campi precedentemente indicati e selezionati nella UserForm
Seconda osservazione: in entrambi i casi, lo scambio che si andrà ad effettuare avverrà con queste modalità:
![]() |
si pone in una variabile temporanea il contenuto della locazione puntata da R e C si copia nella locazione puntata da R(iga) e C(olonna) il contenuto della locazione puntata da R1 e C si copia nella locazione puntata da R1 e C il contenuto precedentemente salvato nella variabile temporanea
For C = 1 To NCamp
|
E' ovvio che nel modulo che contiene le istruzioni appena esaminate, circondate ed evidenziate da una serie di asterischi, è stato necessario aggiungere altro codice per memorizzare i dati nella matrice e per la scelta del campo o dei campi da ordinare. Per il commento a queste istruzioni aggiuntive si rimanda agli articoli già apparsi nel sito o, se proprio necessario, sarà fatto in un altro momento.
Conclusioni
Allego il file che ho usato per testare ed eseguire gli ordinamenti nella matrice. Il file liberamente scaricabile e consultabile è ordinamento in base a piu campi.zip (22KB).
Buon lavoro
prelevato sul sito www.ennius.altervista.org